原文:《Solidity 极简入门: 15. 异常》

我最近在重新学 solidity,巩固一下细节,也写一个「Solidity 极简入门」,供小白们使用(编程大佬可以另找教程),每周更新 1-3 讲。

所有代码和教程开源在 github:github.com/AmazingAng/WTFSolidity

这一讲,我们介绍 solidity 三种抛出异常的方法:error,require 和 assert,并比较三种方法的 gas 消耗。

异常

写智能合约经常会出 bug,solidity 中的异常命令帮助我们 debug。

Error

Error 是 solidity0.8 版本新加的内容,方便且高效(省 gas)的向用户解释操作失败的原因。人们可以在 contract 之外定义异常。下面,我们定义一个 TransferNotOwner 异常,当用户不是代币 owner 的时候尝试转账,会抛出错误:

WTF Solidity极简入门第十五讲:异常

在执行当中,error 必须搭配 revert(回退)命令使用。

WTF Solidity极简入门第十五讲:异常

我们定义了一个 transferOwner1() 函数,他会检查代币的 owner 是不是发起人,如果不是,就会抛出 TransferNotOwner 异常;如果是的话,就会转账。

Require

require 命令是 solidity0.8 版本之前抛出异常的常用方法,目前很多主流合约仍然还在使用它。他很好用,唯一的缺点就是 gas 随着描述异常的字符串长度增加,比 error 命令要高。使用方法:require(检查条件,」异常的描述」),当检查条件不成立的时候,就会抛出异常。

我们用 require 命令重写一下上面的 transferOwner 函数:

WTF Solidity极简入门第十五讲:异常

Assert

assert 命令一般用于程序员写程序 debug,因为他不能解释抛出异常的原因(比 require 少个字符串)。他的用法很简单,assert(检查条件),当检查条件不成立的时候,就会抛出异常。

我们用 assert 命令重写一下上面的 transferOwner 函数:

WTF Solidity极简入门第十五讲:异常

三种方法的 gas 比较

我们比较一下三种抛出异常的 gas 消耗,方法很简单,部署合约,分别运行写的 transferOwner 函数的三个版本。

error 方法 gas 消耗:24445require 方法 gas 消耗:24743assert 方法 gas 消耗:24446

我们可以看到,error 方法 gas cost 最少,其次是 assert,require 方法消耗 gas 最多!因此,error 既可以告知用户抛出异常的原因,又能省 gas,大家要多用!

总结

这一讲,我们介绍 solidity 三种抛出异常的方法:error,require 和 assert,并比较了三种方法的 gas 消耗。结论:error 既可以告知用户抛出异常的原因,又能省 gas。

推特:@0xAA_Science

社区:Discord微信群官网 wtf.academy

所有代码和教程开源在github: github.com/AmazingAng/WTFSolidity