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.
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
0x
prefix - On-chain bytecode fetching via Ethereum RPC
- Beautiful error reporting
cargo install evm-lens
[dependencies]
evm-lens-core = "3.0.0"
CLI:
# From command line argument
evm-lens 60FF61ABCD00
# From file
evm-lens --file bytecode.txt
# From stdin
echo "0x60FF61ABCD00" | evm-lens --stdin
# From contract address (fetches from blockchain)
evm-lens --address 0x123... --rpc https://eth.llamarpc.com
# Show bytecode statistics
evm-lens 60FF61ABCD00 --stats
# Decode function selectors with ABI resolution
evm-lens 63a9059cbb00 --abi
# Compare storage layouts (files only)
evm-lens storage-diff artifacts/old.hex artifacts/new.hex
evm-lens storage-diff old.hex new.hex --json target/storage.json --html target/storage.html
evm-lens storage-diff old.hex new.hex --ci
Library:
use lens_core::disassemble;
let bytecode = hex::decode("60FF61ABCD00")?;
let ops = disassemble(&bytecode)?;
for (position, opcode) in ops {
println!("{:04x}: {:?}", position, opcode);
}
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
EVM Lens supports multiple ways to provide bytecode for analysis:
evm-lens 60FF61ABCD00 # Without 0x prefix
evm-lens 0x60FF61ABCD00 # With 0x prefix
evm-lens --file bytecode.txt # Read from file
echo "0x60FF61ABCD00" | evm-lens --stdin
cat bytecode.txt | evm-lens --stdin
# Use default RPC (eth.llamarpc.com)
evm-lens --address 0x123...
# Use custom RPC endpoint
evm-lens --address 0x123... --rpc https://mainnet.infura.io/v3/YOUR_KEY
evm-lens --address 0x123... --rpc https://eth.llamarpc.com
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
evm-lens 63a9059cbb00 --abi
# Works with any input method
evm-lens --file contract.hex --abi
echo "0x63a9059cbb00" | evm-lens --stdin --abi
evm-lens --address 0x123... --rpc https://eth.llamarpc.com --abi
# Combine with stats for comprehensive analysis
evm-lens 63a9059cbb00 --abi --stats
Compare two compiled artifacts (files containing hex-encoded runtime bytecode) and flag storage layout risks.
evm-lens storage-diff <old.hex> <new.hex> [--json out.json] [--html out.html] [--ci]
- 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:
CompilerMetadata
orHeuristicTrace
.
- 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
evm-lens storage-diff artifacts/old.hex artifacts/new.hex
# Write JSON/HTML reports
evm-lens storage-diff old.hex new.hex --json target/storage.json --html target/storage.html
# CI policy (non-zero on Risk/Break)
evm-lens storage-diff old.hex new.hex --ci
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
- Rust 1.85+ (2024 edition)
- Cargo
git clone https://github.com/andyrobert3/evm-lens
cd evm-lens
cargo build --release
cargo test --workspace
# Run the CLI with different input methods
cargo run -p evm-lens -- 60FF61ABCD00
cargo run -p evm-lens -- --file examples/bytecode.txt
echo "0x60FF61ABCD00" | cargo run -p evm-lens -- --stdin
cargo run -p evm-lens -- --address 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 --rpc https://eth.llamarpc.com
# Test ABI function selector decoding
cargo run -p evm-lens -- 63a9059cbb00 --abi
# Test the library
cargo run --example basic -p evm-lens-core
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 |
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
This project is licensed under the MIT License - see the LICENSE file for details.
- revm - High-performance EVM implementation
- The Ethereum community for EVM specifications