Contract-Invocation

Solidity 如何解碼委託呼叫返回的結構?

  • September 6, 2021

我有一個代理合約,它將呼叫委託給目標合約。代理類似於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],
   ]
 ]
}

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