算术运算的检查模式与非检查模式
当对无限制整数执行算术运算,其结果超出结果类型的范围,这是就发生了上溢出或下溢出。
在Solidity 0.8.0之前,算术运算总是会在发生溢出的情况下进行“截断”,从而得靠引入额外检查库来解决这个问题(如 OpenZepplin 的 SafeMath)。
而从Solidity 0.8.0开始,所有的算术运算默认就会进行溢出检查,额外引入库将不再必要。
如果想要之前“截断”的效果,可以使用 unchecked 代码块:
pragma solidity >0.7.99;
contract C {
function f(uint a, uint b) pure public returns (uint) {
// 溢出会返回“截断”的结果
unchecked { return a - b; }
}
function g(uint a, uint b) pure public returns (uint) {
// 溢出会抛出异常
return a - b;
}
}
调用 f(2, 3) 将返回 2**256-1, 而 g(2, 3) 会触发失败异常。
unchecked 代码块可以在代码块中的任何位置使用,但不可以替代整个函数代码块,同样不可以嵌套。
此设置仅影响语法上位于unchecked
块内的语句。 在块中调用的函数不会此影响
注意:为避免歧义,不能在 unchecked 块中使用 ‘ _;’ 。
下面的这个运算操作符会进行溢出检查,如果上溢出或下溢会触发失败异常。 如果在费检查模式代码块中使用,将不会出现错误:
++, —, +, binary -, unary -, , /, %, **
+=, -=, =, /=, %=
除 0(或除 0取模)的异常是不能被 unchecked 忽略的。