阅读(1557) (15)

检查或未检查的算术

2022-05-12 15:17:28 更新

上溢或下溢是指算术运算的结果值在对不受限制的整数执行时超出结果类型范围的情况。

在 Solidity 0.8.0 之前,算术运算总是会在出现不足或溢出的情况下进行换行,从而导致广泛使用引入额外检查的库。

从 Solidity 0.8.0 开始,默认情况下所有算术运算都会在上溢和下溢时恢复,因此无需使用这些库。

要获得先前的行为,unchecked可以使用一个块:

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;
contract C {
    function f(uint a, uint b) pure public returns (uint) {
        // This subtraction will wrap on underflow.
        unchecked { return a - b; }
    }
    function g(uint a, uint b) pure public returns (uint) {
        // This subtraction will revert on underflow.
        return a - b;
    }
}

调用将返回,而将导致断言失败。f(2, 3)2**256-1g(2, 3)

块可以在unchecked块内的任何地方使用,但不能作为块的替代品。它也不能嵌套。

该设置仅影响语法上位于块内的语句。从unchecked块中调用的函数不继承该属性。

笔记

为避免歧义,您不能在块_;内使用。unchecked

以下运算符将导致上溢或下溢断言失败,如果在未经检查的块中使用,则将无错误地回绕:

++, --, +, 二元-, 一元-, *, /, %,**

+=, -=, *=, /=,%=

警告

unchecked无法使用该块禁用除以零或模零的检查。

笔记

位运算符不执行上溢或下溢检查。<<当使用按位移位 ( , >>, <<=, >>=) 代替整数除法和乘以 2 的幂时,这一点尤其明显。例如,即使会恢复也不会恢复。type(uint256).max << 3type(uint256).max * 8

笔记

第二条语句将导致溢出,因为负范围可以比正范围多保存一个值。int x = type(int).min; -x;

显式类型转换将始终截断并且永远不会导致断言失败,但从整数到枚举类型的转换除外。