0

I am writing an implementation of ERC777TokensRecipient. So that means a function

function tokensReceived(address operator, address from, address to, uint256 amount, bytes data, bytes operatorData) external;

The data field contains 14 uint256 variables

0x000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000e

How would I be able to access these variables?

I know I can get them like this:

function tokensReceived(address _operator, address _from, address _to, uint256 _amount, bytes _data, bytes _operatorData) external {
    uint arg1;
    uint arg2;
    uint arg3;
    uint arg4;
    uint arg5;
    uint arg6;
    uint arg7;
    uint arg8;
    uint arg9;
    uint arg10;
    uint arg11;
    uint arg12;
    uint arg13;
    uint arg14;

    bytes memory tmp = _data;
    assembly {
        arg1  := mload(add(0x020, tmp))
        arg2  := mload(add(0x040, tmp))
        arg3  := mload(add(0x060, tmp))
        arg4  := mload(add(0x080, tmp))
        arg5  := mload(add(0x0A0, tmp))
        arg6  := mload(add(0x0C0, tmp))
        arg7  := mload(add(0x0E0, tmp))
        arg8  := mload(add(0x100, tmp))
        arg9  := mload(add(0x120, tmp))
        arg10 := mload(add(0x140, tmp))
        arg11 := mload(add(0x160, tmp))
        arg12 := mload(add(0x180, tmp))
        arg13 := mload(add(0x1A0, tmp))
        arg14 := mload(add(0x1C0, tmp))
    }
}

But I can only get 7 of the 14 variables before I run into a

CompilerError: Stack too deep, try removing local variables.

According to Error while compiling: Stack too deep, the workaround is to put the local uints into an array. But I do not know how to do that.

Does anyone know how I could write a function like this:

function convertToArrayOfLength14(bytes memory data) internal pure returns (uint[]) {
    // TODO
}
Maarten Dhondt
  • 311
  • 3
  • 8

1 Answers1

2

You could do it in a loop like this:

function convertToArrayOfLength14(bytes memory data) public pure returns (uint256[] memory output)
{
    output = new uint256[](14);
    for (uint256 i=32; i<=output.length*32; i+=32)
    {
        assembly { mstore(add(output, i), mload(add(data, i))) }
    }
}
Jesbus
  • 10,478
  • 6
  • 35
  • 62