Fresh Dispatch Today

ethereum virtual machine opcodes

How Ethereum Virtual Machine Opcodes Work: Everything You Need to Know

June 14, 2026 By Jules Whitfield

Introduction

Ethereum Virtual Machine (EVM) opcodes are the fundamental building blocks of every smart contract on the Ethereum blockchain. Each opcode represents a low-level instruction that the EVM can execute, enabling operations ranging from basic arithmetic to complex state manipulations. Understanding these opcodes is crucial for developers seeking to optimize gas costs, write secure contracts, or audit existing code. This comprehensive roundup covers everything you need to know about EVM opcodes—their categories, execution model, gas costs, and how they turn Solidity code into on-chain execution.

1. What are EVM Opcodes and How Do They Work?

Opcodes are mnemonic symbols representing a specific bytecode instruction. Each opcode is a single byte (256 possible values) that tells the EVM what operation to perform. When a smart contract is deployed, its Solidity source code is compiled into a sequence of these opcodes. The EVM executes them sequentially from a designated program counter, updating its state as it goes.

Key properties of EVM opcodes include:

  • Fixed gas cost per opcode (measured in gas units)
  • Stack-based parameter passing and result storage
  • Deterministic execution across all EVM-compatible blockchains
  • Optimization potential via opcode ordering and selection

For a deeper dive into execution under the Ethereum Virtual Machine, the architecture uses a simple stack model—most opcodes pop inputs from the top of the stack, calculate, and push a result. Exceptions include memory (linear byte array) and storage (persistent 256-bit key-value store) operations.

2. Opcode Categories: Stack, Memory, and Storage

EVM opcodes fall into several categories based on what data they manipulate. Understanding these groups helps developers predict gas consumption:

  • Stack operations (e.g., PUSH, DUP, SWAP, POP) — create, duplicate, or reorder stack values. These are among the cheapest opcodes in gas.
  • Arithmetic and bitwise (e.g., ADD, SUB, MUL, DIV, AND, OR, XOR) — compute simple math or binary logic. Costs increase for more complex operations like EXP or SHL/SHR.
  • Memory manipulation (MLOAD, MSTORE, MSTORE8) — read or write temporary memory. Useful for hash computations and ABI decoding.
  • Storage read/write (SLOAD, SSTORE) — persistent contract state. Writing non-zero to a zero slot is most expensive due to state trie updates.

Mastering these categories allows fine-grained gas optimization—the difference between using a stack variable vs. saving to storage can be 200 times the gas cost.

3. Gas Costs and Execution Model

Every opcode has a predetermined gas cost set in the Ethereum protocol. Gas ensures resources are paid for and limits possible abuse (like infinite loops). Execution proceeds as follows:

The EVM starts at offset 0 of the contract code and fetches one byte per cycle. If the byte represents an invalid opcode (like 0xFE), the transaction reverts. The program counter increments by 1 after most opcodes but can jump forward or backward with JUMP or JUMPI instructions. Valid jump destinations must be marked with JUMPDEST opcodes—this is why older Solidity versions inserted extra JUMPDEST blocks for optimization.

List of gas parameters that affect opcode execution:

  • CostJumpDest: 1 gas for JUMPDEST
  • CostSstoreSet: 20,000 gas for writing non-zero to a storage slot
  • CostSloadEip2200: 800 gas for reading a storage slot (since the Berlin fork)
  • CostCall: 700 gas minimum for a call to another contract
  • CostMemoryExpansion: quadratic fee for allocating dynamic memory

Advanced developers can leverage gas refunds (e.g., clearing storage) when writing contracts that store large volumes of data. The SSTORE refund after the London fork is capped at net gas refunds per transaction.

4. Commonly Used Opcodes Every Developer Should Know

Practical experience shows that 80% of smart contract bytecode uses only about 30 opcodes. Here are the critical ones:

  • PUSH1 through PUSH32: Load a constant (1 to 32 bytes) onto the stack.
  • DUP1 through DUP16: Duplicate the nth value from stack top (DUP1 = duplicate top).
  • ADD, SUB, MUL, DIV: Basic math. All operate on unsigned 256-bit integers.
  • EQ, LT, GT: Comparison operators returning 1 for true, 0 otherwise.
  • ISZERO: Returns 1 if the top value is zero.
  • AND, OR, XOR: Bitwise operations used in masking and flags.
  • MSTORE, MLOAD: Write/read from memory (30 gas + memory expansion cost).
  • SSTORE, SLOAD: Persistent storage (20k/800 gas). Write accesses the state DB.
  • CALL: External contract invocation—pops gas budget, address, value, input data offset/size.
  • JUMP, JUMPI, JUMPDEST: Unconditional / conditional branching inside the contract.
  • RETURN, REVERT: Exit functions returning data or error message (used in safe transfers).
  • SELFDESTRUCT: Deletes contract and sends balance to a target address (deprecated).

Binary analysis with tools like evm-codes or evm-disassembler reveals patterns in these opcodes that can be exploited for gas-golfing—writing optimised Solidity that compiles to fewer opcode steps. For deeper learning, Monte Carlo Simulations for weekly breakdowns of real-world DeFi contract bytecode analysis and opcode hacks.

5. Debugging and Inspecting Opcode Execution

Multiple layers of tools help explore opcode internals:

  • Remix debugger: Step through Solidity's bytecode opcode by opcode, showing stack & memory state.
  • Hardhat and Truffle debug logs: Show VM execution traces with opcode mnemonics.
  • Etherscan VM trace: For verified or non-verified contracts, you can view the raw bytecode and decoded opcode sequence on any transaction.
  • OpenEthereum's evm binary: Allows offline manual opcode simulation and testing.
  • Foundry's cast and anvil: Fast local test network that prints full opcode traces for debug runs.

Common debugging scenarios:

  • "Out of gas" transaction: Verify loops do not run unbounded or accidentally revert due to improper JUMPDEST placement.
  • Unexpected reentrancy: Check CALL opcode sequence—does the storage update happen before or after external call?
  • Gas optimization issue: Replace CALL with DELEGATECALL returning no value, or compress memory expansion sizes.

Ethereum client versions (e.g., Geth, Nethermind—also known as Erigon after the merge) implement the same opcode semantics bit-for-bit. Understanding opcodes first-hand helps detect logic in unverified bytecode or when auditing for backdoors.

Conclusion

EVM opcodes are the atomic operations powering smart contract logic. From pushing constants to calling external contracts, each opcode defines how a blockchain transaction mutates global state. By understanding opcode categories (stack, memory, storage), gas costs, and execution sequence, developers can write tighter, safer, and more efficient contracts. Start practicing by opening a local forked node with npx hardhat node and tracking opcode traces of a simple transfer smart contract. The more you inspect bytecode, the more you internalize gas savings and security best practices.

For regular updates on Ethereum at the opcode level and beyond, remember to Zkrollup Recursive Verification.

References

J
Jules Whitfield

Updates for the curious