智能合约问题-整数溢出

706 阅读3分钟

「这是我参与2022首次更文挑战的第11天,活动详情查看:2022首次更文挑战

前言

智能合约安全问题一直是所有用户、开发者非常关心的问题,因为合约一旦部署就无法撤回,它会永远的存在区块链的世界中。所以在合约真正部署之前,合约的测试和安全问题就显得尤为重要,本文通过整数溢出这个问题,来分析下智能合约。

什么是整数溢出

字面理解,整数通过运算得到的结果比整数的最大值还要大,这就不合理了。所以我们做任何数学运算的时候需要尽量规避这样的风险。整数溢出一般分为又分为上溢和下溢,在智能合约中出现整数溢出的类型包括三种:

  • 乘法溢出
  • 加法溢出
  • 减法溢出

在Solidity语言中,一个 uint8类型 ,只能存储在范围 0到2^8-1,也就是[0,255] 的数字,一个 uint256类型 ,只能存储在范围 0到2^256-1的数字。

在以太坊虚拟机(EVM)中为整数指定固定大小的数据类型,而且是无符号的,这意味着在以太坊虚拟机中一个整型变量只能有一定范围的数字表示,不能超过这个制定的范围。

//SPDX-License-Identifier: UNLICENSEDpragma solidity ^0.8.0;contract MyTest{    //加法溢出    //如果uint256 类型的变量达到了它的最大值(2**256 - 1),如果在加上一个大于0的值便会变成0    function addOverflow() public returns (uint256 _overflow) {        uint256 max = 2**256 - 1;        return max+1;    }    //减法溢出    //如果uint256 类型的变量达到了它的最小值(0),如果在减去一个小于0的值便会变成2**256-1(uin256类型的最大值)    function subUnderflow() public returns (uint256 _underflow) {        uint256 min = 0;        return min - 1;    }        //乘法溢出    //如果uint256 类型的变量超过了它的最大值(2**256 - 1),最后它的值就会回绕变成0    function mulOverflow() public returns (uint256 _underflow) {        uint256 mul = 2**255;        return mul * 2;    }}

如上部署一个简单的测试合约,测试下这几个溢出。

如图对应的addOverflow方法,我们将uint256 类型的max变量设置为它的最大值(2**256 - 1),然后在给max变量加上1,导致上溢,

这可以看到输出的值为0。同理合约中的三个方法依次测试,同样的会得到不一样的结果。

最小值减去一个1,导致下溢,最后min的值便会变成一个很大的值,即2**256-1,也就是uin256类型的最大值。

第三个方法将uint256 类型的mul变量设置为2**255**,然后在给mul变量乘以2,变成2****256,超过最大值导致上溢,最终结果mul的值输出为0。

综上例子,我们可以看到uint256当取最大整数值,上溢之后直接返回值为0,uint256当取0下溢之后直接返回值为2^256-1。

总结

整数溢出就是一个很简单但是很严重的漏洞,因此在平时写智能合约的时候就得注意。写完了还要安全审计,确保不出问题,因为一旦出现问题,都可能带来很大的损失。下一篇讲解怎么防止整数溢出的问题。