Solidity ABI
Explanations and correlations of Solidity's ABI compared to AppLayer's pre-compiled approach.
AppLayer is primarily a native, pre-compiled blockchain, which means its main focus is to run without the need for an EVM. However, the vast majority of the smart contract ecosystem operates and depends on Solidity - not only the contracts themselves but also the data they share across each other.
When developing pre-compiled contracts, AppLayer makes use of an abstraction of Solidity's ABI encoding and decoding processes to properly translate between native and non-native data types. The ABI namespace (src/contract/abi.h
) contains several functions for Solidity ABI-related operations, for managing and manipulating data in Solidity format.
This is only an overview, check the Doxygen docs for more details on how those functions work.
Solidity types
The Types enum contains the supported Solidity data types in the ABI. Each value has an intrinsic equivalency with both the Solidity data type and the native C++ data type that it represents.
Replace the X in "uintX" and "intX" with the desired size number. The ABI supports every size from 8 to 256 (inclusive), in multiples of 8 (e.g. 8, 16, 24, 32, 40, 48, ..., until 256) - in other words, x <= 256 && x % 8 == 0
. Enums are encoded as uint8.
intX
intX
intX_t
intXArr
intX[]
std::vector<intX_t>
uintX
uintX
uintX_t
uintXArr
uintX[]
std::vector<uintX_t>
address
address
Address
addressArr
address[]
std::vector
boolean
bool
bool
booleanArr
bool[]
std::vector
bytes
bytes
Bytes
bytesArr
bytes[]
std::vector
string
string
std::string
stringArr
string[]
std::vector<std::string>
enum
enum
uint8_t
MethodDescription and EventDescription
The MethodDescription and EventDescription structs abstract, respectively, the structures for a given Solidity method and Solidity event, such as their name, type, inputs and outputs, state mutability, anonymity and indexations. Those are used extensively by ContractReflectionInterface
and JsonAbi
, to make it easier to pass data around when performing actions like registering the contract and generating ABI for events.
Encoding and decoding
Encoding and decoding ABI data is done by calling the ABI::Encoder::encodeData()
and ABI::Decoder::decodeData()
functions, respectively. The encode function asks for one or more native C++ types, returning a Bytes
object that is the encoded ABI string. The decode function does the inverse, asking for a Bytes
object with the ABI encoded data (and optionally an index for said data) and returning a std::tuple
with the decoded native C++ types.
If encoding a function call, its signature (also called "functor" - the first 4 bytes of keccak(functionSignature)
) can be encoded with ABI::FunctorEncoder::encode()
, passing the function's name and its arguments along the template.
Here's an example:
Last updated