函数修改器(Function Modifiers)

优质
小牛编辑
132浏览
2023-12-01

修改器(Modifiers)可以用来轻易的改变一个函数的行为。比如用于在函数执行前检查某种前置条件。修改器是一种合约属性,可被继承,同时还可被派生的合约重写(override)。下面我们来看一段示例代码:

pragma solidity ^0.4.0;
contract owned {
    function owned() { owner = msg.sender; }
    address owner;
    // This contract only defines a modifier but does not use
    // it - it will be used in derived contracts.
    // The function body is inserted where the special symbol
    // "_;" in the definition of a modifier appears.
    // This means that if the owner calls this function, the
    // function is executed and otherwise, an exception is
    // thrown.
    modifier onlyOwner {
        if (msg.sender != owner)
            throw;
        _;
    }
}

contract mortal is owned {
    // This contract inherits the "onlyOwner"-modifier from
    // "owned" and applies it to the "close"-function, which
    // causes that calls to "close" only have an effect if
    // they are made by the stored owner.
    function close() onlyOwner {
        selfdestruct(owner);
    }
}

contract priced {
    // Modifiers can receive arguments:
    modifier costs(uint price) {
        if (msg.value >= price) {
            _;
        }
    }
}

contract Register is priced, owned {
    mapping (address => bool) registeredAddresses;
    uint price;
    function Register(uint initialPrice) { price = initialPrice; }
    // It is important to also provide the
    // "payable" keyword here, otherwise the function will
    // automatically reject all Ether sent to it.
    function register() payable costs(price) {
        registeredAddresses[msg.sender] = true;
    }
    function changePrice(uint _price) onlyOwner {
        price = _price;
    }
}

修改器可以被继承,使用将modifier置于参数后,返回值前即可。

特殊_表示使用修改符的函数体的替换位置。

从合约Register可以看出全约可以多继承,通过,号分隔两个被继承的对象。

修改器也是可以接收参数的,如pricedcosts

使用修改器实现的一个防重复进入的例子。

pragma solidity ^0.4.0;
contract Mutex {
    bool locked;
    modifier noReentrancy() {
        if (locked) throw;
        locked = true;
        _;
        locked = false;
    }
    /// This function is protected by a mutex, which means that
    /// reentrant calls from within msg.sender.call cannot call f again.
    /// The `return 7` statement assigns 7 to the return value but still
    /// executes the statement `locked = false` in the modifier.
    function f() noReentrancy returns (uint) {
        if (!msg.sender.call()) throw;
        return 7;
    }
}

例子中,由于call()方法有可能会调回当前方法,修改器实现了防重入的检查。

如果同一个函数有多个修改器,他们之间以空格隔开,修饰器会依次检查执行。

需要注意的是,在Solidity的早期版本中,有修改器的函数,它的return语句的行为有些不同。

在修改器中和函数体内的显式的return语句,仅仅跳出当前的修改器和函数体。返回的变量会被赋值,但整个执行逻辑会在前一个修改器后面定义的"_"后继续执行。

修改器的参数可以是任意表达式。在对应的上下文中,所有的函数中引入的符号,在修改器中均可见。但修改器中引入的符号在函数中不可见,因为它们有可能被重写。