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

Understand relative offsets

An offset is useful only when you know its starting point.

LET’S PICTURE IT

A direction saying walk sixty-four steps needs a clearly marked starting line.

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.

Identify the containing tuple

At the top level, offsets are relative to the start of the encoded argument tuple. The beginning of a complete transaction input is a different location when a selector is present.

Convert the display correctly

An offset of hexadecimal 40 means decimal 64 bytes. It does not mean forty bytes, forty words or sixty-four hexadecimal characters. Every byte occupies two hex digits.

Calculate the absolute position

A top-level string offset of 64 points to calldata byte 68 when four selector bytes precede the arguments. The stored offset itself remains 64.

Repeat the reasoning when nested

A nested tuple has its own local base. Label that base before adding the nested offset, rather than measuring every pointer from the outermost transaction input.

Trace a local example

types: bool,string
values: [true,"go"]
no function selector prefix

word 0 · argument offset 0 bytes
0x0000000000000000000000000000000000000000000000000000000000000001

word 1 · argument offset 32 bytes
0x0000000000000000000000000000000000000000000000000000000000000040

word 2 · argument offset 64 bytes
0x0000000000000000000000000000000000000000000000000000000000000002

word 3 · argument offset 96 bytes
0x676f000000000000000000000000000000000000000000000000000000000000

Two head words precede the string length word.

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

What is hex 0x40 as a byte offset?

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.