Solidity

重入攻擊的事務時間含義

  • December 6, 2019

這是經典的再入攻擊:

function withdrawBalance() public {
   uint amountToWithdraw = userBalances[msg.sender];
   (bool success, ) = msg.sender.call.value(amountToWithdraw)(""); 
   require(success);
   userBalances[msg.sender] = 0;
}

我不明白這是如何工作的。似乎一項事務未在另一項之前完成。我知道在 Dao 攻擊中,使用 call.value() 上的回退函式的合約在調整狀態變數 userBalances 之前操縱系統停止

$$ msg.sender $$,但如果這僅僅是由於通過此回退函式創建的額外時間,則表明這是一個不太可能但可能存在的問題。 假設我在 contractBalance 中有 10 個代幣,使用者可以將它們放入他們的合約餘額中。

function takeAllTokens(uint x) public {
   require(x < contractBalance);
   uint amountToTake = contractBalance;
   uint y = x + 1; // just to give it a couple pico seconds
   contractBalance -= x;
   userBalances[msg.sender] = contractBalance;
}

如果交易沒有完全按順序處理,兩個同時到達並要求 10 個代幣的人最終將各自獲得 10 個代幣,比本範例中的 contractBalance 中的要多。

這僅僅是不可能的,因為在後一種情況下,從一條線到另一條線所需的時間是如此之短,以至於雖然可能,但它的機率被認為是不可能的?

我將嘗試以希望有所幫助的方式解決一些誤解。

這並不像你認為的那樣。

uint y = x + 1; // just to give it a couple pico seconds

關於時間時間的直覺想法並不適用。考慮現在和將來(同步)每個節點如何冗餘執行事務。時間上的開始時間是什麼時候?這不是真的可以定義,是嗎?持續時間相同。如果它可以被測量,它在每個節點上都會有所不同,並且它不是確定性的,因此不是合約可以訪問的東西。

雖然在物理世界中顯然不是這樣,但合約功能和交易應該在邏輯上被理解為即時執行。

沒有並行性,也沒有兩個事務同時執行的可能性。它們在塊中排序,並且每個都在前一個已完成事務的上下文中執行 - 單執行緒順序執行。

塊中的交易按順序在塊時間戳指示的時間時間上或附近即時執行……當發現塊時。

重入與時間無關。它是關於流控制的轉移。易受攻擊的合約期望流量控制恢復,但它可能不會。已獲得流量控制的合約可能會在最終返回之前進行惡作劇。這可能會導致各種邏輯錯誤,因為攻擊者可能能夠在合約處於不一致狀態時呼叫任何函式。

防禦是把所有的驗證放在首位,然後根據需要更新狀態,最後(總是最後)允許流控制傳遞給另一個合約。首先把房子整理好會阻止大多數詭計。

希望能幫助到你。

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