How it works
Permissions live in the address
In Uniswap v4, a hook can't decide later which moments it runs at. Those permissions are fixed by the hook's address: the lowest 14 bits are 14 on/off switches. That's why hook builders "mine" addresses until the bits match the code.
So Fathom doesn't need to call the contract to know what a hook may do. It reads the last four characters of the address. For example, an address ending in 0080 has only bit 7 on: before swaps.
bits = parseInt(address.slice(-4), 16) & 0x3fff
beforeInitialize bit 13 beforeSwap bit 7
afterInitialize bit 12 afterSwap bit 6
beforeAddLiquidity bit 11 beforeDonate bit 5
afterAddLiquidity bit 10 afterDonate bit 4
beforeRemoveLiquidity bit 9 beforeSwapReturnDelta bit 3
afterRemoveLiquidity bit 8 afterSwapReturnDelta bit 2
afterAddLiquidityReturnDelta bit 1
afterRemoveLiquidityReturnDelta bit 0
This part works on real addresses.
Valid combinations
The four "return delta" switches let a hook change amounts. Each only works together with its base switch, and v4 rejects a hook address that has one without the other:
- Rewrites swap amounts needs before swaps.
- Takes from swap output needs after swaps.
- Changes deposit amounts needs after deposits.
- Takes from withdrawals needs after withdrawals.
A hook with no switches at all only makes sense on a pool with dynamic fees.
The score
Every hook starts at 100 and loses points for each power it has. The biggest costs are the ones that touch your money:
- Takes from withdrawals: −28
- Rewrites swap amounts: −22
- Before withdrawals (can refuse them): −20
- Takes from swap output: −18
- Changes deposit amounts: −12
- Before swaps (can refuse swaps or set fees): −8
- Before deposits (can gate who joins): −5
- Watch-only permissions: −1 or −2
80 and up is deep water, 50 to 79 is shoals, under 50 is reef.
Contract checks
- Source code not verified: −15
- Code can be replaced at any time: −18, or −8 behind a timelock
- Owner is a single wallet: −15; a multisig: −6; a timelock: −3
- Owner can change the fee on a hook that charges one: −8
For now these are simulated from the address. A live version would read them from the chain and the explorer.
API
With the Node server running:
GET /api/inspect?hook=0x…— the full report.GET /api/hooks— the hook chart.GET /api/flags— all 14 permissions with their bits.
What Fathom can't do yet
- It doesn't read Robinhood Chain. Owners, upgradeability, verification, pools and names are made up, but stay the same for the same address.
- A score reads what a hook is allowed to do. It isn't an audit of how well the code does it.