1

I have a function with a parameter of bytes calldata that needs to be decoded to a struct, but the call reverts in assembly. I believe the issue has something to do with the nested array. I have used a similiar technique with only a 1-dimensional array and it seems to work OK.

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
}

Inspecting the raw input to transacting with this function does not provide much info. I parsed out below the separate parameters and they seem to be encoded OK:

        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]

Does anyone have any idea what the problem could be here?

Edit:

I think I simplified the problem case. I think there's an issue with decode and dynamic arrays inside structs.

What works:

    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

What does not work (reverts during decode):

    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

Does anyone have any ideas or if I am actually just passing incorrect calldata...

2
  • How are you actually compiling this, which solidity version are you using, what's the IDE ? i'm getting "browser/soltest.sol:13:55: TypeError: Decoding type struct Test.InputParams memory not supported. InputParams memory params = abi.decode(data, (InputParams)); ^---------^" Sep 7, 2020 at 16:37
  • You can compile it using truffle or remix. You have to have pragma experimental ABIEncoderV2; at the top. Sep 8, 2020 at 17:44

1 Answer 1

0

Issue resolved here: https://github.com/ethereum/solidity/issues/9747#issuecomment-687833241

The input calldata was incorrect

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.