写智能合约经常会出bug,Solidity中的异常命令帮助我们debug
error是solidity 0.8.4版本新加的内容,方便高效(省gas)地向用户解释操作失败的原因,同时还可以在抛出异常的同时携带参数,帮助开发者更好地调试。人们可以在contract之外定义异常。
下面定义一个TxNotOwner异常, 当用户不是tonken owner时尝试转账会抛出错误
error TxNotOwner();
也可以定义一个携带参数的异常,来替时尝试转账的账户地址
error TxNotOwner(address sender);
在执行中,error必须搭配revert(回退)命令使用
function TxOwner1(uint256 tokenId, address newOwner) public {
if(_owners[tokenId] != msg.sender){
revert TxNotOwner();
// revert TransferNotOwner(msg.sender);
}
_owners[tokenId] = newOwner;
}
我们定义了一个transferOwner1()函数,它会检查代币的owner是不是发起人,如果不是,就会抛出TransferNotOwner异常;如果是的话,就会转账。
require命令是solidity 0.8版本之前抛出异常的常用方法,目前很多主流合约仍然还在使用它。它很好用,唯一的缺点就是gas随着描述异常的字符串长度增加,比error命令要高。使用方法:require(检查条件,"异常的描述"),当检查条件不成立的时候,就会抛出异常。
使用require重写上面的TxOwner1函数如下:
function TxOwner2(uint256 tokenId, address newOwner) public {
require(_owners[tokenId] == msg.sender, "Transfer Not Owner");
_owners[tokenId] = newOwner;
}
assert命令一般用于程序员debug,因为它不能解释抛出异常的原因(比require少个字符串)。它的用法很简单,assert(检查条件),当检查条件不成立的时候,就会抛出异常。
用assert重写TxOwner1函数如下:
function TxOwner3(uint256 tokenId, address newOwner) public {
assert(_owners[tokenId] == msg.sender);
_owners[tokenId] = newOwner;
}