Reading a report
What each part of a hook's page at /hook/<address> says, and which numbers to look at first.
Every hook has a page at /app/hook/<address>. Opening it runs a fresh scan at the latest block. The page has a header and five parts.
The header
The hook's address, the block the scan read at, the score out of 100 and the verdict (safe, caution or danger). The verdict is the line to read first, and the score second: they are computed differently, and a hook can score well and still be a caution. See Score and verdict.
If the page says there is no contract at the address, nothing is deployed there on Robinhood Chain. Check that you copied the hook's address and not the token's or the pool's.
The eight checks
Each check has a status and one sentence of evidence, written from the facts the scan found: the percentage taken, the owner's address, the callbacks a stranger could call. Read the sentences, not just the colours. A caution on 05 that names an owner and a setFee function says something different from a caution on 05 that names only a claim function.
The order matters for most people:
- 02 What it takes from a swap, if you are about to trade.
- 03 LPs can get out, if you are about to provide liquidity.
- 04 The fee is the fee, for the pool fee itself: its level, and whether the hook sets it.
- 05 No one holds the switch, to know whether what was measured can change tomorrow.
- 06 The code cannot change, to know whether the code itself can change.
The full list is on The eight checks.
What the address allows
The permission register: the fourteen permission bits, each on or off, with what it lets the hook do. The lines that let a hook take from swaps or from LPs, or refuse a withdrawal, are marked. A bit that is off is a hard guarantee: the PoolManager will never call that callback. A bit that is on is only a possibility; the next part says whether it is used. See The permission bits.
What it did to a real swap
One card per pool the scan measured (up to two of the hook's most recent pools). Each card names the pair, the pool fee (a fixed percentage, or "dynamic" with today's value, which check 04 judges), the pool id, and one line per swap direction:
| Line | Meaning |
|---|---|
| nothing taken | The swap paid the pool fee and nothing else. |
| hook takes X% | What the hook kept beyond the pool fee, as a share of the swap. |
| hook adds X% | The output was larger than a hookless pool would give: the hook added to it. |
| refused: reason | The swap reverted. The reason is shown when the hook left one, with custom errors named from the signature database where possible. Only a revert counts as refused. |
| no liquidity below the price, or above the price | The swap went through but consumed nothing: the pool's liquidity ends at the current price on that side, as it often does on launch pools nobody has traded yet. Not measured, not refused. |
| no liquidity at the current price, or too little liquidity to measure | The pool is too thin to measure. |
A thin line says nothing about the hook, good or bad.
A refused swap in one direction while the other direction works is the worst thing a report can show a trader: you may be able to buy and not sell.
The last line of each card is the LP round trip:
- came back whole: liquidity added and removed in the same call returned what went in (a loss of 0.1% or less);
- lost X%: the share of the deposit that did not come back;
- deposit refused: the hook does not accept outside deposits. The pool is closed to outside LPs, and only the hook's own liquidity is in it;
- withdrawal refused: liquidity went in and could not come out.
The exact take, the probe's amount in and the pool state are in the API response for anyone who wants the raw numbers.
Read from the bytecode
Code size, the owner (if owner() answered), whether the hook is a proxy and where its implementation lives, the number of outside calls in the code, whether DELEGATECALL, SELFDESTRUCT or CREATE appear, the constant addresses the code pushes, and the callbacks open to anyone.
Its functions, uncensored
Every selector the dispatcher compares against, with its name from the public signature database where one exists. Owner-style names are marked. A selector with no name is a function nobody has published a signature for; it is not suspicious by itself, but it is unread.
If the page says no dispatcher was found, the bytecode does not route calls the way the Solidity compiler usually does, and the function list is empty for that reason, not because there are no functions.
Before you act on it
Look at the block number and the time. A report is a reading at that block. If the hook has an owner or a dynamic fee, open the page again just before a large trade: it will scan again. Then read Limits once, so you know what a clean report does not cover.