Skip to main content

Try it Live

Run Bytecode examples in the interactive playground
Synthetic opcodes extend the EVM’s 256-instruction set with virtual opcodes representing multi-instruction fusion patterns. They enable treating fused sequences as atomic operations for optimization, analysis, and intermediate representations.

Concept

Standard EVM Opcodes

EVM defines 256 opcodes (0x00-0xFF):
  • 0x00: STOP
  • 0x01: ADD
  • 0x60-0x7F: PUSH1-PUSH32
  • 0xFF: SELFDESTRUCT

Synthetic Opcodes

Synthetic opcodes extend this with virtual instructions for fusions:
  • 0x100: PUSH_ADD (PUSH+ADD fusion)
  • 0x101: PUSH_MUL (PUSH+MUL fusion)
  • 0x102: PUSH_JUMP (PUSH+JUMP fusion)
  • 0x11F: FUNCTION_DISPATCH (function selector pattern)
Synthetic opcodes are compile-time abstractions, not runtime instructions. They represent sequences of real opcodes detected during bytecode analysis.

Why Synthetic Opcodes?

1. Optimization

Treat fusions as atomic operations:

2. Static Analysis

Simplify control flow:
This enables:
  • Control flow graph construction without execution
  • Jump target validation at compile time
  • Dead code detection

3. Intermediate Representation

Build IR for:
  • Decompilers (Solidity source reconstruction)
  • Optimizers (peephole optimization passes)
  • Transpilers (EVM → other VMs)
  • Analyzers (security analysis, gas profiling)

4. Semantic Clarity

Reveal intent:

Synthetic Opcode Reference

Arithmetic (0x100-0x103)

Stack effect: Same as base operation (e.g., PUSH_ADD: -1 input, +1 output = 0 net) Gas: Sum of constituent instructions (e.g., PUSH_ADD = 3 + 3 = 6 gas base)

Bitwise (0x104-0x106)

Memory (0x107-0x109)

Control Flow (0x10A-0x10C)

PUSH_JUMP and PUSH_JUMPI are critical for static analysis:
  • Jump target is compile-time constant (not runtime stack value)
  • Enables CFG construction without execution
  • Allows jump target validation at analysis time
This distinguishes them from dynamic JUMP/JUMPI where target is computed at runtime.

Stack Manipulation (0x10D-0x112)

Multi-Instruction (0x113-0x114)

High-Level (0x115-0x117)

Working with Synthetic Opcodes

Detection

Fusion detection returns OpcodeData with synthetic type:

Type Mapping

Map fusion types to synthetic opcode numbers:

Opcode Names

Map synthetic opcodes to mnemonics:

Use Cases

1. Intermediate Representation

Build IR with synthetic opcodes:

2. Optimization Pass

Optimize using synthetic opcodes:

3. Decompiler

Map synthetic opcodes to high-level constructs:

4. Control Flow Graph

Build CFG using static jumps:

5. Gas Profiling

Profile gas by synthetic opcode:

Integration with Opcode Module

Synthetic opcodes extend the standard Opcode module:

Stack Effects

Compute stack effects for synthetic opcodes:

Gas Costs

Compute gas for synthetic opcodes:

Advanced Patterns

Custom Synthetic Opcodes

Define project-specific synthetic opcodes:

Bytecode Transformation

Transform bytecode using synthetic opcodes:

Limitations

Synthetic opcodes are analysis-time abstractions, not runtime instructions:
  • Cannot execute directly on EVM (must expand to real opcodes)
  • No standard encoding in bytecode format
  • Tool-specific - different tools may define different synthetic opcodes
  • May not survive round-trip (bytecode → synthetic → bytecode may differ)
Use synthetic opcodes for analysis and optimization, not as interchange format.

What They Enable

✅ Simplified intermediate representation ✅ Pattern-based optimization ✅ Static control flow analysis ✅ High-level semantic extraction ✅ Gas profiling by pattern

What They Don’t Provide

❌ Runtime execution semantics ❌ Standard bytecode encoding ❌ Cross-tool compatibility ❌ Lossless round-trip transformation

See Also