0xcalldata

Signature-based decoding

How to decode calldata without an ABI

You can often decode Ethereum transaction input without possessing the contract’s full ABI. The first four bytes provide a function-selector clue; candidate signatures provide the types needed to interpret the remaining bytes. The result is useful, but it is not the same as verifying the exact contract ABI.

The short answer

“Without an ABI” really means without the full ABI. Decoding still needs a schema. A selector database can supply one or more function signatures—such as transfer(address,uint256)—and those input types act as a minimal, one-function ABI.

A worked ERC-20 example

Consider this 68-byte payload. Whitespace and labels are not part of the input.

Raw transaction input
a9059cbb                                                        selector
0000000000000000000000002222222222222222222222222222222222222222  word 1
0000000000000000000000000000000000000000000000000de0b6b3a7640000  word 2
  1. 1

    Extract the selector

    The first four bytes are 0xa9059cbb. They identify a set of possible signatures, not the argument values.

  2. 2

    Find candidate signatures

    Bundled ABIs or public signature databases associate this selector with transfer(address,uint256). Its two input types now tell us how to split and interpret the argument block.

  3. 3

    Decode using those types

    The first word becomes address 0x2222…2222. The second becomes the integer 1000000000000000000. Calling it “one token” requires separate knowledge that this token uses 18 decimals.

  4. 4

    Re-encode and compare

    Encode the recovered values with the same candidate signature. If the result matches the original bytes exactly, the interpretation is structurally consistent. That is stronger evidence than decoding alone, but it proves structural consistency—not which contract produced or accepted the call. Another colliding signature can fit too.

Decode this example →

What the bytes can—and cannot—tell you

QuestionFrom calldata aloneAdditional context needed
Which function?Only a 4-byte selector, not a unique functionTarget contract ABI or code to confirm it
What are the values?Decodable if a candidate type layout fitsVerified target ABI or code for confidence
What are parameters called?Names are not encodedA source ABI with parameter names
What does an integer mean?Only its numeric valueToken decimals, units, enums, or protocol rules
Which contract and chain?Neither is includedTransaction or call context
Did the call succeed?Calldata is input, not an execution resultReceipt, return data, revert data, or trace

A reliable ABI-less decoding workflow

Start locally. Normalize the hex, require at least four bytes, extract the selector, and check known ABIs. A bundled or user-supplied ABI provides a richer schema and often preserves parameter names; only contract-specific verification makes it stronger evidence than an anonymous database entry.

Show an exact local match immediately when one exists, then look up the selector in more than one signature database to check for collisions and long-tail signatures. Parse every valid signature, attempt decoding against each candidate, then re-encode the recovered values. Rank exact byte-for-byte round trips above approximate matches, but keep alternative exact interpretations visible.

Finally, add transaction context when accuracy matters: the chain, destination address, verified implementation ABI, and—when the destination is a proxy—the implementation active at that block. These facts can turn a plausible decode into a confirmed one.

How calldata.dev applies this workflow

The decoder checks your saved ABIs and the bundled standards in this browser, and shows an exact local match as soon as it is available. In the background it queries Sourcify and 4byte.directory with the 4-byte selector, never the complete calldata or argument bytes. Candidate signatures are decoded locally and ranked using an exact re-encoding check. To use your own schema, add any JSON ABI, compiler artifact, or human-readable signatures to the local ABI library; its functions then participate in automatic matching. A saved ABI is still a candidate, not proof that it belongs to the destination address.

When two interpretations are both exact

The selector 0x42966c68 is shared by burn(uint256) and collate_propagate_storage(bytes16). The following argument word is valid under both schemas:

A structurally ambiguous 36-byte call
42966c68
11223344556677889900aabbccddeeff00000000000000000000000000000000
  • As burn(uint256), the word is one very large unsigned integer.
  • As collate_propagate_storage(bytes16), it is 0x11223344556677889900aabbccddeeff followed by the required right padding.

Both candidates re-encode to exactly the same bytes. No ranking trick can prove which meaning was intended; the destination contract’s ABI or bytecode must break the tie.

Inspect the ambiguous call →

When you still need a contract-specific ABI

Unknown or private selectors

A selector database cannot return a signature nobody has submitted. The bytes do not contain enough type information to reconstruct an arbitrary schema reliably.

Selector collisions

Multiple signatures can share four bytes, and more than one layout can decode successfully. Only contract-specific evidence resolves the ambiguity.

Names and domain meaning

ABI encoding omits parameter names, token units, enum labels, and business rules. A verified ABI and source code restore that meaning.

Non-call payloads

Constructor arguments, fallback-specific formats, packed data, return values, revert data, and event logs require different context or decoding rules.

Common ABI-less decoding questions

Can the parameter types be inferred directly from 32-byte words?

Not reliably. A zero-padded word may be a number, address, boolean, fixed bytes, or an offset. Dynamic values add structure, but the correct interpretation still depends on the candidate ABI types.

Why does a decoder show several function signatures?

Their selectors collide, and each displayed type layout could decode the payload. Prefer a verified ABI for the target contract; otherwise compare exactness, source, and transaction context rather than trusting the first result.

Can nested calldata be decoded too?

Yes. When an outer ABI identifies a bytes value, calldata.dev offers a nested-decode control beside values that are at least four bytes long. Expanding it repeats the same local-first selector workflow and can recurse through calls such as Safe → Multicall3 → ERC-20. Raw hex always remains visible because the outer ABI does not prove what the inner bytes mean. No inner selector is looked up publicly until you expand that value.

Is it safe to paste sensitive calldata into calldata.dev?

Encoding and decoding run locally. In automatic lookup mode, the selector is the only calldata-derived value sent to the public signature services; no complete calldata or argument bytes are sent. Like any web service, those providers also receive normal request metadata such as your IP address and request origin. Calldata submitted in an on-chain transaction is public by design.