Token scanners had a good run. Check the ERC-20 for a transfer tax, a blacklist function, a mint backdoor, an owner who can pause transfers — if the token contract is clean, the trade is probably mechanically fair. That assumption quietly broke when Uniswap v4 shipped.
The blind spot
In Uniswap v4, every pool can attach a hook: a contract the PoolManager calls before and after swaps, liquidity changes, and pool initialization. Hooks can revert your swap, reorder it, take a cut of it, or — with the return-delta permissions — take custody of tokens mid-swap.
Which means a perfectly clean token can sit in a pool whose hook decides you cannot sell. The honeypot logic no longer has to live in the token contract, where every scanner looks. It can live in the hook, where almost none of them do.
This matters more because most new v4 pools come from launchpads (Clanker, Zora coins, Flaunch) that attach a shared hook to every pool they create. Users never chose the hook. Most don't know it exists.
What a hook address already tells you
Here is the useful accident of v4's design: a hook's permissions are encoded in its address. The PoolManager reads the final 14 bits of the hook address to decide which callbacks to invoke (see Hooks.sol in v4-core). Deployers grind CREATE2 salts until the address carries the right bits.
So the permission set is decodable from the address alone — no ABI, no verified source, no goodwill from the deployer required.
We put a free decoder on that fact. One real example, live right now — an actual hook on Base with swap-delta custody bits and no verified source anywhere:
GET https://x402.donnyautomation.com/demo/v4hooks/0x74a5ff5fa9cd8cae51bbb19befa20631fb9b80cc
Response (trimmed):
{
"address": "0x74a5ff5fa9cd8cae51bbb19befa20631fb9b80cc",
"deployed": true,
"flags": ["beforeSwap", "afterSwap", "beforeSwapReturnDelta", "afterSwapReturnDelta"],
"verified": false,
"verificationState": "UNVERIFIED",
"verificationSources": [
{ "name": "basescan", "outcome": "no" },
{ "name": "blockscout", "outcome": "no" }
],
"custodyClass": "OPAQUE",
"riskFlags": ["SWAP_DELTA_CUSTODY", "UNVERIFIED_SOURCE", "UNVERIFIED_PRIVILEGED_OWNER"],
"detail": {
"permissionBits": "0b00000011001100",
"ownerSelectors": ["owner()", "transferOwnership(address)"]
},
"disclaimer": "Capability analysis of on-chain state. We classify what a hook CAN do; we never output SAFE."
}
Read that as a sentence: this contract intercepts every swap in its pools, holds the permission to take token deltas from those swaps, has a privileged owner, and nobody can read its source. That is not an accusation of fraud. It is a custody arrangement you were never shown.
The decoder classifies every hook into one of five custody classes:
-
PASSIVE— observes only -
FLOW_CONTROL— can gate, revert, or reorder swaps and liquidity; cannot move funds itself. This is the "why can't I sell" class. -
FEE_TAKING— returns liquidity deltas; can extract value from LP operations -
SWAP_CUSTODY— returns swap deltas; can take custody of swap-leg funds in-flight -
OPAQUE— unverified or upgradeable; the bits say what it can do, nothing says what it will do tomorrow
Verification is checked against three sources (Basescan, Sourcify, Blockscout) and OR-combined, because each one has coverage gaps. When all three are unreachable we report VERIFICATION-UNKNOWN — unchecked is not the same claim as unverified.
Verified is not safe, and Bunni proved it
The obvious objection: "so just require verified source and audits." Bunni v2 is the counterexample worth memorizing.
BunniHook (0x000052423c1dB6B7ff8641b85A7eEfc7B2791888) is a mainstream, non-launchpad hook: verified source, audited by two reputable firms. Our decoder classifies it SWAP_CUSTODY, because its rehypothecation design legitimately uses swap deltas — the custody is the product. In September 2025 a flaw in its liquidity math was exploited for roughly $8.4M across Ethereum and Unichain.
Verified, audited, and still exploitable. That is exactly why this tool refuses to print the word SAFE. A hook that holds custody is a hook that can lose custody, and no static check converts that into a guarantee. What we can do is tell you, before you trade, which contracts stand between you and your tokens, what they are permitted to do, and whether anyone can read them.
Try it
The demo endpoint is free, no key, rate-limited: swap in any hook address on Base.
Need keys or higher limits? The same decoder is on RapidAPI: https://rapidapi.com/donnywin85/api/uniswap-v4-hook-scanner-permission-decoder-custody-risk
https://x402.donnyautomation.com/demo/v4hooks/<hook-address>
If you don't know your pool's hook address, it is the hooks field of the pool key — or scan the PoolManager's Initialize events and you will find that a handful of launchpad hooks control most new pools.
Your token scanner is still worth running. It just isn't looking where v4 moved the risk.
Top comments (0)