ExplainerSep 30, 20266 min read

Reading revert data like a stack trace

0xe450d38c followed by 192 hex characters is not noise. It is a function call in reverse, and you can decode it in one line.

When a contract reverts it returns bytes. Those bytes use exactly the same ABI encoding as a function call: a 4-byte selector, then 32-byte words for each argument.

The selector

The selector is the first 4 bytes of keccak256 of the error signature. Three are special: 0x08c379a0 is Error(string) from require with a message, 0x4e487b71 is Panic(uint256) from the compiler, and anything else is a custom error.

terminal
$ cast sig "ERC20InsufficientBalance(address,uint256,uint256)"
0xe450d38c

$ cast 4byte 0xe450d38c
ERC20InsufficientBalance(address,uint256,uint256)
0xe450d38cErrorERC20InsufficientBalanceAn OpenZeppelin v5 ERC-20 transfer or burn needed more tokens than the sender holds. The data decodes to (sender, balance, needed); top up the balance or lower the amount, minding decimals.

The arguments

After the selector, each static argument fills one 32-byte word: an address is left-padded with zeros, a uint256 is big-endian. Decode with the same signature you would use for calldata.

decode.ts
import { decodeErrorResult, parseAbi } from "viem";

const abi = parseAbi(["error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed)"]);
const { errorName, args } = decodeErrorResult({ abi, data: revertData });
// errorName: "ERC20InsufficientBalance"
// args: [sender, balance, needed]
Tip

No ABI? Paste the full revert data into the EVM selector lookup. It knows the OpenZeppelin v5 errors and the compiler panic codes.

Panics are numbered

Panic(0x11) is arithmetic overflow, 0x12 division by zero, 0x32 an out-of-bounds array index. Since Solidity 0.8 these replace silent wraparound, so a panic usually means a real logic bug, not a user error.

0x4e487b71CriticalPanic(0x11): arithmetic overflow/underflow0x4e487b71 is Panic(uint256); code 0x11 means checked arithmetic over- or underflowed (Solidity ≥0.8). Usually a subtraction where b > a. Validate inputs and revert with a custom error first.