Skip to content

andyrobert3/evm-lens

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

15 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

EVM Lens

CI Rust License: MIT

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 0x prefix
  • On-chain bytecode fetching via Ethereum RPC
  • Beautiful error reporting

๐Ÿš€ Quick Start

Install the CLI

cargo install evm-lens

Use as a Library

[dependencies]
evm-lens-core = "3.0.0"

Example Usage

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);
}

๐ŸŽจ 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

evm-lens 60FF61ABCD00         # Without 0x prefix
evm-lens 0x60FF61ABCD00       # With 0x prefix

File Input

evm-lens --file bytecode.txt  # Read from file

Standard Input

echo "0x60FF61ABCD00" | evm-lens --stdin
cat bytecode.txt | evm-lens --stdin

Blockchain Input

# 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

๐ŸŽฏ 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
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

๐Ÿงฎ Storage Diff

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:
      1. 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 or HeuristicTrace.
  • 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) if max_grade >= Risk.

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

๐Ÿ“Š 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

git clone https://github.com/andyrobert3/evm-lens
cd evm-lens
cargo build --release

Testing

cargo test --workspace

Running Examples

# 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

๐Ÿ“‹ 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.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. 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

About

EVM bytecode analyser

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages