Solidity

throw 會阻止這種遞歸攻擊嗎?

  • July 22, 2017

我正在編寫一個基本合約,以在兩個地址之間平均分配乙太坊。

在我的withdraw()函式中,我有以下程式碼:

function withdraw() {
   uint256 amount = this.balance / 2;
   addressOne.transfer(amount);
   addressTwo.transfer(amount);
}

問題是,像這樣進行後續傳輸會導致遞歸攻擊。的所有者addressOne可以在餘額的另一半發送到 之前呼叫該函式並溢出堆棧addressTwo

反复執行,owneraddressOne可以根據序列耗盡合約(假設餘額相等,即沒有餘數):

在此處輸入圖像描述

我提出的解決方案如下:

if(!addressOne.send(amount)) throw;
if(!addressTwo.send(amount)) throw;

但是這樣的投擲會阻止同樣的攻擊嗎?

這份契約有幾個問題。

  1. 無論是否throw恢復交易,這都不會阻止重入攻擊。如果addressOne是以下契約:
contract AddressOne {
  function() payable {
    OriginalContract.withdraw();

    // some case to stop recursion to prevent exhausting gas
  }
}

addressOne``withdraw可以在被呼叫時耗盡合約。您可以通過以下兩種方式之一來防止這種情況:使用提款流程,每個地址都可以隨意提取自己的資金份額,或者在合約全域狀態上放置互斥鎖。如果您想做前者,請查看我的splitter-contract範例。 2. 任何人都可以呼叫該withdraw函式。我不認為這是故意的。

如果我不正確,請糾正我。

引用自:https://ethereum.stackexchange.com/questions/21466