Analyze EVM bytecode without deploying — disassemble opcodes, detect contract patterns, find security issues, extract metadata.
- Audit before interaction: Understand what a contract does before calling it
- Verify proxy implementations: Detect EIP-1967, UUPS, beacon, and minimal proxy patterns
- Identify standards: Quickly determine if bytecode implements ERC-20, ERC-721, ERC-1155, etc.
- Security scanning: Flag dangerous opcodes like SELFDESTRUCT and DELEGATECALL
- Compiler forensics: Extract Solidity/Vyper compiler versions from metadata
pip install evm-bytecode-analyzer
# With RPC support (fetch bytecode from chain):
pip install evm-bytecode-analyzer[rpc]
# Development:
pip install evm-bytecode-analyzer[dev]# Full analysis of a contract
evm-analyzer analyze 0x6060604052...
# Analyze from file
evm-analyzer analyze contract.bin
# Fetch from chain (requires web3.py)
evm-analyzer analyze --rpc-url https://eth.llamarpc.com --address 0xdAC17F958D2ee523a2206206994597C13D831ec7
# Just disassemble
evm-analyzer disassemble 0x6060604052... --limit 50
# Detect patterns
evm-analyzer patterns 0x6060604052...
# List function selectors
evm-analyzer selectors 0x6060604052...
# JSON output
evm-analyzer analyze 0x6060604052... --jsonfrom evm_bytecode_analyzer import (
disassemble, detect_patterns, scan_security,
extract_metadata, extract_solidity_version,
compute_bytecode_hash, extract_selectors,
)
bytecode = bytes.fromhex("6060604052...")
# Disassemble
opcodes = disassemble(bytecode)
for op in opcodes[:10]:
print(f"{op.offset:04d} {op.name} {op.operand_hex or ''}")
# Detect patterns
patterns = detect_patterns(bytecode)
for p in patterns:
print(f"{p.pattern_name}: {p.description}")
# Security scan
findings = scan_security(bytecode)
for f in findings:
print(f"[{f.severity}] {f.opcode_name} at offset {f.offset}")
# Metadata
metadata = extract_metadata(bytecode)
version = extract_solidity_version(bytecode)Bytecode Input (hex / file / stdin / RPC)
│
▼
┌─────────────┐
│ Disassembler │ → Opcode list, function selectors
└──────┬──────┘
│
┌──────┴──────┐
│ Patterns │ → ERC-20/721/1155, Proxy (EIP-1967, 1167), Multisig
└──────┬──────┘
│
┌──────┴──────┐
│ Metadata │ → CBOR extraction, compiler version, IPFS/bzzr hash
└──────┬──────┘
│
┌──────┴──────┐
│ Security │ → SELFDESTRUCT, DELEGATECALL, CREATE, EXTCODECOPY
└──────┬──────┘
│
▼
AnalysisResult (table / JSON)
| Pattern | Detection Method |
|---|---|
| ERC-20 | Function selectors (transfer, approve, balanceOf, etc.) |
| ERC-721 | Function selectors (ownerOf, safeTransferFrom, tokenURI) |
| ERC-1155 | Function selectors (safeTransferFrom, balanceOf, etc.) |
| ERC-165 | supportsInterface selector |
| EIP-1967 Proxy | Implementation/admin/beacon storage slots |
| EIP-1167 Minimal Proxy | 37-byte clone bytecode pattern |
| Multisig Wallet | submitTransaction, confirmTransaction, executeTransaction selectors |
Solidity embeds CBOR-encoded metadata at the end of bytecode containing:
- Compiler version (e.g., 0.8.15)
- IPFS hash of source metadata
- Swarm (bzzr) hash of source metadata
Vyper similarly embeds version information in the bytecode tail.
| Opcode | Severity | Description |
|---|---|---|
| SELFDESTRUCT | Critical | Contract can be destroyed |
| DELEGATECALL | Warning | External code runs in caller context |
| CALLCODE | Warning | Deprecated call type |
| EXTCODECOPY | Info | Can read arbitrary contract code |
| CREATE | Info | Deploys new contracts |
| CREATE2 | Info | Deploys deterministic contracts |
- Bytecode-only: No storage slot analysis — cannot read proxy implementation address
- Heuristic detection: Pattern matching is best-effort, not guaranteed
- Metadata parsing: Some contracts strip or modify metadata, breaking extraction
- No runtime analysis: Cannot detect runtime-dependent behaviors
- Selector matching only: Doesn't verify function implementations match expected behavior
MIT