npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@liulinhui151/whatsabi

v0.0.4

Published

Guess an ABI from Ethereum bytecode, even if it's unverified

Downloads

104

Readme

WhatsABI

WhatsABI

Guess an ABI from an Ethereum contract address, even if it's unverified.

WhatsABI does bounded-complexity static analysis to disassemble EVM bytecode and map out the possible call flows, which allows us to discover function selectors and other metadata about the contract.

WhatsABI is perfect for building procedural frontends, embedding in wallets, block explorers, or doing bytecode analysis.

Features

WhatsABI is different from other EVM analysis tools in some important ways:

  • Built in Typescript with minimal dependencies, so that it is runnable in the browser and embeddable in wallets.
  • Algorithms used are limited to O(instructions) with a small constant factor, so that complex contracts don't cause it to time out or use unbounded memory.
  • Does not rely on source code, so it works with unverified contracts.
  • Does not assume the source language, so it can work for source languages other than Solidity (Vyper, or even hand-written assembly).
  • Permissive open source (MIT-licensed), so that anyone can use it.

What can WhatsABI do?

  • Return selectors from bytecode.
  • Look up function signatures from selectors.
  • ✨ Resolve proxy contracts!
  • Small bundle (less than 15 KB) that works with Ethers.js, Viem, and others.

Usage

import { ethers } from "ethers";
import { whatsabi } from "@shazow/whatsabi";

const provider = ethers.getDefaultProvider(); // substitute with your fav provider
const address = "0x00000000006c3852cbEf3e08E8dF289169EdE581"; // Or your fav contract address
const code = await provider.getCode(address); // Load the bytecode

// Get just the callable selectors
const selectors = whatsabi.selectorsFromBytecode(code);
console.log(selectors); // -> ["0x06fdde03", "0x46423aa7", "0x55944a42", ...]

// Get an ABI-like list of interfaces
const abi = whatsabi.abiFromBytecode(code);
console.log(abi);
// -> [
//  {"type": "event", "hash": "0x721c20121297512b72821b97f5326877ea8ecf4bb9948fea5bfcb6453074d37f"},
//  {"type": "function", "payable": true, "selector": "0x06fdde03", ...},
//  {"type": "function", "payable": true, "selector": "0x46423aa7", ...},
//   ...

// We also have a suite of database loaders for convenience
const signatureLookup = new whatsabi.loaders.OpenChainSignatureLookup();
console.log(await signatureLookup.loadFunctions("0x06fdde03"));
// -> ["name()"]);
console.log(await signatureLookup.loadFunctions("0x46423aa7"));
// -> ["getOrderStatus(bytes32)"]);

// We also have event loaders!
console.log(await signatureLookup.loadEvents("0x721c20121297512b72821b97f5326877ea8ecf4bb9948fea5bfcb6453074d37f"));
// -> ["CounterIncremented(uint256,address)"]

// There are more fancy loaders in whatsabi.loaders.*, take a look!

// Here's a multiloader with an Etherscan API key, it can be used with autoload below.
// Each source will be attempted until a result is found.
const abiLoader = new whatsabi.loaders.MultiABILoader([
  new whatsabi.loaders.SourcifyABILoader(),
  new whatsabi.loaders.EtherscanABILoader({
    apiKey: "...", // Replace the value with your Etherscan API key
  }),
]);
console.log(await abiLoader.loadABI(address));

Bonus do-all-the-things helper:

...

let result = await whatsabi.autoload(address, {
  provider: provider,

  // * Optional loaders:
  // abiLoader: whatsabi.loaders.defaultABILoader,
  // signatureLoader: whatsabi.loaders.defaultSignatureLookup,

  // There is a handy helper for adding the default loaders but with your own settings
  ... whatsabi.loaders.defaultsWithEnv({
    SOURCIFY_CHAIN_ID: 42161,
    ETHERSCAN_BASE_URL: "https://api.arbiscan.io/api",
    ETHERSCAN_API_KEY: "MYSECRETAPIKEY",
  }),

  // * Optional hooks:
  // onProgress: (phase: string) => { ... }
  // onError: (phase: string, context: any) => { ... }

  onProgress: (phase) => console.log("autoload progress", phase),
  onError: (phase, context) => console.log("autoload error", phase, context),

  // * Optional settings:
  // followProxies: false,
  // enableExperimentalMetadata: false,
});

console.log(result.abi);

// Detail will vary depending on whether `address` source code was available,
// or if bytecode-loaded selector signatures were available, or
// if WhatsABI had to guess everything from just bytecode.

// We can even detect and resolve proxies!
if (result.followProxies) {
    console.log("Proxies detected:", result.proxies);

    result = await result.followProxies();
    console.log(result.abi);
}

Or we can auto-follow resolved proxies, and expand parts of the result object:

const { abi, address } = await whatsabi.autoload(
    "0x4f8AD938eBA0CD19155a835f617317a6E788c868",
    {
        provider,
        followProxies: true,
    },
});

console.log("Resolved to:", address);
// -> "0x964f84048f0d9bb24b82413413299c0a1d61ea9f"

See Also

Some Cool People Said...

Omg WhatsABI by @shazow is so good that it can solve CTFs.
In one of my CTFs, students are supposed to find calldata that doesn’t revert
WhatsABI just spits out the solution automatically😂 I’m impressed!👏

🗣️ Nazar Ilamanov, creator of monobase.xyz

WhatsABI by @shazow takes contract bytecode, disassembled it into a set of EVM instructions, and then looks for the common Solidity's dispatch pattern.
Check out the source, it's actually very elegant!

🗣️ WINTΞR, creator of abi.w1nt3r.xyz

really cool stuff from @shazow
deduce a contract's ABI purely from bytecode

🗣️ t11s, from Paradigm

Caveats

  • Finding valid function selectors works great!
  • Detecting Solidity-style function modifiers (view, payable, etc) is still unreliable.
  • There's some minimal attempts at guessing the presence of arguments, but also unreliable.
  • Call graph traversal only supports static jumps right now. Dynamic jumps are skipped until we add abstract stack tracing, this is the main cause of above's unreliability.
  • Event parsing is janky, haven't found a reliable pattern so assume it's best effort. Feel free to open an issue with good failure examples, especially false negatives.

Development

$ cat .env  # Write an .env file with your keys, or `cp .env.example .env`
export INFURA_API_KEY="..."
export ETHERSCAN_API_KEY="..."
$ nix develop  # Or use your system's package manager to install node/ts/etc
[dev] $ npm install
[dev] $ ONLINE=1 make test

Thanks

  • ethers.js for being excellent, and having a helpful assembler sub-package was inspiring.
  • @jacobdehart for the library name and logo that is totally a wasabi and not a green poop!

License

MIT