DEV Community

CoolBB
CoolBB

Posted on

Ponsfamily V2 Bonding Curve Math (What Your Quoter Must Mirror)

Ponsfamily V2 does not price on a Uniswap pool first. The full supply mints to a constant-product bonding curve that already trades in the same quote asset the future V4 pool will use (native ETH or pairToken). Graduation later seeds that pool from the curve’s real reserves — no router, no oracle.

There is no quote() on the curve. You rebuild the price from getReserves(), feeBps, creatorTaxBps, sellableTokens(), and currentSnipeTaxBps(recipient).

Invariant

The curve is Uniswap-v2-style:

$$x \cdot y = k$$

x is the quote reserve (phantom + real). y is the token reserve. A phantom quote reserve sets the opening price so the first buy is not free. realQuoteReserve() is what actually arrived from traders; graduation watches that against the launch’s threshold.

Core output (from PonsV2BondingCurveMath):

$$
\Delta y = \frac{\Delta x_{\text{net}} \cdot y}{x + \Delta x_{\text{net}}}
$$

On-chain they pass feeBps = 0 into the AMM helper because fees are applied on the quote leg first, not inside the product.

Buy: fees come off the input

Order of operations on buy(quoteIn, minTokensOut, recipient):

  1. Read snipe tax for this recipient (decays from 99% toward 0 over ~5s; exempt addresses skip it).
  2. Take protocol feeBps and optional creatorTaxBps from the quote spent.
  3. Feed what remains into getAmountOut.
  4. If the buy would eat the reserved graduation slice, fill only sellableTokens() and refund the rest.

Sketch:

spent     = quoteIn                       // may clamp to sellable
snipe     = spent * snipeTaxBps / 10_000  // buys only
fee       = spent * feeBps / 10_000
tax       = spent * creatorTaxBps / 10_000
netIn     = spent - snipe - fee - tax
tokensOut = getAmountOut(netIn, quoteReserve, tokenReserve, 0)
Enter fullscreen mode Exit fullscreen mode

Caps: curve fee ≤ 10%, creator tax ≤ 10%, total trade fee ≤ 20%, snipe start ≤ 99%. A taxed buy still nets something.

Sell: fees come off the output

Sells never pay snipe tax.

gross     = getAmountOut(tokensIn, tokenReserve, quoteReserve, 0)
fee       = gross * feeBps / 10_000
tax       = gross * creatorTaxBps / 10_000
quoteOut  = gross - fee - tax
Enter fullscreen mode Exit fullscreen mode

When readyToGraduate() is true, sells revert (CurveGraduated) even before graduate() runs. The curve is already holding pool seed; selling would move the price the pool is supposed to inherit.

Graduation price

After drain, PonsV2GraduationMath seeds V4 with

$$\texttt{sqrtPriceX96} = \sqrt{\frac{\text{amount1}}{\text{amount0}}} \cdot 2^{96}$$

from the curve’s final token and quote amounts. Full-range position. Same quote asset the curve already collected.

What a bot gets wrong

  • Quoting like V3 / V4 before phase == 0 (still on curve).
  • Putting fee inside getAmountOut and subtracting it from quote (double fee).
  • Ignoring phantom vs real quote when estimating “how close to graduate.”
  • Buying at t=0: ~99% snipe tax vs ~1–3% a couple of seconds later. Price impact rarely outruns that decay unless the curve is already graduating.

Read reserves, subtract quote-leg haircuts, then run the product. That is the whole market until the pool exists.


Telegram: https://t.me/C00LBB

Site: https://coolbb.site


Enter fullscreen mode Exit fullscreen mode

Top comments (0)