0xcalldata

Interactive ABI encoding guide

How Ethereum calldata works

Start with a 68-byte ERC-20 transfer, then add dynamic bytes, arrays, tuples, and calldata nested inside calldata. Every example below uses the real encoder: edit a value, then hover the annotated words to see exactly where it is encoded.

Build the bytes yourself

Move through the examples in order or jump to a concept. Valid edits re-encode immediately in your browser; no transaction is sent.

ERC-20Example 1 of 4
transfer(address,uint256)

Selector 0xa9059cbb

Two fixed-size arguments make the byte layout linear: an address word followed by an amount word.

address
uint256
calldata68 bytes
sel0xa9059cbb
transfer(address,uint256)
0x000000000000000000000000002222222222222222222222222222222222222222
to · address =0x22222222…222222
0x200000000000000000000000000000000000000000000000000de0b6b3a7640000
amount · uint256 =1000000000000000000
selector or valueoffset or lengthOpen the current example in the full encoder →

From fixed words to nested calls

Each example adds one ABI rule while keeping the rules from the previous step. The selector comes first in every standard ABI function call shown here; only the argument block grows more structured.

1

Fixed words: ERC-20 transfer

transfer(address,uint256)

Selector 0xa9059cbb

ERC-20 transfer calldata reference

This call is exactly 68 bytes: a 4-byte selector, one 32-byte address word, and one 32-byte integer word. Both inputs have a fixed encoded size, so the head is the entire argument block—there are no offsets or tail.

An address contains 20 bytes and is left-padded with twelve zero bytes to fill its word. The unsigned amount is also left-padded. Its value here is 1000000000000000000 base units, which represents one display token only if the target token uses 18 decimals.

2

One pointer: ERC-1155 transfer

safeTransferFrom(address,address,uint256,uint256,bytes)

Selector 0xf242432a

ERC-1155 safeTransferFrom calldata reference

The first four arguments remain ordinary words. The final bytes data argument is dynamic, so its head word contains 0xa0 instead of the value itself. That offset is 160 bytes—the size of the five-word head—and is measured from the beginning of the argument block, immediately after the selector.

At that destination, the tail stores a 32-byte length word followed by the two data bytes 0x1234, right-padded to a word boundary. The complete example is 228 bytes.

3

Several tails: ERC-1155 batch transfer

safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)

Selector 0x2eb2c2d6

ERC-1155 safeBatchTransferFrom calldata reference

Now three inputs are dynamic: ids, amounts, and data. The head holds three offsets. Each array tail begins with its element count and then stores one word per uint256; the bytes tail uses a byte count and padded content.

For a layout experiment, add an ID and watch its array grow by one word: every tail after it moves 32 bytes. Before using the call, add a matching amount too—ERC-1155 requires ids and amounts to have the same length. Adding both entries grows both tails, so the data tail moves 64 bytes in total.

4

Nested calls: Multicall3 aggregate3

aggregate3((address,bool,bytes)[])

Selector 0x82ad56cb

aggregate3 has one top-level input, but it is a dynamic array of tuples. Because each tuple contains dynamic callData, the array stores an offset for each tuple. Inside each tuple, the target address and failure flag are inline, while another offset points to the length-prefixed bytes.

Those bytes are complete calls of their own. The outer ABI treats them as opaque, but their first four bytes are still function selectors. Because these examples were encoded from known ABIs, we know they correspond to:

This is calldata inside calldata: the outer pointer structure locates each bytes blob, then the inner selector and ABI describe the blob’s own words.

Why decoding needs a schema

ABI encoding is deliberately not self-describing. A 32-byte word does not say whether it represents an address, integer, boolean, or offset, and multiple function signatures can share the same 4-byte selector. A verified ABI for the target implementation on the relevant chain and block gives the contract-specific types and parameter names; selector databases provide candidates when that ABI is unavailable.

This is also different from Solidity’s packed encoding. abi.encodePackedremoves much of the padding and length information, can be ambiguous for multiple dynamic values, and is not the standard format used for external function calls.

Read the formal rules in the Solidity ABI specification.

Common calldata questions

Does calldata always include a function selector?

Standard ABI-encoded function calls do. Constructor arguments and arbitrary fallback payloads follow different rules, while plain ETH receive calls have empty calldata. Return data and event logs are not calldata and use different encodings.

Where are ABI offsets measured from?

An offset is relative to the start of the tuple encoding whose head contains it. For top-level arguments, that tuple begins just after the selector. A dynamic array is a length word followed by a tuple-like element encoding; offsets for dynamic elements are measured from the element area immediately after the length.

Can calldata be decoded without the full ABI?

Often, but not with certainty from the bytes alone. A selector lookup can suggest one or more signatures and their input types. A verified ABI for the target implementation at the relevant block provides the contract-specific interpretation and preserves its parameter names.

Are calldata and transaction input the same thing?

For an Ethereum transaction calling a contract, explorers commonly label the transaction’s data field as input data or calldata. The same ABI-encoded bytes can also be used in an off-chain call or nested inside another function.