24

How to encode and decode ABI data?

Can someone show me an example with web3js library?

1
  • Are you talking about decoding the input and output of a call to a contract? Oe the contract itself? If the former, why? web3 will provide you with stub methods that let you call contract methods without having to do this yourself. Apr 26, 2016 at 14:05

7 Answers 7

10

If the question is about abi params, you can take a look at these two web3.js files:

https://github.com/ChainSafe/web3.js/blob/0.20.7/test/coder.encodeParam.js https://github.com/ChainSafe/web3.js/blob/0.20.7/test/coder.decodeParam.js

Although these functions are not a part of public web3.js interface. Mostly because they need a proper refactor.

There is also a command line tool created especially for encoding function calls and retrieving output data.

https://github.com/ethcore/ethabi

2
8

In case you need an online tool to encode parameters to abi format you can use https://abi.hashex.org/. It has functionality to auto parse contract's abi to get function names and parameter types and provides convenient way to enter their values.

Here is an example of using this service enter image description here

3

web3 1.0:

web3.eth.abi.decodeParameter('address', '0000000000000000000000001829d79cce6aa43d13e67216b355e81a7fffb220')

you should receive: 0x1829D79cCE6aA43D13E67216b355E81A7FfFB220

you can also try:

https://github.com/ConsenSys/abi-decoder

https://github.com/ethereumjs/ethereumjs-abi

3

I modified web3 npm library by including the following line

Web3.SolidityCoder = require('./lib/solidity/coder');

after the Web3 object gets created.

In the client side, you can use it with following code.

web3 = require('web3'); // This will import the web3 library.

web3.SolidityCoder.encodeParams([types array], [values array])
web3.SolidityCoder.decodeParams([types array], encodedData)

This of course is a hack and is suitable for quick testing, if this would be a recommended approach, I could push changes to official web3 library. I'll check with them.

Update: There is a getData() method available in web3.js which you can use for this purpose. Here is the link to documentation: https://github.com/ethereum/wiki/wiki/JavaScript-API#contract-methods

2

The easiest way is to use "abi-decoder". I forked the repository and created index.html for easy usage.

You can download and use it from: https://github.com/Muhammad-Altabba/abi-decoder (you can later check it at https://github.com/ConsenSys/abi-decoder once they will accept my pull request)

To download and run using NPM:

npm install abi-decoder
bower install abi-decoder

Then download https://github.com/Muhammad-Altabba/abi-decoder/index.html to the same directory. Then open the file "index.html" in browser.

You will get:

enter image description here

0

If you mean the data for sending a message, a simple way is to encode it like this:

contract = web3.eth.contract(abi).at(cAddr);
payload = contract['transfer'].getData(to, amont);

The payload is just what you want.

0

The solidity language docs has the formal explanation: https://docs.soliditylang.org/en/v0.4.24/abi-spec.html#argument-encoding

The TL;DR is that the first 4 bytes are the function signature. Arguments are split into 32 byte chunks, then this is all concatenated together.

For example, take the function

function bar(bytes3[2]) public pure {}

If we wanted to call baz with the parameters 69 and true, we would pass 68 bytes total, which can be broken down into:

0xcdcd77c0: the Method ID. This is derived as the first 4 bytes of the Keccak hash of the ASCII form of the signature baz(uint32,bool).

0x0000000000000000000000000000000000000000000000000000000000000045: the first parameter, a uint32 value 69 padded to 32 bytes

0x0000000000000000000000000000000000000000000000000000000000000001: the second parameter - boolean true, padded to 32 bytes

In total: 0xcdcd77c000000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000001

For dynamic arguments, you encode them as their location in the calldata blob. For example:

function sam(bytes, bool, uint[]) public pure {}

If we wanted to call sam with the arguments "dave", true and [1,2,3], we would pass 292 bytes total, broken down into:

0xa5643bf2: the Method ID. This is derived from the signature sam(bytes,bool,uint256[]). Note that uint is replaced with its canonical representation uint256.

`0x0000000000000000000000000000000000000000000000000000000000000060: the location of the data part of the first parameter (dynamic type), measured in bytes from the start of the arguments block. In this case, 0x60.

0x0000000000000000000000000000000000000000000000000000000000000001: the second parameter: boolean true.

0x00000000000000000000000000000000000000000000000000000000000000a0: the location of the data part of the third parameter (dynamic type), measured in bytes. In this case, 0xa0.

0x0000000000000000000000000000000000000000000000000000000000000004: the data part of the first argument, it starts with the length of the byte array in elements, in this case, 4. 0x6461766500000000000000000000000000000000000000000000000000000000: the contents of the first argument: the UTF-8 (equal to ASCII in this case) encoding of "dave", padded on the right to 32 bytes.

0x0000000000000000000000000000000000000000000000000000000000000003: the data part of the third argument, it starts with the length of the array in elements, in this case, 3.

0x0000000000000000000000000000000000000000000000000000000000000001: the first entry of the third parameter.

0x0000000000000000000000000000000000000000000000000000000000000002: the second entry of the third parameter.

0x0000000000000000000000000000000000000000000000000000000000000003: the third entry of the third parameter.

In total: 0xa5643bf20000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000464617665000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003

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.