Reentrant-Attacks

事務範圍的狀態變數

  • March 12, 2017

是否可以創建一個在事務開始時初始化並在結束時重置的狀態變數?

我必須創建一個將價值(ETH)發送到任意地址的合約。我不能從目的地排除契約,為了避免重入攻擊,我想將交易設置為一個executing狀態,以便我可以在開始時驗證該狀態並做出相應的反應。

簡短的回答。

沒有事務範圍的狀態變數。理論上,你可以(虛擬碼)

bool private txnInProgress;

function exclusive() ...
 if(txnInProgress) throw;
 txnInProgress = true;
 // do stuff
 txnInProgress = false;

在實踐中會更難。這傢伙很好地解釋了一些想法: http: //www.blunderingcode.com/writing-secure-solidity/請參閱有關“互斥鎖”的部分。

更好的答案是一種意見。通常最好嘗試否定對鎖的需求。這將是更可取的 IMO,因為它有助於使事情變得簡單。

考慮一個三步過程:

  1. 樂觀的會計。在與不受信任的合約互動之前,確保合約處於“完整”狀態。例如,做會計,balanceOwed[user] -= amount
  2. 嘗試與不受信任的合約互動並測試結果,例如if(!user.sender(amount))
  3. 在失敗的情況下恢復樂觀記帳,例如if(!user.send(amount)) throw;恢復在步驟 1 中執行的記帳。在知道步驟 2 的結果後,您可以安全地記錄成功/失敗事件。要點是在步驟之後更新狀態變數是不安全的2.

…並且更喜歡退出模式而不是咄咄逼人的發送模式,

…並避免將價值轉移與其他邏輯混為一談,

…並且一次只與一個不受信任的契約交談。如果這些互動過於復雜,邊緣情況就更難定義和捕捉。

關於樂觀會計的第一點可以大大有助於重新進入保護。有人可能會爭辯說,重入不是問題,除非當控制權轉移給攻擊者時合約處於不完整狀態。

我希望我描述得相當好。

希望能幫助到你。

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