[英]What causes a reentrancy error in this function?
function recoverContribution() public payable{
require(hasDeadlinePassed(), "deadline has not passed, contributions cannot be recovered rightnow");
require(!(address(this).balance >= minimumTarget), "target has been met, cannot recover contributions now");
require(contributors[msg.sender] != 0, "you have not contributed anything");
payable(msg.sender).transfer(contributors[msg.sender]);
contributors[msg.sender] = 0;
}
如果未達到目標且已超過截止日期,則貢獻者調用上述函數以收回他/她的資金。
這個函數給出了一個重入錯誤和一個gas成本無限錯誤。
這個函數非常簡單,為什么這個函數會出現這樣的潛在錯誤?
關於重入攻擊的簡單理論。
當您在合約上使用任何轉移功能時,將以太幣從您的合同轉移到其他人,如果另一個人是另一個合同,則合同可以在轉移完成之前執行邏輯(查看receive
回退功能) ,在此receive
函數,攻擊者合約可以再次調用你的recoverContribution
函數,並繼續轉移和重新進入。
現在,如果您在轉移后跟蹤以太幣,這將導致重入漏洞,因為您將僅在轉移執行后更新他們的以太幣余額,這是您的函數的情況,因此他們可以通過以下方式清空您的余額調用recoverContribution
,因為您的要求將通過檢查,因為您僅在轉移完成后才更新其余額。
為了避免這種攻擊,只需在轉移之前更新他們的余額,這樣他們的余額將在每次調用時更新,即使他們是從他們的接收功能重新進入。
因此,基本上為了避免對您的功能進行重入攻擊,只需執行以下操作:
function recoverContribution() public payable{
require(hasDeadlinePassed(), "deadline has not passed, contributions cannot be recovered rightnow");
require(!(address(this).balance >= minimumTarget), "target has been met, cannot recover contributions now");
require(contributors[msg.sender] != 0, "you have not contributed anything");
contributors[msg.sender] = 0;
payable(msg.sender).transfer(contributors[msg.sender]);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.