函数修改器
作用
函数修改器(Function Modifiers)可以方便的控制函数的逻辑,比如可以在某个行为执行前检查某个前置条件,函数修改器还支持继承和重写。
定义格式:
modifier onlyOwner { if (msg.sender != owner) throw; _; }
在函数修改器代码块内,判断条件不符合就抛出异常,符合则执行占位符_处代码,_代指的是使用函数修改器的函数体。
函数修改器允许return;(中断当前流程)。但不允许明确的return值。
应用实例1:修改合约所有者
- 定义一个函数实现修改合约所有者的功能
- 只有合约的所有者才能调用该函数
代码:
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; } }
函数修改器可传参
应用实例2:编写一份合约,实现剩余电量Soc交易
- 创建一个函数修改器,参变量为余额和交易额【那么这个函数修改器则可泛化(可复用性提高),不一定要是Soc交易的检查】
pragma solidity ^0.4.0; contract Parameter{ //建立映射,每个账户下有Soc记录 mapping(address=>uint) public Soc; //构造函数,初始化合约创建者的Soc function Parameter(){ Soc[msg.sender]=uint(100); } //函数修改器,用来检查Soc交易方Soc是否足够 modifier balance_check(uint _balance,uint _transactionAmount){ if(_balance<=_transactionAmount) throw; _; } //Soc交易函数 function electricity_transact(address _to,uint _elec_amount) balance_check(Soc[msg.sender],_elec_amount){ if(_to==0x0) throw; Soc[msg.sender]=Soc[msg.sender]-_elec_amount; Soc[_to]=Soc[_to]+_elec_amount; } }
测试操作:
(1)编译、部署合约【部署合约的账户下的在该合约下的Soc会初始化为100】
这里我们部署的账户地址为:0xca35b7d915458ef540ade6068dfe2f44e8fa733c
(2)在electricity_transact函数中,填入其他账户地址和交易的数额
1、先填一个大于100的
尝试交易------------------->抛出异常了
2、再用小于100的交易额
尝试交易------------------>交易成功
再看看对应账户下的Soc
如果函数有返回值
如果函数有返回值,且函数修改器抛出异常,那么将返回对应类型的默认值
测试代码:
pragma solidity ^0.4.0;
contract Return{
//函数修改器永远不成功
modifier A() {
if(false)
_;
}
//返回默认值
function uintReturn() A returns(uint){
uint a = 0;
return uint(1);
}
//返回默认值
function stringReturn() A returns(string){
return "Hello world";
}
}
上例中,我们写了一个特殊的函数修改器A,永远判断不成功。故uintReturn(),stringReturn()中的代码都将不会执行。上述函数将分别返回uint,string的默认值0和空串。
函数修改器执行流程
如果函数修改器 " _; " 后面还有可执行代码,那么在对应函数体return或执行完之后,会继续在函数修改器中往下执行
测试代码:
pragma solidity ^0.4.0;
contract ProcessFlow{
mapping(bool => uint) public mapp;
modifier A(mapping(bool => uint) mapp){
if(mapp[true] == 0){
mapp[true]= 1;
_;
mapp[true]= 3;
}
}
function f() A(mapp) returns(uint){
mapp[true] = 2;
return mapp[true];
}
}
全部代码执行完后,可以看到mapp[true]的值为3
多个函数修改器
一个函数可使用多个函数修改器,定义时依次填写,并用空格隔开。函数修改器执行时,将按定义顺序依次执行。
测试代码:
pragma solidity ^0.4.0;
contract MultiModifier{
address owner = msg.sender;
/// 限制只有创建者才能访问
modifier onlyOwner {
if (msg.sender != owner) throw;
_;
}
modifier inState(bool state){
if(!state) throw;
_;
}
//多个函数修改器
function f(bool state) onlyOwner inState(state) returns(uint){
return 1;
}
}
重写(overwrite)
可以重写父类的函数修改器。来改变父类的修改器行为。
测试代码:
pragma solidity ^0.4.0;
contract bank{
modifier transferLimit(uint _withdraw){
if(_withdraw > 100) throw;
_;
}
}
contract ModifierOverride is bank{
//覆盖了父类的修改器
modifier transferLimit(uint _withdraw){
if(_withdraw > 10) throw;
_;
}
function f(uint withdraw) transferLimit(withdraw) returns(uint){
return withdraw;
}
}
参考文章:http://me.tryblockchain.org/blockchain-solidity-functionModifier.html