Ethereum developers use the Solidity programming language to write smart contract code for the Ethereum network. But how does Solidity work and interact with the Ethereum Virtual Machine (EVM)? It all begins with compiling smart contracts.
This article explains:
- What the Solidity ABI is through introducing the necessity of smart contract compilation
- How the ABI works as the Solidity compiler
- What bytecode is and its function in the process of compilation
- What the Solidity ABI is and how it is different from an API.
- How ABIs work (with examples)
What is smart contract compilation?
Smart contract compilation is the process that converts the Solidity smart contract code into a language compatible with the Ethereum Virtual Machine language.
Developers write smart contracts in Solidity, a high-level programming language that is readable and understandable by humans only. The EVM cannot understand Solidity. Since the virtual machine cannot understand Solidity, compilation converts the human-understandable Solidity code into a machine-readable language. The Ethereum ecosystem uses the Solidity compiler to compile its smart contracts.
What is the Solidity Compiler?
The Solidity compiler, also known as solc, compiles Solidity-based smart contracts into EVM understandable bytecode and the Application Binary Interface (ABI). The bytecode and Solidity contract ABI are the primary components for interacting with Ethereum smart contracts.
What is bytecode?
The bytecode is the smart contract information in a binary format on the Ethereum Virtual Machine. The bytecode is not human-readable and can only be read by a machine (EVM). In other words, Solidity gets compiled and translated into machine-readable bytecode so that EVM can carry out the necessary functions.
The bytecode contains a series of machine-understandable instructions called opcodes, each one-byte (eight bits) long. Thus, a bytecode is an amalgamation of one-byte opcodes.
Bytecode is divided into two types:
- Creation bytecode
- Runtime bytecode
What is creation bytecode?
Smart contract compilation generates the creation bytecode, containing the constructor logic and constructor parameters of smart contracts. The creation bytecode is responsible for generating the runtime bytecode.
When you click on ‘compilation details’ for a smart contract on any Integrated Development Environment (IDE) platform, you see the creation bytecode. Creation bytecode is executed only once during deployment.
To retrieve the on-chain creation bytecode, use:
To retrieve the creation bytecode off-chain by JSON RPC call, use this method: getTransactionByHash.
What is runtime bytecode?
The runtime bytecode is the compiled smart contract data that is stored on-chain as the permanent executable code. Unlike creation bytecode, the runtime bytecode does not contain constructor logic and constructor parameters.
To retrieve the on-chain runtime bytecode, use:
To retrieve runtime bytecode off-chain by JSON RPC call, use this method: getCode
How to Interact with Bytecode
What is the Application Binary Interface (ABI) in Solidity?
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.
An ABI in Solidity is similar to, but also different from, an API (Application Program Interface).
What is the difference between the Solidity ABI and an API?
In web2, APIs facilitate the interaction between web applications and centralized servers, and the Solidity ABI provides smart contract data to applications and other contracts. When an application uses an API to request data from a server, the API feeds it, whereas ABIs access smart contract data in binary bytecode format known as Solidity Binaries.
In the next section, we explain what Solidity Binaries are.
What are Solidity Binaries?
Solidity Binaries are a unique data storage infrastructure for smart contracts in the Ethereum ecosystem.
Developers cannot deploy the human-readable Solidity code on the Ethereum blockchain. Instead, the Solidity smart contract data is stored as raw bytecode in binary format (i.e. a long string of hexadecimal characters). This is known as Solidity Binaries, which makes it cost-efficient to store data on the blockchain.
But how does the ABI access Solidity Binaries? It does so by a process called ABI encoding.
What is Solidity ABI encoding?
The ABI calls the smart contract with function signatures and variable declarations that the EVM-based bytecode can understand. This is known as ABI encoding where the ABI encodes the necessary information for the machine-readable bytecode to process. In most cases, ABI encoding is automated and done by smart contract compilers.
What is ABI decoding?
When the EVM-bytecode executes an instruction and returns a result, it is in a raw hexadecimal format, and the ABI decodes the hexadecimal format, which isn't human-readable, into a human-readable language. This is known as ABI decoding.
You get the Solidity code from the ABI, and basically the ABI acts as the interface for encoding/decoding data into and out of the machine code.
How does Solidity code map to EVM opcodes?
EVM bytecode is made up of a number of opcodes. When ABI encoding calls a function, it refers to a particular opcode. After processing the transaction, the opcode returns a result, which the ABI decodes for the user.
How do ABIs work in Solidity?
An ABI specifies which function to invoke (encoding), and executes the function to return data to the user (decoding). A smart contract contains several functions which are deployed on the EVM as bytecode, and each smart contract has its own ABI which is required to get the results.
Since smart contracts are stored in binary format, the ABI defines the structures and methods to interact with the binary contract. Post-compilation smart contract generates an ABI represented in Solidity JSON ABI format.
Certain IDEs like Remix automatically generate the contract ABI. However, you can also manually create the ABI using the Solidity Compiler NPM package.
Solidity JSON ABI generates the following components:
- Type - defines the nature of the function (receive, fallback, constructor)
- Name - defines the name of the function
- Inputs - array of objects with name, type, components
- Outputs - array of objects similar to inputs
- stateMutability - defines the mutability of the function (pure, view, non-payable or payable)
How does a transaction work with an ABI?
A transaction works with a Solidity ABI file in 3 steps:
- The ABI of a smart contract is provided to the frontend library like EtherJS.
- The frontend library translates the method call and arguments into calldata which is provided as part of a transaction to an Ethereum node.
- After a transaction is validated it generates a receipts trie containing the detailed logs and gas (transaction fees) used.
What is a receipts trie?
An Ethereum transaction generates a receipt called ‘receipts trie’ which records the outcome of a successful transaction. A receipts trie consists of four types of information:
- State of the transaction
- Cumulative gas used
- Set of logs created during execution
- Bloom filter composed from the logs
To better understand how a transaction works, consider the following example.
ERC-20 Token Transfer Example
For instance, you want to transfer an ERC-20 token from one wallet to another. The following code instructs the ABI to send a message to the EVM-based bytecode.
ABI encoding ensures that the bytecode recognizes the function and executes the transaction. After generating a result, ABI decoding translates the result into a human-readable format. The user gets a receipt that ERC-20 tokens have been transferred from one address to the other.
Learn More About Solidity's ABI
While learning Solidity, you will understand that ABI is the cornerstone of Ethereum smart contracts. ABIs facilitate transactions in the blockchain ecosystem. Despite the importance of ABIs in smart contract technology, ABIs are often overlooked in developer tutorials. While beyond the scope of this article, knowing what the Solidity interface is will further your understanding of how contracts interact with each other.
An in-depth understanding of ABI is the stepping stone towards developing robust smart contracts and dApps, and becoming a Solidity dev.