In this track: Dynamic ABI and nested layouts
advanced · 5 MIN READ

Head and tail encoding

Keep fixed-width heads separate from variable-sized payloads.

LET’S PICTURE IT

An index card points to a longer attachment instead of squeezing the attachment into the card.

SEE IT FOR YOURSELF
Follow a dynamic string from head to tailStep 1 / 4
Follow a dynamic string from head to tailArgument headbyte 0 · offset 32hex word ends in 20String tailstarts at byte 32length + contentPositions are measured from argument byte zero, excluding any selectorOffset destinationargument byte 32read a length wordLength = 5hello is five UTF-8 bytescontent starts at byte 64A length word and an offset word have different jobsContent word · argument byte 6468 65 6c 6c 6f5 payload bytes27 padding bytesBlocks are schematic; their drawn widths do not represent the exact byte ratioHeadoffset: 32argument byte 0Tail lengthlength: 5argument byte 32Tail contenthello + paddingargument byte 6432 + 32 + 32 = 96 bytesWith a four-byte selector, total calldata length is 100 bytes

This example encodes one string parameter with value hello. A dynamic argument uses an offset in its head, even when it is the only argument.

Animated local teaching model. No wallet, RPC or live blockchain data. Some labels and hashes are abbreviated for readability.

Classify the fields first

Consider uint256 and string together. The integer goes directly in the head. The string is dynamic, so its head entry contains an offset to a separate tail.

Measure the whole head

For values 7 and hello, the head occupies two words: sixty-four bytes. The string offset is therefore 64, measured from the start of this argument tuple.

Read the attachment

At byte 64, the tail begins with the string byte length, five. The UTF-8 bytes follow and zeros fill the remainder of their final thirty-two-byte word.

Separate framing from layout

A function selector, when present, sits before this argument tuple. Its four bytes do not get added to the stored offset. The offset still uses the tuple start.

Trace a local example

types: uint256,string
values: ["7","hello"]
no function selector prefix

word 0 · argument offset 0 bytes
0x0000000000000000000000000000000000000000000000000000000000000007

word 1 · argument offset 32 bytes
0x0000000000000000000000000000000000000000000000000000000000000040

word 2 · argument offset 64 bytes
0x0000000000000000000000000000000000000000000000000000000000000005

word 3 · argument offset 96 bytes
0x68656c6c6f000000000000000000000000000000000000000000000000000000

Word zero is 7; word one points to argument byte 64.

TURN UNDERSTANDING INTO PRACTICEOpen the ABI encoder →
QUICK CHECK · NO PRESSURE

Where does the string tail start in this example?

Your progress stays in this browser.
Keep exploring the original referenceSolidity documentation ↗

Original explanations by EtherTools. Examples are educational and source-linked; this site is independent of the Ethereum Foundation. Our approach.