solidity智慧合約[49]-安全-溢位***
***回顧
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 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協議 許可協議。轉載請註明出處!