# Explorers and indexers

Everything a Hookr pool pays is on chain and announced in events. This page lists the events by contract, says which event credits an account and in which field, and names the views that answer what events do not.

## Where to start

Index HookrRoot, the shared hook, on Robinhood Chain. From there:

| Contract | How to find it |
| --- | --- |
| Each pool | `PoolOpened` on the root, or `poolConfig(id)` on it: the subject, the quote, its HookrRules, the advisory and the liquidity owner |
| Its HookrRules | The HookrRules address in that `PoolOpened` or in `poolConfig(id)`. Each HookrRules keeps its own claims, so a pool's income is read at its own HookrRules and nowhere else |
| Its arb recapture lane | `PoolLane` on the root, or `laneOf(id)` on it: the executor, its code hash, the partner share and the lane family |
| Its launcher | `launcher` in that `PoolOpened`; on a pool launched through Hookr it is also the pool's liquidity owner |
| The protocol recipient | `protocolRecipient()` on the HookrRules: Hookr's treasury |
| The router | `curatedRouter()` on the root |
| The PoolManager | Uniswap v4's, on [Contracts and addresses](/docs/reference/contracts-and-addresses); its `Initialize` names the hook, and the pool id is the one the hook's events carry |
| Other roots | `RootRegistered` and `FactoryRootRegistered` on the registry; a hook you deploy emits its own `PoolOpened` |

Hookr's release contracts, the hook, the launcher, the router and the treasury among them, are on [Contracts and addresses](/docs/reference/contracts-and-addresses), verified on Sourcify as an exact match. A pool's own `PoolOpened` names the HookrRules and the launcher it uses, on Hookr's hook as on a hook you deploy.

## Events by contract

| Contract | Events |
| --- | --- |
| HookrRoot | `PoolOpened` once per pool, with the pool id, its launcher, its policy hash, its HookrRules and its advisory; `HookFee(id, quote, earned, refund, burned)` per swap; `PoolLane(id, executor, codeHash, partnerBps, family)` once per pool with arb recapture; `CorrectionSucceeded(id, phase, trader, reportedProfit, pushed, currency)` and `CorrectionFailed(id, phase, trader, reason)` per arb recapture frame; `LaneCodeChanged`; `ClaimsSwept(id, currency, amount)` when the root's own claims are swept to a lane pool's HookrRules |
| Every HookrRules | `RulesBound(id, root, configHash, config)` once per pool; `FeesAllocated(id, quote, protocol, royalty, refund, advisoryRecipient, advisoryFee)` per swap and per executor leg's advisory take; `IntegratorPaid(id, quote, integrator, amount)` per swap on a pool with an integrator; `Claimed(quote, beneficiary, to, amount)` per claim |
| A HookrRules with arb recapture | `RecaptureSplit(id, trader, traderAmount, lp, pot, protocol, currency, reportedProfit)` per push; `LpShareDonated(id, amount0, amount1)` as the LP share is released; `PoolAccrued(id, currency, amount)` and `PoolClaimed(id, to, currency, amount)` for the liquidity owner's accrual; `ClaimsSwept(currency, amount)` for what the root swept in |
| A HookrRules with King of the Pool | `LeaderChanged(id, leader, amount, epochStart)`; `CrownVoided(id, voided, restored, epochStart)`; `KingCrowned(id, winner, amount, epochStart)`; `EpochRolled(id, closedEpochStart, nextEpochStart, potCarried)`; `PotReleased(id, amount)` |
| Hookr's core, on top of the above | `CoreBlocksBound(id, word)` once per pool; `CoreBlockAllocated(id, payer, charge, outflow, recipient, amount)` per swap that paid Swap Cut, Exit Clock, Storm Fee or Sandwich Guard; `ExitRebated(id, seller, amount)`; `SandwichRepriced(id, trader, amount)`; `StormStepped(id, fromPips, toPips, variance)`; `ExitRecordCut(id, wallet, poker, cut)`; `HolderMoved`, `HolderCredited(id, wallet, amount)`, `HolderForfeited`, `HolderPotClosed` and `HolderPotCarried` for Holder Pot; `PlaceChanged(id, place, account, amount, epochStart)` and `PlaceCrowned(id, place, winner, amount, epochStart)` for a podium; `PotToppedUp(id, from, amount, epochStart)`; `RecaptureIntegratorSlice(id, currency, integrator, amount)` |
| HookrRouter | `SwapExecuted(poolId, payer, recipient, amountIn, amountOut)` per swap; `SwapRelayed(poolId, payer, feeRecipient, outputFee)` for a relayed swap's fee; `SwapGated(poolId, payer, gate, funder)` for a gated swap; `Swept` |
| HookrLauncher | `FamilyLaunched`, `MemberLaunched(familyId, member, poolId, quote, liquidity)`, `DevBuyExecuted`, `LaunchFeePaid`; `LiquidityAdded`, `LiquidityRemoved` and `LPFeesCollected(familyId, member, poolId, owner, recipient, amount0, amount1)` as the launch position moves; `ClaimsRedeemed` |
| HookrTreasury | `ProtocolCollected(source, currency, to, amount)` each time the treasury collects a HookrRules' protocol claim; `ProtocolForwarded` and `ProtocolForwardDeferred` for the delivery to its target |
| PoolManager | Uniswap's `Initialize`, `Swap`, `ModifyLiquidity` and `Donate`, keyed by the same pool id |

The HookrRules events come from its own address, the arb recapture and King of the Pool events included, and on Hookr's core the Hook Blocks run inside it, so a block's event comes from the core's address too. The lane events come from the root.

Three signatures are shared, so key every log by the contract that emitted it. `Claimed(currency, beneficiary, to, amount)` is also the referral distributor's; `ClaimsSwept` has a pool id on the root and none on a HookrRules; `FeesAllocated` is a swap's settlement on HookrRules and an executor leg's advisory take on HookrRecapture, with every amount but `advisoryFee` zero.

## Who is credited, by which event

A HookrRules credits an account by adding to its claims in one currency. The event that records the credit carries the pool id, and the account it names is in the field below.

| Income | Credited to | Event and field |
| --- | --- | --- |
| Hookr's share of a swap's block fees | the protocol recipient | `FeesAllocated.protocol`, what the protocol recipient kept |
| An integrator's rate of that share | the pool's integrator | `IntegratorPaid.integrator` and `amount` |
| The creator royalty on a buy | `config(id).royaltyTo` | `FeesAllocated.royalty`; the event names no recipient |
| A partial fill's refund | the swap's payer | `FeesAllocated.refund`; a swap through Hookr's router names the payer in `SwapExecuted.payer` in the same transaction |
| An advisory's fee, or an executor leg's advisory take | `FeesAllocated.advisoryRecipient` | `FeesAllocated.advisoryFee` |
| The trader's share of an arb recapture | `RecaptureSplit.trader` | `RecaptureSplit.traderAmount`, zero when no trader is paid |
| Hookr's cut of an arb recapture | the protocol recipient | `RecaptureSplit.protocol` |
| An integrator's slice of that cut, on Hookr's core | `RecaptureIntegratorSlice.integrator` | `RecaptureIntegratorSlice.amount` |
| A King of the Pool prize | `KingCrowned.winner`, and on Hookr's core `PlaceCrowned.winner` | `amount`, in the pool's quote |
| Swap Cut, Exit Clock, Storm Fee or Sandwich Guard paid to the creator | `CoreBlockAllocated.recipient`: the liquidity owner's accrual at outflow 1, `royaltyTo` at outflow 4 | `CoreBlockAllocated.amount`, net of Hookr's share; `charge` is 0 Swap Cut, 1 Exit Clock, 2 Storm Fee, 3 Sandwich Guard; outflow 2 feeds Holder Pot and 3 the King of the Pool pot, with no recipient |
| Exit Clock's rebate to a seller | `ExitRebated.seller` | `ExitRebated.amount` |
| A holder's Holder Pot earnings | `HolderCredited.wallet` | `HolderCredited.amount` |
| The liquidity owner's accrual, once moved | `PoolClaimed.to` | `PoolClaimed.amount`; the accrual itself was `PoolAccrued` |
| What the root swept | the protocol recipient | `ClaimsSwept.amount` on the HookrRules |

Two legs of an arb recapture are not claims. `RecaptureSplit.lp` is the pool's pending LP share, donated to its in-range liquidity by `LpShareDonated` or, with none in range, accrued to the liquidity owner by `PoolAccrued`; `RecaptureSplit.pot` goes into the King of the Pool pot, which `KingCrowned`, `PlaceCrowned` and `PotReleased` pay out later.

The liquidity owner's accrual moves into claims only when the liquidity owner calls `claimPool(id, to)`. On a pool launched through Hookr the launcher is the liquidity owner, and the launch's owner moves it with `claimRecapture(familyId, member, to)`, or with any withdraw or fee collection on the member.

## Claims

Every credit is a claim: nothing is pushed to an account. The HookrRules holds one balance per currency and account, pooled across every pool on it, and `claimable(currency, account)` reads it.

| Call | What it does |
| --- | --- |
| `claim(currency)` | Pays the caller's whole balance to the caller |
| `claimTo(currency, to)` | Pays it to `to` |
| `claimAsClaims(currency, to)` | Moves it to `to` as PoolManager ERC-6909 claims, for a quote that no longer transfers exact amounts |

Each one emits `Claimed(currency, beneficiary, to, amount)` with the caller as `beneficiary`, and a zero balance reverts with `NothingToClaim`. A balance above the PoolManager's signed 128-bit limit is paid in chunks, one per call.

One payment is not a claim: a relayed swap's `outputFee` goes to `SwapRelayed.feeRecipient` inside the swap.

The treasury is paid the same way. Anyone can call `collect(source, currency)` or `collectTo(source, currency)` on it, which calls `claimTo` on the HookrRules named as `source`, so one transaction carries its `Claimed` with the treasury as beneficiary and the treasury's `ProtocolCollected`.

## Proving one account's income

1. List the HookrRules the account was credited on. Each pool names its own in `poolConfig(id)`, and every credit event carries its pool id.
2. On each, sum the credit events above that name the account, by currency. The pool id is on the credit event.
3. Check the sum against `claimable(currency, account)` plus the account's `Claimed` logs there. The two agree.
4. Read `Claimed.to` for where the money went. `beneficiary` is the account whose balance was paid.

`Claimed` names no pool, so a per-pool statement comes from the credit events and a per-account statement from `Claimed`. An account's LP income is not a claim: it reaches the position through `LpShareDonated` and the pool's base fee, and leaves through the PoolManager or the launcher's `LPFeesCollected`.

## Views

| View | What it answers |
| --- | --- |
| `claimable(currency, account)` on the HookrRules | The balance waiting to be claimed |
| `config(id)` on the HookrRules | The pool's frozen settings: `royaltyTo`, `integrator`, `potBps`, `protocolShareBps` and the rest of its `RulesConfig` |
| `integration(id)` on HookrRules | The pool's integrator and its rate |
| `protocolRecipient()` and `trustedRoot()` on the HookrRules | The treasury the protocol share is credited to, and the one root that may settle |
| `recaptureConfig(id)` and `recaptureMode(id)` on a HookrRules with arb recapture | The frozen recapture terms and pot share; 0 no recapture, 1 recapture, 2 with King of the Pool |
| `pendingPrize(id)`, and `hill(id)` and `podium(id)` on Hookr's core | What closing the round now would credit, the round's leader, spend and pot, and each place on the podium |
| `poolAccrued(id, currency)` and `poolAccruedCurrencies(id)` | The liquidity owner's accrual not yet moved into claims |
| `poolConfig(id)` and `laneOf(id)` on the root | The pool's configuration and its lane |
| `integrator(account)` and `feeTerms(integrator, recapture, id)` on the treasury | An integrator's listed rate and the terms a new pool would freeze |

## Block numbers and clocks

Logs and `eth_getLogs` use Robinhood Chain's own block numbers, and the LP share's release counts them too. `RulesConfig.guardEndBlock` and `removalLockedUntil(id)` are parent-chain blocks, and `epochStart` in the King of the Pool events is a timestamp.

The latest block's `l1BlockNumber` gives the parent-chain number to compare those with; `eth_blockNumber` gives Robinhood Chain's own.

---

This page: https://hookr.fun/docs/pools/indexers. Every docs page as Markdown: https://hookr.fun/docs.md.
