阅读(4630) (11)

函数修饰符

2022-05-13 10:04:09 更新

修饰符可用于以声明方式更改函数的行为。例如,您可以使用修饰符在执行函数之前自动检查条件。

修饰符是合约的可继承属性,可以被派生合约覆盖,但前提是它们被标记为virtual。有关详细信息,请参阅 修改器覆盖

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.1 <0.9.0;

contract owned {
    constructor() { owner = payable(msg.sender); }
    address payable 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 {
        require(
            msg.sender == owner,
            "Only owner can call this function."
        );
        _;
    }
}

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

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

contract Register is priced, destructible {
    mapping (address => bool) registeredAddresses;
    uint price;

    constructor(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() public payable costs(price) {
        registeredAddresses[msg.sender] = true;
    }

    function changePrice(uint price_) public onlyOwner {
        price = price_;
    }
}

contract Mutex {
    bool locked;
    modifier noReentrancy() {
        require(
            !locked,
            "Reentrant call."
        );
        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() public noReentrancy returns (uint) {
        (bool success,) = msg.sender.call("");
        require(success);
        return 7;
    }
}

如果你想访问一个m在 contract 中定义的修饰符C,你可以使用C.m它来引用它而无需虚拟查找。只能使用当前合约或其基础合约中定义的修饰符。修饰符也可以在库中定义,但它们的使用仅限于同一库的函数。

通过在以空格分隔的列表中指定多个修饰符来将多个修饰符应用于函数,并按显示的顺序进行评估。

修饰符不能隐式访问或更改它们修改的函数的参数和返回值。它们的值只能在调用时显式传递给它们。

从修饰符或函数体显式返回仅保留当前修饰符或函数体。_在前面的修饰符之后分配返回变量并且控制流继续。

警告

在早期版本的 Solidity 中,return具有修饰符的函数中的语句表现不同。

从修饰符 with 显式返回return;不会影响函数返回的值。然而,修饰符可以选择根本不执行函数体,在这种情况下,返回变量被设置为它们的默认值,就像函数有一个空的函数体一样。

该_符号可以多次出现在修饰符中。每次出现都替换为函数体。

修饰符参数允许使用任意表达式,在这种情况下,从函数中可见的所有符号在修饰符中都是可见的。修饰符中引入的符号在函数中不可见(因为它们可能会因覆盖而改变)。