Abi

abi.decode 與 pragma 實驗性 ABIEncoderV2 使用嵌套數組還原

  • September 8, 2020

我有一個帶有字節 calldata 參數的函式,需要將其解碼為結構,但呼叫會在彙編中恢復。我相信這個問題與嵌套數組有關。我使用了一種類似的技術,只有一維數組,它似乎工作正常。

struct InputParams {
   address[] exchangeAddresses;
   address[][] exchangePoolOrPaths;
   address[] tokenAddresses;
   uint256 tokenStartAmount;
   uint256[] tokenAmountsExpected;
}

function execute(uint blockNumber, bytes calldata data, bool admin) external
{
   InputParams memory params = abi.decode(data, (InputParams));  // this reverts in assembly
}

檢查使用此函式進行交易的原始輸入並不能提供太多資訊。我在單獨的參數下面解析出來,它們似乎編碼正常:

       0xb83775a0  // function signature
       0000000000000000000000000000000000000000000000000000000000000000  // parameter "blockNumber" == 0
       0000000000000000000000000000000000000000000000000000000000000060  // parameter bytes calldata "data" offset value
       0000000000000000000000000000000000000000000000000000000000000001  // parameter "admin" == 1
       00000000000000000000000000000000000000000000000000000000000002c0  // struct InputParams length 
       00000000000000000000000000000000000000000000000000000000000000a0  // offset of exchangeAddresses[]
       0000000000000000000000000000000000000000000000000000000000000100  // offset of exchangePoolOrPaths[][]
       00000000000000000000000000000000000000000000000000000000000001e0  // offset of tokenAddresses[]
       0000000000000000000000000000000000000000000000004563918244f40000  // value of tokenStartAmount
       0000000000000000000000000000000000000000000000000000000000000260  // offset of tokenAmountsExpected[]
       0000000000000000000000000000000000000000000000000000000000000002  // number of items in exchangeAddresses[]
       0000000000000000000000001cb3aca0179bc96cd9612d6c27285b0458a2500f  // value of exchangeAddresses[0]
       00000000000000000000000080d73310b92da08b230adf441a6352e8f9631a77  // value of exchangeAddresses[1]
       0000000000000000000000000000000000000000000000000000000000000002  // number of items in exchangePoolOrPaths[*][]
       0000000000000000000000000000000000000000000000000000000000000040  // offset of array at exchangePoolOrPaths[0]
       0000000000000000000000000000000000000000000000000000000000000080  // offset of array at exchangePoolOrPaths[1]
       0000000000000000000000000000000000000000000000000000000000000001  // number of items in array at exchangePoolOrPaths[0]
       000000000000000000000000b5ffd0a221fc94de9255382e70ce1aec76b68c89  // value of exchangePoolOrPaths[0][0]
       0000000000000000000000000000000000000000000000000000000000000001  // number of items in array at exchangePoolOrPaths[1]
       0000000000000000000000003b3d4eefdc603b232907a7f3d0ed1eea5c62b5f7  // value of exchangePoolOrPaths[1][0]
       0000000000000000000000000000000000000000000000000000000000000003  // number of items in tokenAddresses[]
       000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2  // value of tokenAddresses[0]
       0000000000000000000000000ae055097c6d159879521c384f1d2123d1f195e6  // value of tokenAddresses[1]
       000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2  // value of tokenAddresses[2]
       0000000000000000000000000000000000000000000000000000000000000002  // number of items in tokenAmountsExpected[]
       0000000000000000000000000000000000000000000000039fe550f187a54000  // value of tokenAmountsExpected[0]
       0000000000000000000000000000000000000000000000004563918244f40000  // value of tokenAmountsExpected[1]

有誰知道這裡可能出現什麼問題?

編輯:

我想我簡化了問題案例。我認為結構內的解碼和動態數組存在問題。

什麼有效:

   struct InputParams
   {
       address[2] exchangeAddresses;
   }

   function execute(uint blockNumber, bytes calldata data, bool admin) external
   {
       InputParams memory params = abi.decode(data, (InputParams));
   }

with calldata:

0xb83775a0
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000060
0000000000000000000000000000000000000000000000000000000000000001
0000000000000000000000000000000000000000000000000000000000000040
000000000000000000000000b5ffd0a221fc94de9255382e70ce1aec76b68c89
0000000000000000000000003b3d4eefdc603b232907a7f3d0ed1eea5c62b5f7

什麼不起作用(在解碼期間恢復):

   struct InputParams
   {
       address[] exchangeAddresses;
   }

   function execute(uint blockNumber, bytes calldata data, bool admin) external
   {
       InputParams memory params = abi.decode(data, (InputParams));
   }

with calldata:

0xb83775a0
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000060
0000000000000000000000000000000000000000000000000000000000000001
0000000000000000000000000000000000000000000000000000000000000080
0000000000000000000000000000000000000000000000000000000000000020
0000000000000000000000000000000000000000000000000000000000000002
000000000000000000000000b5ffd0a221fc94de9255382e70ce1aec76b68c89
0000000000000000000000003b3d4eefdc603b232907a7f3d0ed1eea5c62b5f7

有沒有人有任何想法,或者如果我實際上只是傳遞了不正確的呼叫數據……

問題在這裡解決:https ://github.com/ethereum/solidity/issues/9747#issuecomment-687833241

輸入的呼叫數據不正確

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