簡體   English   中英

是什么導致此函數中的重入錯誤?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM