cdump / evmole

Extracts function selectors and arguments from bytecode, even for unverified contracts

Home Page:https://cdump.github.io/evmole/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

EVMole

npm Crates.io PyPI license

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

Try it online

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 sevm evmhound heimdall smpl
largest1k
1000
contracts

24427
functions
FP contracts 1 πŸ₯ˆ 0 πŸ₯‡ 0 πŸ₯‡ 75 68 95
FN contracts 0 πŸ₯‡ 0 πŸ₯‡ 0 πŸ₯‡ 40 103 9
FP functions 192 πŸ₯ˆ 0 πŸ₯‡ 0 πŸ₯‡ 720 650 749
FN functions 0 πŸ₯‡ 0 πŸ₯‡ 0 πŸ₯‡ 191 114 12
Time 0.6s Β· 1.6s Β· 2.1s 2.9s 34.8s(*) 0.7s 379.5s(*) 1.7s
random50k
50000
contracts

1171102
functions
FP contracts 1 πŸ₯‡ 43 1 693 519 4136
FN contracts 9 πŸ₯‡ 11 85 2903 4669 77
FP functions 3 πŸ₯‡ 51 3 10798 545 14652
FN functions 10 πŸ₯‡ 12 1759 3538 4943 96
Time 9.8s Β· 20.2s Β· 39s 55.9s 1343s(*) 11.5s 9881.1s(*) 47.9s
vyper
780
contracts

21244
functions
FP contracts 0 πŸ₯‡ 30 0 19 780 185
FN contracts 0 πŸ₯‡ 780 21 300 780 480
FP functions 0 πŸ₯‡ 30 0 19 780 197
FN functions 0 πŸ₯‡ 21244 336 8273 21244 12971
Time 0.4s Β· 0.8s Β· 1.2s 2.1s 55.1s(*) 0.4s 29.1s(*) 1.1s

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 14.0%, 3417 πŸ₯‡ 31.1%, 7603 58.3%, 14242
Time 1.2s Β· 12.6s Β· 30.1s 385.6s(*) 0.6s
random50k
50000
contracts

1171102
functions
Errors 4.5%, 52777 πŸ₯‡ 19.4%, 227078 54.9%, 643213
Time 33.7s Β· 337.7s Β· 1002.4s 9594.6s(*) 9.6s
vyper
780
contracts

21244
functions
Errors 49.6%, 10544 πŸ₯‡ 100.0%, 21244 56.8%, 12077
Time 0.8s Β· 8.0s Β· 16.9s 29.6s(*) 0.5s

See benchmark/README.md for the methodology and commands to reproduce these results

versions: evmole v0.3.7; whatsabi v0.12.0; sevm v0.6.18; evm-hound-rs v0.1.4; heimdall-rs v0.8.3

(*): sevm and heimdall-rs are full decompilers, not limited to extracting function selectors

How it works

Short: Executes code with a custom EVM and traces CALLDATA usage.

Long: TODO

License

MIT

About

Extracts function selectors and arguments from bytecode, even for unverified contracts

https://cdump.github.io/evmole/

License:MIT License


Languages

Language:Rust 37.8%Language:Python 33.4%Language:JavaScript 23.1%Language:HTML 2.7%Language:Makefile 1.4%Language:Dockerfile 0.9%Language:Shell 0.7%