在solidity中一旦出现异常,则当前交易将会回滚(即相当于没有发生过,除了你的gas被消耗了)。solidity
里抛出异常的方法有三种:errorrequireassert对于可能出现异常抛出的地方,solidity也提供了try-catch方法进行异常捕获处理。
在solidity
中一旦出现异常,则当前交易将会回滚(即相当于没有发生过,除了你的gas被消耗了)。
`solidity`里抛出异常的方法有三种:
error
require
assert
对于可能出现异常抛出的地方,solidity
也提供了try-catch
方法进行异常捕获处理。
error
是solidity 0.8.4
新加的内容,方便且高效(省gas
)地向用户解释操作失败的原因,同时还可以在抛出异常的同时携带参数,帮助开发者更好地调试。
使用error
需要用户自己定义error
类型和抛出的参数,同时需要搭配revert
使用。例子如下:
error TransferNotOwner(); // 自定义error
function transferOwner1(uint256 tokenId, address newOwner) public {
if(_owners[tokenId] != msg.sender){
// revert 将会返回后面的一个数值,同时回滚交易
// 在 0.8.4 后允许抛出 error 错误,帮助调试代码
// revert 会剩余的 gas 返回调用者
revert TransferNotOwner();
}
_owners[tokenId] = newOwner;
}
require
命令是solidity 0.8
之前抛出异常的常用方法,根据条件判断是否抛出异常require(检查条件,"异常的描述")
。优点是好用,缺点是随着require
后返回的字符串的长度的增加,gas
费用也在增加,比error
高。例子如下:
function transferOwner2(uint256 tokenId, address newOwner) public {
require(_owners[tokenId] == msg.sender, "Transfer Not Owner");
_owners[tokenId] = newOwner;
}
assert
命令一般用于程序员写程序debug
,因为它不能解释抛出异常的原因(比require
少个字符串)assert(检查条件)
。最大的缺点是条件不成立后,抛出异常且gas
用回全部消耗掉。例子如下:
function transferOwner3(uint256 tokenId, address newOwner) public {
assert(_owners[tokenId] == msg.sender);
_owners[tokenId] = newOwner;
}
在solidity 0.6
版本后,solidity
也添加了异常处理方法,并且try-catch
只能被用于external
函数(只能由外部调用的函数)或创建合约时constructor
(被视为external
函数)的调用。基本语法如下:
try externalContract.f() {
// call成功的情况下 运行一些代码
} catch Error(string memory reson){
// 这里一般是 require/revert 的异常抛出,毕竟参数是 string
// call 失败的情况下 运行一些代码
} catch (bytes memory reason) {
// assert 的异常抛出
// catch 失败的 assert()
emit CatchByte(reason);
}
现在真正使用的异常抛出方法有:error
(新兴)、require
,而assert
由于其高费用而常常不予考虑。
对于异常捕获tyr-catch
只能在调用外部函数(包括生成新合约)时使用。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!