solidity智慧合約[53]-安全-重入***
重入***
當呼叫外部的合約時,外部合約會接管控制流程,從而可能給自己的資料帶來意想不到的修改。2016年6月,以太坊最大眾籌專案The DAO被***,***獲得超過350萬個以太幣。正是由於此陷阱。
重入***本質
1、呼叫外部合約
2、fallback回撥函式被多次執行
3、邏輯順序出現問題
4、call函式沒有gaslimit的限制。
5、call函式返回值為true或false。出錯不會執行回滾。
案例剖析
1、部署合約Vulnerable、Malicious、transferEther,假設地址為 addrA、addrB、addrC
2、 將addrB傳遞到 Vulnerable合約的 add中。 完成此操作後,將balance對映的金額增加100。附帶5 ether。讓Vulnerable合約一開始就有5 ether。
3、將addrA的地址傳遞到Malicious合約的instance中,儲存地址。
4、呼叫transferEther合約的test方法,傳遞addrB的地址。由於合約的轉賬方法出發了fallback回撥函式。因此執行了Vulnerable合約中的withdrawEquity方法。此方法執行了語句 msg.sender.call.value(x)();而當前的msg.sender為Malicious合約地址,又會再次執行Malicious合約的回撥函式。而這時, ____balanceOf[msg.sender] 的金額還沒有變為0.使得Vulnerable不停的轉移資金給Malicious合約。一直到到達了gaslimit的限制從而終止。但是由於call函式返回值為true或false。只有最後的函數出錯會執行回滾。其他函式會正常的執行。
1 |
|
解決辦法
1、替換順序,這樣當重複執行withdrawEquity函式時,資金已經變為了0。
1 |
function withdrawEquity() public returns(bool){ |
2、替換為更安全的send、transfer函式
3、對於呼叫外部合約的時候保持警惕。
本文連結: https://dreamerjonson.com/2018/11/25/solidity-53-security-reentrancy/
版權宣告: 本部落格所有文章除特別宣告外,均採用 CC BY 4.0 CN協議 許可協議。轉載請註明出處!