基本概念 函数修改器可以一定程度上改变函数的行为。可以作为函数执行的先行条件,如果符合函数修改器定义的条件,才可以执行函数体内容。关于函数修改器,可以把理解成if的变相。
函数修改器定义 函数修改器的定义语法如下:
1 2 3 4 5 6 7 8 modifier 修改器名 { 条件体.. _; } function a ( ) 修改器名 { 函数体.. }
当要执行a()时,会先去执行修改器,判断条件体,如果符合条件,才会继续执行a();如果不符合条件,a()将不执行。”_;”在这里表示的是a(). 通过一个小栗子,直观的感受下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 pragma solidity ^0.4 .0 ; contract Ownable { address public owner = msg.sender ; modifier onlyOwner { if (msg.sender != owner) throw ; _; } function changeOwner (address _newOwner ) onlyOwner { if (_newOwner == 0x0 ) throw ; owner = _newOwner; } }
在上述的例子中,我们实现了只有合约所有者才能修改合约归属的权限的功能。
函数修改器参数 函数修改器可以接收上下文中存在的任意变量组成的表达式,直接在函数修改器中传入参数。
1 2 3 4 5 6 modifier 修改器名(uint 参数1 , string 参数2 ) { if (参数1 >10 && 参数2 != "男" ) _; }
函数修改器执行规则 当函数的修改器条件判断不成功,如果函数没有返回值,对应的函数将不执行;如果函数有返回值,那将返回对应类型的默认值。 而函数修改器中的条件体,不论函数是否符合条件,都会继续执行完毕修改器中的后续逻辑。 参考如下实例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 pragma solidity ^0.4 .0 ; contract Test { mapping (bool => uint) public mapp; modifier A (mapping(bool => uint) mapp ) { if (mapp[true ] == 0 ) { mapp[true ]= 1 ; _; mapp[true ]= 3 ; } } function f1 ( ) A (mapp) returns (uint ) { mapp[true ] = 2 ; return mapp[true ]; } modifier B (mapping(bool => uint) mapp ) { if (mapp[true ] == 1 ) { mapp[true ]= 1 ; _; mapp[true ]= 3 ; } mapp[true ]=7 ; } function f2 ( ) B (mapp) returns (uint ) { mapp[true ] = 2 ; return mapp[true ]; } }
多函数修改器 当一个函数拥有多个函数修改器时,执行顺序是按照先后顺序依次执行。如果有一个不满足,函数即不能执行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 pragma solidity ^0.4 .0 ; contract Test { modifier A (uint a ) { if (a<10 ) throw ; _; } modifier B (uint b ) { if (b<10 ) throw ; _; } function f (uint a, uint b ) A (a) B (b) returns (uint ) { return 777 ; } }
函数修改器的继承与重写 子类可以使用父类中的函数修改器,也可以重写父类的函数修改器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 pragma solidity ^0.4 .0 ; contract Father { modifier A (uint a ) { if (a > 100 ) throw ; _; } } contract Son is Father { modifier A (uint a ) { if (a > 50 ) throw ; _; } function f (uint a ) A (a) returns (uint ) { return 777 ; } }
应用 结合现实场景中的应用。在一些敏感操作中,我们需要设定特定的权限才允许执行相关操作;再者我们可以利用函数修改器进行数据的校验;还可以利用简单的函数修改器来进行重入锁的机制。
权限控制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 pragma solidity ^0.4 .0 ; contract Ownable { address public owner = msg.sender ; modifier onlyOwner { if (msg.sender != owner) throw ; _; } function changeOwner (address _newOwner ) onlyOwner { if (_newOwner == 0x0 ) throw ; owner = _newOwner; } }
数据校验 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 contract DataVerifiable { modifier refundEtherSentByAccident ( ) { if (msg.value > 0 ) throw ; _; } modifier throwIfAddressIsInvalid (address _target ) { if (_target == 0x0 ) throw ; _; } modifier throwIfIsEmptyString (string _id ) { if (bytes (_id).length == 0 ) throw ; _; } modifier throwIfEqualToZero (uint _id ) { if (_id == 0 ) throw ; _; } modifier throwIfIsEmptyBytes32 (bytes32 _id ) { if (_id == "" ) throw ; _; } }
重入锁实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 pragma solidity ^0.4 .0 ; contract Mutex { bool locked; modifier noReentrancy ( ) { require (!locked); locked = true ; _; locked = false ; } function f ( ) noReentrancy returns (uint) { require (msg.sender .call ()); return 7 ; } }
文章作者: 米兰
原始链接: https://blog.milanchen.site/posts/solidity-modifiers.html
版权声明: 转载请声明出处