{
  "markdown": "![EVMole](./.github/logo.svg)\n\n[![try it online](https://img.shields.io/badge/Try_It_Online-evmole.xyz-brightgreen)](https://evmole.xyz/)\n[![npm](https://img.shields.io/npm/v/evmole)](https://www.npmjs.com/package/evmole)\n[![Crates.io](https://img.shields.io/crates/v/evmole?color=e9b44f)](https://crates.io/crates/evmole)\n[![PyPI](https://img.shields.io/pypi/v/evmole?color=006dad)](https://pypi.org/project/evmole)\n[![Go](https://img.shields.io/badge/go-pkg-00ADD8)](https://pkg.go.dev/github.com/cdump/evmole/go)\n\nEVMole 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, [state mutability](https://docs.soliditylang.org/en/latest/contracts.html#state-mutability), persistent and transient storage layouts, and CBOR metadata, even for unverified contracts.\n\n## Key Features\n\n- Multi-language support: Available as [JavaScript](#javascript), [Rust](#rust), [Python](#python), and [Go](#go) libraries.\n- High accuracy and performance: [Outperforms](#benchmark) existing tools.\n- Broad compatibility: Tested with both Solidity and Vyper compiled contracts.\n- Lightweight: Clean codebase with minimal external dependencies.\n- Unverified contract analysis: Extracts information even from unverified bytecode.\n- Selector dispatch classification: Distinguishes normal ABI dispatch from selectors handled by fallback logic.\n- CBOR metadata: Extracts string-keyed values from a terminal, length-suffixed CBOR map without assuming a particular compiler.\n\n\n## Usage\n### JavaScript\n[API documentation](./javascript/#api) and [usage examples](./javascript/#usage) (Node.js, Vite, webpack, Parcel, esbuild)\n```sh\nnpm i evmole\n```\n```javascript\nimport { contractInfo } from 'evmole'\n\nconst code = '0x6080604052348015600e575f80fd5b50600436106030575f3560e01c80632125b65b146034578063b69ef8a8146044575b5f80fd5b6044603f3660046046565b505050565b005b5f805f606084860312156057575f80fd5b833563ffffffff811681146069575f80fd5b925060208401356001600160a01b03811681146083575f80fd5b915060408401356001600160e01b0381168114609d575f80fd5b80915050925092509256'\n\nconsole.log( contractInfo(code, {selectors:true, arguments:true, stateMutability:true}) )\n// {\n//   functions: [\n//     {\n//       selector: '2125b65b',\n//       bytecodeOffset: 52,\n//       dispatch: 'abi',\n//       arguments: 'uint32,address,uint224',\n//       stateMutability: 'pure'\n//     },\n//     ...\n```\n\n### Rust\nDocumentation is available on [docs.rs](https://docs.rs/evmole/latest/evmole/)\n```rust\nlet code = hex::decode(\"6080604052348015600e575f80fd5b50600436106030575f3560e01c80632125b65b146034578063b69ef8a8146044575b5f80fd5b6044603f3660046046565b505050565b005b5f805f606084860312156057575f80fd5b833563ffffffff811681146069575f80fd5b925060208401356001600160a01b03811681146083575f80fd5b915060408401356001600160e01b0381168114609d575f80fd5b80915050925092509256\").unwrap();\n\nprintln!(\"{:?}\", evmole::contract_info(\n    evmole::ContractInfoArgs::new(&code)\n        .with_selectors()\n        .with_arguments()\n        .with_state_mutability()\n    )\n);\n// Contract {\n//     functions: Some([\n//         Function {\n//             selector: [33, 37, 182, 91],\n//             bytecode_offset: 52,\n//             dispatch: Abi,\n//             arguments: Some([Uint(32), Address, Uint(224)]),\n//             state_mutability: Some(Pure)\n//         },\n//         ...\n```\n\n### Python\n[API documentation](./python/#api)\n```sh\npip install evmole --upgrade\n```\n```python\nfrom evmole import contract_info\n\ncode = '0x6080604052348015600e575f80fd5b50600436106030575f3560e01c80632125b65b146034578063b69ef8a8146044575b5f80fd5b6044603f3660046046565b505050565b005b5f805f606084860312156057575f80fd5b833563ffffffff811681146069575f80fd5b925060208401356001600160a01b03811681146083575f80fd5b915060408401356001600160e01b0381168114609d575f80fd5b80915050925092509256'\n\nprint( contract_info(code, selectors=True, arguments=True, state_mutability=True) )\n# Contract(\n#     functions=[\n#     Function(\n#             selector=2125b65b,\n#             bytecode_offset=52,\n#             dispatch=\"abi\",\n#             arguments=uint32,address,uint224,\n#             state_mutability=pure),\n#     ...\n```\n\n### Go\n[API documentation](./go/#api-reference)\n```sh\ngo get github.com/cdump/evmole/go\n```\n```go\npackage main\n\nimport (\n    \"context\"\n    \"encoding/hex\"\n    \"fmt\"\n\n    \"github.com/cdump/evmole/go\"\n)\n\nfunc main() {\n    code, _ := hex.DecodeString(\"6080604052348015600e575f80fd5b50600436106030575f3560e01c80632125b65b146034578063b69ef8a8146044575b5f80fd5b6044603f3660046046565b505050565b005b5f805f606084860312156057575f80fd5b833563ffffffff811681146069575f80fd5b925060208401356001600160a01b03811681146083575f80fd5b915060408401356001600160e01b0381168114609d575f80fd5b80915050925092509256\")\n\n    info, _ := evmole.ContractInfo(context.Background(), code, evmole.Options{\n        Selectors:       true,\n        Arguments:       true,\n        StateMutability: true,\n    })\n\n    for _, fn := range info.Functions {\n        fmt.Printf(\"%s: %s @ %d\\n\", fn.Selector, *fn.Arguments, fn.BytecodeOffset)\n    }\n    // 2125b65b: uint32,address,uint224 @ 52\n    // b69ef8a8:  @ 68\n}\n```\n\n### Foundry\n<a href=\"https://getfoundry.sh/\">Foundry's cast</a> uses the Rust implementation of EVMole\n```sh\n\n$ cast selectors $(cast code 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2)\n0x06fdde03                           view\n0x095ea7b3  address,uint256          nonpayable\n0x18160ddd                           view\n0x23b872dd  address,address,uint256  nonpayable\n...\n\n$ cast selectors --resolve $(cast code 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2)\n0x06fdde03                           view        name()\n0x095ea7b3  address,uint256          nonpayable  approve(address,uint256)\n0x18160ddd                           view        totalSupply()\n0x23b872dd  address,address,uint256  nonpayable  transferFrom(address,address,uint256)\n...\n```\n\n### AI agents\n\nFor application code, use one of the language bindings above. For agent-driven\nbytecode analysis, choose one integration.\n\n#### JSON CLI\n\nUse for one-off analysis and scripts:\n\n```bash\nnpx -y evmole analyze --bytecode 0x...\n```\n\n#### Portable skill\n\nInstall routing and interpretation guidance for supported agents:\n\n```bash\nnpx skills add cdump/evmole --skill evm-bytecode-analysis -g\n```\n\n#### Local MCP server\n\nExpose EVMole as a typed local tool:\n\n```bash\nnpx -y evmole-mcp\n```\n\nAll integrations expect deployed/runtime bytecode and run locally without\nsending bytecode to an EVMole-operated service. See the\n[agent integration guide](./agent/README.md) for setup, schemas,\nlimitations, and privacy details.\n\n\n## Benchmark\n\n### function selectors\n<i>FP/FN</i> - [False Positive/False Negative](https://en.wikipedia.org/wiki/False_positives_and_false_negatives) errors; <b>smaller is better</b>\n\n<table>\n <tr>\n  <td>Dataset</td>\n  <td></td>\n  <td><b><i>evmole</i></b> <a href=\"benchmark/providers/evmole-rs/\"><b><i>rs</i></b></a> · <a href=\"benchmark/providers/evmole-js/\"><b><i>js</i></b></a> · <a href=\"benchmark/providers/evmole-py/\"><b><i>py</i></b></a> · <a href=\"benchmark/providers/evmole-go/\"><b><i>go</i></b></a></td>\n  <td><a href=\"benchmark/providers/whatsabi/\"><b><i>whatsabi</i></b></a></td>\n  <td><a href=\"benchmark/providers/sevm/\"><b><i>sevm</i></b></a></td>\n  <td><a href=\"benchmark/providers/evm-hound-rs/\"><b><i>evmhound</i></b></a></td>\n  <td><a href=\"benchmark/providers/heimdall-rs/\"><b><i>heimdall</i></b></a></td>\n </tr>\n <tr>\n  <td rowspan=\"5\"><b>coverage2k</b><br><sub>solidity<br><br>2000<br>addresses<br><br>45650<br>functions</sub></td>\n  <td><i>FP <sub>addrs</sub></i></td>\n  <td>0 🥇</td>\n  <td>4</td>\n  <td>1</td>\n  <td>56</td>\n  <td>3</td>\n </tr>\n <tr>\n  <td><i>FN <sub>addrs</sub></i></td>\n  <td>0 🥇</td>\n  <td>11</td>\n  <td>0 🥇</td>\n  <td>224</td>\n  <td>166</td>\n </tr>\n <tr>\n  <td><i>FP <sub>funcs</sub></i></td>\n  <td>0 🥇</td>\n  <td>10</td>\n  <td>10</td>\n  <td>616</td>\n  <td>27</td>\n </tr>\n <tr>\n  <td><i>FN <sub>funcs</sub></i></td>\n  <td>0 🥇</td>\n  <td>145</td>\n  <td>0 🥇</td>\n  <td>821</td>\n  <td>342</td>\n </tr>\n <tr>\n  <td><i>Time</i></td>\n  <td>24ms · 0.3s · 31ms · 0.1s</td>\n  <td>2.0s</td>\n  <td>28s<sup>(*)</sup></td>\n  <td>86ms</td>\n  <td>111s<sup>(*)</sup></td>\n </tr>\n <tr><td colspan=\"7\"></td></tr>\n <tr>\n  <td rowspan=\"5\"><b>random10k</b><br><sub>solidity<br><br>10000<br>addresses<br><br>223316<br>functions</sub></td>\n  <td><i>FP <sub>addrs</sub></i></td>\n  <td>0 🥇</td>\n  <td>19</td>\n  <td>16</td>\n  <td>224</td>\n  <td>7</td>\n </tr>\n <tr>\n  <td><i>FN <sub>addrs</sub></i></td>\n  <td>0 🥇</td>\n  <td>44</td>\n  <td>1</td>\n  <td>838</td>\n  <td>819</td>\n </tr>\n <tr>\n  <td><i>FP <sub>funcs</sub></i></td>\n  <td>0 🥇</td>\n  <td>65</td>\n  <td>112</td>\n  <td>3157</td>\n  <td>260</td>\n </tr>\n <tr>\n  <td><i>FN <sub>funcs</sub></i></td>\n  <td>0 🥇</td>\n  <td>173</td>\n  <td>7</td>\n  <td>4112</td>\n  <td>1021</td>\n </tr>\n <tr>\n  <td><i>Time</i></td>\n  <td>0.1s · 0.8s · 0.2s · 0.8s</td>\n  <td>7.1s</td>\n  <td>80s<sup>(*)</sup></td>\n  <td>0.4s</td>\n  <td>533s<sup>(*)</sup></td>\n </tr>\n <tr><td colspan=\"7\"></td></tr>\n <tr>\n  <td rowspan=\"5\"><b>coverage1k</b><br><sub>vyper<br><br>1000<br>addresses<br><br>38759<br>functions</sub></td>\n  <td><i>FP <sub>addrs</sub></i></td>\n  <td>0 🥇</td>\n  <td>560</td>\n  <td>0 🥇</td>\n  <td>2</td>\n  <td>0 🥇</td>\n </tr>\n <tr>\n  <td><i>FN <sub>addrs</sub></i></td>\n  <td>0 🥇</td>\n  <td>998</td>\n  <td>788</td>\n  <td>525</td>\n  <td>998</td>\n </tr>\n <tr>\n  <td><i>FP <sub>funcs</sub></i></td>\n  <td>0 🥇</td>\n  <td>560</td>\n  <td>0 🥇</td>\n  <td>5</td>\n  <td>0 🥇</td>\n </tr>\n <tr>\n  <td><i>FN <sub>funcs</sub></i></td>\n  <td>0 🥇</td>\n  <td>38759</td>\n  <td>34077</td>\n  <td>16218</td>\n  <td>38759</td>\n </tr>\n <tr>\n  <td><i>Time</i></td>\n  <td>91ms · 0.4s · 0.1s · 0.3s</td>\n  <td>1.9s</td>\n  <td>5.4s<sup>(*)</sup></td>\n  <td>67ms</td>\n  <td>12s<sup>(*)</sup></td>\n </tr>\n</table>\n\n### function arguments\n<i>Errors</i> - when at least 1 inferred argument is incorrect: `(uint256,string)` ≠ `(uint256,bytes)`\n\n<table>\n <tr>\n  <td>Dataset</td>\n  <td></td>\n  <td><b><i>evmole</i></b> <a href=\"benchmark/providers/evmole-rs/\"><b><i>rs</i></b></a> · <a href=\"benchmark/providers/evmole-js/\"><b><i>js</i></b></a> · <a href=\"benchmark/providers/evmole-py/\"><b><i>py</i></b></a> · <a href=\"benchmark/providers/evmole-go/\"><b><i>go</i></b></a></td>\n  <td><a href=\"benchmark/providers/heimdall-rs/\"><b><i>heimdall</i></b></a></td>\n </tr>\n <tr>\n  <td rowspan=\"2\"><b>coverage2k</b><br><sub>solidity<br><br>45650<br>functions</sub></td>\n  <td><i>Errors</i></td>\n  <td>8.5% 🥇<br><sub>3883</sub></td>\n  <td>23.3%<br><sub>10643</sub></td>\n </tr>\n <tr>\n  <td><i>Time</i></td>\n  <td>0.8s · 1.7s · 1.1s · 2.1s</td>\n  <td>111s<sup>(*)</sup></td>\n </tr>\n <tr><td colspan=\"4\"></td></tr>\n <tr>\n  <td rowspan=\"2\"><b>random10k</b><br><sub>solidity<br><br>223316<br>functions</sub></td>\n  <td><i>Errors</i></td>\n  <td>6.8% 🥇<br><sub>15296</sub></td>\n  <td>21.4%<br><sub>47878</sub></td>\n </tr>\n <tr>\n  <td><i>Time</i></td>\n  <td>3.5s · 6.9s · 4.2s · 9.7s</td>\n  <td>511s<sup>(*)</sup></td>\n </tr>\n <tr><td colspan=\"4\"></td></tr>\n <tr>\n  <td rowspan=\"2\"><b>coverage1k</b><br><sub>vyper<br><br>38759<br>functions</sub></td>\n  <td><i>Errors</i></td>\n  <td>45.4% 🥇<br><sub>17590</sub></td>\n  <td>100.0%<br><sub>38759</sub></td>\n </tr>\n <tr>\n  <td><i>Time</i></td>\n  <td>0.5s · 1.1s · 0.6s · 1.4s</td>\n  <td>12s<sup>(*)</sup></td>\n </tr>\n</table>\n\n### function state mutability\n\n<i>Errors</i> - Results are not equal (treating `view` and `pure` as equivalent to `nonpayable`)\n\n<i>Errors strict</i> - Results are strictly unequal (`nonpayable` ≠ `view`). Some ABIs mark `pure`/`view` functions as `nonpayable`, so not all strict errors indicate real issues.\n\n<table>\n <tr>\n  <td>Dataset</td>\n  <td></td>\n  <td><b><i>evmole</i></b> <a href=\"benchmark/providers/evmole-rs/\"><b><i>rs</i></b></a> · <a href=\"benchmark/providers/evmole-js/\"><b><i>js</i></b></a> · <a href=\"benchmark/providers/evmole-py/\"><b><i>py</i></b></a> · <a href=\"benchmark/providers/evmole-go/\"><b><i>go</i></b></a></td>\n  <td><a href=\"benchmark/providers/whatsabi/\"><b><i>whatsabi</i></b></a></td>\n  <td><a href=\"benchmark/providers/sevm/\"><b><i>sevm</i></b></a></td>\n  <td><a href=\"benchmark/providers/heimdall-rs/\"><b><i>heimdall</i></b></a></td>\n </tr>\n <tr>\n  <td rowspan=\"3\"><b>coverage2k</b><br><sub>solidity<br><br>45647<br>functions</sub></td>\n  <td><i>Errors</i></td>\n  <td>0.0% 🥇<br><sub>18</sub></td>\n  <td>52.2%<br><sub>23810</sub></td>\n  <td>11.2%<br><sub>5133</sub></td>\n  <td>19.6%<br><sub>8951</sub></td>\n </tr>\n <tr>\n  <td><i>Errors strict</i></td>\n  <td>9.0% 🥇<br><sub>4107</sub></td>\n  <td>70.9%<br><sub>32346</sub></td>\n  <td>62.3%<br><sub>28429</sub></td>\n  <td>41.3%<br><sub>18835</sub></td>\n </tr>\n <tr>\n  <td><i>Time</i></td>\n  <td>10s · 11s · 9.7s · 20s</td>\n  <td>3.1s</td>\n  <td>29s<sup>(*)</sup></td>\n  <td>112s<sup>(*)</sup></td>\n </tr>\n <tr><td colspan=\"6\"></td></tr>\n <tr>\n  <td rowspan=\"3\"><b>random10k</b><br><sub>solidity<br><br>223273<br>functions</sub></td>\n  <td><i>Errors</i></td>\n  <td>0.0% 🥇<br><sub>39</sub></td>\n  <td>48.8%<br><sub>108928</sub></td>\n  <td>9.3%<br><sub>20713</sub></td>\n  <td>18.6%<br><sub>41507</sub></td>\n </tr>\n <tr>\n  <td><i>Errors strict</i></td>\n  <td>8.9% 🥇<br><sub>19940</sub></td>\n  <td>69.9%<br><sub>156081</sub></td>\n  <td>60.9%<br><sub>136069</sub></td>\n  <td>40.1%<br><sub>89519</sub></td>\n </tr>\n <tr>\n  <td><i>Time</i></td>\n  <td>48s · 50s · 46s · 88s</td>\n  <td>12s</td>\n  <td>81s<sup>(*)</sup></td>\n  <td>512s<sup>(*)</sup></td>\n </tr>\n <tr><td colspan=\"6\"></td></tr>\n <tr>\n  <td rowspan=\"3\"><b>coverage1k</b><br><sub>vyper<br><br>38278<br>functions</sub></td>\n  <td><i>Errors</i></td>\n  <td>0.1% 🥇<br><sub>34</sub></td>\n  <td>100.0%<br><sub>38278</sub></td>\n  <td>96.2%<br><sub>36814</sub></td>\n  <td>100.0%<br><sub>38278</sub></td>\n </tr>\n <tr>\n  <td><i>Errors strict</i></td>\n  <td>1.2% 🥇<br><sub>441</sub></td>\n  <td>100.0%<br><sub>38278</sub></td>\n  <td>98.4%<br><sub>37650</sub></td>\n  <td>100.0%<br><sub>38278</sub></td>\n </tr>\n <tr>\n  <td><i>Time</i></td>\n  <td>45s · 39s · 44s · 89s</td>\n  <td>2.0s</td>\n  <td>5.5s<sup>(*)</sup></td>\n  <td>12s<sup>(*)</sup></td>\n </tr>\n</table>\n\n### Control Flow Graph\n\n<i>False Negatives</i> - Valid blocks possibly incorrectly marked unreachable by CFG analysis. Lower count usually indicates better precision.\n\n<table>\n <tr>\n  <td></td>\n  <td><b><i>evmole</i></b> <a href=\"benchmark/providers/evmole-rs/\"><b><i>rs</i></b></a> · <a href=\"benchmark/providers/evmole-js/\"><b><i>js</i></b></a> · <a href=\"benchmark/providers/evmole-py/\"><b><i>py</i></b></a> · <a href=\"benchmark/providers/evmole-go/\"><b><i>go</i></b></a></td>\n  <td><a href=\"benchmark/providers/ethersolve\"><b><i>ethersolve</i></b></a></td>\n  <td><a href=\"benchmark/providers/evm-cfg\"><b><i>evm-cfg</i></b></a></td>\n  <td><a href=\"benchmark/providers/sevm\"><b><i>sevm</i></b></a></td>\n  <td><a href=\"benchmark/providers/heimdall-rs\"><b><i>heimdall-rs</i></b></a></td>\n  <td><a href=\"benchmark/providers/evm-cfg-builder\"><b><i>evm-cfg-builder</i></b></a></td>\n </tr>\n <tr>\n  <td><i>Basic Blocks</i></td>\n  <td>92.8% 🥇<br><sub>483212</sub></td>\n  <td>52.5%<br><sub>273518</sub></td>\n  <td>58.6%<br><sub>305248</sub></td>\n  <td>37.3%<br><sub>194368</sub></td>\n  <td>32.6%<br><sub>169980</sub></td>\n  <td>14.5%<br><sub>75383</sub></td>\n </tr>\n <tr>\n  <td><i>False Negatives</i></td>\n  <td>7.2% 🥇<br><sub>37496</sub></td>\n  <td>47.5%<br><sub>247190</sub></td>\n  <td>41.4%<br><sub>215460</sub></td>\n  <td>62.7%<br><sub>326340</sub></td>\n  <td>67.4%<br><sub>350728</sub></td>\n  <td>85.5%<br><sub>445325</sub></td>\n </tr>\n <tr>\n  <td><i>Time</i></td>\n  <td>14s · 26s · 12s · 55s</td>\n  <td>888s</td>\n  <td>36s</td>\n  <td>9.8s</td>\n  <td>20s</td>\n  <td>359s</td>\n </tr>\n</table>\n\ndataset flow-challenge500, 500 contracts, 520,708 blocks\n\n### notes\n\nSee [benchmark/README.md](./benchmark/) for the methodology and commands to reproduce these results\n\n<i>versions: evmole v0.9.3; <a href=\"https://github.com/shazow/whatsabi\">whatsabi</a> v0.25.0; <a href=\"https://github.com/acuarica/evm\">sevm</a> v0.7.4; <a href=\"https://github.com/g00dv1n/evm-hound-rs\">evm-hound-rs</a> v0.1.4; <a href=\"https://github.com/Jon-Becker/heimdall-rs\">heimdall-rs</a> v0.9.3</i>\n\n<sup>(*)</sup>: <b>sevm</b> and <b>heimdall-rs</b> are full decompilers, not limited to extracting function selectors\n\n## How it works\n\nEVMole uses symbolic execution with a custom EVM implementation to trace how CALLDATA flows through the bytecode:\n\nThis approach is more accurate than static pattern matching because it follows the actual execution paths the EVM would take, correctly handling complex dispatchers, proxy patterns, and compiler-specific optimizations from both Solidity and Vyper.\n\n## Talks\n- [EVMole: function selectors and arguments from bytecode](https://www.youtube.com/watch?v=l0udabGej54) - BlockSplit 2024\n- [EVMole: function selectors and arguments from bytecode](https://ethcc.io/archives/evmole-function-selectors-and-arguments-from-bytecode) - EthCC 2024\n- [Reconstructing Control Flow Graphs from EVM Bytecode](https://www.youtube.com/watch?v=1Xd6PhEHMHM) - ETHTaipei 2025\n- [Reconstructing Control Flow Graphs from EVM Bytecode: Faster, Better, Stronger](https://www.youtube.com/watch?v=UL6-3EZbv3E) - EthCC 2025\n\n## License\nMIT\n",
  "bytes": 17424,
  "sha": "3c0175c21083fa3b8226e28b14fd5eb68f3697540d93773a098041d534b444f3",
  "repo_slug": "cdump/evmole",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_cdump_evmole_4c9c0b9e/readme"
}