Try it Live Run Bytecode examples in the interactive playground
The Bytecode iterator returns instructions as a discriminated union (OpcodeData) representing different instruction categories and fusion patterns.
Base Instruction Type
All instruction objects share common fields:
interface BaseInstruction {
pc : number // Program counter (byte offset)
type : InstructionType // Discriminator for union
}
Instruction Categories
Regular Instructions
Standard single-byte opcodes (ADD, MUL, SWAP1, etc.):
interface RegularInstruction extends BaseInstruction {
type : 'regular'
opcode : number // Raw opcode byte (0x00-0xFF)
}
Example:
{
type : 'regular' ,
pc : 4 ,
opcode : 0x01 // ADD
}
PUSH Instructions
PUSH1 through PUSH32 with immediate data:
interface PushInstruction extends BaseInstruction {
type : 'push'
opcode : number // PUSH1 (0x60) through PUSH32 (0x7F)
value : bigint // Pushed value
size : number // Push size in bytes (1-32)
}
Example:
{
type : 'push' ,
pc : 0 ,
opcode : 0x60 , // PUSH1
value : 42 n ,
size : 1
}
JUMPDEST Instructions
Valid jump destinations with block metadata:
interface JumpdestInstruction extends BaseInstruction {
type : 'jumpdest'
pc : number
gas_cost : number // Gas cost from here to next terminator
min_stack : number // Min stack depth required for this block
max_stack : number // Max stack depth reached in this block
}
Example:
{
type : 'jumpdest' ,
pc : 23 ,
gas_cost : 156 , // Total gas to execute block
min_stack : 2 , // Needs 2 items on stack minimum
max_stack : 5 // Block pushes up to 5 items total
}
JUMPDEST metadata enables efficient block-level gas estimation and stack validation without re-analyzing.
JUMP Instructions
Dynamic unconditional jump (target determined at runtime):
interface JumpInstruction extends BaseInstruction {
type : 'jump'
pc : number
}
Example:
jump type indicates dynamic JUMP (not fused with PUSH). Target validation occurs at runtime.
JUMPI Instructions
Dynamic conditional jump (target and condition determined at runtime):
interface JumpiInstruction extends BaseInstruction {
type : 'jumpi'
pc : number
}
Example:
{
type : 'jumpi' ,
pc : 67
}
PC Instructions
PC opcode returning current program counter:
interface PcInstruction extends BaseInstruction {
type : 'pc'
pc : number
value : number // Value that PC will push (equals pc field)
}
Example:
{
type : 'pc' ,
pc : 100 ,
value : 100 // PC pushes its own position
}
STOP Instructions
Halts execution:
interface StopInstruction extends BaseInstruction {
type : 'stop'
pc : number
}
INVALID Instructions
Invalid opcodes or undefined instruction bytes:
interface InvalidInstruction extends BaseInstruction {
type : 'invalid'
pc : number
}
Fusion Instructions
Optimizable multi-instruction patterns detected during analysis.
Arithmetic Fusions
PUSH + ADD
interface PushAddFusion extends BaseInstruction {
type : 'push_add_fusion'
value : bigint // PUSH value
pc : number // Position of PUSH
}
Represents: PUSH value + ADD → Add immediate value to stack top.
PUSH + MUL
interface PushMulFusion extends BaseInstruction {
type : 'push_mul_fusion'
value : bigint
pc : number
}
Represents: PUSH value + MUL → Multiply stack top by immediate.
PUSH + SUB
interface PushSubFusion extends BaseInstruction {
type : 'push_sub_fusion'
value : bigint
pc : number
}
Represents: PUSH value + SUB → Subtract immediate from stack top.
PUSH + DIV
interface PushDivFusion extends BaseInstruction {
type : 'push_div_fusion'
value : bigint
pc : number
}
Represents: PUSH value + DIV → Divide stack top by immediate.
Bitwise Fusions
PUSH + AND
interface PushAndFusion extends BaseInstruction {
type : 'push_and_fusion'
value : bigint
pc : number
}
Represents: PUSH value + AND → Bitwise AND with immediate.
PUSH + OR
interface PushOrFusion extends BaseInstruction {
type : 'push_or_fusion'
value : bigint
pc : number
}
Represents: PUSH value + OR → Bitwise OR with immediate.
PUSH + XOR
interface PushXorFusion extends BaseInstruction {
type : 'push_xor_fusion'
value : bigint
pc : number
}
Represents: PUSH value + XOR → Bitwise XOR with immediate.
Memory Fusions
PUSH + MLOAD
interface PushMloadFusion extends BaseInstruction {
type : 'push_mload_fusion'
value : bigint // Memory offset
pc : number
}
Represents: PUSH offset + MLOAD → Load from immediate memory address.
PUSH + MSTORE
interface PushMstoreFusion extends BaseInstruction {
type : 'push_mstore_fusion'
value : bigint // Memory offset
pc : number
}
Represents: PUSH offset + MSTORE → Store to immediate memory address.
PUSH + MSTORE8
interface PushMstore8Fusion extends BaseInstruction {
type : 'push_mstore8_fusion'
value : bigint // Memory offset
pc : number
}
Represents: PUSH offset + MSTORE8 → Store byte to immediate memory address.
Control Flow Fusions
PUSH + JUMP
interface PushJumpFusion extends BaseInstruction {
type : 'push_jump_fusion'
value : bigint // Jump target (can be validated at compile-time)
pc : number
}
Represents: PUSH target + JUMP → Static jump to known destination.
Static jumps can be validated during bytecode analysis. If value points to invalid JUMPDEST, bytecode is malformed.
PUSH + JUMPI
interface PushJumpiFusion extends BaseInstruction {
type : 'push_jumpi_fusion'
value : bigint // Jump target
pc : number
}
Represents: PUSH target + JUMPI → Conditional jump to known destination (condition still runtime).
ISZERO + PUSH + JUMPI
interface IszeroJumpiFusion extends BaseInstruction {
type : 'iszero_jumpi'
target : bigint // Jump destination
original_length : number // Size of original 3-instruction sequence
pc : number
}
Represents: ISZERO + PUSH target + JUMPI → Inverted conditional jump pattern.
Common in Solidity:
Compiles to: ISZERO + PUSH <skip_offset> + JUMPI
Advanced Stack Fusions
DUP2 + MSTORE + PUSH
interface Dup2MstorePushFusion extends BaseInstruction {
type : 'dup2_mstore_push'
push_value : bigint
original_length : number
pc : number
}
Represents: DUP2 + MSTORE + PUSH value → Common memory write pattern.
DUP3 + ADD + MSTORE
interface Dup3AddMstoreFusion extends BaseInstruction {
type : 'dup3_add_mstore'
original_length : number
pc : number
}
Represents: DUP3 + ADD + MSTORE → Offset calculation + store.
SWAP1 + DUP2 + ADD
interface Swap1Dup2AddFusion extends BaseInstruction {
type : 'swap1_dup2_add'
original_length : number
pc : number
}
Represents: SWAP1 + DUP2 + ADD → Stack manipulation + arithmetic.
PUSH + DUP3 + ADD
interface PushDup3AddFusion extends BaseInstruction {
type : 'push_dup3_add'
value : bigint
original_length : number
pc : number
}
Represents: PUSH value + DUP3 + ADD → Immediate addition with stack duplication.
PUSH + ADD + DUP1
interface PushAddDup1Fusion extends BaseInstruction {
type : 'push_add_dup1'
value : bigint
original_length : number
pc : number
}
Represents: PUSH value + ADD + DUP1 → Add immediate and duplicate result.
MLOAD + SWAP1 + DUP2
interface MloadSwap1Dup2Fusion extends BaseInstruction {
type : 'mload_swap1_dup2'
original_length : number
pc : number
}
Represents: MLOAD + SWAP1 + DUP2 → Memory load with stack rearrangement.
Multi-Instruction Fusions
MULTI_PUSH
interface MultiPushFusion extends BaseInstruction {
type : 'multi_push'
count : number // Number of consecutive PUSHes (2-3)
values : [ bigint , bigint , bigint ] // Values (unused entries are 0)
original_length : number
pc : number
}
Represents: Multiple consecutive PUSH instructions (2 or 3).
Example:
PUSH1 0x01
PUSH1 0x02
PUSH1 0x03
→ { type: 'multi_push', count: 3, values: [1n, 2n, 3n] }
MULTI_POP
interface MultiPopFusion extends BaseInstruction {
type : 'multi_pop'
count : number // Number of consecutive POPs (2-3)
original_length : number
pc : number
}
Represents: Multiple consecutive POP instructions (2 or 3).
Solidity-Specific Patterns
FUNCTION_DISPATCH
interface FunctionDispatchFusion extends BaseInstruction {
type : 'function_dispatch'
selector : number // 4-byte function selector
target : bigint // Jump destination for this function
original_length : number
pc : number
}
Represents: PUSH4 selector + EQ + PUSH target + JUMPI → Function selector matching.
Solidity pattern:
function myFunc () external { ... }
Generates function dispatch checking msg.sig == 0x12345678.
Detect all functions by collecting function_dispatch patterns. Extract function selectors for ABI reconstruction.
CALLVALUE_CHECK
interface CallvalueCheckFusion extends BaseInstruction {
type : 'callvalue_check'
original_length : number
pc : number
}
Represents: CALLVALUE + DUP1 + ISZERO → Check if ETH sent (non-payable modifier).
Solidity pattern:
function nonPayable () external { ... } // no `payable` modifier
Compiler inserts check: revert if msg.value > 0.
PUSH0 + PUSH0 + REVERT
interface Push0RevertFusion extends BaseInstruction {
type : 'push0_revert'
original_length : number
pc : number
}
Represents: PUSH0 + PUSH0 + REVERT → Empty revert (no error message).
Solidity pattern:
Or failed require() with no message.
Union Type Definition
Complete TypeScript union:
type OpcodeData =
| RegularInstruction
| PushInstruction
| JumpdestInstruction
| JumpInstruction
| JumpiInstruction
| PcInstruction
| StopInstruction
| InvalidInstruction
// Arithmetic fusions
| PushAddFusion
| PushMulFusion
| PushSubFusion
| PushDivFusion
// Bitwise fusions
| PushAndFusion
| PushOrFusion
| PushXorFusion
// Memory fusions
| PushMloadFusion
| PushMstoreFusion
| PushMstore8Fusion
// Control flow fusions
| PushJumpFusion
| PushJumpiFusion
| IszeroJumpiFusion
// Stack fusions
| Dup2MstorePushFusion
| Dup3AddMstoreFusion
| Swap1Dup2AddFusion
| PushDup3AddFusion
| PushAddDup1Fusion
| MloadSwap1Dup2Fusion
// Multi-instruction fusions
| MultiPushFusion
| MultiPopFusion
// Solidity patterns
| FunctionDispatchFusion
| CallvalueCheckFusion
| Push0RevertFusion
Type Guards
Use TypeScript discriminated union for type-safe handling:
function analyzeInstruction ( inst : OpcodeData ) {
switch ( inst . type ) {
case 'push' :
console . log ( `PUSH ${ inst . value } ` );
break ;
case 'jumpdest' :
console . log ( `JUMPDEST: gas= ${ inst . gas_cost } , stack=[ ${ inst . min_stack } , ${ inst . max_stack } ]` );
break ;
case 'push_jump_fusion' :
console . log ( `Static jump to ${ inst . value } ` );
break ;
case 'function_dispatch' :
console . log ( `Function ${ inst . selector . toString ( 16 ) } ` );
break ;
case 'regular' :
console . log ( `Opcode 0x ${ inst . opcode . toString ( 16 ) } ` );
break ;
default :
// TypeScript ensures exhaustiveness
const _exhaustive : never = inst ;
}
}
Pattern Detection
Detect specific patterns during iteration:
// Find all static jumps
const staticJumps : bigint [] = [];
for ( const inst of code . scan ({ detectFusions: true })) {
if ( inst . type === 'push_jump_fusion' ) {
staticJumps . push ( inst . value );
}
}
// Extract function selectors
const functions : Map < number , bigint > = new Map ();
for ( const inst of code . scan ({ detectFusions: true })) {
if ( inst . type === 'function_dispatch' ) {
functions . set ( inst . selector , inst . target );
}
}
// Detect non-payable functions
let hasCallvalueCheck = false ;
for ( const inst of code . scan ({ detectFusions: true })) {
if ( inst . type === 'callvalue_check' ) {
hasCallvalueCheck = true ;
break ;
}
}
See Also