Extracts function selectors and arguments from EVM bytecode
Project description
EVMole
This library extracts function selectors and arguments from Ethereum Virtual Machine (EVM) bytecode, even for unverified contracts.
- JavaScript, Rust and Python implementations
- Clean code with zero external dependencies (py & js)
- Faster and more accurate than other existing tools
- Tested on Solidity and Vyper compiled contracts
Usage
JavaScript
$ npm i evmole
import {functionArguments, functionSelectors} from 'evmole'
// Also supported: const e = require('evmole'); e.functionSelectors();
const code = '0x6080604052348015600e575f80fd5b50600436106030575f3560e01c80632125b65b146034578063b69ef8a8146044575b5f80fd5b6044603f3660046046565b505050565b005b5f805f606084860312156057575f80fd5b833563ffffffff811681146069575f80fd5b925060208401356001600160a01b03811681146083575f80fd5b915060408401356001600160e01b0381168114609d575f80fd5b80915050925092509256'
console.log( functionSelectors(code) )
// Output(list): [ '2125b65b', 'b69ef8a8' ]
console.log( functionArguments(code, '2125b65b') )
// Output(str): 'uint32,address,uint224'
Rust
Documentation available on docs.rs
let code = hex::decode("6080604052348015600e575f80fd5b50600436106030575f3560e01c80632125b65b146034578063b69ef8a8146044575b5f80fd5b6044603f3660046046565b505050565b005b5f805f606084860312156057575f80fd5b833563ffffffff811681146069575f80fd5b925060208401356001600160a01b03811681146083575f80fd5b915060408401356001600160e01b0381168114609d575f80fd5b80915050925092509256").unwrap();
println!("{:x?}", evmole::function_selectors(&code, 0));
// Output(Vec<[u8;4]>): [[21, 25, b6, 5b], [b6, 9e, f8, a8]]
println!("{}", evmole::function_arguments(&code, &[0x21, 0x25, 0xb6, 0x5b], 0));
// Output(String): uint32,address,uint224
Python
$ pip install evmole --upgrade
from evmole import function_arguments, function_selectors
code = '0x6080604052348015600e575f80fd5b50600436106030575f3560e01c80632125b65b146034578063b69ef8a8146044575b5f80fd5b6044603f3660046046565b505050565b005b5f805f606084860312156057575f80fd5b833563ffffffff811681146069575f80fd5b925060208401356001600160a01b03811681146083575f80fd5b915060408401356001600160e01b0381168114609d575f80fd5b80915050925092509256'
print( function_selectors(code) )
# Output(list): ['2125b65b', 'b69ef8a8']
print( function_arguments(code, '2125b65b') )
# Output(str): 'uint32,address,uint224'
Foundry
Foundy's cast uses the Rust implementation of EVMole
$ cast selectors $(cast code 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2)
0x06fdde03
0x095ea7b3 address,uint256
0x18160ddd
0x23b872dd address,address,uint256
...
$ cast selectors --resolve $(cast code 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2)
0x06fdde03 name()
0x095ea7b3 address,uint256 approve(address,uint256)
0x18160ddd totalSupply()
0x23b872dd address,address,uint256 transferFrom(address,address,uint256)
...
See examples for more
Benchmark
function selectors
FP/FN - False Positive/False Negative errors; smaller is better
Dataset | evmole rs · js · py | whatsabi | evm-hound-rs | heimdall-rs | simple | ||
largest1k 1000 contracts 24427 functions |
FP contracts | 1 🥈 | 0 🥇 | 75 | 18 | 95 | |
FN contracts | 0 🥇 | 8 | 40 | 102 | 9 | ||
FP functions | 192 🥈 | 0 🥇 | 720 | 600 | 749 | ||
FN functions | 0 🥇 | 8 🥈 | 191 | 113 | 12 | ||
Time | 0.7s · 1.5s · 2.0s | 3.0s | 0.7s | 727.2s | 1.9s | ||
random50k 50000 contracts 1171102 functions |
FP contracts | 1 🥇 | 43 | 693 | waiting fixes | 4136 | |
FN contracts | 9 🥇 | 31 | 2903 | 77 | |||
FP functions | 3 🥇 | 51 | 10798 | 14652 | |||
FN functions | 10 🥇 | 32 | 3538 | 96 | |||
Time | 9.8s · 19.6s · 36.4s | 52.3s | 11.5s | 46.3s | |||
vyper 780 contracts 21244 functions |
FP contracts | 0 🥇 | 30 | 19 | 0 | 185 | |
FN contracts | 0 🥇 | 780 | 300 | 780 | 480 | ||
FP functions | 0 🥇 | 30 | 19 | 0 | 197 | ||
FN functions | 0 🥇 | 21244 | 8273 | 21244 | 12971 | ||
Time | 0.6s · 0.9s · 1.4s | 2.3s | 0.6s | 17.0s | 1.2s |
function arguments
Errors - when at least 1 argument is incorrect: (uint256,string)
!= (uint256,bytes)
; smaller is better
Dataset | evmole rs · js · py | heimdall-rs | simple | |
largest1k 1000 contracts 24427 functions |
Errors | 15.0%, 3652 🥇 | 42.7%, 10438 | 58.3%, 14242 |
Time | 1.1s · 7.5s · 15.7s | 731.4s | 0.8s | |
random50k 50000 contracts 1171102 functions |
Errors | 5.1%, 59484 🥇 | waiting fixes | 54.9%, 643213 |
Time | 22.6s · 247.0s · 584.7s | 9.5s | ||
vyper 780 contracts 21244 functions |
Errors | 50.9%, 10805 🥇 | 100.0%, 21244 | 56.8%, 12077 |
Time | 0.9s · 7.3s · 13.9s | 16.8s | 0.7s |
See benchmark/README.md for the methodology and commands to reproduce these results
versions: evmole v0.3.3; whatsabi v0.11.0; evm-hound-rs v0.1.4; heimdall-rs v0.7.3
How it works
Short: Executes code with a custom EVM and traces CALLDATA usage.
Long: TODO
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.