Solidity - 算术运算的截断模式(unchecked)与检查模式(checked)- 0.8.0新特性

0.8.0版本开始,算术运算有两个计算模式,一个是“wrapping”(截断)模式或为“unchecked”(不检查)模式,即在发生溢出的情况下会进行“截断”,不会触发失败异常,从而得靠引入额外的检查库来解决这个问题(如OpenZeppelin中的SafeMath库);另一个是"checked"(检查)模式。默认情况下,算术运算使用的是“checked”模式,会进行溢出检查,如果结果溢出,会出现失败异常回退。

举个栗子:

uint8最大值为255,255加上一个大于0的整数会溢出(上溢),加上unchecked{}则不检查是否溢出,溢出则截断显示;否则默认使用截断模式检查溢出,发生异常回退。

测试0.8.0或以上版本 

测试代码

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7; 

/// @dev 示例合约:uint8最大值为255,255加上一个大于0的整数会溢出,加上unchecked不会检查是否溢出
contract TestUncheck {  
    /// @dev 检查溢出(checked模式)
    function withoutUnchecked() external pure returns (uint8) {
        uint8 a = 255;
        uint8 b = 5;
        return (a + b);
    }

    /// @dev 不检查溢出(unchecked模式或称为截断模式)
    function withUnchecked() external pure returns (uint8) { 
        uint8 a = 255;
        uint8 b = 5;
        // 不检查溢出,输出溢出结果
        unchecked { 
            return (a + b);
        }
    }
}

测试检查模式(checked) 

检查模式,由于数据溢出,发生异常回退。

测试截断模式 (unchecked或wrapping)

截断模式,虽然255+5溢出了,但输出了溢出结果4。

unchecked 代码块可以在代码块中的任何位置使用,但不可以替代整个函数代码块,同样不可以嵌套。

此设置仅影响语法上位于 unchecked 块内的语句。 在块中调用的函数不会此影响。

测试0.8.0之前版本

0.8.0之前版本为“wrapping”(截断)模式,即在发生溢出的情况下会进行“截断”,不会触发失败异常,从而得靠引入额外的检查库来解决这个问题(如OpenZeppelin中的SafeMath库)

测试代码 

测试一个离0.8.0最近版本0.7.6,合约代码如下:

// SPDX-License-Identifier: MIT
pragma solidity ^0.7.6; 

/// @dev 测试0.8.0以前版本,溢出为截断模式
contract TestOverflow {  
    /// @dev 不检查溢出(wrapping模式)
    function overflow() external pure returns (uint8) {
        uint8 a = 255;
        uint8 b = 5;
        return (a + b);
    }
}

测试结果(wrapping模式)

输出截断数据,即为不检查模式 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值