智能合约 | 断言处理和自定义修饰符

164 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 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");

        _;

    }