-
Notifications
You must be signed in to change notification settings - Fork 25
ABI Specification
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.
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.
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.
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 ofmethod
(the method name) -
0x050000007b
-INT
token, big-endian serialization of 4-byte integer value123
-
0x01ff
-BYTE
token,-1
encoded as a byte -
0x21000568656c6c6f
-STRING
token, length (5), UTF-8 encoding ofhello