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

Padding dynamic bytes

The payload is right-padded while its length remains exact.

LET’S PICTURE IT

A partly filled shipping tray has empty spaces after its contents, but the item count stays unchanged.

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.

Distinguish bytes from bytes3

Dynamic bytes and fixed bytes3 can hold the same three content bytes but have different ABI layouts. Dynamic bytes needs a tuple offset and a length prefix.

Preserve payload order

For 0x123456, the payload starts with 12 34 56. Standard dynamic-byte encoding places zeros after the payload to reach the next word boundary.

Round content size upward

Three content bytes require twenty-nine padding bytes. Thirty-two content bytes require no extra content padding word; thirty-three require sixty-four padded content bytes.

Read using the declared length

The decoder uses the length to separate original data from padding. A zero byte inside the declared payload remains data and must not be trimmed merely because it is zero.

Trace a local example

types: bytes
values: ["0x123400"]
no function selector prefix

word 0 · argument offset 0 bytes
0x0000000000000000000000000000000000000000000000000000000000000020

word 1 · argument offset 32 bytes
0x0000000000000000000000000000000000000000000000000000000000000003

word 2 · argument offset 64 bytes
0x1234000000000000000000000000000000000000000000000000000000000000

Three payload bytes include a real final 00, followed by padding.

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

Does a trailing zero inside the declared byte length remain data?

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.