verify console
x402 v2Some B20 tokens keep issuer backdoors. There's no source to read.
Mint, freeze, seize, pause: B20 Check reads these rights straight from the chain and returns a signed verdict per token. $0.01 a call, EIP-712 signature, so you can recover the signer and verify the answer instead of trusting the API.
Started as an internal check for my own agents, now it's just open.
# paid route, the x402 exchange > GET /v1/verify/{address} < HTTP/1.1 402 Payment Required PAYMENT-REQUIRED: eyJ4NDAyVmVyc2lvbiI6Miw… decoded: { scheme "exact" network "eip155:8453" price "$0.01 USDC" payTo 0x26B57af5022250F01497F3e19dd537d01d124BA1 asset 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 } > GET again, X-PAYMENT: USDC payment signature < HTTP/1.1 200, signed verdict # this console calls the free demo route > GET /v1/demo/{address} < awaiting run
example response · run a check to replace it
- ADMIN_ACTIVE issuer admin role is active
- VIA_LAUNCHER deployed through a launcher
The live index
source /v1/stats · cached 10 minA token minted a minute ago still gets a verdict: anything newer than the snapshot is scanned live at request time. A check that cannot complete returns not_indexed, never a silent ok.
how to verify
Snapshot block and token count are returned by the free stats route:
curl -s https://b20check.com/v1/statsOne request, one payment, one signed verdict
x402 exact scheme · eip155:8453The x402 flow in four steps. No account setup on either side.
What the verdict covers
15 flags · 4 groupsB20 tokens are protocol-native on Base: no deployed source on an explorer, and the issuer can keep live control after launch. That leaves four groups of facts worth checking before any value moves.
Issuer powers
Whether the issuer can mint, freeze, seize or pause, whether admin rights are active, supply cap status and transfer restrictions. Reported as structured booleans, not prose.
Identity
Imposter and lookalike detection on names and symbols, plus recognition of canonical assets such as native USDC.
Activity
Observed on-chain issuer actions: mints, burns, freezes, seizures, pauses, role changes, and the block of the last action. What actually happened, not what could.
Data freshness
Every response states its data source: indexed, live, or not_indexed. A token that cannot be fully checked is never signed as ok. Missing data fails closed, never false-clean.
Verify the signature, not this page
EIP-712 · ~10 min TTLEvery verdict ships an EIP-712 attestation pinned to a Base block, with a roughly 10-minute TTL and a deterministic content id. To trust it, recompute the hash from the payload and recover the signer; the booleans in the response are just a convenience.
// 1. fetch the attestation from any verify response (paid or free demo)
// 2. recompute payloadHash from the canonical payload (UTF-8, no unicode escaping)
// 3. rebuild the EIP-712 message, recoverTypedDataAddress, compare to 0x1388d1e3751512955A53C7c2795Eaf8a3B029e6A
// 4. check now < expiresAt (a valid signature over an expired verdict is stale)The full EIP-712 types, domain, and canonical-payload recipe are published at /v1/schema (field x-attestationVerification), so you can recompute the hash without this repo.
Call it from code
discovery · CDP x402 BazaarNo signup, no keys, no subscription. Discover the price straight from the endpoint:
curl -i https://b20check.com/v1/verify/0xb2000000000000000000001fd821494127f35af0
# returns 402 with a base64 PAYMENT-REQUIRED header carrying price, payTo, assetOr let an x402 client pay automatically:
import { privateKeyToAccount } from "viem/accounts";
import { wrapFetchWithPayment, x402Client } from "@x402/fetch";
import { ExactEvmScheme } from "@x402/evm";
const account = privateKeyToAccount(process.env.AGENT_KEY);
const client = new x402Client().register("eip155:8453", new ExactEvmScheme(account));
const fetchPaid = wrapFetchWithPayment(fetch, client);
const res = await fetchPaid("https://b20check.com/v1/verify/" + token); // auto-pays on the 402
const check = await res.json();Or add it to your assistant
MCP · Claude / ChatGPTNo code needed: the check speaks the Model Context Protocol. Add it once as a connector, then ask in plain language whether a B20 token is safe. The assistant runs the check and reads you the verdict.
Paste this connector URL into Claude, under Settings then Connectors, or add it in ChatGPT as a custom MCP connector:
https://b20check.com/mcpPrefer a local server? The same tools ship as an npm package. For Claude Desktop and other clients that launch MCP servers themselves, add this to the config:
{ "mcpServers": { "b20check": { "command": "npx", "args": ["-y", "b20check-mcp"] } } }/v1/verify endpoint (x402) has no rate limitcom.b20check/b20check and on Smithery