Contract ABI Specification — Solidity 0.8.13 documentation (2024)

Basic Design

The Contract Application Binary Interface (ABI) is the standard way to interact with contracts in the Ethereum ecosystem, bothfrom outside the blockchain and for contract-to-contract interaction. Data is encoded according to its type,as described in this specification. The encoding is not self describing and thus requires a schema in order to decode.

We assume the interface functions of a contract are strongly typed, known at compilation time and static.We assume that all contracts will have the interface definitions of any contracts they call available at compile-time.

This specification does not address contracts whose interface is dynamic or otherwise known only at run-time.

Function Selector

The first four bytes of the call data for a function call specifies the function to be called. It is thefirst (left, high-order in big-endian) four bytes of the Keccak-256 hash of the signature ofthe function. The signature is defined as the canonical expression of the basic prototype without datalocation specifier, i.e.the function name with the parenthesised list of parameter types. Parameter types are split by a singlecomma - no spaces are used.

Note

The return type of a function is not part of this signature. InSolidity’s function overloading return types are not considered.The reason is to keep function call resolution context-independent.The JSON description of the ABI however contains both inputs and outputs.

Argument Encoding

Starting from the fifth byte, the encoded arguments follow. This encoding is also used inother places, e.g. the return values and also event arguments are encoded in the same way,without the four bytes specifying the function.

Types

The following elementary types exist:

  • uint<M>: unsigned integer type of M bits, 0 < M <= 256, M % 8 == 0. e.g. uint32, uint8, uint256.

  • int<M>: two’s complement signed integer type of M bits, 0 < M <= 256, M % 8 == 0.

  • address: equivalent to uint160, except for the assumed interpretation and language typing.For computing the function selector, address is used.

  • uint, int: synonyms for uint256, int256 respectively. For computing the functionselector, uint256 and int256 have to be used.

  • bool: equivalent to uint8 restricted to the values 0 and 1. For computing the function selector, bool is used.

  • fixed<M>x<N>: signed fixed-point decimal number of M bits, 8 <= M <= 256,M % 8 == 0, and 0 < N <= 80, which denotes the value v as v / (10 ** N).

  • ufixed<M>x<N>: unsigned variant of fixed<M>x<N>.

  • fixed, ufixed: synonyms for fixed128x18, ufixed128x18 respectively. Forcomputing the function selector, fixed128x18 and ufixed128x18 have to be used.

  • bytes<M>: binary type of M bytes, 0 < M <= 32.

  • function: an address (20 bytes) followed by a function selector (4 bytes). Encoded identical to bytes24.

The following (fixed-size) array type exists:

  • <type>[M]: a fixed-length array of M elements, M >= 0, of the given type.

    Note

    While this ABI specification can express fixed-length arrays with zero elements, they’re not supported by the compiler.

The following non-fixed-size types exist:

  • bytes: dynamic sized byte sequence.

  • string: dynamic sized unicode string assumed to be UTF-8 encoded.

  • <type>[]: a variable-length array of elements of the given type.

Types can be combined to a tuple by enclosing them inside parentheses, separated by commas:

  • (T1,T2,...,Tn): tuple consisting of the types T1, …, Tn, n >= 0

It is possible to form tuples of tuples, arrays of tuples and so on. It is also possible to form zero-tuples (where n == 0).

Mapping Solidity to ABI types

Solidity supports all the types presented above with the same names with theexception of tuples. On the other hand, some Solidity types are not supportedby the ABI. The following table shows on the left column Solidity types thatare not part of the ABI, and on the right column the ABI types that representthem.

Solidity

ABI

address payable

address

contract

address

enum

uint8

user defined value types

its underlying value type

struct

tuple

Warning

Before version 0.8.0 enums could have more than 256 members and were represented by thesmallest integer type just big enough to hold the value of any member.

Design Criteria for the Encoding

The encoding is designed to have the following properties, which are especially useful if some arguments are nested arrays:

  1. The number of reads necessary to access a value is at most the depth of the valueinside the argument array structure, i.e. four reads are needed to retrieve a_i[k][l][r]. In aprevious version of the ABI, the number of reads scaled linearly with the total number of dynamicparameters in the worst case.

  2. The data of a variable or array element is not interleaved with other data and it isrelocatable, i.e. it only uses relative “addresses”.

Formal Specification of the Encoding

We distinguish static and dynamic types. Static types are encoded in-place and dynamic types areencoded at a separately allocated location after the current block.

Definition: The following types are called “dynamic”:

  • bytes

  • string

  • T[] for any T

  • T[k] for any dynamic T and any k >= 0

  • (T1,...,Tk) if Ti is dynamic for some 1 <= i <= k

All other types are called “static”.

Definition: len(a) is the number of bytes in a binary string a.The type of len(a) is assumed to be uint256.

We define enc, the actual encoding, as a mapping of values of the ABI types to binary strings suchthat len(enc(X)) depends on the value of X if and only if the type of X is dynamic.

Definition: For any ABI value X, we recursively define enc(X), dependingon the type of X being

  • (T1,...,Tk) for k >= 0 and any types T1, …, Tk

    enc(X) = head(X(1)) ... head(X(k)) tail(X(1)) ... tail(X(k))

    where X = (X(1), ..., X(k)) andhead and tail are defined for Ti as follows:

    if Ti is static:

    head(X(i)) = enc(X(i)) and tail(X(i)) = "" (the empty string)

    otherwise, i.e. if Ti is dynamic:

    head(X(i)) = enc(len( head(X(1)) ... head(X(k)) tail(X(1)) ... tail(X(i-1)) ))tail(X(i)) = enc(X(i))

    Note that in the dynamic case, head(X(i)) is well-defined since the lengths ofthe head parts only depend on the types and not the values. The value of head(X(i)) is the offsetof the beginning of tail(X(i)) relative to the start of enc(X).

  • T[k] for any T and k:

    enc(X) = enc((X[0], ..., X[k-1]))

    i.e. it is encoded as if it were a tuple with k elementsof the same type.

  • T[] where X has k elements (k is assumed to be of type uint256):

    enc(X) = enc(k) enc([X[0], ..., X[k-1]])

    i.e. it is encoded as if it were an array of static size k, prefixed withthe number of elements.

  • bytes, of length k (which is assumed to be of type uint256):

    enc(X) = enc(k) pad_right(X), i.e. the number of bytes is encoded as auint256 followed by the actual value of X as a byte sequence, followed bythe minimum number of zero-bytes such that len(enc(X)) is a multiple of 32.

  • string:

    enc(X) = enc(enc_utf8(X)), i.e. X is UTF-8 encoded and this value is interpretedas of bytes type and encoded further. Note that the length used in this subsequentencoding is the number of bytes of the UTF-8 encoded string, not its number of characters.

  • uint<M>: enc(X) is the big-endian encoding of X, padded on the higher-order(left) side with zero-bytes such that the length is 32 bytes.

  • address: as in the uint160 case

  • int<M>: enc(X) is the big-endian two’s complement encoding of X, padded on the higher-order (left) side with 0xff bytes for negative X and with zero-bytes for non-negative X such that the length is 32 bytes.

  • bool: as in the uint8 case, where 1 is used for true and 0 for false

  • fixed<M>x<N>: enc(X) is enc(X * 10**N) where X * 10**N is interpreted as a int256.

  • fixed: as in the fixed128x18 case

  • ufixed<M>x<N>: enc(X) is enc(X * 10**N) where X * 10**N is interpreted as a uint256.

  • ufixed: as in the ufixed128x18 case

  • bytes<M>: enc(X) is the sequence of bytes in X padded with trailing zero-bytes to a length of 32 bytes.

Note that for any X, len(enc(X)) is a multiple of 32.

Function Selector and Argument Encoding

All in all, a call to the function f with parameters a_1, ..., a_n is encoded as

function_selector(f) enc((a_1, ..., a_n))

and the return values v_1, ..., v_k of f are encoded as

enc((v_1, ..., v_k))

i.e. the values are combined into a tuple and encoded.

Examples

Given the contract:

open in Remix

// SPDX-License-Identifier: GPL-3.0pragma solidity >=0.4.16 <0.9.0;contract Foo { function bar(bytes3[2] memory) public pure {} function baz(uint32 x, bool y) public pure returns (bool r) { r = x > 32 || y; } function sam(bytes memory, bool, uint[] memory) public pure {}}

Thus for our Foo example if we wanted to call baz with the parameters 69 andtrue, 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 ofthe ASCII form of the signature baz(uint32,bool).

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

  • 0x0000000000000000000000000000000000000000000000000000000000000001: the second parameter - booleantrue, padded to 32 bytes

In total:

0xcdcd77c000000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000001

It returns a single bool. If, for example, it were to return false, its output would bethe single byte array 0x0000000000000000000000000000000000000000000000000000000000000000, a single bool.

If we wanted to call bar with the argument ["abc", "def"], we would pass 68 bytes total, broken down into:

  • 0xfce353f6: the Method ID. This is derived from the signature bar(bytes3[2]).

  • 0x6162630000000000000000000000000000000000000000000000000000000000: the first part of the firstparameter, a bytes3 value "abc" (left-aligned).

  • 0x6465660000000000000000000000000000000000000000000000000000000000: the second part of the firstparameter, a bytes3 value "def" (left-aligned).

In total:

0xfce353f661626300000000000000000000000000000000000000000000000000000000006465660000000000000000000000000000000000000000000000000000000000

If we wanted to call sam with the arguments "dave", true and [1,2,3], we wouldpass 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

Use of Dynamic Types

A call to a function with the signature f(uint,uint32[],bytes10,bytes) with values(0x123, [0x456, 0x789], "1234567890", "Hello, world!") is encoded in the following way:

We take the first four bytes of sha3("f(uint256,uint32[],bytes10,bytes)"), i.e. 0x8be65246.Then we encode the head parts of all four arguments. For the static types uint256 and bytes10,these are directly the values we want to pass, whereas for the dynamic types uint32[] and bytes,we use the offset in bytes to the start of their data area, measured from the start of the valueencoding (i.e. not counting the first four bytes containing the hash of the function signature). These are:

  • 0x0000000000000000000000000000000000000000000000000000000000000123 (0x123 padded to 32 bytes)

  • 0x0000000000000000000000000000000000000000000000000000000000000080 (offset to start of data part of second parameter, 4*32 bytes, exactly the size of the head part)

  • 0x3132333435363738393000000000000000000000000000000000000000000000 ("1234567890" padded to 32 bytes on the right)

  • 0x00000000000000000000000000000000000000000000000000000000000000e0 (offset to start of data part of fourth parameter = offset to start of data part of first dynamic parameter + size of data part of first dynamic parameter = 4*32 + 3*32 (see below))

After this, the data part of the first dynamic argument, [0x456, 0x789] follows:

  • 0x0000000000000000000000000000000000000000000000000000000000000002 (number of elements of the array, 2)

  • 0x0000000000000000000000000000000000000000000000000000000000000456 (first element)

  • 0x0000000000000000000000000000000000000000000000000000000000000789 (second element)

Finally, we encode the data part of the second dynamic argument, "Hello, world!":

  • 0x000000000000000000000000000000000000000000000000000000000000000d (number of elements (bytes in this case): 13)

  • 0x48656c6c6f2c20776f726c642100000000000000000000000000000000000000 ("Hello, world!" padded to 32 bytes on the right)

All together, the encoding is (newline after function selector and each 32-bytes for clarity):

0x8be65246 0000000000000000000000000000000000000000000000000000000000000123 0000000000000000000000000000000000000000000000000000000000000080 3132333435363738393000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000e0 0000000000000000000000000000000000000000000000000000000000000002 0000000000000000000000000000000000000000000000000000000000000456 0000000000000000000000000000000000000000000000000000000000000789 000000000000000000000000000000000000000000000000000000000000000d 48656c6c6f2c20776f726c642100000000000000000000000000000000000000

Let us apply the same principle to encode the data for a function with a signature g(uint[][],string[])with values ([[1, 2], [3]], ["one", "two", "three"]) but start from the most atomic parts of the encoding:

First we encode the length and data of the first embedded dynamic array [1, 2] of the first root array [[1, 2], [3]]:

  • 0x0000000000000000000000000000000000000000000000000000000000000002 (number of elements in the first array, 2; the elements themselves are 1 and 2)

  • 0x0000000000000000000000000000000000000000000000000000000000000001 (first element)

  • 0x0000000000000000000000000000000000000000000000000000000000000002 (second element)

Then we encode the length and data of the second embedded dynamic array [3] of the first root array [[1, 2], [3]]:

  • 0x0000000000000000000000000000000000000000000000000000000000000001 (number of elements in the second array, 1; the element is 3)

  • 0x0000000000000000000000000000000000000000000000000000000000000003 (first element)

Then we need to find the offsets a and b for their respective dynamic arrays [1, 2] and [3].To calculate the offsets we can take a look at the encoded data of the first root array [[1, 2], [3]]enumerating each line in the encoding:

0 - a - offset of [1, 2]1 - b - offset of [3]2 - 0000000000000000000000000000000000000000000000000000000000000002 - count for [1, 2]3 - 0000000000000000000000000000000000000000000000000000000000000001 - encoding of 14 - 0000000000000000000000000000000000000000000000000000000000000002 - encoding of 25 - 0000000000000000000000000000000000000000000000000000000000000001 - count for [3]6 - 0000000000000000000000000000000000000000000000000000000000000003 - encoding of 3

Offset a points to the start of the content of the array [1, 2] which is line2 (64 bytes); thus a = 0x0000000000000000000000000000000000000000000000000000000000000040.

Offset b points to the start of the content of the array [3] which is line 5 (160 bytes);thus b = 0x00000000000000000000000000000000000000000000000000000000000000a0.

Then we encode the embedded strings of the second root array:

  • 0x0000000000000000000000000000000000000000000000000000000000000003 (number of characters in word "one")

  • 0x6f6e650000000000000000000000000000000000000000000000000000000000 (utf8 representation of word "one")

  • 0x0000000000000000000000000000000000000000000000000000000000000003 (number of characters in word "two")

  • 0x74776f0000000000000000000000000000000000000000000000000000000000 (utf8 representation of word "two")

  • 0x0000000000000000000000000000000000000000000000000000000000000005 (number of characters in word "three")

  • 0x7468726565000000000000000000000000000000000000000000000000000000 (utf8 representation of word "three")

In parallel to the first root array, since strings are dynamic elements we need to find their offsets c, d and e:

0 - c - offset for "one"1 - d - offset for "two"2 - e - offset for "three"3 - 0000000000000000000000000000000000000000000000000000000000000003 - count for "one"4 - 6f6e650000000000000000000000000000000000000000000000000000000000 - encoding of "one"5 - 0000000000000000000000000000000000000000000000000000000000000003 - count for "two"6 - 74776f0000000000000000000000000000000000000000000000000000000000 - encoding of "two"7 - 0000000000000000000000000000000000000000000000000000000000000005 - count for "three"8 - 7468726565000000000000000000000000000000000000000000000000000000 - encoding of "three"

Offset c points to the start of the content of the string "one" which is line 3 (96 bytes);thus c = 0x0000000000000000000000000000000000000000000000000000000000000060.

Offset d points to the start of the content of the string "two" which is line 5 (160 bytes);thus d = 0x00000000000000000000000000000000000000000000000000000000000000a0.

Offset e points to the start of the content of the string "three" which is line 7 (224 bytes);thus e = 0x00000000000000000000000000000000000000000000000000000000000000e0.

Note that the encodings of the embedded elements of the root arrays are not dependent on each otherand have the same encodings for a function with a signature g(string[],uint[][]).

Then we encode the length of the first root array:

  • 0x0000000000000000000000000000000000000000000000000000000000000002 (number of elements in the first root array, 2; the elements themselves are [1, 2] and [3])

Then we encode the length of the second root array:

  • 0x0000000000000000000000000000000000000000000000000000000000000003 (number of strings in the second root array, 3; the strings themselves are "one", "two" and "three")

Finally we find the offsets f and g for their respective root dynamic arrays [[1, 2], [3]] and["one", "two", "three"], and assemble parts in the correct order:

0x2289b18c - function signature 0 - f - offset of [[1, 2], [3]] 1 - g - offset of ["one", "two", "three"] 2 - 0000000000000000000000000000000000000000000000000000000000000002 - count for [[1, 2], [3]] 3 - 0000000000000000000000000000000000000000000000000000000000000040 - offset of [1, 2] 4 - 00000000000000000000000000000000000000000000000000000000000000a0 - offset of [3] 5 - 0000000000000000000000000000000000000000000000000000000000000002 - count for [1, 2] 6 - 0000000000000000000000000000000000000000000000000000000000000001 - encoding of 1 7 - 0000000000000000000000000000000000000000000000000000000000000002 - encoding of 2 8 - 0000000000000000000000000000000000000000000000000000000000000001 - count for [3] 9 - 0000000000000000000000000000000000000000000000000000000000000003 - encoding of 310 - 0000000000000000000000000000000000000000000000000000000000000003 - count for ["one", "two", "three"]11 - 0000000000000000000000000000000000000000000000000000000000000060 - offset for "one"12 - 00000000000000000000000000000000000000000000000000000000000000a0 - offset for "two"13 - 00000000000000000000000000000000000000000000000000000000000000e0 - offset for "three"14 - 0000000000000000000000000000000000000000000000000000000000000003 - count for "one"15 - 6f6e650000000000000000000000000000000000000000000000000000000000 - encoding of "one"16 - 0000000000000000000000000000000000000000000000000000000000000003 - count for "two"17 - 74776f0000000000000000000000000000000000000000000000000000000000 - encoding of "two"18 - 0000000000000000000000000000000000000000000000000000000000000005 - count for "three"19 - 7468726565000000000000000000000000000000000000000000000000000000 - encoding of "three"

Offset f points to the start of the content of the array [[1, 2], [3]] which is line 2 (64 bytes);thus f = 0x0000000000000000000000000000000000000000000000000000000000000040.

Offset g points to the start of the content of the array ["one", "two", "three"] which is line 10 (320 bytes);thus g = 0x0000000000000000000000000000000000000000000000000000000000000140.

Events

Events are an abstraction of the Ethereum logging/event-watching protocol. Log entries provide the contract’saddress, a series of up to four topics and some arbitrary length binary data. Events leverage the existing functionABI in order to interpret this (together with an interface spec) as a properly typed structure.

Given an event name and series of event parameters, we split them into two sub-series: those which are indexed andthose which are not.Those which are indexed, which may number up to 3 (for non-anonymous events) or 4 (for anonymous ones), are usedalongside the Keccak hash of the event signature to form the topics of the log entry.Those which are not indexed form the byte array of the event.

In effect, a log entry using this ABI is described as:

  • address: the address of the contract (intrinsically provided by Ethereum);

  • topics[0]: keccak(EVENT_NAME+"("+EVENT_ARGS.map(canonical_type_of).join(",")+")") (canonical_type_ofis a function that simply returns the canonical type of a given argument, e.g. for uint indexed foo, it wouldreturn uint256). This value is only present in topics[0] if the event is not declared as anonymous;

  • topics[n]: abi_encode(EVENT_INDEXED_ARGS[n - 1]) if the event is not declared as anonymousor abi_encode(EVENT_INDEXED_ARGS[n]) if it is (EVENT_INDEXED_ARGS is the series of EVENT_ARGS thatare indexed);

  • data: ABI encoding of EVENT_NON_INDEXED_ARGS (EVENT_NON_INDEXED_ARGS is the series of EVENT_ARGSthat are not indexed, abi_encode is the ABI encoding function used for returning a series of typed valuesfrom a function, as described above).

For all types of length at most 32 bytes, the EVENT_INDEXED_ARGS array containsthe value directly, padded or sign-extended (for signed integers) to 32 bytes, just as for regular ABI encoding.However, for all “complex” types or types of dynamic length, including all arrays, string, bytes and structs,EVENT_INDEXED_ARGS will contain the Keccak hash of a special in-place encoded value(see Encoding of Indexed Event Parameters), rather than the encoded value directly.This allows applications to efficiently query for values of dynamic-length types(by setting the hash of the encoded value as the topic), but leaves applications unableto decode indexed values they have not queried for. For dynamic-length types,application developers face a trade-off between fast search for predetermined values(if the argument is indexed) and legibility of arbitrary values (which requires thatthe arguments not be indexed). Developers may overcome this tradeoff and achieve bothefficient search and arbitrary legibility by defining events with two arguments — oneindexed, one not — intended to hold the same value.

Errors

In case of a failure inside a contract, the contract can use a special opcode to abort execution and revertall state changes. In addition to these effects, descriptive data can be returned to the caller.This descriptive data is the encoding of an error and its arguments in the same way as data for a functioncall.

As an example, let us consider the following contract whose transfer function alwaysreverts with a custom error of “insufficient balance”:

open in Remix

// SPDX-License-Identifier: GPL-3.0pragma solidity ^0.8.4;contract TestToken { error InsufficientBalance(uint256 available, uint256 required); function transfer(address /*to*/, uint amount) public pure { revert InsufficientBalance(0, amount); }}

The return data would be encoded in the same way as the function callInsufficientBalance(0, amount) to the function InsufficientBalance(uint256,uint256),i.e. 0xcf479181, uint256(0), uint256(amount).

The error selectors 0x00000000 and 0xffffffff are reserved for future use.

Warning

Never trust error data.The error data by default bubbles up through the chain of external calls, whichmeans that a contract may receive an error not defined in any of the contractsit calls directly.Furthermore, any contract can fake any error by returning data that matchesan error signature, even if the error is not defined anywhere.

JSON

The JSON format for a contract’s interface is given by an array of function, event and error descriptions.A function description is a JSON object with the fields:

  • type: "function", "constructor", "receive" (the “receive Ether” function) or "fallback" (the “default” function);

  • name: the name of the function;

  • inputs: an array of objects, each of which contains:

    • name: the name of the parameter.

    • type: the canonical type of the parameter (more below).

    • components: used for tuple types (more below).

  • outputs: an array of objects similar to inputs.

  • stateMutability: a string with one of the following values: pure (specified to not readblockchain state), view (specified to not modify the blockchainstate), nonpayable (function does not accept Ether - the default) and payable (function accepts Ether).

Constructor and fallback function never have name or outputs. Fallback function doesn’t have inputs either.

Note

Sending non-zero Ether to non-payable function will revert the transaction.

Note

The state mutability nonpayable is reflected in Solidity by not specifyinga state mutability modifier at all.

An event description is a JSON object with fairly similar fields:

  • type: always "event"

  • name: the name of the event.

  • inputs: an array of objects, each of which contains:

    • name: the name of the parameter.

    • type: the canonical type of the parameter (more below).

    • components: used for tuple types (more below).

    • indexed: true if the field is part of the log’s topics, false if it one of the log’s data segment.

  • anonymous: true if the event was declared as anonymous.

Errors look as follows:

  • type: always "error"

  • name: the name of the error.

  • inputs: an array of objects, each of which contains:

    • name: the name of the parameter.

    • type: the canonical type of the parameter (more below).

    • components: used for tuple types (more below).

Note

There can be multiple errors with the same name and even with identical signaturein the JSON array, for example if the errors originate from differentfiles in the smart contract or are referenced from another smart contract.For the ABI, only the name of the error itself is relevant and not where it isdefined.

For example,

open in Remix

// SPDX-License-Identifier: GPL-3.0pragma solidity ^0.8.4;contract Test { constructor() { b = hex"12345678901234567890123456789012"; } event Event(uint indexed a, bytes32 b); event Event2(uint indexed a, bytes32 b); error InsufficientBalance(uint256 available, uint256 required); function foo(uint a) public { emit Event(a, b); } bytes32 b;}

would result in the JSON:

[{"type":"error","inputs": [{"name":"available","type":"uint256"},{"name":"required","type":"uint256"}],"name":"InsufficientBalance"}, {"type":"event","inputs": [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"bytes32","indexed":false}],"name":"Event"}, {"type":"event","inputs": [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"bytes32","indexed":false}],"name":"Event2"}, {"type":"function","inputs": [{"name":"a","type":"uint256"}],"name":"foo","outputs": []}]

Handling tuple types

Despite that names are intentionally not part of the ABI encoding they do make a lot of sense to be includedin the JSON to enable displaying it to the end user. The structure is nested in the following way:

An object with members name, type and potentially components describes a typed variable.The canonical type is determined until a tuple type is reached and the string description upto that point is stored in type prefix with the word tuple, i.e. it will be tuple followed bya sequence of [] and [k] withintegers k. The components of the tuple are then stored in the member components,which is of array type and has the same structure as the top-level object except thatindexed is not allowed there.

As an example, the code

open in Remix

// SPDX-License-Identifier: GPL-3.0pragma solidity >=0.7.5 <0.9.0;pragma abicoder v2;contract Test { struct S { uint a; uint[] b; T[] c; } struct T { uint x; uint y; } function f(S memory, T memory, uint) public pure {} function g() public pure returns (S memory, T memory, uint) {}}

would result in the JSON:

[ { "name": "f", "type": "function", "inputs": [ { "name": "s", "type": "tuple", "components": [ { "name": "a", "type": "uint256" }, { "name": "b", "type": "uint256[]" }, { "name": "c", "type": "tuple[]", "components": [ { "name": "x", "type": "uint256" }, { "name": "y", "type": "uint256" } ] } ] }, { "name": "t", "type": "tuple", "components": [ { "name": "x", "type": "uint256" }, { "name": "y", "type": "uint256" } ] }, { "name": "a", "type": "uint256" } ], "outputs": [] }]

Strict Encoding Mode

Strict encoding mode is the mode that leads to exactly the same encoding as defined in the formal specification above.This means offsets have to be as small as possible while still not creating overlaps in the data areas and thus no gaps areallowed.

Usually, ABI decoders are written in a straightforward way just following offset pointers, but some decodersmight enforce strict mode. The Solidity ABI decoder currently does not enforce strict mode, but the encoderalways creates data in strict mode.

Non-standard Packed Mode

Through abi.encodePacked(), Solidity supports a non-standard packed mode where:

  • types shorter than 32 bytes are concatenated directly, without padding or sign extension

  • dynamic types are encoded in-place and without the length.

  • array elements are padded, but still encoded in-place

Furthermore, structs as well as nested arrays are not supported.

As an example, the encoding of int16(-1), bytes1(0x42), uint16(0x03), string("Hello, world!") results in:

0xffff42000348656c6c6f2c20776f726c6421 ^^^^ int16(-1) ^^ bytes1(0x42) ^^^^ uint16(0x03) ^^^^^^^^^^^^^^^^^^^^^^^^^^ string("Hello, world!") without a length field

More specifically:

  • During the encoding, everything is encoded in-place. This means that there isno distinction between head and tail, as in the ABI encoding, and the lengthof an array is not encoded.

  • The direct arguments of abi.encodePacked are encoded without padding,as long as they are not arrays (or string or bytes).

  • The encoding of an array is the concatenation of theencoding of its elements with padding.

  • Dynamically-sized types like string, bytes or uint[] are encodedwithout their length field.

  • The encoding of string or bytes does not apply padding at the endunless it is part of an array or struct (then it is padded to a multiple of32 bytes).

In general, the encoding is ambiguous as soon as there are two dynamically-sized elements,because of the missing length field.

If padding is needed, explicit type conversions can be used: abi.encodePacked(uint16(0x12)) == hex"0012".

Since packed encoding is not used when calling functions, there is no special supportfor prepending a function selector. Since the encoding is ambiguous, there is no decoding function.

Warning

If you use keccak256(abi.encodePacked(a, b)) and both a and b are dynamic types,it is easy to craft collisions in the hash value by moving parts of a into b andvice-versa. More specifically, abi.encodePacked("a", "bc") == abi.encodePacked("ab", "c").If you use abi.encodePacked for signatures, authentication or data integrity, makesure to always use the same types and check that at most one of them is dynamic.Unless there is a compelling reason, abi.encode should be preferred.

Encoding of Indexed Event Parameters

Indexed event parameters that are not value types, i.e. arrays and structs are notstored directly but instead a keccak256-hash of an encoding is stored. This encodingis defined as follows:

  • the encoding of a bytes and string value is just the string contentswithout any padding or length prefix.

  • the encoding of a struct is the concatenation of the encoding of its members,always padded to a multiple of 32 bytes (even bytes and string).

  • the encoding of an array (both dynamically- and statically-sized) isthe concatenation of the encoding of its elements, always padded to a multipleof 32 bytes (even bytes and string) and without any length prefix

In the above, as usual, a negative number is padded by sign extension and not zero padded.bytesNN types are padded on the right while uintNN / intNN are padded on the left.

Warning

The encoding of a struct is ambiguous if it contains more than one dynamically-sizedarray. Because of that, always re-check the event data and do not rely on the search resultbased on the indexed parameters alone.

Contract ABI Specification — Solidity 0.8.13 documentation (2024)

FAQs

How do you calculate ABI Solidity? ›

To do this, you need to go back to the “Solidity Compiler” tab and scroll down. There, you'll see the copy icon and “ABI”: So, just click the above-marked area and you will have your smart contract's ABI in your clipboard.

What is ABI in Solidity contract? ›

The Application Binary Interface (ABI) is an interpreter that facilitates communication with the EVM bytecode. The Solidity ABI is a human-readable list of methods on a smart contract for executing particular functions. You can use the ABI with a library like ethers. js to interact with smart contracts.

What does pragma Solidity 0.8 0 mean? ›

pragma solidity >=0.8. 0 <0.9. 0: This means that the source code is to be compiled with a version of solidity that is greater than or equal to 0.8. 0 but less than 0.9.

How do you find ABI for Ethereum contract? ›

To get the ABI, go to the Remix window and click on the ABI button as shown in the screenshot below. Click Access button to access the contract. You may check the various functions of the contract as in the case of Remix deployment. Note that the contact is now deployed on an external Ganache Blockchain.

How do you manually calculate ABI? ›

Health care providers calculate ABI by dividing the blood pressure in an artery of the ankle by the blood pressure in an artery of the arm. The result is the ABI. If this ratio is less than 0.9, it may mean that a person has peripheral artery disease (PAD) in the blood vessels in his or her legs.

How do you interpret ABI? ›

Interpreting the Ankle Brachial Index
  1. Normal ABI ranges from 1.0 — 1.4. Pressure is normally higher in the ankle than the arm.
  2. Values above 1.4 suggest a noncompressible calcified vessel. ...
  3. An value below 0.9 is considered diagnostic of PAD.
  4. Values less than 0.5 suggests severe PAD.

How do I interact with smart contract with ABI? ›

Interact with deployed smart contracts
  1. Perform a read operation. To perform a read operation, you need the address that the contract was deployed to and the contract's ABI. ...
  2. Perform a write operation. To perform a write operation, send a transaction to update the stored value. ...
  3. Verify an updated value.
Aug 8, 2022

What does an ABI contain? ›

In computer software, an application binary interface (ABI) is an interface between two binary program modules. Often, one of these modules is a library or operating system facility, and the other is a program that is being run by a user.

Why is ABI needed? ›

ABI allows anyone writing a smart contract to be able to communicate between a web application written in a high-level language like Javascript and the bytecode that the EVM understands.

Do we need SafeMath in Solidity 0.8 0? ›

If you have a smart contract in >=0.8. 0, you do not need SafeMath anymore and you can ditch it from your imports.

What is abi coder pragma? ›

ABI Coder Pragma

It is considered non-experimental as of Solidity 0.6. 0 and it is enabled by default starting with Solidity 0.8. 0. The old ABI coder can still be selected using pragma abicoder v1; . The set of types supported by the new encoder is a strict superset of the ones supported by the old one.

Is Solidity low level or high level? ›

Solidity is an object-oriented, high-level language for implementing smart contracts.

How do I verify my smart contract on Ethereum? ›

Click the “Save API key” button. Then, select the contract you want to verify and provide its contract address. Hit “Verify Contract”. That's it, your contract should now be verified on Etherscan.

How do I check my smart contract with ETH? ›

A smart contract can be read by visiting a project's Etherscan (if based on Ethereum) and GitHub page. For the sake of this lesson, we will use Yearn Finance as an example. We found the Etherscan page for Yearn Finance by typing its ticker (YFI) into the search bar.

How do you calculate Ethereum in smart contracts? ›

The best way to view a token's smart contract is through Etherscan, a block explorer and analytics platform built on Ethereum. Block explorers like Etherscan allow users to search and index real-time and historical information about a blockchain.

What does an ABI value of 0.70 indicate? ›

The ABI is calculated as the higher pressure at the ankle divided by the higher of the left and right arm pressures. An ABI ratio above 0.90 is normal, 0.71-0.90 indicates mild obstruction, 0.41-0.70 indicates moderate obstruction, and <0.40 indicates severe obstruction.

What does an ABI value of 1.4 to indicate? ›

A normal ankle-brachial index is between 1.0 and 1.4. Normal. Stiff blood vessels in your limbs may be from advanced age, diabetes or calcification. Borderline.

What is normal ABI values? ›

A normal ABI value is 1.10 to 1.40. This is because among individuals without PAD, lower extremity arterial pressures increase with greater distance from the heart, due to increasing impedance with increasing arterial taper, resulting in higher systolic pressures at the ankle compared with the brachial arteries.

What does ABI of 0.5 mean? ›

On the other hand, an ABI of 0.5 means that only 50% of the blood is reaching the ankles, and 50% is blocked by PAD.

What does ABI of 1.3 mean? ›

INTERPRETATION OF ABI RESULTS

PAD is graded as mild to moderate if the ABI is between 0.4 and 0.9, and an ABI less than 0.40 is suggestive of severe PAD [19]. An ABI value greater than 1.3 is also considered abnormal, suggestive of non-compressible vessels.

What does an ABI of 1.1 mean? ›

A normal resting ankle-brachial index is 1 to 1.1. This means that your blood pressure at your ankle is the same or greater than the pressure at your arm and there is no significant narrowing or blockage of blood flow. The resting ankle-brachial index is abnormal when: The ABI is less than 0.95.

How do you do a smart contract step by step? ›

How to create a smart contract
  1. Step 1: Connect to the Ethereum network. ...
  2. Step 2: Choose a test network. ...
  3. Step 3: Fund your wallet with Testnet ETH. ...
  4. Step 4: Use the Remix browser to write your smart contract. ...
  5. Step 5: Create a . ...
  6. Step 6: Complete your smart contract code. ...
  7. Step 7: Deploy the smart contract.
Jun 15, 2022

How do you structure a smart contract? ›

Create and Deploy your Smart Contract
  1. Step 1: Connect to the Ethereum network. ...
  2. Step 2: Create your app (and API key) ...
  3. Step 3: Create an Ethereum account (address) ...
  4. Step 4: Add ether from a Faucet. ...
  5. Step 5: Check your Balance. ...
  6. Step 6: Initialize our project. ...
  7. Step 7: Download Hardhat. ...
  8. Step 8: Create Hardhat project.

How do I connect my smart contract to UI? ›

  1. Step 1: Clone the starter files. ...
  2. Step 2: Check out the starter files. ...
  3. Step 3: Read from your smart contract. ...
  4. Step 4: Set up your Ethereum wallet. ...
  5. Step 5: Connect Metamask to your UI. ...
  6. Step 6: Implement the updateMessage function. ...
  7. Step 7: Make your own custom dApp 🚀

What is the difference between API and ABI? ›

What is the Difference Between an ABI and an API? An ABI is a low-level interface that defines how two pieces of software communicate with each other, while an API is a higher-level interface that defines how two pieces of software interact with each other.

How do I create an ABI? ›

​ One of the most common ways is to copy the ABI using the ABI button under compile tab of Ethereum REMIX IDE after the smart contract has complied. Another way is compiling and generating ABI using solc, which provides JavaScript bindings for Solidity Compiler.

Do you need ABI to interact with contract? ›

You can also interact with the contracts using various Ethereum libraries; here's an example in Ruby. For that purpose you'll need the ABI(Application Binary Interface) and the smart contract address. The ABI defines the functions and types used in the contract. Learn more in our comprehensive guide on ABI.

What does ABI mean coding? ›

(Application Binary Interface) A specification for a specific hardware platform combined with the operating system. It is one step beyond the application program interface (API), which defines the calls from the application to the operating system.

What is the best IDE for Solidity? ›

The 7 Best Solidity IDEs for Solidity Development (2023)
  • Remix.
  • VScode.
  • EthFiddle.
  • IntelliJ IDEA.
  • Atom.
  • Embark.
  • Yakindu.
Oct 4, 2022

Can you learn Solidity without knowing programming? ›

Solidity is user-friendly for anyone with basic familiarity with other coding languages like Python, C++, and Java. Professionals with experience in programming concepts and coding languages can usually learn Solidity in 1-6 months. If you have no programming experience, it may take longer.

Which language is best for Solidity? ›

Solidity

It is influenced by Java, C ++, and Python and is the best language for smart contracts. Ethereum smart contracts are written in Solidity.

What is ABI in web3? ›

The web3. eth. abi functions let you encode and decode parameters to ABI (Application Binary Interface) for function calls to the EVM (Ethereum Virtual Machine).

What does pragma mean in code? ›

A pragma is a compiler directive that allows you to provide additional information to the compiler. This information can change compilation details that are not otherwise under your control. For example, the pack pragma affects the layout of data within a structure. Compiler pragmas are also called directives.

Is Solidity well paid? ›

In general, Solidity developers with a strong background in software engineering and experience working on blockchain projects are likely to command higher salaries. According to data from Glassdoor, the average salary for a Solidity developer in the United States is around $121,000 per year.

Are Solidity developers in demand? ›

Similar to other tech positions, demand is high, but the number of skilled workers remains low. As of 2022, Solidity is less than a decade old, which is hardly enough time to train the estimated coders the industry needs. Universities and colleges don't even teach Solidity to programmers.

Is it worth to learn Solidity? ›

Is learning Solidity in 2022 worthwhile? YES. The main programming language for building smart contracts on the Ethereum blockchain is Solidity. Crypto, NFT, and Defi enthusiasts should learn this programming language.

Who verifies a smart contract? ›

Moreover, smart contracts do not require a middleman to execute because the code of a smart contract is verified by all the participants in the blockchain network.

How do I verify a Solidity contract? ›

You can verify your contracts using the Dashboard, Tenderly Hardhat plugin, or CLI. When verifying contracts through the Dashboard, you need to import the source file or the metadata file generated by the Solidity compiler, the address/network, and compiler settings.

How are smart contracts verified? ›

Smart Contract verification is the process of matching a Smart Contract's source code to its on-chain bytecode. This involves the recompilation of a Smart Contract to verify that its source code has actually generated the bytecode deployed on-chain.

How much ETH is smart contracts locked? ›

Ethereum continues to get fundamentally stronger in terms of becoming a decentralized financial layer and almost a quarter of the supply is now locked in smart contracts.

How do I verify my smart contract on blockchain? ›

Navigate to the Contract tab at the Explorer page for your contract's address. Click Verify & Publish to enter the smart contract verification page. Libraries can be provided. If they are, they must be deployed, independently verified and in the Add Contract Libraries section.

How do I retrieve data from smart contract? ›

How To Get The Latest Prices From Your Smart Contract
  1. Add a Testnet to your MetaMask wallet. This can be ETH (Kovan or Rinkeby), Binance Smart Chain (Testnet), etc. ...
  2. Find the Data Feed Address For Your Chain and Crypto Pair. ...
  3. Add the code to your Solidity smart contract. ...
  4. Deploy To Metamask and Test.
Apr 20, 2022

How do you calculate gas for a transaction in Ethereum? ›

How Is the Gas Fee Calculated? The gas fee is calculated using Gas Limit * Gas Price per Unit. 1 So if the gas limit was 20,000 and the price per unit was 200 gwei, the calculation would be 20,000 * 200 = 4,000,000 gwei or 0.004 ETH.

What language are smart contracts written in? ›

The first generation of contracts tend to be written in C++ and compiled into WASM, but there are also compilers for other common languages such as Rust, Python, and Solidity.

How do you write a smart contract in Solidity? ›

Your first Smart contract​
  1. // SPDX-License-Identifier: MIT. pragma solidity >=0.4.0 <0.7.0; contract SimpleStorage {
  2. uint storedData; function set(uint x) public { storedData = x;
  3. } function get() public view returns (uint) { return storedData;
Feb 28, 2023

How is ABI nursing calculated? ›

The ABI is calculated as the higher pressure at the ankle divided by the higher of the left and right arm pressures. An ABI ratio above 0.90 is normal, 0.71-0.90 indicates mild obstruction, 0.41-0.70 indicates moderate obstruction, and <0.40 indicates severe obstruction.

How do I get my ABI from contract address Etherscan? ›

The quickest way to get a contracts ABI is via Ether Scan.
  1. Visit Ether Scan.
  2. Input the smart contract address into the search bar at the top of the screen.
  3. Scroll down about half way and select the “Contract” tab.

How do I get my ABI from contract address truffle? ›

The easiest way to get a contract ABI is just to read a JSON file under the ./build/contracts directory. You can get ABI, bytecode and etc. heew after you build a smart contract by using Truffle. For example, when you build a ExampleSmartContract class, ./build/contracts/ExampleSmartcontract.

How do you calculate TBI? ›

The arm and big toe systolic blood pressure measurements are recorded. Then the big toe systolic pressures are divided by the highest arm pressure to establish an TBI measurement for each leg.

What does an ABI of 0.8 mean? ›

If your ABI is 0.9 or lower, you have PAD. You should make an appointment with a vascular medicine specialist. A low ankle-brachial index means you have a higher risk of: Heart attack.

What is normal ABI range? ›

A normal ABI value is 1.10 to 1.40. This is because among individuals without PAD, lower extremity arterial pressures increase with greater distance from the heart, due to increasing impedance with increasing arterial taper, resulting in higher systolic pressures at the ankle compared with the brachial arteries.

How do I get a custom ABI? ›

Once logged in, go to Custom ABIs, and on the right of the dashboard, click Add New. You will be presented with a pop-up window to append a custom ABI to a smart contract. There, enter the Name, Address (Contract Address), and the intended Custom ABI to add to the contract.

What is ABI of a smart contract? ›

The ABI indicates the caller of the function to encode the needed information like function signatures and variable declarations in a format that the EVM can understand to call that function in bytecode; this is called ABI encoding.

How do I retrieve my tokens sent to a contract address? ›

What if I sent tokens to a contract address? Unfortunately, there is no guarantee anyone can retrieve your tokens if you sent them to a contract address. A contract address is not a repository of tokens; it is essentially a computer program, a set of code, that performs some function on the blockchain.

How do you interact with contract truffles? ›

With the help of the truffle console, one can easily interact with the smart contract and get the deployed smart contract address.
  1. Implementation: This example includes using the truffle console to get the deployed smart contract address.
  2. Step 1: Open Vs-code.
  3. Step 2: Create a folder.
  4. Step 3: Install the truffle.
Dec 2, 2022

How do I claim contract tokens? ›

First, deploy a Token Drop contract from the dashboard by clicking on + Deploy new contract . Once deployed, set your claim conditions under the Claim Phases which outline the rules of how tokens can be claimed. Inside the _app.

How do you interact with a contract using Truffle? ›

  1. Install Truffle.
  2. Create a project.
  3. Compile a project.
  4. Integrate with MetaMask.
  5. Work with contracts Work with contracts. Deploy a contract. Interact with contracts.
  6. Use Truffle Dashboard.
  7. Debug and test Debug and test. Use the Truffle debugger. Use Truffle Develop and the Console. Run automated tests. ...
  8. Use NPM package manager.

What does ABI 1.3 mean? ›

A normal ABI reading is 1.0 (with a range of 0.9 to 1.3), which means that your legs are receiving just as much blood flow as your arms. If your blood pressure is lower in the ankle than the arm, a blockage is likely present in an artery somewhere between your heart and ankle - and, if so, you may have PAD.

What is a normal TBI value? ›

The normal range for a TBI is considered to be an index > 0.65. It the TBI is below 0.65 there is reduced blood flow to the small vessels in the big toe.

What is the difference between ABI and TBI? ›

TBIs are injuries to the brain caused by an external force. ABIs are a broader category of brain injuries; they include injuries to the brain caused either by an external force or as a result of stroke or other illness that affects the brain.

Top Articles
Latest Posts
Article information

Author: Ouida Strosin DO

Last Updated:

Views: 6322

Rating: 4.6 / 5 (76 voted)

Reviews: 91% of readers found this page helpful

Author information

Name: Ouida Strosin DO

Birthday: 1995-04-27

Address: Suite 927 930 Kilback Radial, Candidaville, TN 87795

Phone: +8561498978366

Job: Legacy Manufacturing Specialist

Hobby: Singing, Mountain biking, Water sports, Water sports, Taxidermy, Polo, Pet

Introduction: My name is Ouida Strosin DO, I am a precious, combative, spotless, modern, spotless, beautiful, precious person who loves writing and wants to share my knowledge and understanding with you.