Skip to main content
All trading happens on the launch clone — resolve it once via factory.launchOf(token). There is no router: approvals go to the launch itself — the quote token for buys, the launched token for sells — and no function takes a token argument.

The four entry points

Two payment shapes, four distinct selectors — not overloads. All take a deadline and a mandatory recipient. Quote-token (ERC-20) entries:
Native entries — only where the launch accepts native (acceptsNative()):
buyWithNative has no amountIn — the amount is msg.value.

Units — read this twice

Everything is denominated in the quote token’s own decimals: amountIn, minAmountOut on sell, quotes, reserves, event amounts. minTokensOut is always in launch-token units (18 decimals).
sellForNative’s minAmountOut is denominated in the NATIVE coin, because that is the unit the caller receives — as are quoteSellForNative’s nativeOut and quoteBuyWithNative’s nativeRefund. On a chain whose quote has 6 decimals and whose native view has 18, mixing the two is a silent 10¹² error, not a revert.

Recipient and refund semantics

  • Buys: tokens go to recipient; any refund goes to the payer (msg.sender). Only the curve-completing buy refunds — it takes exactly what is left on the curve and returns the overshoot (native refunds come back unwrapped, plus any sub-unit dust). That buy also graduates the launch.
  • Sells: tokens are pulled from msg.sender with transferFrom, so the seller approves the launched token to the launch first. recipient redirects only the proceeds.

The anti-snipe window

A launch may open with a surcharge on buys that starts near the whole trade and decays to nothing over a window of seconds, measured from openedAt():
  • Buys only. Sells are never surcharged.
  • Keyed on the recipient, not the sender. A buy through an aggregator has the aggregator as msg.sender and the buyer as recipient — a router is never treated as the sniper.
  • Exempt: the creator, and any address the creator listed in launchParams (at most 32). The atomic opening buy at creation goes to the creator, so it is never surcharged.
  • Capped: curve fee plus surcharge never exceeds 9,999 bps.
  • Kept by the protocol. None of the surcharge goes to the creator, so a creator cannot profit from their own launch being sniped.
  • No separate event: Trade.fee includes it.
The window’s parameters are part of the launch’s config() (snipeTaxBps, snipeWindow, snipeDecay); the contract bounds them to a window of at most 600 seconds and a decay exponent from 1 to 24, and a window of zero turns the surcharge off. For a given buyer:

Quoting

  • quoteBuy does not know who the tokens are for, so it answers for a buyer who is not exempt — the highest fee anyone would pay. Use quoteBuyFor for the exact figure; past the window the two agree. quoteBuyWithNative also assumes a non-exempt buyer, and has no …For variant.
  • quoteBuy/quoteSell return zeros instead of reverting outside the Trading phase, and quoteSell also for tokensIn > sold — treat zeros as “not tradable”, not as a price.
  • quoteBuyWithNative is not quoteBuy(nativeIn / divisor): native→quote truncation is returned as dust in native units. Use the native quoter for native trades.
Reproducing the curve off-chain costs no RPC per quote once you hold the state. Launch type 1 is constant-product over virtual reserves:
The buy that would exceed the remaining curve supply takes exactly what is left and refunds the overshoot (fees recomputed on the gross actually needed, rounding up). Read reserve(), sold() and openedAt() from storage, the parameters from config(), and exemptions from isExempt — these are the constant-product implementation’s own vocabulary, deliberately outside the cross-type interface, so bind the concrete type-1 ABI.

Where the fee goes

To a trader, fee is one number. Behind it, curveFeeProtocolBps of the base fee goes to the protocol and the rest to the creator, while any anti-snipe surcharge goes wholly to the protocol. Both sides accrue in the launch (protocolFees(), creatorFees()) and leave through collectFees(), which either recipient may call, in any phase, and which pays both sides. The arithmetic, the caps, and every other fee the launchpad charges are on Fees.

Errors you will hit

Revert reasons may gain new cases over time; none will silently change meaning.
The buy that fills the curve graduates it, in the same transaction: it costs more gas than an ordinary buy, and the graduation reward goes to its msg.sender — a router that fills a curve receives the reward. If graduation cannot complete, that buy reverts and the curve keeps trading just short of full. The factory’s creationPaused never affects trading on existing curves.