EVM Lens
Fast and colorful EVM bytecode disassembler
EVM Lens is a high-performance Ethereum Virtual Machine (EVM) bytecode disassembler written in Rust. It provides both a library (evm-lens-core) and a beautiful command-line tool (evm-lens) for analyzing EVM bytecode.
๐ฆ Crates
This workspace contains two crates:
evm-lens-core - The Core Library
- Fast EVM bytecode disassembly using revm
- Position-accurate opcode extraction
- Result-based error handling
- Zero-copy iteration where possible
evm-lens - The CLI Tool
- Colorful terminal output with opcode categorization
- Multiple input methods: direct hex, files, stdin, and blockchain
- Support for hex strings with/without
0xprefix - On-chain bytecode fetching via Ethereum RPC
- Beautiful error reporting
๐ Quick Start
Install the CLI
Use as a Library
[]
= "3.0.0"
Example Usage
CLI:
# From command line argument
# From file
# From stdin
|
# From contract address (fetches from blockchain)
# Show bytecode statistics
# Decode function selectors with ABI resolution
# Compare storage layouts (files only)
Library:
use disassemble;
let bytecode = decode?;
let ops = disassemble?;
for in ops
๐จ Features
Core Capabilities:
- ๐ Disassemble EVM bytecode from multiple sources - hex strings, files, stdin, and live contract addresses
- ๐ Generate statistics summary including bytecode length, number of opcodes, and maximum stack depth
- ๐ฏ Decode function selectors - automatically resolve PUSH4 instructions to human-readable function signatures using 4byte.directory
- ๐งฎ Storage diff - compare two artifacts and flag storage layout changes with JSON/HTML reports and CI-friendly exit codes
๐ฅ Input Methods
EVM Lens supports multiple ways to provide bytecode for analysis:
Direct Hex Input
File Input
Standard Input
|
|
Blockchain Input
# Use default RPC (eth.llamarpc.com)
# Use custom RPC endpoint
๐ฏ ABI Function Selector Decoding
EVM Lens can automatically decode 4-byte function selectors found in PUSH4 instructions to their human-readable function signatures:
# Decode function selectors using --abi flag
# Works with any input method
|
# Combine with stats for comprehensive analysis
๐งฎ Storage Diff
Compare two compiled artifacts (files containing hex-encoded runtime bytecode) and flag storage layout risks.
- Inputs:
<old.hex>,<new.hex>: file paths containing hex-encoded runtime bytecode (with or without 0x).
- How it works:
- Builds a StorageLayout for each input using a composite resolver:
- Compiler metadata (if available), 2) conservative bytecode heuristic (PUSHโฆ then SLOAD/SSTORE).
- Computes a per-slot diff with statuses:
Same | Added | Removed | TypeChanged | PackingChanged. - Assigns grades:
Ok | Risk | Break(Added=Ok, Removed/TypeChanged=Break, PackingChanged=Risk). - Records provenance per side:
CompilerMetadataorHeuristicTrace.
- Builds a StorageLayout for each input using a composite resolver:
- Outputs:
- CLI one-line summary with counts and max grade.
- Optional JSON (
--json) and HTML (--html) reports.
- CI:
- With
--ci, exits nonโzero (code 2) ifmax_grade >= Risk.
- With
Examples:
# Basic compare
# Write JSON/HTML reports
# CI policy (non-zero on Risk/Break)
๐ Example Output
EVM BYTECODE DISASSEMBLY
==================================================
0000 โ PUSH1 # Stack operation (green)
0002 โ PUSH2 # Stack operation (green)
0005 โ ADD # Arithmetic (yellow)
0006 โ MSTORE # Memory operation (blue)
0007 โ RETURN # Termination (white)
==================================================
5 opcodes total
With --stats flag:
EVM BYTECODE DISASSEMBLY
==================================================
0000 โ PUSH1
0002 โ PUSH2
0005 โ STOP
==================================================
3 opcodes total
BYTECODE STATISTICS
==================================================
Byte length: 6
Number of opcodes: 3
Max stack depth: 2
With --abi flag (function selector decoding):
EVM BYTECODE DISASSEMBLY
==================================================
0000 โ PUSH4 # 0xa9059cbb โ transfer(address,uint256)
0005 โ PUSH20
001a โ PUSH9
0024 โ BLOCKHASH
==================================================
4 opcodes total
๐ง Development
Prerequisites
- Rust 1.85+ (2024 edition)
- Cargo
Building
Testing
Running Examples
# Run the CLI with different input methods
|
# Test ABI function selector decoding
# Test the library
๐ Supported Opcodes
All standard EVM opcodes are supported:
| Category | Examples |
|---|---|
| Stack | PUSH1-PUSH32, POP, DUP1-DUP16, SWAP1-SWAP16 |
| Arithmetic | ADD, SUB, MUL, DIV, MOD, ADDMOD, MULMOD |
| Comparison | LT, GT, SLT, SGT, EQ, ISZERO |
| Bitwise | AND, OR, XOR, NOT, BYTE, SHL, SHR, SAR |
| Memory | MLOAD, MSTORE, MSTORE8, MSIZE, MCOPY |
| Storage | SLOAD, SSTORE, TLOAD, TSTORE |
| Control | JUMP, JUMPI, JUMPDEST, PC, GAS |
| Block Info | BLOCKHASH, COINBASE, TIMESTAMP, NUMBER |
| Calls | CALL, CALLCODE, DELEGATECALL, STATICCALL |
| Create | CREATE, CREATE2 |
| Termination | STOP, RETURN, REVERT, SELFDESTRUCT |
| Crypto | KECCAK256, ECRECOVER |
๐ค Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
๐ License
This project is licensed under the MIT License - see the LICENSE file for details.
๐ Acknowledgments
- revm - High-performance EVM implementation
- The Ethereum community for EVM specifications