在solidity中一旦出现异常,则当前交易将会回滚(即相当于没有发生过,除了你的gas被消耗了)。solidity里抛出异常的方法有三种:errorrequireassert对于可能出现异常抛出的地方,solidity也提供了try-catch方法进行异常捕获处理。
在solidity中一旦出现异常,则当前交易将会回滚(即相当于没有发生过,除了你的gas被消耗了)。
`solidity`里抛出异常的方法有三种:
errorrequireassert
对于可能出现异常抛出的地方,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只能在调用外部函数(包括生成新合约)时使用。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!