Documentation Index Fetch the complete documentation index at: https://voltaire.tevm.sh/llms.txt
Use this file to discover all available pages before exploring further.
Try it Live Run Opcode examples in the interactive playground
Validation
Methods for validating opcodes and checking opcode categories.
Opcode Validity
Opcode.isValid(opcode)
Check if byte value is a valid EVM opcode.
import * as Opcode from '@tevm/primitives/Opcode'
Opcode . isValid ( 0x00 ) // true (STOP)
Opcode . isValid ( 0x01 ) // true (ADD)
Opcode . isValid ( 0x60 ) // true (PUSH1)
Opcode . isValid ( 0xFF ) // true (SELFDESTRUCT)
// Invalid opcodes
Opcode . isValid ( 0x0C ) // false (undefined)
Opcode . isValid ( 0x0D ) // false (undefined)
Opcode . isValid ( 0x21 ) // false (undefined, between KECCAK256 and ADDRESS)
Opcode . isValid ( 0x4B ) // false (undefined, after BLOBBASEFEE)
Parameters:
opcode: number - Byte value to check (0x00-0xFF)
Returns: boolean - True if valid EVM opcode
Use cases:
Validate bytecode before execution
Filter out undefined opcodes during disassembly
Detect malformed or invalid bytecode
Defined in: primitives/Opcode/BrandedOpcode/isValid.js
Opcode.isValidOpcode(opcode)
Alias for isValid().
const valid = Opcode . isValidOpcode ( 0x60 ) // true
Parameters:
opcode: number - Byte value
Returns: boolean - True if valid opcode
Jump Validation
Opcode.isValidJumpDest(bytecode, offset)
Check if offset is a valid JUMPDEST in bytecode.
import * as Opcode from '@tevm/primitives/Opcode'
const bytecode = new Uint8Array ([
0x60 , 0x04 , // PUSH1 0x04
0x56 , // JUMP
0x5B , // JUMPDEST (offset 3)
0x00 // STOP
])
Opcode . isValidJumpDest ( bytecode , 3 ) // true (valid JUMPDEST)
Opcode . isValidJumpDest ( bytecode , 0 ) // false (PUSH1, not JUMPDEST)
Opcode . isValidJumpDest ( bytecode , 1 ) // false (inside PUSH data)
Opcode . isValidJumpDest ( bytecode , 99 ) // false (out of bounds)
Parameters:
bytecode: Uint8Array - Contract bytecode
offset: number - Program counter offset to check
Returns: boolean - True if offset is valid JUMPDEST
Validation rules:
Offset must be within bytecode bounds
Byte at offset must be JUMPDEST (0x5B)
Offset must not be inside PUSH immediate data
Defined in: primitives/Opcode/BrandedOpcode/isValidJumpDest.js
Opcode.isJumpDestination(opcode)
Check if opcode is JUMPDEST (0x5B).
Opcode . isJumpDestination ( 0x5B ) // true
Opcode . isJumpDestination ( 0x56 ) // false (JUMP, not JUMPDEST)
Parameters:
opcode: BrandedOpcode - Opcode to check
Returns: boolean - True if JUMPDEST
Defined in: primitives/Opcode/BrandedOpcode/isJumpDestination.js
Category Checks
Opcode.isPush(opcode)
Check if opcode is PUSH0-PUSH32.
import * as Opcode from '@tevm/primitives/Opcode'
Opcode . isPush ( 0x5F ) // true (PUSH0)
Opcode . isPush ( 0x60 ) // true (PUSH1)
Opcode . isPush ( 0x7F ) // true (PUSH32)
Opcode . isPush ( 0x01 ) // false (ADD)
Opcode . isPush ( 0x80 ) // false (DUP1)
Parameters:
opcode: BrandedOpcode - Opcode to check
Returns: boolean - True if PUSH0-PUSH32 (0x5F-0x7F)
Defined in: primitives/Opcode/BrandedOpcode/isPush.js
Opcode.isDup(opcode)
Check if opcode is DUP1-DUP16.
Opcode . isDup ( 0x80 ) // true (DUP1)
Opcode . isDup ( 0x8F ) // true (DUP16)
Opcode . isDup ( 0x60 ) // false (PUSH1)
Opcode . isDup ( 0x90 ) // false (SWAP1)
Parameters:
opcode: BrandedOpcode - Opcode to check
Returns: boolean - True if DUP1-DUP16 (0x80-0x8F)
Defined in: primitives/Opcode/BrandedOpcode/isDup.js
Opcode.isSwap(opcode)
Check if opcode is SWAP1-SWAP16.
Opcode . isSwap ( 0x90 ) // true (SWAP1)
Opcode . isSwap ( 0x9F ) // true (SWAP16)
Opcode . isSwap ( 0x80 ) // false (DUP1)
Opcode . isSwap ( 0xA0 ) // false (LOG0)
Parameters:
opcode: BrandedOpcode - Opcode to check
Returns: boolean - True if SWAP1-SWAP16 (0x90-0x9F)
Defined in: primitives/Opcode/BrandedOpcode/isSwap.js
Opcode.isLog(opcode)
Check if opcode is LOG0-LOG4.
Opcode . isLog ( 0xA0 ) // true (LOG0)
Opcode . isLog ( 0xA4 ) // true (LOG4)
Opcode . isLog ( 0xA5 ) // false (undefined)
Opcode . isLog ( 0x9F ) // false (SWAP16)
Parameters:
opcode: BrandedOpcode - Opcode to check
Returns: boolean - True if LOG0-LOG4 (0xA0-0xA4)
Defined in: primitives/Opcode/BrandedOpcode/isLog.js
Opcode.isJump(opcode)
Check if opcode is JUMP or JUMPI.
Opcode . isJump ( 0x56 ) // true (JUMP)
Opcode . isJump ( 0x57 ) // true (JUMPI)
Opcode . isJump ( 0x5B ) // false (JUMPDEST)
Opcode . isJump ( 0x00 ) // false (STOP)
Parameters:
opcode: BrandedOpcode - Opcode to check
Returns: boolean - True if JUMP (0x56) or JUMPI (0x57)
Defined in: primitives/Opcode/BrandedOpcode/isJump.js
Opcode.isTerminating(opcode)
Check if opcode terminates execution.
Opcode . isTerminating ( 0x00 ) // true (STOP)
Opcode . isTerminating ( 0xF3 ) // true (RETURN)
Opcode . isTerminating ( 0xFD ) // true (REVERT)
Opcode . isTerminating ( 0xFE ) // true (INVALID)
Opcode . isTerminating ( 0xFF ) // true (SELFDESTRUCT)
Opcode . isTerminating ( 0x01 ) // false (ADD)
Parameters:
opcode: BrandedOpcode - Opcode to check
Returns: boolean - True if STOP, RETURN, REVERT, INVALID, or SELFDESTRUCT
Terminating opcodes:
STOP (0x00) - Halts execution
RETURN (0xF3) - Returns from call
REVERT (0xFD) - Reverts state changes
INVALID (0xFE) - Invalid opcode trap
SELFDESTRUCT (0xFF) - Destroys contract
Defined in: primitives/Opcode/BrandedOpcode/isTerminating.js
Opcode.isTerminator(opcode)
Alias for isTerminating().
const terminates = Opcode . isTerminator ( 0xF3 ) // true
Validation Patterns
Validate Bytecode
function validateBytecode ( bytecode : Uint8Array ) : string [] {
const errors : string [] = []
const instructions = Opcode . parse ( bytecode )
for ( const inst of instructions ) {
if ( ! Opcode . isValid ( inst . opcode )) {
errors . push ( `Invalid opcode 0x ${ inst . opcode . toString ( 16 ) } at offset ${ inst . offset } ` )
}
}
return errors
}
Check Jump Safety
function hasUnsafeJumps ( bytecode : Uint8Array ) : boolean {
const instructions = Opcode . parse ( bytecode )
const validDests = Opcode . jumpDests ( bytecode )
for ( const inst of instructions ) {
if ( Opcode . isJump ( inst . opcode )) {
// In real analysis, would need symbolic execution to get jump target
// This is simplified
if ( validDests . size === 0 ) {
return true // Has jumps but no valid destinations
}
}
}
return false
}
Categorize Instructions
interface InstructionCategories {
push : number
dup : number
swap : number
log : number
jump : number
terminating : number
other : number
}
function categorizeInstructions ( bytecode : Uint8Array ) : InstructionCategories {
const instructions = Opcode . parse ( bytecode )
const categories : InstructionCategories = {
push: 0 ,
dup: 0 ,
swap: 0 ,
log: 0 ,
jump: 0 ,
terminating: 0 ,
other: 0
}
for ( const inst of instructions ) {
if ( Opcode . isPush ( inst . opcode )) categories . push ++
else if ( Opcode . isDup ( inst . opcode )) categories . dup ++
else if ( Opcode . isSwap ( inst . opcode )) categories . swap ++
else if ( Opcode . isLog ( inst . opcode )) categories . log ++
else if ( Opcode . isJump ( inst . opcode )) categories . jump ++
else if ( Opcode . isTerminating ( inst . opcode )) categories . terminating ++
else categories . other ++
}
return categories
}
Find Invalid Opcodes
function findInvalidOpcodes ( bytecode : Uint8Array ) : number [] {
const instructions = Opcode . parse ( bytecode )
const invalidOffsets : number [] = []
for ( const inst of instructions ) {
if ( ! Opcode . isValid ( inst . opcode )) {
invalidOffsets . push ( inst . offset )
}
}
return invalidOffsets
}
Validate PUSH Consistency
function validatePushInstructions ( bytecode : Uint8Array ) : boolean {
const instructions = Opcode . parse ( bytecode )
for ( const inst of instructions ) {
if ( Opcode . isPush ( inst . opcode )) {
const expectedBytes = Opcode . pushBytes ( inst . opcode )
// PUSH0 has no immediate
if ( expectedBytes === 0 && inst . immediate !== undefined ) {
return false
}
// Other PUSHes must have immediate data
if ( expectedBytes > 0 ) {
if ( ! inst . immediate || inst . immediate . length !== expectedBytes ) {
return false
}
}
}
}
return true
}
Check for Unreachable Code
function findUnreachableCode ( bytecode : Uint8Array ) : Set < number > {
const instructions = Opcode . parse ( bytecode )
const reachable = new Set < number >([ 0 ]) // Start is reachable
for ( const inst of instructions ) {
if ( ! reachable . has ( inst . offset )) {
continue // Skip unreachable instructions
}
// Next instruction is reachable unless this terminates
if ( ! Opcode . isTerminating ( inst . opcode )) {
// Find next instruction offset
const nextOffset = inst . offset + 1 + ( inst . immediate ?. length ?? 0 )
reachable . add ( nextOffset )
}
// JUMP/JUMPI make destinations reachable (would need symbolic execution for actual targets)
}
const unreachable = new Set < number >()
for ( const inst of instructions ) {
if ( ! reachable . has ( inst . offset )) {
unreachable . add ( inst . offset )
}
}
return unreachable
}
See Also