solidity学习笔记(8)—— 函数修饰符及自定义修饰符

在Solidity中,函数修饰符规定了函数的行为、调用规则。在Solidity语言中预置的修饰符有如下一些:

1、函数和状态变量可见性修饰符
public:在外部和内部均可见(创建存储/状态变量的访问者函数)
private:仅在当前合约中可见
external: 只有外部可见(仅对函数)- 仅仅在消息调用中(通过this.fun)
internal: 只有内部可见

2、状态变量储存位置修饰符
storage:变量储存在区块链中,状态变量默认是storage类型;
memory:变量储临时存在内存中,局部变量默认是memory类型;

3、接受Ether修饰符
payable:允许函数在调用同时接收Ether

4、函数读取状态变量修饰符
pure:不允许修改或访问状态变量-这还没有强制执行
view:不允许修改状态变量-这还没有强制执行
constant(for function):等同于view
constant(for state variables):除了初始化之外,不允许赋值操作,类似JavaScript中的常量

自定义修饰符

函数修改器(Function Modifiers)

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

OpenZeppelin库的Ownable 合约

下面是一个 Ownable 合约的例子: 来自 OpenZeppelin Solidity 库的 Ownable 合约。 OpenZeppelin 是主打安保和社区审查的智能合约库,你可以在自己的 DApps中引用。

所以Ownable 合约基本都会这么干:

  • 合约创建,构造函数先行,将其 owner 设置为msg.sender(其部署者)
  • 为它加上一个修饰符 onlyOwner,它会限制陌生人的访问,将访问某些函数的权限锁定在 owner 上。
  • 允许将合约所有权转让给他人。

看一下源码:

/**
 * @title Ownable
 * @dev The Ownable contract has an owner address, and provides basic authorization control
 * functions, this simplifies the implementation of "user permissions".
 */
​
contract Ownable {
  address public owner;
  event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
  /**
   * @dev The Ownable constructor sets the original `owner` of the contract to the sender
   * account.
   */
  function Ownable() public {
    owner = msg.sender;
  }
​
  /**
   * @dev Throws if called by any account other than the owner.
   */
​
  modifier onlyOwner() {
    require(msg.sender == owner);
    _;
  }
​
  /**
   * @dev Allows the current owner to transfer control of the contract to a newOwner.
   * @param newOwner The address to transfer ownership to.
   */
​
  function transferOwnership(address newOwner) public onlyOwner {
    require(newOwner != address(0));
    OwnershipTransferred(owner, newOwner);
    owner = newOwner;
  }
}

我们来看一下函数修改器onlyOwner是怎么定义和使用的?
首先:要定义一个modifier,形式与函数很像,可以有参数,但是不需要返回值;
其次:特殊 _; 是必要的,它表示使用修改符的函数体的替换位置;
第三:使用将modifier置于参数后,返回值前即可。

其他合约如何使用onlyOwner?

继承!函数修改器是可以继承的,只要新建的合约继承Ownable合约,即可使用这个修改器。

########################################
####     其他合约如何使用onlyOwner?   ####
########################################
​
contract MyContract is Ownable {
  event LaughManiacally(string laughter);
​
  //注意! `onlyOwner`上场 :
  function likeABoss() external onlyOwner {
    LaughManiacally("Muahahahaha");
  }
}

带参数的函数修改器
之前我们已经读过一个简单的函数修饰符了:onlyOwner。函数修饰符也可以带参数。例如:

// 存储用户年龄的映射
mapping (uint => uint) public age;
// 限定用户年龄的修饰符
modifier olderThan(uint _age, uint _userId) {
  require(age[_userId] >= _age);
  _;
}
// 必须年满16周岁才允许开车 (至少在美国是这样的).
// 我们可以用如下参数调用`olderThan` 修饰符:
function driveCar(uint _userId) public olderThan(16, _userId) {
  // 其余的程序逻辑
}

使用修改器实现的一个防重复进入的例子。
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)