Solidity modifier

Solidity 中关键字 modifier 用于声明一个函数修改器。函数修改器的作用与 Spring 中的切面功能很相似,当它作用于一个函数上,可以在函数执行前或后预先执行 modifier 中的逻辑,以增强其功能。

我们来看一个函数修改器经典的应用 OpenZeppelin 库中的 Ownable 合约,下面是其中关键的代码:

/// Ownable 可以判断合约的调用者是否为当前合约的owner,
/// 从而避免其他人随意的调用一些合约的关键操作。
/// 同时,owner 可以指定任何其他人为此合约新的 owner,
/// 显然,只有当前owner才能指定其他人为新的owner。
contract Ownable {
    // 变量 owner 指定此合约的owner
    address public owner;
    // 发布事件 - 此合约owner已经换人(此逻辑与modifier无关,可以忽略)
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
    
    // 构造函数 - 创建合约自动执行,初始化合约所有人为合约创建者
    function Ownable() public {
        owner = msg.sender;
    }

    // 定义一个函数修改器
    modifier onlyOwner() {
        // 判断此函数调用者是否为owner
        require(msg.sender == owner);
        _;
    }
    
    // owner可以用此函数将owner所有权转换给其他人,显然次函数只有owner才能调用
    // 函数末尾加上onlyOwner声明,onlyOwner正是上面定义的modifier
    function transferOwnership(address newOwner) public onlyOwner {
        require(newOwner != address(0));
        OwnershipTransferred(owner, newOwner);
        owner = newOwner;
    }
}

上述合约的 transferOwnership 函数用于 owner 将所有权转让给其他人,于是在末尾声明 onlyOwner 修改器,onlyOwner 将在 transferOwnership 执行前,先执行

require(msg.sender == owner);

以保证此函数的调用者为 owner ,如果不是 owner 则抛出异常。

 

 _ 的作用

函数修改器中有一行代码只有下划线 _ ,在实际执行中,我们可以将被修饰函数的代码视为下划线处的代码。即,下划线实际上帮我们标记了被 modifier 修饰函数的执行位置。如上例中

modifier onlyOwner() {
  require(msg.sender == owner);
  _;
}

下划线在 require(msg.sender == owner)  后面,则被修饰函数 transferOwnership 在此判断条件之后执行。

Solidity modifier 功能与Spring中的切面非常相似,可以将一些通用的操作提取出来,提高编码效率,降低代码耦合性。智能合约支持继承,通过继承上述合约,可以直接使用其中定义的 OnlyOwner,在自己的合约中直接使用。

Solidity 众筹智能合约,提供一个安全、完整的 Solidity 智能合约案例,用于通过众筹方式进行筹资。 1. 募资人 struct Donee用于表示一个募资项目,其中包括募资人地址、目标 ...