# EVMole [![try it online](https://img.shields.io/badge/Try_It_Online-github.io-brightgreen)](https://cdump.github.io/evmole/) [![npm](https://img.shields.io/npm/v/evmole)](https://www.npmjs.com/package/evmole) [![Crates.io](https://img.shields.io/crates/v/evmole?color=e9b44f)](https://crates.io/crates/evmole) [![PyPI](https://img.shields.io/pypi/v/evmole?color=006dad)](https://pypi.org/project/evmole) EVMole is a powerful library that extracts information from Ethereum Virtual Machine (EVM) bytecode, including [function selectors](https://docs.soliditylang.org/en/latest/abi-spec.html#function-selector), arguments, and [state mutability](https://docs.soliditylang.org/en/latest/contracts.html#state-mutability), even for unverified contracts. ## Key Features - Multi-language support: Available as [JavaScript](#javascript), [Rust](#rust), and [Python](#python) libraries. - High accurancy and performance: [Outperforms](#benchmark) existing tools. - Broad compatibility: Tested with both Solidity and Vyper compiled contracts. - Lightweight: Clean codebase with minimal external dependencies. - Unverified contract analysis: Extracts information even from unverified bytecode. ## Usage ### JavaScript [API documentation](./javascript/#api) and [usage examples](./javascript#usage) (node, vite, webpack, parcel, esbuild) ```sh $ npm i evmole ``` ```javascript import { functionSelectors, functionArguments, functionStateMutability } from 'evmole' const code = '0x6080604052348015600e575f80fd5b50600436106030575f3560e01c80632125b65b146034578063b69ef8a8146044575b5f80fd5b6044603f3660046046565b505050565b005b5f805f606084860312156057575f80fd5b833563ffffffff811681146069575f80fd5b925060208401356001600160a01b03811681146083575f80fd5b915060408401356001600160e01b0381168114609d575f80fd5b80915050925092509256' console.log(functionSelectors(code)); // [ '2125b65b', 'b69ef8a8' ] console.log(functionArguments(code, '2125b65b')); // 'uint32,address,uint224' console.log(functionStateMutability(code, '2125b65b')); // 'pure' ``` ### Rust Documentation is available on [docs.rs](https://docs.rs/evmole/latest/evmole/) ```rust let code = hex::decode("6080604052348015600e575f80fd5b50600436106030575f3560e01c80632125b65b146034578063b69ef8a8146044575b5f80fd5b6044603f3660046046565b505050565b005b5f805f606084860312156057575f80fd5b833563ffffffff811681146069575f80fd5b925060208401356001600160a01b03811681146083575f80fd5b915060408401356001600160e01b0381168114609d575f80fd5b80915050925092509256").unwrap(); println!("{:x?} | {} | {:?}", evmole::function_selectors(&code, 0), evmole::function_arguments(&code, &[0x21, 0x25, 0xb6, 0x5b], 0), evmole::function_state_mutability(&code, &[0x21, 0x25, 0xb6, 0x5b], 0), ); // [[21, 25, b6, 5b], [b6, 9e, f8, a8]] | uint32,address,uint224 | Pure ``` ### Python [API documentation](./python/#api) ```sh $ pip install evmole --upgrade ``` ```python from evmole import function_selectors, function_arguments, function_state_mutability code = '0x6080604052348015600e575f80fd5b50600436106030575f3560e01c80632125b65b146034578063b69ef8a8146044575b5f80fd5b6044603f3660046046565b505050565b005b5f805f606084860312156057575f80fd5b833563ffffffff811681146069575f80fd5b925060208401356001600160a01b03811681146083575f80fd5b915060408401356001600160e01b0381168114609d575f80fd5b80915050925092509256' print(function_selectors(code)) # ['2125b65b', 'b69ef8a8'] print(function_arguments(code, '2125b65b')) # uint32,address,uint224 print(function_state_mutability(code, '2125b65b')) # pure ``` ### Foundry Foundy's cast uses the Rust implementation of EVMole ```sh $ 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) ... ``` ## Benchmark ### function selectors FP/FN - [False Positive/False Negative](https://en.wikipedia.org/wiki/False_positives_and_false_negatives) errors; smaller is better
Dataset | evmole rs · js · py | whatsabi | sevm | evmhound | heimdall | smpl | |
largest1k 1000 addresses 24427 functions |
FP addrs | 1 🥈 | 0 🥇 | 0 🥇 | 75 | 18 | 95 |
FN addrs | 0 🥇 | 0 🥇 | 0 🥇 | 40 | 111 | 9 | |
FP funcs | 192 🥈 | 0 🥇 | 0 🥇 | 720 | 600 | 749 | |
FN funcs | 0 🥇 | 0 🥇 | 0 🥇 | 191 | 147 | 12 | |
Time | 0.5s · 0.7s · 0.6s | 3.2s | 44s(*) | 0.5s | 341s(*) | 1.8s | |
random50k 50000 addresses 1171102 functions |
FP addrs | 1 🥇 | 43 | 1 | 693 | 3 | 4136 |
FN addrs | 9 🥇 | 11 | 10 | 2903 | 4708 | 77 | |
FP funcs | 3 🥇 | 51 | 3 | 10798 | 29 | 14652 | |
FN funcs | 10 🥇 | 12 | 11 | 3538 | 6098 | 96 | |
Time | 4.5s · 8.5s · 7.8s | 54s | 2458s(*) | 6.1s | 8576s(*) | 46s | |
vyper 780 addresses 21244 functions |
FP addrs | 0 🥇 | 30 | 0 | 19 | 0 | 185 |
FN addrs | 0 🥇 | 780 | 21 | 300 | 780 | 480 | |
FP funcs | 0 🥇 | 30 | 0 | 19 | 0 | 197 | |
FN funcs | 0 🥇 | 21244 | 336 | 8273 | 21244 | 12971 | |
Time | 0.4s · 0.6s · 0.4s | 2.4s | 43s(*) | 0.4s | 27s(*) | 1.1s |
Dataset | evmole rs · js · py | heimdall | smpl | |
largest1k 24427 functions |
Errors | 14.0% 🥇 3410 |
31.1% 7593 |
58.3% 14242 |
Time | 1.1s · 4.8s · 1.4s | 342s(*) | 0.7s | |
random50k 1171102 functions |
Errors | 4.5% 🥇 52662 |
19.4% 227612 |
54.9% 643213 |
Time | 25s · 127 · 32 | 8544s(*) | 9.5s | |
vyper 21244 functions |
Errors | 48.5% 🥇 10300 |
100.0% 21244 |
56.8% 12077 |
Time | 0.8s · 3.0s · 1.0s | 28s(*) | 0.6s |
Dataset | evmole rs · js · py | whatsabi | sevm | heimdall | smpl | |
largest1k 24427 functions |
Errors | 0.0% 🥇 0 |
68.1% 16623 |
2.1% 501 |
25.4% 6201 |
2.6% 643 |
Errors strict | 18.7% 🥇 4558 |
79.3% 19370 |
59.0% 14417 |
54.9% 13403 |
60.9% 14864 |
|
Time | 9.5s · 19s · 9.4s | 3.8s | 46s(*) | 339s(*) | 0.7s | |
random50k 1160861 functions |
Errors | 0.0% 🥇 35 |
30.2% 351060 |
0.3% 3370 |
11.6% 134195 |
2.2% 24961 |
Errors strict | 6.7% 🥇 77945 |
58.1% 674922 |
55.7% 646831 |
27.7% 321494 |
57.7% 670318 |
|
Time | 214s · 471s · 240s | 85s | 2331s(*) | 8151s(*) | 9.4s | |
vyper 21166 functions |
Errors | 0.5% 🥇 110 |
100.0% 21166 |
77.8% 16462 |
100.0% 21166 |
1.8% 390 |
Errors strict | 4.2% 🥇 888 |
100.0% 21166 |
91.0% 19253 |
100.0% 21166 |
59.6% 12610 |
|
Time | 10s · 15s · 10s | 2.4s | 41s(*) | 28s(*) | 0.6s |