0

I have a function in my Solidity contract whose prototype is:

function checkLastCustomerInvoices() public view returns (bytes32 [] memory)

When I call it from the Truffle console it returns an array of elements, namely :

truffle(development)> myContractInstance.checkLastCustomerInvoices(); [ '0x0000000000000000000000000000000000000000000000000000657567656f74', '0x0000000000000000000000000000000000000000000000000000656e61756c74', '0x0000000000000000000000000000000000000000000000000065726365646573' ]

When I call it from the browser with JSON-RPC, with the JavaScript code :

function checkLastCustomerInvoices()
{
    myContractInstance.checkLastCustomerInvoices(function(err,res){
           if (err)
                   console.log(err);
                else
                     {  
                        console.log(res);
                     }
       }
     );
    return false;
}

It returns in my browser's console:

function checkLastCustomerInvoices()
Array [ "0x0000000000000000000000000000000000000000000000000000000000000020" ]
{"id":1,"jsonrpc":"2.0","result":"0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000657567656f740000000000000000000000000000000000000000000000000000656e61756c740000000000000000000000000000000000000000000000000065726365646573"}

So the result returned by JSON-RPC seems to be a string that concatenates in some way :

0x
0000000000000000000000000000000000000000000000000000000000000020
0000000000000000000000000000000000000000000000000000000000000003
0000000000000000000000000000000000000000000000000000657567656f74
0000000000000000000000000000000000000000000000000000656e61756c74
0000000000000000000000000000000000000000000000000065726365646573

Besides the 0x, The first line is 32 (what use ?) The second line the number of elements and the 3 other lines my array elements.

Where is described this encoding ? Is there a standard JavaScript method used to parse this string to a JavaScript array ?

Thanks

1
  • I guess 32 is for bytes32 : size of each array element..
    – humhum
    Jan 30, 2019 at 13:55

2 Answers 2

0

Not sure how to do this from a browser, but from a (client-side) node script, you can do:

const web3_eth_abi = require("web3-eth-abi");
const array = web3_eth_abi.decodeParameter("uint256[]", yourReturnedObject.result);
6
  • Thanks, this could be a trail, but I'm looking for a solution in JSON-RPC and don't know if I can use web3.js on on remote ethereum client side. The documentation (github.com/ethereum/wiki/wiki/JSON-RPC#returns-24) states that any call is returned as string of DATA without any further information on its formatting. So I guess there must be some hidden documentation somewhere, but I'm unable to fin it...
    – humhum
    Jan 30, 2019 at 13:42
  • @humhum: Yes, but you can take that string and convert it into an object via obj = JSON.parse(str). Jan 30, 2019 at 14:12
  • Don't get it : obj=JSON.parse(str) will make an object from a string containing JSON syntax. It won't in any case create an object from 'result' whose formatting comes from JSON-RPC …
    – humhum
    Jan 30, 2019 at 15:18
  • @humhum: It should create a JSON object with a result field. Jan 30, 2019 at 15:21
  • Yes but it doesn't change the problem: the result object field still contains that string: Proof: In the console: (used elipses instead of real characters to shorten the comment..) >>obj=JSON.parse('{"id":1,"jsonrpc":"2.0","result":"0x ......"}'); Object { id: 1, jsonrpc: "2.0", result: "0x..." } >>obj.result "0x...."
    – humhum
    Jan 30, 2019 at 15:44
0

Arrays are encoded with a 32 bytes denoting a position (offset) from the beginning of the data. Then at that offset you will find another 32 bytes showing the length. After that you will have all the array elements.

In your case the first 32 bytes show an offset of 0x20 = 32, then at position 32 we have another 32 bytes showing the length of 1, and then 1 record of 32 bytes encode the actual element.

Find a detailed example below to understand this better.

The following article explains this in more detail: https://medium.com/@hayeah/how-to-decipher-a-smart-contract-method-call-8ee980311603

> encode_abi(
  ["uint256[]", "uint256[]", "uint256[]"],
  [[0xa1, 0xa2, 0xa3], [0xb1, 0xb2, 0xb3], [0xc1, 0xc2, 0xc3]]
).hex()
/************* HEAD (32*3 bytes) *************/
// arg1: look at position 0x60 for array data
0000000000000000000000000000000000000000000000000000000000000060
// arg2: look at position 0xe0 for array data
00000000000000000000000000000000000000000000000000000000000000e0
// arg3: look at position 0x160 for array data
0000000000000000000000000000000000000000000000000000000000000160
/************* TAIL (128**3 bytes) *************/
// position 0x60. Data for arg1.
// Length followed by elements.
0000000000000000000000000000000000000000000000000000000000000003
00000000000000000000000000000000000000000000000000000000000000a1
00000000000000000000000000000000000000000000000000000000000000a2
00000000000000000000000000000000000000000000000000000000000000a3
// position 0xe0. Data for arg2.
0000000000000000000000000000000000000000000000000000000000000003
00000000000000000000000000000000000000000000000000000000000000b1
00000000000000000000000000000000000000000000000000000000000000b2
00000000000000000000000000000000000000000000000000000000000000b3
// position 0x160. Data for arg3.
0000000000000000000000000000000000000000000000000000000000000003
00000000000000000000000000000000000000000000000000000000000000c1
00000000000000000000000000000000000000000000000000000000000000c2
00000000000000000000000000000000000000000000000000000000000000c3

Your Answer

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

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