***回顾
1 | 2016年6月,以太坊最大众筹项目The DAO被***,***获得超过350万个以太币,最终导致以太坊分叉为ETH和ETC。 |
溢出
孔子曾经说过 过犹不及
。做事情都有限度,一旦超过了限度就会适得其反。理解溢出问题最好的是在千禧之年爆发的千年虫事件。过去,由于计算机程序中使用两个数字来表示年份,如1998年被表示为“98”、1999年被表示为“99”;而2000年被表示为“00”,这样将会导致某些程序在计算时得到不正确的结果,如把“00”误解为1900年。在嵌入式系统中可能存在同样的问题,这有可能导致设备停止运转或者发生更加灾难性的后果。
solidity中的溢出问题
下面是一个简单的函数,其功能是将桉树加1.例如传递4,返回5。传递200,返回201。但是里面暗藏着陷阱。例如当传递255的时候,会返回0…这就是溢出。这是由于uint8的最大值为255,在内存中:为1111 1111
。一旦加1之后,变为了1 0000 0000
,但是最大的位数为8位。截断之后,变为了0000 0000
因此返回的结果为0。
1 | function add(uint8 a) public pure returns(uint8){ |
safeMath避免溢出问题
因此我们可以看到,对于4则运算,很容易的发生溢出问题。OpenZeppelin 建立了一个叫做 SafeMath 的 库。这就规避掉溢出问题。
1 | library SafeMath { |
BEC代币***全纪实
如下为BEC代币的源代码抽离出来的部分。2018年4月份BEC代币遭到***的溢出袭击。***为自己的两个账号转移了2^255次方的代币。导致市场的恐慌,币价一度一文不值。***手法被披露的24小时内,就有类似30多个合约遭受***
在TokenExample合约中,有一个batchTransfer函数。此函数的功能为对账户进行转账操作。第一个参数为动态长度地址,明确要转账的账户。第二个参数为转账的金额。 要转账成功,必须要保证在balance资金表中,发送者必须有超过总金额(账户数量转账金额)。但是 uint256 amount = uint256(cnt) value;这段代码并没有做安全的乘法,导致可能会发生溢出***。当***调用合约的时候,在remix中:
输入地址数组以及:[“0xb4D30Cac5124b46C2Df0CF3e3e1Be05f42119033”,“0x0e823fFE018727585EaF5Bc769Fa80472F76C3d7”],
以及
value"0x8000000000000000000000000000000000000000000000000000000000000000"即2*255,
使得amount=2^255 * 2,超出uint256类型的范围[0,2**256-1],溢出为0,发送者账户余额不减少,并且,本例中,发送者的代币可以为零,实现"无中生有"。
1 |
|
本文链接: https://dreamerjonson.com/2018/11/24/solidity-49-overflow/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY 4.0 CN协议 许可协议。转载请注明出处!