Skip to content

ABI Specification

aion-shidokht edited this page Jul 30, 2019 · 5 revisions

While AVM applications don't need to use the ABI, it is provided as a convenience for invoking methods within a specific DApp instance in a type-safe way.

Note that the higher-level logic to meaningfully interact with the ABI is found in ABIEncoder, ABIDecoder and ABIStreamingEncoder. These are made to be called from inside or outside of a DApp.

Data types

The ABI describes how method names and data types (as either method arguments or return values) are encoded. The ABI supports the following data types (although, if looking at ABIToken, you will realize that they aren't organized this way)

Type Array Dimensions
byte 1, 2
boolean 1, 2
char 1, 2
short 1, 2
int 1, 2
float 1, 2
long 1, 2
double 1, 2
Address 1
String 1
BigInteger* 1

*Note that BigInteger is supported from version 1.

Data encoding scheme

The encoding approach is based on the assumption that all data going through the ABI is a list of any of the supported types. The encoded format is a binary stream, in which each element of the stream is encoded in-order (note that an empty binary stream is equivalent to an empty object list).

Each element of the list starts with a type token (each 1 byte long, see ABIToken for details), followed by a length (only in cases where length matters, encoded as a big-endian short), followed by the data (of either a fixed-size or one influenced by the length, depending on the type token).

There are also 2 special modifier tokens: ARRAY and NULL. ARRAY must come before the type it describes, followed by the array length. NULL must come before the type it describes or an ARRAY (yes, this means that the type of null value is encoded). Note that primitive arrays are handled as their own types, meaning that ARRAY always refers to a reference type (String, Address, or a primitive array). NULL can similarly only be applied to reference types (there is no such thing as a "null" primitive). In the case where a null array is required, NULL must come before ARRAY.

For greater details regarding how this encoding works, the ABIEncoderTest show the physical encoding details of various types.

Regarding the length field included for some types: this refers to the number of elements in the data type, but what those elements are does depend on the type: primitives arrays are the number of primitive elements (stored inline, as a stream of the raw data), reference arrays are the number of elements encoded (stored as a sequence of encoded elements, each with their own type token - as they can be null), and STRING length is the number of bytes required to contain the UTF-8 encoding of the string (number of bytes, not characters).

Method invocations are like any other object list except that the first element must be the name of the method. This is also why null values have type: Method invocations require argument types for correct method binding.

Example

To send the arguments {123, -1, "hello"} of a Java method,

public static void method(int i, byte b, String s)

Encoding this via ABIUtil.encodeMethodArguments("method", 123, (byte)-1, "hello") yields a result of 0x2100066d6574686f64050000007b01ff21000568656c6c6f which breaks down into the following fragments:

  • 0x2100066d6574686f64 - STRING token, length (6), UTF-8 encoding of method (the method name)
  • 0x050000007b - INT token, big-endian serialization of 4-byte integer value 123
  • 0x01ff - BYTE token, -1 encoded as a byte
  • 0x21000568656c6c6f - STRING token, length (5), UTF-8 encoding of hello
Clone this wiki locally