Reentrant-Attacks
事務範圍的狀態變數
是否可以創建一個在事務開始時初始化並在結束時重置的狀態變數?
我必須創建一個將價值(ETH)發送到任意地址的合約。我不能從目的地排除契約,為了避免重入攻擊,我想將交易設置為一個
executing
狀態,以便我可以在開始時驗證該狀態並做出相應的反應。
簡短的回答。
沒有事務範圍的狀態變數。理論上,你可以(虛擬碼)
bool private txnInProgress; function exclusive() ... if(txnInProgress) throw; txnInProgress = true; // do stuff txnInProgress = false;
在實踐中會更難。這傢伙很好地解釋了一些想法: http: //www.blunderingcode.com/writing-secure-solidity/請參閱有關“互斥鎖”的部分。
更好的答案是一種意見。通常最好嘗試否定對鎖的需求。這將是更可取的 IMO,因為它有助於使事情變得簡單。
考慮一個三步過程:
- 樂觀的會計。在與不受信任的合約互動之前,確保合約處於“完整”狀態。例如,做會計,
balanceOwed[user] -= amount
;- 嘗試與不受信任的合約互動並測試結果,例如
if(!user.sender(amount))
…- 在失敗的情況下恢復樂觀記帳,例如
if(!user.send(amount)) throw;
恢復在步驟 1 中執行的記帳。在知道步驟 2 的結果後,您可以安全地記錄成功/失敗事件。要點是在步驟之後更新狀態變數是不安全的2.…並且更喜歡退出模式而不是咄咄逼人的發送模式,
…並避免將價值轉移與其他邏輯混為一談,
…並且一次只與一個不受信任的契約交談。如果這些互動過於復雜,邊緣情況就更難定義和捕捉。
關於樂觀會計的第一點可以大大有助於重新進入保護。有人可能會爭辯說,重入不是問題,除非當控制權轉移給攻擊者時合約處於不完整狀態。
我希望我描述得相當好。
希望能幫助到你。