跳转至

函数

// function <函数名> (参数类型 参数名) <函数可见性> <状态可变性> <returns (返回值类型)>
function add(uint x, uint y) external pure returns (uint) {
    return x + y;
}

visibility

函数可见性

  • private 调用范围:合约内部
  • public 调用范围:合约内部、外部、继承合约
  • internal 调用范围:合约内部、继承合约
  • external 调用范围:合约外部、合约内部只能用 this.fuction_name() 的方式调用

状态变量可见性,不支持 external,默认为 internal,建议明确标识可见性

// 系统会自动给 `public` 的状态变量添加getter方法
// 编译后自动生成一个只读方法:myString()
string public myString = "hello world";

state mutability

状态可变性

  • pure 不能读取也不能写入状态变量,不消耗Gas
  • view 能读取但是不能写入状态变量,不消耗Gas
  • payable 可支付的
contract Demo {
    uint public num;

    // 读取状态变量,使用 view
    function viewFunc() external view returns (uint) {
        return num;
    }

    // 不读取状态变量,使用 pure
    function pureFunc(uint x) external pure returns (uint) {
        return x;
    }

    // 修改状态变量,不需要声明可变性
    function inc() external {
        num += 1;
    }
}

函数返回

contract Demo {
    // 写法1
    function demo1() public pure returns (uint, bool) {
        return (1, true);
    }

    // 写法2
    function demo2() public pure returns (uint x, bool y) {
        return (1, true);
    }

    // 写法3,隐式返回
    function demo3() public pure returns (uint x, bool y) {
        x = 1;
        y = true;
    }
}

调用函数,将返回赋值给变量

// 假设 demo() 函数有三个返回值
(uint _a, bool _b, address _c) = demo();  // 读取函数返回的所有值
(, bool _b, ) = returnNamed();  // 只读取需要的返回值,可以节省Gas

内置函数

address(this).balance  // 智能合约本身的余额,this指的是正在执行的合约实例
gasleft(): (uint256) // 剩余 gas
blockhash(uint blockNumber): (bytes32)  // 给定区块的哈希值 – 只适用于256最近区块, 不包含当前区块

modifier

函数修饰器,类似Python里的装饰器

下划线分号 _; 表示函数在哪里执行

modifier demo1 {
    _;  // 先运行函数再运行修饰器代码
    ...
}

modifier demo2 {
    ...
    _;  // 先运行修饰器代码再运行函数
}

modifier demo3 {
    ...
    _;  // 中间运行
    ...
}

// 使用修饰器
function dec() external demo1 {
    ...
}
  • 带参数的修饰器
// 下划线分号 _; 表示函数在哪里执行,在前/后则表示函数调用装饰器代码前/后运行函数
modifier cap(uint _x) {
    require(_x < 100, "x >- 100");
    _;
}

// 只有当 _x 满足条件时才执行函数
function incBy(uint _x) external cap(_x) {
    count += _x;
}

constructor

构造函数,相当于 Python Class 中的 def __init__(self),主要用于初始化

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

contract Demo {
    address public owner;
    uint public x;

    // 仅在部署时执行一次,所以构造函数中定义owner就会是合约部署者
    constructor(uint _x) {
        owner = msg.sender;
        x = _x;
    }
}