
Assayer
Assayer is a noncustodial token safety scanner built around forked-state simulation. Given an ERC-20 address and a chain RPC, it forks the live chain at a pinned block, funds a fresh throwaway account by overriding balances in the fork (no real funds), and then actually buys the token through the chain's DEX router, transfers it, and sells it back, measuring whether the sell succeeds, the effective buy and sell taxes, and the transfer gas. A second layer reads the deployed bytecode, resolves proxies, flags dangerous owner capabilities, and checks heuristics like liquidity locking. The two layers merge into one serde report. The whole tool is built on a hard principle: it reduces risk and never certifies safety, so it emits no "safe" verdict, keeps sellable: None (unknown) distinct from Some(false) (proven), and attaches its limitations to every report. It is published to crates.io as an embeddable crate, ships a CLI and a self-hostable service with a web UI, and is proven against real tokens, including a confirmed honeypot it correctly reports as cannot-sell.
GitHub Repository: https://github.com/frdrckj/tokenassayer
Crates: tokenassayer-core · tokenassayer-cli
Features
- Buy / Sell / Transfer Simulation: The behavioral heart. It funds a fresh, unprivileged account via state override, buys the token through the DEX router, transfers it to another account, then sells it back, computing
sellable, effective buy and sell taxes in basis points against the AMM quote, and transfer gas. A second fresh account repeats the buy and sell, catching "only the first buyer can sell" and transfer-restriction honeypots that static analysis alone misses. - Fork Database: A revm
DatabaseRefbacked by an Alloy provider that lazily fetches accounts and storage, caches them in memory, and pins every read to one block for determinism. The sync-to-async bridge runs the engine off any Tokio worker so the library cannot panic on a buggy or current-thread caller, honoring the never-panic contract for code embedded in other people's services. - Static Analysis: Fetches deployed bytecode and resolves proxies, EIP-1167 minimal clones and EIP-1967 transparent and beacon proxies, so it analyzes the real implementation rather than the shell. It flags dangerous capabilities by scanning runtime
PUSH4selectors (mint, blacklist, pause, fee and tax setters, max-transaction and max-wallet limits, trading toggles) and checks whether ownership is renounced by reading the live owner. - Liquidity and Holder Heuristics: Weaker, clearly-labeled signals: the share of DEX LP held by the burn address or a known locker, and the owner's share of supply as a concentration proxy. Each carries
Evidence::Heuristicand documents its false-positive modes, so deep distributed liquidity is never mistaken for proof of a rug. - Honesty by Construction: Never emits a "safe" verdict, only "no traps detected in this simulation."
sellable: None(could not determine) is distinct fromSome(false)(proven not sellable), so a verdict is never fabricated when the simulation cannot run. Every report carries disclaimers, and a flag is framed as a reason to investigate, not proof of malice (a legitimate token like Binance-Peg USDT is correctly flagged as mintable with a live owner). - Cross-Chain, Config-Only: Runs on BNB Chain (PancakeSwap v2), Ethereum, and Base (Uniswap v2). The engine is chain-generic, so adding a chain is pure configuration (router, factory, wrapped-native, lockers) with no code changes, and
Chainis#[non_exhaustive]so new chains stay non-breaking. - Risk Score: A saturating, severity-weighted aggregate from 0 to 100, deliberately shown only next to the individual flags and the disclaimers, never on its own.
- Adversarial Multi-Agent Review: A fan-out review of the tax math, the fork bridge, the detectors, the public API, and the never-panic contract, where every finding is refuted or confirmed by an independent skeptic. It surfaced ten real issues, all since fixed, including a buy-tax measurement bias, a beacon-proxy false negative, and a fabricated-blockhash bug.
- Real-Token Proof and CI: A fixture suite asserts verdicts against reality: a GoPlus-confirmed honeypot reports cannot-sell with critical flags, while blue chips (CAKE, USDT, USDC) report sellable across all three chains. It also proves determinism (same token and block yields an identical report) and a never-panic robustness contract over garbage input, with unit tests for every static detector and the tax math. CI runs fmt, clippy with warnings denied, and the test suite.
- Library, CLI, Service, and Live Dashboard: Published to crates.io as
tokenassayer-core(embeddable) andtokenassayer-cli. A self-hostable axum service exposesGET /check,/health, and/metricswith a per-chain RPC, a concurrency cap, and a per-scan timeout, and serves a single-page web UI, paste an address, pick a chain, and the assay renders as a report with a hallmark verdict stamp, severity-graded findings, and always-visible limitations. The whole thing runs from source with one command.
Stack
• Scanner Core & CLI
- Rust - The scanner core, simulation engine, and CLI.
- revm - Local EVM execution against the forked chain state.
- Alloy - RPC providers, primitive types, and ABI encoding via the
sol!macro (not the deprecated ethers-rs). - clap - The
tokenassayercommand-line interface.
• Engine & Service
- Tokio - Async runtime and the off-runtime engine thread that drives the synchronous EVM.
- axum - REST API (
/check), health and Prometheus-style metrics endpoints, and the web UI route. - serde / tracing - The serializable
RiskReportcontract and structured logging.
• Quality & Distribution
- crates.io - Published, embeddable
tokenassayer-coreandtokenassayer-cli. - GitHub Actions - CI across fmt, clippy (warnings denied), and the test suite.
• Demo Dashboard
- A single static HTML page served by the engine, with no build step.