Solidity

如果使用 address.call() 呼叫失敗,如何防止完全失去狀態?

  • March 23, 2022

程式碼:

interface MyInterface {
   function functionName(uint256 x, uint256 y, uint256 z) external returns (uint256[] memory k);
}

然後我的契約中有以下內容,它使用了外部契約addr

MyInterface(addr).functionName(x,y,z);
MyInterface(addr).functionName(x,y,z);
MyInterface(addr).functionName(x,y,z);

如果 3 個函式呼叫中的任何一個失敗,我想在那裡停止執行,但確保已保存由先前函式呼叫引起的任何狀態更改。

很多時候,我在 etherscan 上看到了部分執行的此類事務。據我所知,如果出現錯誤,solidity 不會保存任何更改。

在這個答案中:當拋出發生時,整個事務是否會恢復?,已經提到可以使用較低級別的程式碼。

以下是我正在考慮的解決方案:

addr.call(abi.encodeWithSignature("functionName(uint256, uint256, uint256)",x,y,z));
addr.call(abi.encodeWithSignature("functionName(uint256, uint256, uint256)",x,y,z));
addr.call(abi.encodeWithSignature("functionName(uint256, uint256, uint256)",x,y,z));

如果其中一個呼叫失敗,之前的呼叫導致的先前狀態更改是否仍然存在?

如果您使用 call 之類的低級函式,狀態更改將持續存在,您將必須顯式檢查 ‘call’ 的返回值,並恢復整個事務。

(bool success,) = address.call(.....)
if(!success){
revert("Failed")
}

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