0

I want to understand how to encode the following arrays in Solidity.

Dynamic Arrays

For example, the following:

function getDynamicUintArray() public pure returns (uint[] memory) {
        uint[] memory array = new uint[](3);
        array[0] = 1;
        array[1] = 2;
        array[2] = 3;
        return array;
    }

Following the formal specification in documentation: We will proceed as follows:

enc(array) = enc(len(array)) enc(array[0]) enc(array[1]) enc([array[2])

This would result in the following:

0000000000000000000000000000000000000000000000000000000000000003
0000000000000000000000000000000000000000000000000000000000000001
0000000000000000000000000000000000000000000000000000000000000002
0000000000000000000000000000000000000000000000000000000000000003

The problem is when I do this for a contract I deployed on Rinkeby, and execute the following RPC call:

curl <rinkeby_endpoint> -X POST --data '{"jsonrpc":"2.0", "method":"eth_call", "params":[{"from": "<send_address>", "to": "0xaD2bbEeF0A1FCa287d7a1d6cFa925E8C79cC7aC0", "data": "0x421fc531"}, "latest"], "id":4}'

I get the following result:

{"jsonrpc":"2.0","id":4,"result":"0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003"}

Which has an extra 0000000000000000000000000000000000000000000000000000000000000020 at the beginning. What is exactly that extra ?

Structs Array

Also, when encoding structs. The following example:

struct Foo {
        string id;
        string name;
    }

When I run the following function:

function getMultipleFoo() public pure returns (Foo[] memory) {
        Foo[3] multipleFoo;
        Foo memory _foo = Foo("id", "name");
        multipleFoo[0] = _foo;
        multipleFoo[1] = _foo;
        multipleFoo[2] = _foo;
        return multipleFoo;
    }

I should be receiving something like:

0000000000000000000000000000000000000000000000000000000000000060 == offset of first struct
0000000000000000000000000000000000000000000000000000000000000120 == offset of second struct
00000000000000000000000000000000000000000000000000000000000001e0 == offset of third struct

0000000000000000000000000000000000000000000000000000000000000040 == offset of first struct string
0000000000000000000000000000000000000000000000000000000000000080 == offset of second struct string
0000000000000000000000000000000000000000000000000000000000000002 == first string length
6964000000000000000000000000000000000000000000000000000000000000 == "id" hex representation
0000000000000000000000000000000000000000000000000000000000000004 == second string length
6e616d6500000000000000000000000000000000000000000000000000000000 == "name" hex representation

0000000000000000000000000000000000000000000000000000000000000040 == offset of first struct string
0000000000000000000000000000000000000000000000000000000000000080 == offset of second struct string
0000000000000000000000000000000000000000000000000000000000000002 == first string length
6964000000000000000000000000000000000000000000000000000000000000 == "id" hex representation
0000000000000000000000000000000000000000000000000000000000000004 == second string length
6e616d6500000000000000000000000000000000000000000000000000000000 == "name" hex representation

0000000000000000000000000000000000000000000000000000000000000040 == offset of first struct string
0000000000000000000000000000000000000000000000000000000000000080 == offset of second struct string
0000000000000000000000000000000000000000000000000000000000000002 == first string length
6964000000000000000000000000000000000000000000000000000000000000 == "id" hex representation
0000000000000000000000000000000000000000000000000000000000000004 == second string length
6e616d6500000000000000000000000000000000000000000000000000000000 == "name" hex representation

However, when I get the return value of that function call, I get an extra 0000000000000000000000000000000000000000000000000000000000000020 at the beginning like in the first case.

1

If you pass as a parameter or receive from a function a value of non-canonical type, such as a string or an array, then the offset of its description is passed in the position of the corresponding parameter or return value.

Accordingly, for two bytse32 arrays it will be (array1[2], array2[3]):

000 0000000000000000000000000000000000000000000000000000000000000040
020 00000000000000000000000000000000000000000000000000000000000000a0

040 0000000000000000000000000000000000000000000000000000000000000002
060 0000000000000000000000000000000000000000000000000000000000000101
080 0000000000000000000000000000000000000000000000000000000000000102

0a0 0000000000000000000000000000000000000000000000000000000000000003
0c0 0000000000000000000000000000000000000000000000000000000000000201
0e0 0000000000000000000000000000000000000000000000000000000000000202
100 0000000000000000000000000000000000000000000000000000000000000203

Unfortunately, I can no longer find the documents where this was described, so attaching a link to my instructions for working with the ROC API (it is a translation of my article on habr.com) https://github.com/oldmadjackal/Crowd/blob/master/Doc/Wiki/Habr-Ethereum-RPC_API.docx

5
  • Thank you for your answer. But I am not sure of two things: - is this specified somewhere in the documentation ? - Why are we encoding the length of the array at 040 and 0a0 positions? These are static sized arrays I think ? – rachid chami Dec 27 '20 at 9:23
  • Sorry, I was wrong - the offsets will be 0x40 (not 0x20) and 0xa0. Fixed. – Mad Jackal Dec 27 '20 at 10:32
  • and this is always the behaviour ? We always set in the first 32bytes the place of the first element ? Even if it is a static array containing static datatype like uint in the example ? – rachid chami Dec 27 '20 at 11:32
  • Could you please refer me to where this is specified ? – rachid chami Dec 27 '20 at 11:33
  • Unfortunately, I can no longer find the documents where this was described, so attaching a link to my instructions for working with the ROC API (it is a translation of my article on habr.com) github.com/oldmadjackal/Crowd/blob/master/Doc/Wiki/… – Mad Jackal Dec 28 '20 at 6:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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