What this tool does
The Calldata Decoder turns a raw 0x transaction input into the function it calls and the arguments it carries. It is built for the moment you are staring at an unlabelled hex blob in a block explorer, a mempool feed, a multisig queue, or a failed transaction, and need to know what it actually does.
Every other calldata decoder in this category makes you bring the ABI. bia.is, solarity.dev’s decoder, and OpenChain’s old ABI tool all start with a text area where you paste the contract’s ABI JSON, and only then will they decode your bytes. That is the hard half of the job, and it is the half they hand back to you: if the contract is unverified, or a proxy, or one of forty deployments of the same protocol with drifting signatures, finding the right ABI is the work.
This tool only needs the contract address. evmquery resolves the ABI server-side, then decodes against it.
Key facts
- Decodes raw calldata from a contract address alone. No ABI JSON to paste, no ABI file to find, no 4byte guesswork.
- The ABI comes from evmquery’s contract resolution: verified source first (Sourcify, Etherscan), then code-reuse matching against known bytecode, IPFS metadata, known interfaces, and signature databases (OpenChain, 4byte, evmole).
- Proxy-aware. Paste an EIP-1967, UUPS, Beacon, EIP-1167, EIP-2535 diamond, Gnosis Safe, or EIP-7702 address and the decoder runs against the implementation’s ABI, not the proxy’s own stub.
- Matching is exact, not probabilistic: the 4-byte function selector is checked against the methods this specific contract exposes, so overloads and same-selector collisions resolve to the right one.
- Covers Ethereum, Base, BNB Smart Chain, and Polygon, with more EVM chains being added.
How to use it
- Paste the contract address the transaction was sent to.
- Pick the chain it is deployed on.
- Paste the raw calldata, the
0x-prefixed input data from the transaction. - Run it and read the decoded function and arguments in the result panel.
The result panel shows the matched function’s canonical signature, its 4-byte selector, the address the method actually executes on, and where its ABI was resolved from. Below that, every argument is listed with its name, its Solidity type, and its decoded value. A raw JSON toggle at the bottom shows the full resolved schema for debugging.
If nothing matches, the tool says so explicitly rather than guessing at a decode.
What is happening under the hood
Calldata has exactly two parts. The first four bytes are the function selector: the leading four bytes of keccak256 over the function’s canonical signature, so transfer(address,uint256) hashes down to 0xa9059cbb. Everything after that is the ABI-encoded argument list, packed into 32-byte words with offsets for the dynamic types.
Decoding the second part is mechanical, and every EVM library does it. The problem is the first part. A selector is a one-way hash of a signature, so you cannot invert 0xa9059cbb back into transfer(address,uint256). You either already know the ABI, or you look the selector up in a signature database and hope the answer applies to your contract. That hope is the failure mode: signature databases are crowd-sourced and full of collisions and near-duplicates, and they know nothing about which overload the contract in front of you actually implements.
This tool resolves the ABI from the address first, then matches. That request is the same one behind the Contract Inspector:
POST /query/describe{ "chain": "evm_ethereum", "schema": { "contracts": { "target": { "address": "0x..." } } }, "include": ["resolution"]}- The response lists every method evmquery could resolve for that address, each with a real ABI fragment:
name,inputs,outputs,stateMutability. - If the address is a proxy, resolution follows the chain first. Each method reports the
executesAtaddress its logic runs on, and diamonds get their facets flattened into one method list. - Each method also reports its
source, so you can see whether a given signature came from verified source or from a signature database, and calibrate how much to trust the decode. - The tool then computes each resolved method’s selector locally, finds the one matching your calldata’s first four bytes, and decodes the remaining bytes against that method’s
inputs.
Because the candidate set is “methods this contract exposes” rather than “every signature anyone ever uploaded”, a match is a real match.
Build this yourself
Two steps: resolve the ABI over REST, then decode locally with whatever ABI library you already use. The examples target USDC on Ethereum and a balanceOf(address) call.
REST (curl)
curl -X POST https://api.evmquery.com/api/v1/query/describe \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "chain": "evm_ethereum", "schema": { "contracts": { "target": { "address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" } } }, "include": ["resolution"] }'Python
import requestsfrom eth_utils import function_abi_to_4byte_selectorfrom eth_abi import decode
CALLDATA = "0x70a0823100000000000000000000000028c6c06298d514db089934071355e5743bf21d60"
resp = requests.post( "https://api.evmquery.com/api/v1/query/describe", headers={"x-api-key": "YOUR_API_KEY"}, json={ "chain": "evm_ethereum", "schema": { "contracts": {"target": {"address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"}}, }, "include": ["resolution"], }, timeout=10,)
methods = resp.json()["contracts"][0]["methods"]selector = bytes.fromhex(CALLDATA[2:10])
match = next( (m for m in methods if function_abi_to_4byte_selector(m["abi"]) == selector), None,)if match is None: raise SystemExit(f"no resolved method with selector 0x{selector.hex()}")
types = [i["type"] for i in match["abi"]["inputs"]]print(match["abi"]["name"], decode(types, bytes.fromhex(CALLDATA[10:])))# balanceOf ('0x28c6c06298d514db089934071355e5743bf21d60',)TypeScript
import { decodeAbiParameters, toFunctionSelector } from "viem";
const CALLDATA = "0x70a0823100000000000000000000000028c6c06298d514db089934071355e5743bf21d60";
const resp = await fetch("https://api.evmquery.com/api/v1/query/describe", { method: "POST", headers: { "x-api-key": process.env.EVMQUERY_API_KEY!, "Content-Type": "application/json", }, body: JSON.stringify({ chain: "evm_ethereum", schema: { contracts: { target: { address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" } }, }, include: ["resolution"], }),});
const { contracts } = await resp.json();const selector = CALLDATA.slice(0, 10);
const match = contracts[0].methods.find( (m) => toFunctionSelector(m.abi) === selector,);if (!match) throw new Error(`no resolved method with selector ${selector}`);
const args = decodeAbiParameters(match.abi.inputs, `0x${CALLDATA.slice(10)}`);console.log(match.abi.name, args);// balanceOf [ '0x28C6c06298d514Db089934071355E5743bf21d60' ]The free tier has no monthly cap. Get a free API key to drop these snippets into your project.
When you would use this
- Reviewing a multisig transaction before you sign it. A Safe queue shows you a target address and a hex blob. Decoding it is the difference between approving a treasury transfer and approving an owner change.
- Debugging a reverting transaction. Confirm the call you built is the call you meant to build, with the arguments you meant to pass, before you go looking for the revert reason.
- Reading an unverified or unfamiliar contract’s traffic. When the explorer shows “Method ID 0x…” and nothing else, resolution from the address often recovers a signature the explorer did not have.
- Auditing what a script or bot actually sent. Feed logged calldata back through the decoder and check it against what the code intended.
- Untangling proxy traffic. Calldata sent to a proxy address decodes against the implementation’s ABI, which is where the function you care about lives.
FAQ
Do I need the contract’s ABI to decode calldata here?
No. That is the difference between this and most calldata decoders. You paste the contract address and evmquery resolves the ABI server-side, from verified source (sourcify, etherscan) where it exists, then from code-reuse matching, metadata-ipfs, known-interface matching, and signature databases (openchain, fourbyte, evmole). The decoder runs against whatever it resolves.
What is a function selector?
The first four bytes of calldata, and the only part of it that says which function is being called. It is the first four bytes of the keccak256 hash of the function’s canonical signature, so transfer(address,uint256) becomes 0xa9059cbb. Everything after those four bytes is the ABI-encoded argument list.
Can I look up a 4byte signature without a contract address?
Not on this page. A standalone 4byte signature lookup tells you what a selector is probably called, but it cannot tell you which overload a specific contract actually exposes, so the arguments it decodes can be wrong. Resolving the ABI from the address first removes that ambiguity, which is why the address field is required.
Why does it say no matching function?
The selector in your calldata does not match any method evmquery resolved for that address. Usually the calldata belongs to a different contract or a different version of the same one, the function is not part of the contract’s public ABI (internal, or removed in an upgrade), or the ABI could not be fully resolved for that address. The Contract Inspector shows the full resolved method list, which tells you which of the three you are looking at.
Does it follow proxies?
Yes. Contract resolution follows EIP-1967, UUPS, Beacon, EIP-1167 minimal proxies, EIP-2535 diamonds, Gnosis Safe, and EIP-7702 delegations, so pasting a proxy address decodes against the implementation’s ABI rather than the proxy’s own near-empty one.
Which chains are supported?
Ethereum, Base, BNB Smart Chain, and Polygon today. More EVM chains are being added on the evmquery backend.
Can I use this from my own application?
Yes. The ABI resolution step is a single POST to the public REST API, and the decoding step is a few lines of viem, ethers, or eth-abi. See the snippets above. The free tier has no monthly cap, and bringing your own API key removes the rate limit applied to this page.
Limits and accuracy
- The decode is only as good as the resolved ABI. Methods resolved from signature databases rather than verified source can carry an imprecise parameter list, and the result panel reports the source for exactly this reason.
- Resolution reflects the contract’s current on-chain state. Calldata from an old transaction sent to a since-upgraded proxy may not match today’s implementation ABI.
- Constructor arguments and raw ETH transfers are not calldata in this sense and will not match anything.
- The demo is rate limited per browser. If you hit the limit, grab a free API key and the limit goes away.
A successful decode tells you what a transaction claims to call, not whether it is safe to sign. Argument values still need reading.
Related
- Contract Inspector: the full resolved method schema for an address, and the place to look when a selector does not match
- Fixing
could not decode result data (value="0x")in Ethers and Viem: the mirror-image problem, when a call’s return data will not decode instead of its input - Proxy Contract Detector: a narrower read on the proxy chain the decoder resolves through
- evmquery for developers: the full integration story