Overview
Opcode:0x5b
Introduced: Frontier (EVM genesis)
JUMPDEST marks a valid destination for JUMP and JUMPI instructions. It’s the only opcode that JUMP/JUMPI can target - attempting to jump to any other instruction causes InvalidJump error.
This is a critical security feature that prevents arbitrary code execution by restricting where jumps can land.
Specification
Stack Input: None Stack Output: None Gas Cost: 1 (JumpdestGas) Operation:Behavior
JUMPDEST serves two purposes: At execution time:- Consumes 1 gas (cheapest opcode)
- Increments program counter
- No other side effects (no stack/memory changes)
- Analyzed during bytecode deployment/validation
- Positions marked as valid jump destinations
- Used to validate JUMP/JUMPI targets
- Only valid target for JUMP/JUMPI
- Cannot be inside PUSH data
- Multiple JUMPDESTs can exist in bytecode
- Can be consecutive (JUMPDEST JUMPDEST is valid)
Examples
Basic JUMPDEST
Valid Jump Target
JUMPDEST in PUSH Data (Invalid)
Consecutive JUMPDESTs
Gas Cost
Cost: 1 gas (JumpdestGas) JUMPDEST is the cheapest opcode in the EVM. Comparison:- JUMPDEST: 1 gas (cheapest)
- PC: 2 gas
- PUSH1-32: 3 gas
- ADD/SUB: 3 gas
- JUMP: 8 gas
Edge Cases
Empty Stack
Out of Gas
JUMPDEST at End
Multiple JUMPDESTs Same Location
Common Usage
Function Entry Points
Every internal function starts with JUMPDEST:Loop Start
Branch Targets
Jump Table
Implementation
- TypeScript
JUMPDEST Validation
Bytecode Analysis
Before execution, bytecode is analyzed to identify valid JUMPDESTs:- Scan bytecode linearly
- Mark JUMPDEST positions (0x5b)
- Skip PUSH data (don’t mark 0x5b inside PUSH as valid)
- Build set of valid destinations
Validation at Jump Time
Testing
Test Coverage
Security
Critical Security Feature
JUMPDEST validation prevents arbitrary code execution: Without JUMPDEST requirement:- Jumping into middle of multi-byte instructions
- Jumping into PUSH data
- Executing data as code
- Arbitrary control flow hijacking
PUSH Data vs Real JUMPDEST
Critical distinction:- Track PUSH boundaries
- Only mark 0x5b as valid if NOT in PUSH data
- Reject jumps to PUSH data even if byte value is 0x5b
Static vs Dynamic Analysis
Static analysis (deployment time):- Scan bytecode for all JUMPDESTs
- Build valid destination set
- O(n) time complexity, done once
- Check if jump target is in valid set
- O(1) lookup with hash set
- Fast validation on every JUMP/JUMPI
Malicious Bytecode
Attack attempt:Compiler Behavior
Automatic JUMPDEST Insertion
Solidity automatically inserts JUMPDEST at:- Function entry points
- Loop starts
- Branch targets
- Case statements
Optimization
Compilers can optimize unreachable JUMPDESTs:Label Resolution
Solidity labels are resolved to JUMPDEST positions at compile time:Historical Context
JUMPDEST was introduced in Frontier to:- Prevent arbitrary code execution
- Enable static analysis of control flow
- Distinguish code from data
- Support jump validation without runtime overhead
- Unrestricted jumps (rejected - too dangerous)
- Jump tables only (rejected - not flexible enough)
- Type system for code pointers (rejected - too complex)
References
- Yellow Paper - Section 9.4.3 (JUMPDEST instruction)
- EVM Codes - JUMPDEST
- Solidity Docs - Assembly
- EVM Deep Dives - Jump Validation

