函数assert
和require
可以用于检查条件,如果条件不满足则抛出异常。
assert():
函数只能用于测试内部错误,检查不变量,正常的函数代码永远不会产生Panic, 甚至是基于一个无效的外部输入时。 如果发生了,那就说明出现了一个需要你修复的 bug。如果使用得当,语言分析工具可以识别出那些会导致 Panic 的 assert
条件和函数调用。
想象为一个过于自信的实现方式,即使有错误,也会执行并扣除 gas。
下列情况将会产生一个Panic异常: 提供的错误码编号,用来指示Panic的类型。
- 0x01: 如果你调用
assert
的参数(表达式)结果为 false 。 - 0x11: 在``unchecked { … }``外,如果算术运算结果向上或向下溢出。
- 0x12; 如果你用零当除数做除法或模运算(例如
5 / 0
或23 % 0
)。 - 0x21: 如果你将一个太大的数或负数值转换为一个枚举类型。
- 0x22: 如果你访问一个没有正确编码的存储byte数组.
- 0x31: 如果在空数组上
.pop()
。 - 0x32: 如果你访问
bytesN
数组(或切片)的索引太大或为负数。(例如:x[i]
而i >= x.length
或i < 0
). - 0x41: 如果你分配了太多的内内存或创建了太大的数组。
- 0x51: 如果你调用了零初始化内部函数类型变量。
require():
想象为一个更有礼貌些的实现方式,会发现错误,不扣除 gas。
函数要么创建一个 Error(string)
类型的错误,或者没有错误数据的错误并且 require
函数应该用于确认条件有效性,例如输入变量,或合约状态变量是否满足条件,或验证外部合约调用返回的值。
下列情况将会产生一个 Error(string)
(或没有数据)的错误:
- 如果你调用
require
的参数(表达式)最终结果为false
。 - 如果你在不包含代码的合约上执行外部函数调用。
- 如果你通过合约接收以太币,而又没有
payable
修饰符的公有函数(包括构造函数和 fallback 函数)。 - 如果你的合约通过公有 getter 函数接收 Ether 。
在下面的情况下,来自外部调用的错误数据(如果提供的话)被转发,这意味可能 Error 或 Panic 都有可能触发。
- 如果
.transfer()
失败。 - 如果你通过消息调用调用某个函数,但该函数没有正确结束(例如, 它耗尽了 gas,没有匹配函数,或者本身抛出一个异常),不包括使用低级别
call
,send
,delegatecall
,callcode
或staticcall
的函数调用。低级操作不会抛出异常,而通过返回false
来指示失败。 - 如果你使用
new
关键字创建合约,但合约创建 没有正确结束 。
可以给 require
提供一个消息字符串,而 assert
不行。 在下例中,你可以看到如何轻松使用``require`` 检查输入条件以及如何使用 assert
检查内部错误.
revert():
revert
函数是另一个可以在代码块中处理异常的方法, 可以用来标记错误并回退当前的调用。revert
调用中还可以包含有关错误信息的参数,这个信息会被返回给调用者,并且产生一个 Error(string)
错误。
https://blog.csdn.net/tianlongtc/article/details/80261757
https://learnblockchain.cn/docs/solidity/control-structures.html#assert-require-revert