Market data & payouts
Index pools by pool id, price a launch in its own quote, and read fees, bonding and creator payouts correctly.
On this page
Pool identity
The launch’s hook address is part of the pool key, so a pool id cannot be derived from the token pair alone. Prefer the emitted TokenCreated.poolId or hook.poolId(), then cross-check the key you computed.
PoolKey = (currency0, currency1, fee, tickSpacing, hooks)
currencies sorted numerically by address
poolId = keccak256(abi.encode(currency0, currency1, fee, tickSpacing, hooks))
Ethereum Keccak-256, full ABI encoding.
Not SHA3-256. Not abi.encodePacked.
This family uses fee 10000 (1% in v4 units) and tickSpacing 200.
Validate the observed key rather than assuming those constants.Index by the triple (chain id, PoolManager address, pool id). Read Initialize to map a pool to its currencies, fee, spacing and hook, then index Swap, ModifyLiquidity and Donate from the same manager, where the pool id is indexed in topic 1. Deduplicate by chain, transaction hash and log index, and keep canonical block hashes so a reorg stays recoverable.
Price and units
r = sqrtPriceX96^2 / 2^192 exact arithmetic; raw currency1 per raw currency0
quote per token = r if the launch token is currency0
= 1 / r if the launch token is currency1
human units = that value * 10^(tokenDecimals - quoteDecimals)Read both tokens’ decimals() and the launch’s quote asset. Keep exact integers or rationals until you format for display. A price denominated in an arbitrary quote is not a USD price, and a site’s default supply is not a contract-wide guarantee, so read totalSupply().
Classify buys and sells
Swap.sender is usually a router
It is the immediate caller. Even tx.from need not be the end user once relayers or account abstraction are involved.
Do not double count a dev buy
A Portal DevBuy event can describe the same trade as a PoolManager Swap. Count it once.
Pool deltas are not user execution
With hooks, router fees or bundled calls, core deltas do not equal the user’s final debits and credits. Inspect the whole execution before reporting an execution price.
Fees and bonding
v4 launch tokens have no transfer tax. The tax is applied by the pool’s hook on swaps, so a wallet-to-wallet transfer pays nothing. Read every rate from the launch’s own hook.
| Hook getter | What it returns |
|---|---|
| buyTaxBps() / sellTaxBps() | That launch’s per-leg tax in basis points, fixed for the life of the hook. |
| poolFee() | Pool fee in v4 units, where 10000 is 1%. |
| totalFeeBps() | The base schedule per leg: pool fee converted to bps, plus that leg’s launch tax. |
| currentSnipeTaxBps() | The current opening surcharge for an ordinary trader. |
| bonded() | Whether the bonding milestone has latched. |
| bondBound() / bondTick() | Whether the milestone is bound, and its threshold tick. |
Each creator tax leg is at most 1000 bps. One leg may be zero; both zero is rejected at launch. The base schedule excludes router and service fees, gas, and the opening surcharge, which runs for three seconds and has its own exemptions and a combined-rate cap. Simulate at the relevant block rather than promising that adding displayed percentages predicts a route’s execution.
progress = (tick - tickStart) / (tickBond - tickStart)
Direction is preserved for either token order.
Guard a zero span. Clamp only for display.
A tick retreat does NOT clear an already latched bonded state.Quotes and payouts
The pair’s quote asset and the payout asset are separate concepts, and they diverge on Portal #7. Do not infer the payout asset from the eleventh launch word or from the Portal’s current quote registry.
| Portal | Quote and payout handling |
|---|---|
| #3 to #5 | Fixed historical USDC quote. Use that launch’s historical splitter ABI; #5 claims pay the quote leg in native USDC. |
| #6 | Quote is launch word 10. The creator share is credited for claim; the quote leg pays in the launch quote ERC-20. |
| #7 | Quote is launch word 10 and does not change, but the splitter may convert selected revenue to USDC. Read splitter.converts(), quoteAsset() and defaultQuoteAsset(). |
claim(address) on #7 returns three values; earlier versions return different shapes behind the same selector. Read claimable quote, launch-token and USDC balances separately with the #7 ABI. Allocation basis points are shares of collected revenue, not extra percentages charged on a trade.
Before you go live
Discovery from every supported Portal
Including #7 from the bundle’s separate section. A failed lookup must not become a false absence.
Exact 9, 10 and 11 word decoding
With legacy v3 kept separate, and the #6 and #7 launch selectors kept separate.
Token to Portal to hook to pool id binding
Two different hooks from one implementation version must both be accepted without requiring identical runtime bytecode. Hooks are not clones, and constructor immutables differ per launch.
Two pools indexed through one manager
Without mixing their events or volume, and with restart and backfill deduplication working.
Correct ordering, scaling and side classification
With non-USDC quotes handled in their own units.
Hook-aware buy and sell simulation
With slippage limits, accurate fee disclosure, and no double-counted dev buy. The Portal is a launch contract, not the swap router.
Bonded state read independently of tick
Unavailable data must not render as a false unbonded or zero state.
Asset-specific payout accounting
For every splitter version you support, including #7 conversion, pending and fallback outcomes, if you display payouts at all.