How Locksley scans a token

Everything below runs live against Robinhood Chain (chain id 4663) when you open a report. Nothing is cached longer than 90 seconds and no transaction is ever sent.

1 · Buy / sell simulation

A small probe contract is placed at the Uniswap Universal Router address inside an eth_call with state overrides, so the pool and its hook see a normal router as the sender. The probe buys the token with 0.001 ETH (or 5 USDG), transfers half to a second probe address, sells its half, then asks the second address to sell too. Each step runs as a separate self-call so a revert is captured and reported instead of hiding the other results. If the buy works but a sell reverts, the token is a honeypot. A sell that fails only from the second wallet means the token restricts transfers.

2 · Hook fee isolation

For hooked pools the same simulation is replayed with the hook's code replaced by an empty pass-through hook. The pool id and price are identical, so the only difference in output is what the hook took. That number is reported as the hook fee; transfer taxes (tokens lost on take or on wallet transfers) are measured separately; the LP fee comes from the pool key. Buy tax = hook fee + transfer tax on the buy path, LP fee excluded.

3 · Liquidity positions

ModifyLiquidity events of the pool are read for the launch window and the latest window, aggregated per position and priced with the current pool state. Positions minted through the PositionManager are traced to their NFT owner: a dead address means burned, a verified contract named like a locker means locked, any other contract is listed by name, and a plain wallet means the liquidity can be withdrawn at any time. The full history is built progressively: every scan advances a durable per-pool index (stored server-side) and keeps indexing for a few minutes after the report is served, so coverage grows with each visit until it reaches 100%. The report shows the coverage reached so far.

3b · Holder map

Every Transfer of the token since its creation is indexed into balances and a transfer graph. The report shows the top 25 holders as a bubble map, the share held by the top 10 wallets, and the share held by wallets that received tokens directly from the deployer (a common shape for hidden team allocations). The pool, the Locksley Vault, dead addresses and known contracts are labelled. Like the liquidity history, the holder index is progressive and durable: coverage grows with each visit.

4 · Owner powers

The runtime bytecode is walked opcode by opcode. Function selectors found in the dispatcher are matched against a catalogue of privileged signatures (mint, blacklist, pause, trading toggles, tax setters, limits, upgrades, rescue). DELEGATECALL / SELFDESTRUCT / CREATE2 are flagged, EIP-1967 and EIP-1167 proxies are detected and the implementation is analysed instead. Sourcify supplies verification status, contract names and the compiler; Uniswap's hooklist supplies hook metadata (permissions, swap access, upgradeability).

Score

Start at 100. Every finding lists its own deduction, so the number is always explainable. A honeypot is 0 regardless of anything else. 85+ is an A, 70+ B, 55+ C, 40+ D, below that F. DANGER is a honeypot or a score under 40, CAUTION under 70, otherwise LOOKS OK — which means the automated checks passed, not that the token is a good buy.

Locksley Vault

Warden holds Uniswap v4 LP NFTs. The lock owner can claim swap fees at any time: Warden itself builds the PositionManager call as DECREASE_LIQUIDITY(0) + TAKE_PAIR, and that is the only call it can make, so liquidity cannot leave before the unlock time. Locks can be extended or made permanent (FOREVER), never shortened; a permanent lock keeps the NFT alive so fees remain claimable, unlike burning. Hollow locks ERC-20 tokens or vests them linearly with a cliff, recording the amount that actually arrived (fee-on-transfer safe). Neither contract has any admin power over locked assets; the owner can only change the flat fee (capped at 0.01 ETH) and its recipient. A token whose LP NFT sits in Warden gets a “locked in Locksley Vault” finding in every scan, read from the contract at scan time.

API

GET /api/scan/<address> returns the full report as JSON (optionally ?pool=<poolId> to force a specific v4 pool). GET /api/vault/<lockId> returns a lock. GET /api/index/<poolId>?from=<initBlock> advances a pool's history index for up to two minutes and returns the coverage; GET /api/index-status/<address>?pool=<poolId> reports how far the liquidity and holder indexes have got. GET /api/badge/<address> returns an SVG badge with the live score you can embed on your own site (<img src="…/api/badge/0x…">). Numbers that don't fit in JSON are decimal strings. Limits: 30 scans and 60 badge loads per 10 minutes per client; CORS is open.