Chapter 03 · Pricing

Pricing

The fixed $10,000 opening FDV, the Chainlink quote price, quote decimals and the tick it becomes.

Every Hookarc pool opens with the whole 1,000,000,000 supply valued at $10,000. The quote's Chainlink price only decides how many tokens one unit of quote buys at the open. That number becomes a Uniswap tick, and the tick is the boundary of the single-sided seed position. Because USDC has 6 decimals and cirBTC has 8, the library also carries the quote's decimals through to the raw price the pool stores.

From a USD price to tokens per quote

OpeningPrice.tokensPerQuoteUnit(usd8) = SUPPLY × usd8 / 10,000e8: whole tokens (18 decimals) per one whole unit of quote, before decimals are applied.

QuoteFeed answerTokens per one whole quote unitRaw price when the quote is currency0
USDC at $1.001.00e8100,000 tokens per USDC1e17 token-wei per raw USDC unit (10⁻⁶ USDC)
USDC at $0.9990.999e899,900 tokens per USDC9.99e16
cirBTC at $65,00065,000e86,500,000,000 tokens per cirBTC6.5e19 token-wei per satoshi

A pool therefore always opens at $0.00001 per token; the quote just changes the unit that figure is expressed in. For cirBTC the whole supply is worth about 0.15 cirBTC at $65,000, so one cirBTC buys more than the supply at the opening price and the first buy of any size climbs the curve quickly. That is expected and is why the Launch preview shows the opening price per token in the quote and in dollars.

Opening price derivationEvery pool opens at a $10,000 fully diluted valuation. The quote price only decides how many tokens one quote unit buys; the quote decimals (6 for USDC, 8 for cirBTC) scale that into the raw pool price.
yesnoyesnoChainlink answerquote / USD · 8 decimalstokensPerQuoteUnitSUPPLY × usd8 / 10,000e8quote iscurrency0?price = t · 1e18 / 10^decprice = inversesqrt(raw price) << 96raw sqrtPriceX96 · bounds checkedgetTickAtSqrtPrice(raw)floor toward −∞ to spacing 60getSqrtPriceAtTick(tick)price sits exactly on the tickquote iscurrency0?range [minUsableTick, tick]all 1e9 tokens sit as currency1range [tick, maxUsableTick]all 1e9 tokens sit as currency0initialize + seedPriceOutOfRangereverts when raw sqrtPriceX96 leaves (MIN, MAX)or the floored tick leaves the usable range.

Decimals

OpeningPrice.opening(quoteUsd8, quoteDecimals, quoteIsCurrency0) takes the decimals the registry stored when the quote was added (quoteDecimals(quote), 6 to 18). Uniswap's price is raw currency1 per raw currency0, so the library scales tokens-per-quote by 1e18 / 10^decimals before it takes the square root. The same helper computes fdvQuote = 1e9 × 10^decimals × 1e8 / usd8, the opening valuation in raw quote units, which Anti-Snipe uses as its cap basis. The library is tested for 6, 8 and 18 decimals in both orientations.

From tokens per quote to a tick

If the quote is currency0, the raw price is tokens-per-quote scaled as above; if the token is currency0, the price is the inverse. The library takes the square root, shifts by 96 bits, checks it lies strictly inside (MIN_SQRT_PRICE, MAX_SQRT_PRICE), converts it to a tick, floors the tick toward negative infinity to a multiple of 60 and converts back. The pool therefore opens exactly on a tick boundary, which is what a single-sided position needs.

The seed range

  • Quote is currency0 (the usual case for USDC at 0x3600…): the position spans [minUsableTick, openingTick]. All tokens sit as currency1 above the current price, waiting to be bought with quote.
  • Token is currency0 (the usual case for cirBTC at 0x171A…): the position spans [openingTick, maxUsableTick]. All tokens sit as currency0 below the current price.

In both cases the pool holds only tokens at the open. The first buy pays quote into the pool; the price then follows the constant-product curve inside that one position. Because the position is single-sided and the LP fee is zero, the opening price is also the lowest price the pool can ever show: selling everything back returns the pool to the opening tick, never below it.

Rounding and the fixed-FDV promise

Flooring the tick means the on-chain opening price is at most 0.6 % below the exact $10,000 target (one tick spacing of 60 is about 0.6 %). The UI shows the exact figure derived from the feed; the chain shows the floored tick. The AntiSnipe cap uses the unrounded fdvQuote, so that the cap is a clean share of the stated FDV.

read the code
  • contracts/src/libraries/OpeningPrice.sol tokensPerQuoteUnit(), opening(), the fdvQuote helper
  • contracts/test/OpeningPrice.t.sol 6, 8 and 18 decimals, both orientations, extreme feeds, tick alignment
  • web/app/(app)/launch/page.tsx tokensPerQuote, quotePerToken and fdvQuote as shown in the UI