Solidity
使用 DELEGATECALL 時如何冒泡自定義錯誤?
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’s
revert(p, s)
與合約 A 中的自定義錯誤進行還原。p
指錯誤字節數組從哪裡開始的指針,s
指字節數組的長度。由於
returndata
是一個動態大小的字節數組,指針的前 32 位儲存它的大小,我們mload(returndata)
要檢索它。同樣,add(32, returndata)
將是指向字節數組開始位置的指針。總而言之,它形成了 linerevert(add(32, returndata), mload(returndata))
,它恢復了你從合約 B 中得到的錯誤。