Member-only story
Solidity Tutorial: All About Calldata
Understanding the “data” field of an Ethereum transaction in Solidity

This is Part III of the “All About Data Locations” sub-series.
Today, we will learn the specificities of the calldata
and why you should privilege it over other data locations like memory
. We will use the code examples from the Gnosis safe contract to understand the three EVM opcodes related to calldata
.
Table of ContentsIntroduction
Layout of calldata
Basics of calldata
Accessing calldata in Solidity
Calldata opcodes With Assembly
Creating calldata for Low-level Calls
Extracting Bytes Calldata Slices
calldata in Internal Functions
calldata in Constructor
Introduction
If you are familiar with web3.js or ethers.js, you have probably looked at the data
field passed as a parameter to .send({ ... })
or .sendTransaction({ ... })
.
This is the calldata (in short), or “the data sent along a message call” (whether we are referring to a staticcall
, a contract call, or an actual transaction that changes any form of state — blockchain state or contract state, does not matter here).
The calldata is a special data location in the EVM. It refers to the raw hex bytes sent along any message call transaction between two addresses. For the EVM, any data contained in the calldata was given as input by an address (whether an EOA or a smart contract) to perform an external call.
When calling a contract (either from an EOA or another contract), the calldata is the data location containing the initial input parameters (= arguments) of the function being called. This is where the parameters of public
or external
functions are stored.
Looking at other programming languages, the calldata in the EVM are comparable to:
- the dynamic memory in C++ (add reference).
- the heap memory in C# (add reference).
Layout of calldata
Calldata is made of bytes laid out continuously in the same way as memory. This is opposed to the layout of other data locations like storage or stack, which is made of words (32 bytes long).