Solidity

使用 DELEGATECALL 時如何冒泡自定義錯誤?

  • October 8, 2021

Solidity v0.8.4 引入了自定義錯誤

error Unauthorized();

假設我有契約 A,它委託呼叫契約 B。後者恢復為上面定義的自定義錯誤。我怎樣才能在契約 A 中冒泡這個錯誤?

查看我從 openzepplin 的 Address.sol 修改的這個函式。

function _delegatecall(address target, bytes memory data) internal returns (bytes memory) {
   (bool success, bytes memory returndata) = target.delegatecall(data);
   if (!success) {
       if (returndata.length == 0) revert();
       assembly {
           revert(add(32, returndata), mload(returndata))
       }
   }
   return returndata;
}

returndata是一個動態大小的字節數組。如果委託呼叫失敗,returndata將是失敗呼叫引發的錯誤對象。假設我有合約 A,它委託呼叫合約 B。後者返回自定義錯誤GonnaMakeIt(uint256 data)。然後,returndata將是:

0xbf42f2660000000000000000000000000000000000000000000000000000000000000539
 +------+---------------------------------------------------------------+
 selector                       uint256 data

然後,我們利用 Yul’srevert(p, s)與合約 A 中的自定義錯誤進行還原。p指錯誤字節數組從哪裡開始的指針,s指字節數組的長度。

由於returndata是一個動態大小的字節數組,指針的前 32 位儲存它的大小,我們mload(returndata)要檢索它。同樣,add(32, returndata)將是指向字節數組開始位置的指針。總而言之,它形成了 line revert(add(32, returndata), mload(returndata)),它恢復了你從合約 B 中得到的錯誤。

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