携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第17天,点击查看活动详情
断言处理和自定义修饰符
断言处理是为了及时止损,众所周知,对于非view的智能合约函数,都是需要消耗gas的,gas就相当于汽油,时真金白银,为此在用户执行合约时,需要指定执行此函数允许消耗的gas上线(gas limit)。 当gas充足且合约没有错误时,合约在执行的时候一般都会顺利完成,但是当gas不足或者合约存在问题的时候,合约将不能顺利执行。为了不让执行到一半出现问题,solidty推荐我们使用state-reverting机制,就像是数据库中的事物一样。使用判断语句检测合约运行过程中的错误,当错误发生时主动调用revert回退合约调用前的状态。这种方式相对assert和require断言来说是麻烦的。
assert和require断言
- assert函数原型
function assert(bool cond_expr);
- require原型
function require(bool cond_expr,string msg);
这两个函数都是solidty内置的断言函数,断定某件事100%成立,否则回退。从他们的函数原型可知,assert只需要传入条件判断表达式,require需要传入条件判断表达式和错误提示信息。而且assert比较贪心,当方式回退时,assert会扣光剩余的gas(根据gas limit扣),而requir心怀大义,它会把剩余的gas返回给调用者。
- 代码示例
//代币转入
function tokenTransfer(uint _ercnum) public {
// 断言,判断调用者ERC20代币是否大于零,否则回退并提示
require(IERC20(ercaddress).balanceOf(msg.sender) > 0 ,
"not sufficient funds");
uint conToken = _ercnum * 9 / 10;
//断言,contoken要大于20
assert(conToken>20);
IERC20(ercaddress).transferFrom(msg.sender,address(this),conToken);
uint priToken = _ercnum * 1 / 10;
IERC20(ercaddress).transferFrom(msg.sender,priAddress,priToken);
}
自定义修饰符
有些断言需要多个函数去使用,如果每一个函数都添加一个断言处理,代码量不仅会变大,也不高级,因此设计出了一个自定义修饰符modifier
,让我们对断言组合封装,方便我们在其他函数中使用。
- 语法
modifier name(){
require(······);
···
_ ;//占位符,标识modifier结束
}
- 代码示例:
//只有管理员才可执行
// conAdmin为前面声明的管理员账户
modifier onlyAdmin() {
require(msg.sender == conAdmin ,
"only admin can do this");
_;
}