Ethereum ABI Encoding Explanation

Solidity is a statically typed language, below you will be able to find a list of the main types (fig1.) and informations about how they are encoded in the ABI. More detailed informations can be found in the solidity documentation. Each of these types could be static or dynamic. As we can read in the ethereum wiki :

“Static types are encoded in-place and dynamic types are encoded at a separately allocated location after the current block.”

Functions are not really a type but we explain how it is encoded because we are considering the ABI encoding (function encoding is needed while calling a function). In the tuple part, we will introduce what we have called an only-static tuple and will explain how this kind of tuple are treated differently while encoding.

Fig1. main types

Uint (static) :

An unsigned integer between 8 and 256 bits long, padded left to 32 bytes while encoding.

Int (static) :

A two’s complement signed integer between 8 and 256 bits long, padded left to 32 bytes while encoding.

Address (static) :

A 20 bytes hexadecimal, encoded like an uint.

Bool (static) :

An uint8 where 0 is used for false and 1 for true.

Bytes<m> (static) :

A binary type of m bytes with 0<m<=32. The byte sequence is encoded as it is and padded right to 32 bytes.

Fig2. The illustrated different static types

Bytes (dynamic) :

A dynamic sized bytes sequence padded on the right if needed. The encoded sequence is prepended with the number of bytes.

String (dynamic) :

A string is encoded in utf-8 and then treated has a bytes type. The number of bytes represents here the number of characters in the string.

Fig3. Bytes and string encoded

Non-fixed size Array (dynamic) :

A non-fixed array is an array with a dynamic number of elements. While encoding, non-fixed array are prefixed by the number of elements they have.

Fixed-size Array (dynamic and static) :

A fixed-size array is an array of m elements with m >=0. Elements of the array are treated like a tuple with only one type. If this type is fixed, the array is like an only-static tuple (see tuple section below).

Examples of array can be found in the examples section.

Tuples (dynamic and static) :

A tuple is a combination of types.

A tuple can contain static or dynamic types, an only-static tuple means that the tuple contains only static elements. Only-static tuple is the different elements padded to 32 bytes and put one after the other, the tail will be empty. An only-static tuple is considered as a static type.

A tuple which contains at least a single dynamic element is encoded in a different way. If the element is dynamic it’s head represents an offset where you can find the encoded element (this is called the tail of the element), if an element is static the head is the encoded element. An offset means the number of bytes between the first head of the tuple and the element.

Fig4. Difference between static and dynamic tuples

Function selector and arguments :

Function selector is represented by hashing the function’s signature with keccak256 and by taking the first 4 bytes of the result. The arguments passed to the function are then treated like a tuple.

Fig5. Illustrated function

Examples :

In fig6. you can see a dynamic array of fixed struct. As you can see the number of element is prefixing the encoding of the elements.

Fig6. Dynamic array of fixed struct

In fig7. You can see a dynamic array of dynamic struct, this can be for example a list of differents assets for a shop.

Fig7. Array of Dynamic struct

In fig8. you can see a tuple containing the two arrays of fig5. and fig6. This can be for example a function which is returning (array1, array2).

Fig8. Tuple of arrays

And finally, an example of commented bytecode. This is an asset for the game : Beyond The Void.

Fig9. Commented bytecode of struct asset