EVM Bytecode Viewer
Decode Ethereum smart contract bytecode into color-coded, annotated opcodes. View stack effects, immediate data, and descriptions.
Opcode Category Guide
PUSH, POP, DUP, SWAP — stack manipulation
ADD, MUL, SUB, DIV — math operations
MLOAD, MSTORE, CALLDATACOPY — memory ops
SLOAD, SSTORE — persistent contract storage
JUMP, JUMPI, RETURN, REVERT — control flow
CALLER, CALLVALUE, KECCAK256 — context
How the EVM Executes Bytecode
The Ethereum Virtual Machine is a stack-based machine. Each opcode operates on a stack of 32-byte (256-bit) values. Opcodes push values onto the stack, pop values from it, or perform operations. The EVM also has memory (volatile byte array), storage (persistent key-value store), and access to call context (sender, value, calldata). The program counter advances through the bytecode, with JUMP and JUMPI enabling branching to JUMPDEST-marked positions.
Opcode Categories Explained
EVM opcodes are grouped by function. Stack opcodes (PUSH, POP, DUP, SWAP) manipulate the stack directly. Arithmetic opcodes (ADD, MUL, SUB, DIV, EXP, MOD) perform math on stack values. Memory opcodes (MLOAD, MSTORE, CALLDATACOPY) read and write volatile memory. Storage opcodes (SLOAD, SSTORE) access persistent contract storage — the most expensive operations. Control flow opcodes (JUMP, JUMPI, RETURN, REVERT) direct execution. Environmental opcodes expose context like CALLER, CALLVALUE, and BLOCKHASH.
Analyzing Unknown Smart Contract Bytecode
When you encounter unknown bytecode, look for common patterns: a PUSH4 followed by EQ and JUMPI near the start is typically the function dispatch table, comparing the 4-byte selector from CALLDATALOAD(0) against known selectors. A sequence of SLOAD or SSTORE indicates state variable access. Multiple REVERT instructions often mark input validation checks. DELEGATECALL combined with SLOAD patterns suggests a proxy contract. The function selector PUSH4 values can be cross-referenced with 4byte.directory to identify function names.
Frequently Asked Questions
What is EVM bytecode?
EVM bytecode is the low-level binary representation of a smart contract deployed on Ethereum. When you compile a Solidity (or Vyper) contract, the compiler outputs bytecode — a sequence of one-byte opcodes and optional immediate data. The EVM interprets this bytecode instruction-by-instruction when a contract is called.
Where can I get a contract's bytecode?
You can get a contract's bytecode from Etherscan by navigating to the contract address and looking at the 'Contract' tab — it shows both the creation bytecode and deployed bytecode. You can also retrieve it with eth_getCode using any JSON-RPC provider, e.g., web3.eth.getCode(address) or cast code <address> with Foundry.
What is the difference between creation and deployed bytecode?
Creation bytecode is the full bytecode sent in a deployment transaction. It includes a constructor that, when executed, returns the deployed bytecode to be stored on-chain. Deployed bytecode (runtime code) is what is actually stored at the contract address and executed on every call. Creation bytecode is typically longer as it includes the constructor logic.
What are PUSH opcodes?
PUSH1 through PUSH32 are a family of opcodes that push N bytes of immediate data (the bytes immediately following the opcode) onto the stack. PUSH1 is the most common — it pushes 1 byte. PUSH32 pushes a full 32-byte (256-bit) value. PUSH0 (EIP-3855, introduced in Shanghai) pushes a zero without any immediate bytes.
Why should I watch out for SELFDESTRUCT?
SELFDESTRUCT (opcode 0xff) deletes the contract from the blockchain and sends its ETH balance to the specified address. In older contracts it was used for upgrades, but it's a destructive and irreversible operation. Its behavior was also changed in EIP-6780 (Cancun), so modern usage should be reviewed carefully.