Out-of-Gas

當 throw 發生時,整個事務是否會恢復?

  • September 13, 2016

我有一個呼叫另一個呼叫另一個合約的合約。如果在第二個合約的某處發生拋出(或氣體不足錯誤),整個交易是否會被還原,或者只是第二個和第三個合約中的東西會恢復,而從第一個合約執行還站著嗎?

在 Solidity 中,預設情況下是的。

在 EVM 級別上,拋出(錯誤跳轉、氣體耗盡或任何其他異常)只會恢復它在內部的呼叫。Solidity 有助於將異常繼續向下堆棧,直到一切都被撤消。

可以使用較低級別的程式碼(特別是 address.call())來防止這種情況。是一個將其用作即興嘗試擷取結構的範例。

為了補充@Matthew 的答案,這取決於如何在 Solidity 中進行呼叫。

如果C呼叫D.foo(), 並foo執行 a throw,那麼是的,整個事務將被還原。

如果C像 , 一樣執行“較低級別的原始呼叫” D.call(bytes4(sha3('foo()'))),並且foo執行 a throw,則僅foo還原及其子呼叫。這是因為原始呼叫不會傳播任何異常:原始呼叫D.call僅返回一個布爾值,指示呼叫是否成功或遇到異常。


更多細節

在 Solidity 中,athrow通過生成導致無效跳轉目標的字節碼來引發異常。(對於其他情況,請參閱Solidity 編譯到無效跳轉目的地的所有情況。)

從 Solidity 的角度來看,未吞下或未擷取/未處理的異常將導致整個事務被還原。

目前在 Solidity 中沒有辦法擷取異常,因此一個異常,例如throw,將導致整個事務被還原。

但是,原始呼叫“吞沒”異常:原始呼叫不會傳播異常,這就是為什麼只有子呼叫會被還原。

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