Contract-Invocation
Solidity 如何解碼委託呼叫返回的結構?
我有一個代理合約,它將呼叫委託給目標合約。代理類似於DSProxy。
其中,有一個
execute
功能:function execute(address target, bytes memory data) external payable returns (bytes memory response) { // ... (bool success, bytes memory returndata) = target.delegatecall(data); // ... }
誰的工作是將呼叫委託給提供的
target
並返回response
類型為bytes memory
.現在,假設我正在呼叫一個返回結構的目標合約:
contract TargetEcho { struct TargetStruct { uint256 foo; uint256 bar; } function echoStruct(TargetStruct calldata input) external pure returns (TargetStruct calldata) { return input; } }
Solidity 編譯器必須對
TargetStruct calldata
返回類型做一些事情。它必須以某種方式對其進行解碼。它是如何完成的?
讓我們用ethers.js憑經驗解決這個問題:
const input = { foo: BigNumber.from("3"), bar: BigNumber.from("1") }; const data: string = targetEcho.interface.encodeFunctionData("echoStruct", [input]); const response = await proxy.callStatic.execute(target, data); console.log({ input, response });
這會產生以下輸出:
{ input: { foo: BigNumber { _hex: '0x03', _isBigNumber: true }, bar: BigNumber { _hex: '0x01', _isBigNumber: true }, }, response: '0x00000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001' }
因此,答案是 Solidity 解包結構欄位並連接它們的值,而不考慮鍵。這使其與代理合約中定義
bytes memory
的變數類型兼容。response
幸運的是 ethers.js 能夠解碼響應字元串:
const decodedResponse = targetEcho.interface.decodeFunctionResult("echoStruct", response);
輸出:
{ decodedResponse: [ [ [BigNumber], [BigNumber], foo: [BigNumber], bar: [BigNumber], ] ] }