变量
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract HelloWorld {
string public myString = "hello world"; // 自带get()方法
bool public b = false; // 默认值 false
uint public u = 123; // uint8/uint16/uint256 0 to 2^8-1 默认值0
int public i = -123; // -2^255 to 2^255-1 默认值0
int public minInt = type(int).min;
int public maxInt = type(int).max;
address public addr = 0x0000000000000000000000000000000000000000; // 地址 私钥算公钥,公钥算地址 默认值40个0
byte32 public b32 = 0x0000000000000000000000000000000000000000000000000000000000000000; // 32位16进制 默认值64个0
}
状态变量&局部变量
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract HelloWorld {
uint public i;
bool public b;
address public myAddress;
function foo() external {
uint x = 123;
bool f = false;
x += 456;
f = true;
i = 123;
b = true;
myAddress = address(1);
}
}
全局变量
链上和账户
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract HelloWorld {
// view 可以读取全局变量和状态变量
function globalVars() external view returns (address,uint,uint){
address sender = msg.sender; // 全局变量-账户内容,调用这个函数的地址(上一个调用者,可能是人或合约)是什么
uint timestamp = block.timestamp; // 区块时间戳,只读。写入方法就是出块的时间
uint blockNum = block.number;
return (sender,timestamp,blockNum);
}
}
常量
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
// 21442 gas 常量消耗更少的gas值,不修改的值定义为常量
contract Contracts {
address public constant MY_ADDRESS = 0x000000000000000000000000000000000000000F;
uint public constant MY_UINT = 123;
}
// 23575 gas
contract Var {
address public MY_ADDRESSS = 0x000000000000000000000000000000000000000C;
}
数组
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract Array {
uint[] public nums= [4,2,3]; // 变长数组
uint[] public nums2 = [1,2,3]; // 变长数组
uint[3] public numsFixed = [4,5,6]; // 定长数组
function examples() external {
nums.push(4); // 添加元素
uint x = nums[0]; // 访问元素
nums[0] = 3; // 修改元素
delete nums[0]; // 删除元素(不影响数组长度,被删元素位置变成默认值)
nums.pop(); // 弹出元素
uint len = nums.length; // 元素长度
// 内存中创建数组(内存中的数组长度固定)
uint[] memory a = new uint[](5);
a[1] = 123;
}
// 返回数组
function returnArray() external view returns (uint[] memory){
return nums;
}
}
删除数组元素 | 移动元素
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
// 缺点:浪费gas
// 优点:顺序不变
contract Array {
uint[] public arr;
function examples() external {
arr = [1,2,3];
delete arr[1]; // [1,0,3]
}
function remove(uint _index) public{
require(_index < arr.length, "index out of bound");
for(uint i = _index; i < arr.length-1; i++){
arr[i]=arr[i+1];
}
arr.pop();
}
// 285955 gas
function test() external {
arr = [1,2,3,4,5];
remove(2);
//[1,2,4,5]
assert(arr[0] == 1);
assert(arr[1] == 2);
assert(arr[2] == 4);
assert(arr[3] == 5);
assert(arr.length == 4);
arr = [1];
remove(0);
assert(arr.length == 0);
}
}
删除数组元素 | 交换元素
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
// 缺点:顺序变化
// 优点:节约gas
contract Array {
uint[] public arr;
function examples() external {
arr = [1,2,3];
delete arr[1]; // [1,0,3]
}
function remove(uint _index) public{
require(_index < arr.length, "index out of bound");
arr[_index]=arr[arr.length-1];
arr.pop();
}
// 284651 gas
function test() external {
arr = [1,2,3,4,5];
remove(2);
//[1,2,5,4]
assert(arr[0] == 1);
assert(arr[1] == 2);
assert(arr[2] == 5);
assert(arr[3] == 4);
assert(arr.length == 4);
arr = [1];
remove(0);
assert(arr.length == 0);
}
}
Map
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract Mapping {
mapping(address => uint) public balances; // 地址余额
mapping(address => mapping(address => bool)) public isFriend; // 嵌套map
address public thisAddr;
address public sender;
function examples() external {
balances[msg.sender] = 123; // 设置数据
uint bal = balances[msg.sender]; // 获取数据
uint bal2 = balances[address(1)]; // 返回一个不存在的数据,默认值0
balances[msg.sender] +=456; // 增加数据
// delete balances[msg.sender]; // 删除数据(数据变为0)
isFriend[msg.sender][address(this)] = true;
sender = msg.sender;
thisAddr = address(this);
}
}
函数
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract HelloWorld {
/*
external 外部函数,只能被外部读取,当前合约内部不能调用
pure 纯函数,不能读写状态变量,只能读写局部变量,即不会对链上有任何操作
*/
function add(uint x,uint y) external pure returns (uint){
return x + y;
}
function sub(uint x,uint y) external pure returns (uint){
return x - y;
}
}
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract HelloWorld {
uint public count;
// 因为要读取状态变量,所以不能带 view或者pure
function inc() external {
count +=1;
}
function dec() external {
count -=1;
}
}
函数修改器
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract Contracts {
bool public paused;
uint public count;
function setPause(bool _paused) external {
paused = _paused;
}
modifier whenNotPaused(){
require(!paused,"paused");
_;
}
function inc() external whenNotPaused{
count += 1;
}
function dec() external whenNotPaused{
count -= 1;
}
modifier cap(uint _x){
require(_x<100,"x >= 100");
_;
}
function incBy(uint _x) external whenNotPaused cap(_x){
count += _x;
}
}
构造函数
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
// 仅能执行一次,用于初始化账号地址等
contract Contracts {
address public owner;
uint public x;
constructor(uint _x){
owner = msg.sender;
x = _x;
}
}
返回值
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract FunctionOutputs {
// 返回值未命名
function returnMany() public pure returns (uint,bool){
return (1,true);
}
// 返回值被命名-1
function named() public pure returns (uint x,bool b){
return (1,true);
}
// 返回值被命名-2
function assigned() public pure returns (uint x,bool b){
x = 1;
b = true;
}
// 接收返回值
function destructingAssigments() public pure {
(uint x,bool b) = returnMany(); // 接收所有返回值
(,bool t) = returnMany(); // 接收部分返回值
}
}
结构体
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract Structs {
struct Car {
string model;
uint year;
address owner;
}
Car public car;
Car[] public cars;
mapping(address =>Car[]) public carsByOwner;
function examples() external {
Car memory toyota = Car("Toyota", 1990, msg.sender);
Car memory lambo = Car({model:"Lamorghini", year:1980, owner: msg.sender});
Car memory tesla;
tesla.model = "Tesla";
tesla.year = 2010;
tesla.owner = msg.sender;
cars.push(toyota);
cars.push(lambo);
cars.push(tesla);
cars.push(Car("Ferrari", 2020, msg.sender));
Car memory _car = cars[0]; // memory 不可修改 只可读取
_car.model;
_car.year;
_car.owner;
Car storage __car = cars[0]; // storage 可修改
__car.year = 1999;
delete _car.owner; // 删除一个变量为默认值
delete cars[1]; // 下标1的元素的所有属性变为默认值
}
}
枚举
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract Enum {
enum Status {
None, // 第一个值为默认值
Pending,
Shipped,
Completed,
Rejected,
Canceled
}
Status public status;
struct Order {
address buyer;
Status status;
}
Order[] public orders;
function get() view external returns (Status){
return status;
}
function set(Status _status) external {
status = _status;
}
function ship() external {
status = Status.Shipped;
}
function reset() external {
delete status;
}
}
结构控制
if else
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract Contracts {
function example(uint _x) external pure returns (uint){
if(_x<10){
return 1;
} else if (_x<20){
return 2;
} else {
return 3;
}
}
function ternary(uint _x) external pure returns (uint){
return _x < 10 ? 1 : 2 ;
}
}
for while
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract Contracts {
function loops() external pure {
for(uint i=0; i<10; i++){
if(i==3){
continue;
}
if(i==8){
break;
}
}
uint j = 0;
while (j < 10){
j++;
}
}
}
报错控制
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
// require , revert , assert
// gas费退还,状态回滚
// 8.0可以自定义错误,节约gas
contract Contracts {
function testRequire(uint _i) public pure {
require(_i <= 10, "i > 10");
}
function testRevert(uint _i) public pure {
if(_i>10){
revert("i>10");
}
}
uint public num = 123;
function testAssert() public view {
assert(num == 123);
}
function foo(uint _i) public {
num += 1;
// require(_i<10);
if(_i>10){
revert("i>10");
}
}
// 自定义报错
error MyError(address caller, uint i);
function testCustomError(uint _i) public view {
if (_i > 10){
revert MyError(msg.sender,_i);
}
}
}
综合练习 - 权限控制
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract Ownable {
address public owner;
constructor(){
owner = msg.sender;
}
modifier onlyOwner(){
require(msg.sender == owner,"not owner");
_;
}
function setOwner(address _newOwner) external onlyOwner{
require(_newOwner != address(0),"invalid address");
owner = _newOwner;
}
function onlyOwnerCanCallThisFunc() external onlyOwner {
// code
}
function anyOneCanCall() external{
// code
}
}