Skip to main content

Overview

EVM instructions are the atomic operations that smart contract bytecode compiles to. Tevm implements all 166 opcodes from the Ethereum Yellow Paper, organized into 11 functional categories. Each instruction operates on a 256-bit word stack with precise gas costs and well-defined semantics. All implementations are zero-copy, tree-shakeable, and tested against official Ethereum test vectors.

Complete Instruction Reference

Arithmetic Operations (0x01-0x0b)

11 opcodes for integer arithmetic with 256-bit overflow semantics:
OpcodeNameGasStack EffectDescription
0x01ADD3a, b → a+bAddition with mod 2^256
0x02MUL5a, b → a*bMultiplication with mod 2^256
0x03SUB3a, b → a-bSubtraction with mod 2^256
0x04DIV5a, b → a/bUnsigned division (0 if b=0)
0x05SDIV5a, b → a/bSigned division
0x06MOD5a, b → a%bUnsigned modulo
0x07SMOD5a, b → a%bSigned modulo
0x08ADDMOD8a, b, N → (a+b)%NAddition modulo N
0x09MULMOD8a, b, N → (a*b)%NMultiplication modulo N
0x0aEXP10+50/bytea, b → a^bExponentiation
0x0bSIGNEXTEND5b, x → ySign extension

Comparison & Logic (0x10-0x15)

6 opcodes for comparison operations returning 0 or 1:
OpcodeNameGasStack EffectDescription
0x10LT3a, b → a < bUnsigned less than
0x11GT3a, b → a > bUnsigned greater than
0x12SLT3a, b → a < bSigned less than
0x13SGT3a, b → a > bSigned greater than
0x14EQ3a, b → a==bEquality
0x15ISZERO3a → a==0Is zero

Bitwise Operations (0x16-0x1d)

8 opcodes for bit manipulation:
OpcodeNameGasStack EffectDescription
0x16AND3a, b → a&bBitwise AND
0x17OR3a, b → a|bBitwise OR
0x18XOR3a, b → a^bBitwise XOR
0x19NOT3a → ~aBitwise NOT
0x1aBYTE3i, x → x[i]Byte at index
0x1bSHL3shift, val → val<<shiftShift left
0x1cSHR3shift, val → val>>shiftLogical shift right
0x1dSAR3shift, val → val>>shiftArithmetic shift right

Keccak (0x20)

1 opcode for cryptographic hashing:
OpcodeNameGasStack EffectDescription
0x20SHA330+6/wordoffset, len → hashKeccak256 hash

Execution Context (0x30-0x3f)

16 opcodes for accessing transaction and account context:
OpcodeNameGasStack EffectDescription
0x30ADDRESS2→ addrCurrent contract address
0x31BALANCE100/2600addr → balanceAccount balance
0x32ORIGIN2→ addrTransaction origin
0x33CALLER2→ addrMessage sender
0x34CALLVALUE2→ valueWei sent with call
0x35CALLDATALOAD3offset → dataLoad 32 bytes from calldata
0x36CALLDATASIZE2→ sizeSize of calldata
0x37CALLDATACOPY3+3/worddestOffset, offset, len →Copy calldata to memory
0x38CODESIZE2→ sizeSize of contract code
0x39CODECOPY3+3/worddestOffset, offset, len →Copy code to memory
0x3aGASPRICE2→ priceTransaction gas price
0x3bEXTCODESIZE100/2600addr → sizeExternal contract code size
0x3cEXTCODECOPY100/2600+3/wordaddr, destOffset, offset, len →Copy external code
0x3dRETURNDATASIZE2→ sizeSize of return data
0x3eRETURNDATACOPY3+3/worddestOffset, offset, len →Copy return data to memory
0x3fEXTCODEHASH100/2600addr → hashExternal contract codehash

Block Information (0x40-0x4a)

11 opcodes for accessing block context:
OpcodeNameGasStack EffectDescription
0x40BLOCKHASH20blockNum → hashBlock hash of recent block
0x41COINBASE2→ addrBlock miner address
0x42TIMESTAMP2→ timestampBlock timestamp
0x43NUMBER2→ blockNumBlock number
0x44DIFFICULTY2→ difficultyBlock difficulty (prevrandao post-merge)
0x45GASLIMIT2→ limitBlock gas limit
0x46CHAINID2→ chainIdChain ID
0x47SELFBALANCE5→ balanceCurrent contract balance
0x48BASEFEE2→ baseFeeBlock base fee (EIP-1559)
0x49BLOBHASH3index → hashBlob versioned hash (EIP-4844)
0x4aBLOBBASEFEE2→ baseFeeBlob base fee (EIP-4844)

Stack Operations (0x50, 0x5f-0x9f)

86 opcodes for stack manipulation: POP (0x50): Remove top item (2 gas) PUSH0-PUSH32 (0x5f-0x7f): Push N-byte value onto stack (3 gas)
  • 0x5f: PUSH0 (Cancun+)
  • 0x60-0x7f: PUSH1 through PUSH32
DUP1-DUP16 (0x80-0x8f): Duplicate Nth stack item (3 gas)
  • 0x80: DUP1 (duplicate 1st item)
  • 0x8f: DUP16 (duplicate 16th item)
SWAP1-SWAP16 (0x90-0x9f): Swap top with Nth item (3 gas)
  • 0x90: SWAP1 (swap with 2nd item)
  • 0x9f: SWAP16 (swap with 17th item)
See Stack Operations for complete reference.

Memory Operations (0x51-0x53, 0x5e)

4 opcodes for volatile memory access:
OpcodeNameGasStack EffectDescription
0x51MLOAD3+expansionoffset → valueLoad 32 bytes from memory
0x52MSTORE3+expansionoffset, value →Store 32 bytes to memory
0x53MSTORE83+expansionoffset, value →Store 1 byte to memory
0x5eMCOPY3+3/word+expansiondestOffset, offset, len →Copy memory (Cancun+)

Storage Operations (0x54-0x55, 0x5c-0x5d)

4 opcodes for persistent and transient storage:
OpcodeNameGasStack EffectDescription
0x54SLOAD100/2100key → valueLoad from persistent storage
0x55SSTORE100-20000key, value →Store to persistent storage
0x5cTLOAD100key → valueLoad from transient storage (Cancun+)
0x5dTSTORE100key, value →Store to transient storage (Cancun+)

Control Flow (0x00, 0x56-0x58, 0x5b, 0xf3, 0xfd)

7 opcodes for program flow control:
OpcodeNameGasStack EffectDescription
0x00STOP0Halt execution
0x56JUMP8dest →Jump to destination
0x57JUMPI10dest, cond →Conditional jump
0x58PC2→ counterProgram counter
0x5bJUMPDEST1Jump destination marker
0xf3RETURN0offset, len →Halt and return data
0xfdREVERT0offset, len →Halt and revert state

Logging (0xa0-0xa4)

5 opcodes for event emission:
OpcodeNameGasStack EffectDescription
0xa0LOG0375+375/topic+8/byteoffset, len →Log with 0 topics
0xa1LOG1375+375/topic+8/byteoffset, len, topic1 →Log with 1 topic
0xa2LOG2375+375/topic+8/byteoffset, len, topic1, topic2 →Log with 2 topics
0xa3LOG3375+375/topic+8/byteoffset, len, topic1, topic2, topic3 →Log with 3 topics
0xa4LOG4375+375/topic+8/byteoffset, len, topic1-4 →Log with 4 topics

System Operations (0xf0-0xf2, 0xf4-0xf5, 0xfa, 0xff)

7 opcodes for contract interaction:
OpcodeNameGasStack EffectDescription
0xf0CREATE32000value, offset, len → addrCreate contract
0xf1CALL100-9000gas, addr, value, argsOffset, argsLen, retOffset, retLen → successCall contract
0xf2CALLCODE100-9000gas, addr, value, argsOffset, argsLen, retOffset, retLen → successCall with current context (deprecated)
0xf4DELEGATECALL100-9000gas, addr, argsOffset, argsLen, retOffset, retLen → successCall preserving sender/value
0xf5CREATE232000value, offset, len, salt → addrCreate with deterministic address
0xfaSTATICCALL100-9000gas, addr, argsOffset, argsLen, retOffset, retLen → successCall without state changes
0xffSELFDESTRUCT5000-30000addr →Destroy contract

Gas Cost Details

Base Costs

All opcodes have minimum gas costs defined in the Yellow Paper:
  • 0 gas: STOP, RETURN (base), REVERT (base)
  • 2 gas: Most context/block info reads
  • 3 gas: Arithmetic, comparison, bitwise, stack ops
  • 5 gas: MUL, DIV, MOD family
  • 8 gas: ADDMOD, MULMOD, JUMP

Dynamic Costs

Several instructions have variable costs:
  • Memory expansion: 3 gas/word + quadratic growth
  • SSTORE: 100-20,000 based on storage slot state
  • EXP: 50 gas per byte of exponent
  • LOG: 375 base + 375/topic + 8/byte
  • CALL/CREATE: 100 base + value transfer + memory + gas forwarding

Access Lists (EIP-2929)

Post-Berlin, storage and account access costs vary:
  • Cold access: First access in transaction (2,600 gas for accounts, 2,100 for storage)
  • Warm access: Subsequent accesses (100 gas)
  • Precompiles: Always warm

Stack Machine Model

Stack Properties

  • Depth: 1024 elements maximum
  • Word size: 256 bits (32 bytes)
  • Access: Only top 16 elements accessible (via DUP/SWAP)
  • Overflow: Pushing to full stack causes exception
  • Underflow: Pop from empty stack causes exception

Stack Notation

a, b → c means:
  1. Pop b from top
  2. Pop a from new top
  3. Push c to stack
Example: ADD pops two values, pushes their sum.

Memory Model

Memory Properties

  • Size: Grows dynamically, starts at 0
  • Expansion: Quadratic cost prevents abuse
  • Volatility: Cleared after transaction
  • Alignment: Byte-addressable, no alignment requirements
  • Zero-initialized: Unwritten memory reads as 0

Memory Gas

memory_cost = memory_size_word * 3 + memory_size_word^2 / 512 Expansion cost is incremental from previous maximum size.

Storage Model

Persistent Storage (SLOAD/SSTORE)

  • Key-value: 256-bit keys and values
  • Initial zero: All slots start at 0
  • Permanence: Survives transactions
  • Gas complexity: SSTORE pricing based on:
    • Cold vs. warm access (EIP-2929)
    • Original value vs. current value (EIP-2200)
    • Zero vs. nonzero transitions

Transient Storage (TLOAD/TSTORE) - Cancun+

  • Ephemeral: Cleared after transaction
  • Fixed cost: 100 gas per operation
  • Use case: Reentrancy guards, temporary state
  • No refunds: Unlike persistent storage

Hardfork Changes

London (EIP-1559)

  • BASEFEE (0x48): Access to block base fee

Shanghai

  • PUSH0 (0x5f): Push constant zero (cheaper than PUSH1)

Cancun (Dencun)

  • MCOPY (0x5e): Efficient memory copying
  • TLOAD (0x5c): Transient storage read
  • TSTORE (0x5d): Transient storage write
  • BLOBHASH (0x49): Access to blob versioned hashes
  • BLOBBASEFEE (0x4a): Blob gas pricing

Prague (upcoming)

Implementation

TypeScript

import * as Instructions from '@tevm/voltaire/evm/instructions';

// Stack operations
const stack = new Stack();
Instructions.Arithmetic.add(stack);  // Performs ADD
Instructions.Stack.push(stack, 42n); // Push value
const result = Instructions.Stack.pop(stack);

// Memory operations
const memory = new Memory();
Instructions.Memory.mstore(memory, 0n, value);
const loaded = Instructions.Memory.mload(memory, 0n);

Zig

const std = @import("std");
const instructions = @import("evm").instructions;

pub fn execute(opcode: u8, ctx: *ExecutionContext) !void {
    switch (opcode) {
        0x01 => try instructions.arithmetic.add(ctx.stack),
        0x02 => try instructions.arithmetic.mul(ctx.stack),
        // ... handle all 166 opcodes
        else => return error.InvalidOpcode,
    }
}

References