变量

  1. // SPDX-License-Identifier: GPL-3.0
  2. pragma solidity >=0.7.0 <0.9.0;
  3. contract HelloWorld {
  4. string public myString = "hello world"; // 自带get()方法
  5. bool public b = false; // 默认值 false
  6. uint public u = 123; // uint8/uint16/uint256 0 to 2^8-1 默认值0
  7. int public i = -123; // -2^255 to 2^255-1 默认值0
  8. int public minInt = type(int).min;
  9. int public maxInt = type(int).max;
  10. address public addr = 0x0000000000000000000000000000000000000000; // 地址 私钥算公钥,公钥算地址 默认值40个0
  11. byte32 public b32 = 0x0000000000000000000000000000000000000000000000000000000000000000; // 32位16进制 默认值64个0
  12. }

状态变量&局部变量

  1. // SPDX-License-Identifier: GPL-3.0
  2. pragma solidity >=0.7.0 <0.9.0;
  3. contract HelloWorld {
  4. uint public i;
  5. bool public b;
  6. address public myAddress;
  7. function foo() external {
  8. uint x = 123;
  9. bool f = false;
  10. x += 456;
  11. f = true;
  12. i = 123;
  13. b = true;
  14. myAddress = address(1);
  15. }
  16. }

语法 - 图1

全局变量

链上和账户

  1. // SPDX-License-Identifier: GPL-3.0
  2. pragma solidity >=0.7.0 <0.9.0;
  3. contract HelloWorld {
  4. // view 可以读取全局变量和状态变量
  5. function globalVars() external view returns (address,uint,uint){
  6. address sender = msg.sender; // 全局变量-账户内容,调用这个函数的地址(上一个调用者,可能是人或合约)是什么
  7. uint timestamp = block.timestamp; // 区块时间戳,只读。写入方法就是出块的时间
  8. uint blockNum = block.number;
  9. return (sender,timestamp,blockNum);
  10. }
  11. }

语法 - 图2

常量

  1. // SPDX-License-Identifier: GPL-3.0
  2. pragma solidity >=0.7.0 <0.9.0;
  3. // 21442 gas 常量消耗更少的gas值,不修改的值定义为常量
  4. contract Contracts {
  5. address public constant MY_ADDRESS = 0x000000000000000000000000000000000000000F;
  6. uint public constant MY_UINT = 123;
  7. }
  8. // 23575 gas
  9. contract Var {
  10. address public MY_ADDRESSS = 0x000000000000000000000000000000000000000C;
  11. }

数组

  1. // SPDX-License-Identifier: GPL-3.0
  2. pragma solidity >=0.7.0 <0.9.0;
  3. contract Array {
  4. uint[] public nums= [4,2,3]; // 变长数组
  5. uint[] public nums2 = [1,2,3]; // 变长数组
  6. uint[3] public numsFixed = [4,5,6]; // 定长数组
  7. function examples() external {
  8. nums.push(4); // 添加元素
  9. uint x = nums[0]; // 访问元素
  10. nums[0] = 3; // 修改元素
  11. delete nums[0]; // 删除元素(不影响数组长度,被删元素位置变成默认值)
  12. nums.pop(); // 弹出元素
  13. uint len = nums.length; // 元素长度
  14. // 内存中创建数组(内存中的数组长度固定)
  15. uint[] memory a = new uint[](5);
  16. a[1] = 123;
  17. }
  18. // 返回数组
  19. function returnArray() external view returns (uint[] memory){
  20. return nums;
  21. }
  22. }

删除数组元素 | 移动元素

  1. // SPDX-License-Identifier: GPL-3.0
  2. pragma solidity >=0.7.0 <0.9.0;
  3. // 缺点:浪费gas
  4. // 优点:顺序不变
  5. contract Array {
  6. uint[] public arr;
  7. function examples() external {
  8. arr = [1,2,3];
  9. delete arr[1]; // [1,0,3]
  10. }
  11. function remove(uint _index) public{
  12. require(_index < arr.length, "index out of bound");
  13. for(uint i = _index; i < arr.length-1; i++){
  14. arr[i]=arr[i+1];
  15. }
  16. arr.pop();
  17. }
  18. // 285955 gas
  19. function test() external {
  20. arr = [1,2,3,4,5];
  21. remove(2);
  22. //[1,2,4,5]
  23. assert(arr[0] == 1);
  24. assert(arr[1] == 2);
  25. assert(arr[2] == 4);
  26. assert(arr[3] == 5);
  27. assert(arr.length == 4);
  28. arr = [1];
  29. remove(0);
  30. assert(arr.length == 0);
  31. }
  32. }

删除数组元素 | 交换元素

  1. // SPDX-License-Identifier: GPL-3.0
  2. pragma solidity >=0.7.0 <0.9.0;
  3. // 缺点:顺序变化
  4. // 优点:节约gas
  5. contract Array {
  6. uint[] public arr;
  7. function examples() external {
  8. arr = [1,2,3];
  9. delete arr[1]; // [1,0,3]
  10. }
  11. function remove(uint _index) public{
  12. require(_index < arr.length, "index out of bound");
  13. arr[_index]=arr[arr.length-1];
  14. arr.pop();
  15. }
  16. // 284651 gas
  17. function test() external {
  18. arr = [1,2,3,4,5];
  19. remove(2);
  20. //[1,2,5,4]
  21. assert(arr[0] == 1);
  22. assert(arr[1] == 2);
  23. assert(arr[2] == 5);
  24. assert(arr[3] == 4);
  25. assert(arr.length == 4);
  26. arr = [1];
  27. remove(0);
  28. assert(arr.length == 0);
  29. }
  30. }

Map

  1. // SPDX-License-Identifier: GPL-3.0
  2. pragma solidity >=0.7.0 <0.9.0;
  3. contract Mapping {
  4. mapping(address => uint) public balances; // 地址余额
  5. mapping(address => mapping(address => bool)) public isFriend; // 嵌套map
  6. address public thisAddr;
  7. address public sender;
  8. function examples() external {
  9. balances[msg.sender] = 123; // 设置数据
  10. uint bal = balances[msg.sender]; // 获取数据
  11. uint bal2 = balances[address(1)]; // 返回一个不存在的数据,默认值0
  12. balances[msg.sender] +=456; // 增加数据
  13. // delete balances[msg.sender]; // 删除数据(数据变为0)
  14. isFriend[msg.sender][address(this)] = true;
  15. sender = msg.sender;
  16. thisAddr = address(this);
  17. }
  18. }

函数

  1. // SPDX-License-Identifier: GPL-3.0
  2. pragma solidity >=0.7.0 <0.9.0;
  3. contract HelloWorld {
  4. /*
  5. external 外部函数,只能被外部读取,当前合约内部不能调用
  6. pure 纯函数,不能读写状态变量,只能读写局部变量,即不会对链上有任何操作
  7. */
  8. function add(uint x,uint y) external pure returns (uint){
  9. return x + y;
  10. }
  11. function sub(uint x,uint y) external pure returns (uint){
  12. return x - y;
  13. }
  14. }

语法 - 图3

  1. // SPDX-License-Identifier: GPL-3.0
  2. pragma solidity >=0.7.0 <0.9.0;
  3. contract HelloWorld {
  4. uint public count;
  5. // 因为要读取状态变量,所以不能带 view或者pure
  6. function inc() external {
  7. count +=1;
  8. }
  9. function dec() external {
  10. count -=1;
  11. }
  12. }

函数修改器

  1. // SPDX-License-Identifier: GPL-3.0
  2. pragma solidity >=0.7.0 <0.9.0;
  3. contract Contracts {
  4. bool public paused;
  5. uint public count;
  6. function setPause(bool _paused) external {
  7. paused = _paused;
  8. }
  9. modifier whenNotPaused(){
  10. require(!paused,"paused");
  11. _;
  12. }
  13. function inc() external whenNotPaused{
  14. count += 1;
  15. }
  16. function dec() external whenNotPaused{
  17. count -= 1;
  18. }
  19. modifier cap(uint _x){
  20. require(_x<100,"x >= 100");
  21. _;
  22. }
  23. function incBy(uint _x) external whenNotPaused cap(_x){
  24. count += _x;
  25. }
  26. }

构造函数

  1. // SPDX-License-Identifier: GPL-3.0
  2. pragma solidity >=0.7.0 <0.9.0;
  3. // 仅能执行一次,用于初始化账号地址等
  4. contract Contracts {
  5. address public owner;
  6. uint public x;
  7. constructor(uint _x){
  8. owner = msg.sender;
  9. x = _x;
  10. }
  11. }

返回值

  1. // SPDX-License-Identifier: GPL-3.0
  2. pragma solidity >=0.7.0 <0.9.0;
  3. contract FunctionOutputs {
  4. // 返回值未命名
  5. function returnMany() public pure returns (uint,bool){
  6. return (1,true);
  7. }
  8. // 返回值被命名-1
  9. function named() public pure returns (uint x,bool b){
  10. return (1,true);
  11. }
  12. // 返回值被命名-2
  13. function assigned() public pure returns (uint x,bool b){
  14. x = 1;
  15. b = true;
  16. }
  17. // 接收返回值
  18. function destructingAssigments() public pure {
  19. (uint x,bool b) = returnMany(); // 接收所有返回值
  20. (,bool t) = returnMany(); // 接收部分返回值
  21. }
  22. }

结构体

  1. // SPDX-License-Identifier: GPL-3.0
  2. pragma solidity >=0.7.0 <0.9.0;
  3. contract Structs {
  4. struct Car {
  5. string model;
  6. uint year;
  7. address owner;
  8. }
  9. Car public car;
  10. Car[] public cars;
  11. mapping(address =>Car[]) public carsByOwner;
  12. function examples() external {
  13. Car memory toyota = Car("Toyota", 1990, msg.sender);
  14. Car memory lambo = Car({model:"Lamorghini", year:1980, owner: msg.sender});
  15. Car memory tesla;
  16. tesla.model = "Tesla";
  17. tesla.year = 2010;
  18. tesla.owner = msg.sender;
  19. cars.push(toyota);
  20. cars.push(lambo);
  21. cars.push(tesla);
  22. cars.push(Car("Ferrari", 2020, msg.sender));
  23. Car memory _car = cars[0]; // memory 不可修改 只可读取
  24. _car.model;
  25. _car.year;
  26. _car.owner;
  27. Car storage __car = cars[0]; // storage 可修改
  28. __car.year = 1999;
  29. delete _car.owner; // 删除一个变量为默认值
  30. delete cars[1]; // 下标1的元素的所有属性变为默认值
  31. }
  32. }

枚举

  1. // SPDX-License-Identifier: GPL-3.0
  2. pragma solidity >=0.7.0 <0.9.0;
  3. contract Enum {
  4. enum Status {
  5. None, // 第一个值为默认值
  6. Pending,
  7. Shipped,
  8. Completed,
  9. Rejected,
  10. Canceled
  11. }
  12. Status public status;
  13. struct Order {
  14. address buyer;
  15. Status status;
  16. }
  17. Order[] public orders;
  18. function get() view external returns (Status){
  19. return status;
  20. }
  21. function set(Status _status) external {
  22. status = _status;
  23. }
  24. function ship() external {
  25. status = Status.Shipped;
  26. }
  27. function reset() external {
  28. delete status;
  29. }
  30. }

结构控制

if else

  1. // SPDX-License-Identifier: GPL-3.0
  2. pragma solidity >=0.7.0 <0.9.0;
  3. contract Contracts {
  4. function example(uint _x) external pure returns (uint){
  5. if(_x<10){
  6. return 1;
  7. } else if (_x<20){
  8. return 2;
  9. } else {
  10. return 3;
  11. }
  12. }
  13. function ternary(uint _x) external pure returns (uint){
  14. return _x < 10 ? 1 : 2 ;
  15. }
  16. }

for while

  1. // SPDX-License-Identifier: GPL-3.0
  2. pragma solidity >=0.7.0 <0.9.0;
  3. contract Contracts {
  4. function loops() external pure {
  5. for(uint i=0; i<10; i++){
  6. if(i==3){
  7. continue;
  8. }
  9. if(i==8){
  10. break;
  11. }
  12. }
  13. uint j = 0;
  14. while (j < 10){
  15. j++;
  16. }
  17. }
  18. }

报错控制

  1. // SPDX-License-Identifier: GPL-3.0
  2. pragma solidity >=0.7.0 <0.9.0;
  3. // require , revert , assert
  4. // gas费退还,状态回滚
  5. // 8.0可以自定义错误,节约gas
  6. contract Contracts {
  7. function testRequire(uint _i) public pure {
  8. require(_i <= 10, "i > 10");
  9. }
  10. function testRevert(uint _i) public pure {
  11. if(_i>10){
  12. revert("i>10");
  13. }
  14. }
  15. uint public num = 123;
  16. function testAssert() public view {
  17. assert(num == 123);
  18. }
  19. function foo(uint _i) public {
  20. num += 1;
  21. // require(_i<10);
  22. if(_i>10){
  23. revert("i>10");
  24. }
  25. }
  26. // 自定义报错
  27. error MyError(address caller, uint i);
  28. function testCustomError(uint _i) public view {
  29. if (_i > 10){
  30. revert MyError(msg.sender,_i);
  31. }
  32. }
  33. }

综合练习 - 权限控制

  1. // SPDX-License-Identifier: GPL-3.0
  2. pragma solidity >=0.7.0 <0.9.0;
  3. contract Ownable {
  4. address public owner;
  5. constructor(){
  6. owner = msg.sender;
  7. }
  8. modifier onlyOwner(){
  9. require(msg.sender == owner,"not owner");
  10. _;
  11. }
  12. function setOwner(address _newOwner) external onlyOwner{
  13. require(_newOwner != address(0),"invalid address");
  14. owner = _newOwner;
  15. }
  16. function onlyOwnerCanCallThisFunc() external onlyOwner {
  17. // code
  18. }
  19. function anyOneCanCall() external{
  20. // code
  21. }
  22. }