Skip to main content

Try it Live

Run Opcode examples in the interactive playground

Constructors

Methods for working with EVM opcodes and parsing bytecode.

Opcode Identity

Opcode(value)

Identity function for type branding. Casts number to BrandedOpcode.
import { Opcode } from '@tevm/primitives/Opcode'

const add = Opcode(0x01)      // ADD
const push1 = Opcode(0x60)    // PUSH1
const invalid = Opcode(0xFE)  // INVALID
Parameters:
  • value: number - Opcode byte value (0x00-0xFF)
Returns: BrandedOpcode - Branded opcode Note: This is a zero-cost type branding function. No validation is performed. Use isValid() to check if byte is a valid opcode. Defined in: primitives/Opcode/Opcode.js:85

Opcode Constants

All EVM opcodes exported as pre-branded constants:
import * as Opcode from '@tevm/primitives/Opcode'

// Arithmetic (0x00-0x0B)
Opcode.STOP        // 0x00
Opcode.ADD         // 0x01
Opcode.MUL         // 0x02
Opcode.SUB         // 0x03
Opcode.DIV         // 0x04
Opcode.MOD         // 0x05
Opcode.ADDMOD      // 0x08
Opcode.MULMOD      // 0x09
Opcode.EXP         // 0x0A
Opcode.SIGNEXTEND  // 0x0B

// Comparison (0x10-0x14)
Opcode.LT          // 0x10
Opcode.GT          // 0x11
Opcode.SLT         // 0x12
Opcode.SGT         // 0x13
Opcode.EQ          // 0x14

// Bitwise (0x15-0x1D)
Opcode.ISZERO      // 0x15
Opcode.AND         // 0x16
Opcode.OR          // 0x17
Opcode.XOR         // 0x18
Opcode.NOT         // 0x19
Opcode.BYTE        // 0x1A
Opcode.SHL         // 0x1B
Opcode.SHR         // 0x1C
Opcode.SAR         // 0x1D

// Crypto (0x20)
Opcode.KECCAK256   // 0x20

// Environmental (0x30-0x3F)
Opcode.ADDRESS     // 0x30
Opcode.BALANCE     // 0x31
Opcode.ORIGIN      // 0x32
Opcode.CALLER      // 0x33
Opcode.CALLVALUE   // 0x34
Opcode.CALLDATALOAD   // 0x35
Opcode.CALLDATASIZE   // 0x36
Opcode.CALLDATACOPY   // 0x37
Opcode.CODESIZE       // 0x38
Opcode.CODECOPY       // 0x39
Opcode.GASPRICE       // 0x3A
Opcode.EXTCODESIZE    // 0x3B
Opcode.EXTCODECOPY    // 0x3C
Opcode.RETURNDATASIZE // 0x3D
Opcode.RETURNDATACOPY // 0x3E
Opcode.EXTCODEHASH    // 0x3F

// Block (0x40-0x4A)
Opcode.BLOCKHASH   // 0x40
Opcode.COINBASE    // 0x41
Opcode.TIMESTAMP   // 0x42
Opcode.NUMBER      // 0x43
Opcode.DIFFICULTY  // 0x44
Opcode.GASLIMIT    // 0x45
Opcode.CHAINID     // 0x46
Opcode.SELFBALANCE // 0x47
Opcode.BASEFEE     // 0x48
Opcode.BLOBHASH    // 0x49
Opcode.BLOBBASEFEE // 0x4A

// Stack/Memory/Storage (0x50-0x5F)
Opcode.POP         // 0x50
Opcode.MLOAD       // 0x51
Opcode.MSTORE      // 0x52
Opcode.MSTORE8     // 0x53
Opcode.SLOAD       // 0x54
Opcode.SSTORE      // 0x55
Opcode.JUMP        // 0x56
Opcode.JUMPI       // 0x57
Opcode.PC          // 0x58
Opcode.MSIZE       // 0x59
Opcode.GAS         // 0x5A
Opcode.JUMPDEST    // 0x5B
Opcode.TLOAD       // 0x5C
Opcode.TSTORE      // 0x5D
Opcode.MCOPY       // 0x5E
Opcode.PUSH0       // 0x5F

// PUSH1-PUSH32 (0x60-0x7F)
Opcode.PUSH1       // 0x60
Opcode.PUSH2       // 0x61
// ... PUSH3-PUSH31 ...
Opcode.PUSH32      // 0x7F

// DUP1-DUP16 (0x80-0x8F)
Opcode.DUP1        // 0x80
Opcode.DUP2        // 0x81
// ... DUP3-DUP15 ...
Opcode.DUP16       // 0x8F

// SWAP1-SWAP16 (0x90-0x9F)
Opcode.SWAP1       // 0x90
Opcode.SWAP2       // 0x91
// ... SWAP3-SWAP15 ...
Opcode.SWAP16      // 0x9F

// LOG0-LOG4 (0xA0-0xA4)
Opcode.LOG0        // 0xA0
Opcode.LOG1        // 0xA1
Opcode.LOG2        // 0xA2
Opcode.LOG3        // 0xA3
Opcode.LOG4        // 0xA4

// System (0xF0-0xFF)
Opcode.CREATE      // 0xF0
Opcode.CALL        // 0xF1
Opcode.CALLCODE    // 0xF2
Opcode.RETURN      // 0xF3
Opcode.DELEGATECALL // 0xF4
Opcode.CREATE2     // 0xF5
Opcode.AUTH        // 0xF6 (EIP-3074)
Opcode.AUTHCALL    // 0xF7 (EIP-3074)
Opcode.STATICCALL  // 0xFA
Opcode.REVERT      // 0xFD
Opcode.INVALID     // 0xFE
Opcode.SELFDESTRUCT // 0xFF
Defined in: primitives/Opcode/BrandedOpcode/constants.js

Bytecode Parsing

Opcode.parse(bytecode)

Parse bytecode into array of instructions with offsets and immediates.
import * as Opcode from '@tevm/primitives/Opcode'

const bytecode = new Uint8Array([
  0x60, 0x80,           // PUSH1 0x80
  0x60, 0x40,           // PUSH1 0x40
  0x52,                 // MSTORE
  0x60, 0x04,           // PUSH1 0x04
  0x36,                 // CALLDATASIZE
  0x10,                 // LT
  0x61, 0x00, 0x49,     // PUSH2 0x0049
  0x57,                 // JUMPI
])

const instructions = Opcode.parse(bytecode)
// [
//   { offset: 0, opcode: 0x60, immediate: Uint8Array([0x80]) },
//   { offset: 2, opcode: 0x60, immediate: Uint8Array([0x40]) },
//   { offset: 4, opcode: 0x52 },
//   { offset: 5, opcode: 0x60, immediate: Uint8Array([0x04]) },
//   { offset: 7, opcode: 0x36 },
//   { offset: 8, opcode: 0x10 },
//   { offset: 9, opcode: 0x61, immediate: Uint8Array([0x00, 0x49]) },
//   { offset: 12, opcode: 0x57 }
// ]
Parameters:
  • bytecode: Uint8Array - Raw contract bytecode
Returns: Instruction[] - Array of parsed instructions Instruction type:
type Instruction = {
  offset: number           // Program counter offset
  opcode: BrandedOpcode    // Opcode byte
  immediate?: Uint8Array   // Immediate data for PUSH instructions
}
Behavior:
  • Automatically skips PUSH immediate bytes
  • Handles incomplete PUSH data at end of bytecode
  • Returns instruction with offset, opcode, and optional immediate data
Defined in: primitives/Opcode/BrandedOpcode/parse.js:21

Opcode.pushOpcode(byteCount)

Get PUSH opcode for given byte count.
import * as Opcode from '@tevm/primitives/Opcode'

const push1 = Opcode.pushOpcode(1)   // 0x60 (PUSH1)
const push2 = Opcode.pushOpcode(2)   // 0x61 (PUSH2)
const push32 = Opcode.pushOpcode(32) // 0x7F (PUSH32)
Parameters:
  • byteCount: number - Number of bytes to push (1-32)
Returns: BrandedOpcode - Corresponding PUSH opcode Throws:
  • Error if byteCount < 1 or > 32
Defined in: primitives/Opcode/BrandedOpcode/pushOpcode.js

Jump Destination Analysis

Opcode.jumpDests(bytecode)

Find all valid JUMPDEST positions in bytecode.
import * as Opcode from '@tevm/primitives/Opcode'

const bytecode = new Uint8Array([
  0x60, 0x04,     // PUSH1 0x04
  0x56,           // JUMP
  0x5B,           // JUMPDEST (offset 3)
  0x60, 0x01,     // PUSH1 0x01
  0x60, 0x02,     // PUSH1 0x02
  0x01,           // ADD
  0x00            // STOP
])

const dests = Opcode.jumpDests(bytecode)
// Set([3]) - JUMPDEST at offset 3
Parameters:
  • bytecode: Uint8Array - Contract bytecode
Returns: Set<number> - Set of valid JUMPDEST offsets Behavior:
  • Correctly skips PUSH immediate data
  • Only includes JUMPDEST opcodes (0x5B) not inside PUSH data
  • Returns empty set if no valid JUMPDESTs found
Defined in: primitives/Opcode/BrandedOpcode/jumpDests.js

Common Patterns

Build PUSH Instruction

function buildPush(value: bigint): Uint8Array {
  const hex = value.toString(16).padStart(2, '0')
  const bytes = Hex.toBytes('0x' + hex)

  const byteCount = bytes.length
  const pushOp = Opcode.pushOpcode(byteCount)

  return new Uint8Array([pushOp, ...bytes])
}

// Example: PUSH1 0x42
const instruction = buildPush(0x42n)
// Uint8Array([0x60, 0x42])

Find All PUSH Instructions

function findAllPushes(bytecode: Uint8Array): Instruction[] {
  const instructions = Opcode.parse(bytecode)

  return instructions.filter(inst =>
    Opcode.isPush(inst.opcode)
  )
}

Validate Jump Targets

function validateJumps(bytecode: Uint8Array): boolean {
  const instructions = Opcode.parse(bytecode)
  const validDests = Opcode.jumpDests(bytecode)

  for (const inst of instructions) {
    // Check JUMP and JUMPI instructions
    if (Opcode.isJump(inst.opcode)) {
      // In real execution, jump target comes from stack
      // This is simplified validation
      // Would need to track stack to get actual target
    }
  }

  return true
}

Extract Constants

function extractConstants(bytecode: Uint8Array): bigint[] {
  const instructions = Opcode.parse(bytecode)
  const constants: bigint[] = []

  for (const inst of instructions) {
    if (inst.immediate && Opcode.isPush(inst.opcode)) {
      const value = BigInt(Hex(inst.immediate))
      constants.push(value)
    }
  }

  return constants
}

See Also