Documentation
Trading the curve
Before graduation the only venue is the launch's own bonding curve. It has no fixed address —
read it from factory.getLaunchedToken(token).curve.
Approve the curve for both legs: the quote asset to buy, the memecoin to sell.
The two slippage bounds are not the same kind of bound#
This surprises people, and it is deliberate.
On a buy, minTokensOut is a price bound. A buy that would take more than the remaining
allocation is clamped rather than reverted — you get the remaining tokens and the unspent
quote is refunded to msg.sender in the same transaction. The bound is then enforced as an
implied price rather than a quantity, so a partial fill at an acceptable price succeeds.
That means you can safely overshoot the graduation threshold. Sending more than the curve can absorb is normal and costs nothing.
On a sell, minQuoteOut is a strict quantity bound. You get at least that much or the
call reverts.
The sell side closes early#
A sell reverts with CurveGraduated as soon as readyToGraduate() becomes true — which is
before the graduated flag is set and before anyone has called graduate.
So there is a window where the curve looks live, graduated is still false, and every sell
reverts. If your UI reads graduated to decide whether selling is possible, it will offer a
button that cannot work. Read readyToGraduate() too.
Referrals#
The four-argument buy overload takes a referrer:
function buy(uint256 quoteIn, uint256 minTokensOut, address recipient, address referrer)Three things to know:
- The binding is written for
recipient, notmsg.sender. - It is consulted only on that address's first referred trade, and is permanent after that. Passing a fresh referrer later cannot poach an existing relationship.
- A bad referrer reverts the whole buy.
SelfReferralandReciprocalReferralare not swallowed. Validate before you put an address in the call — particularly if it came from a URL parameter.
sell has no referrer argument; only an existing binding applies.
Users can also bind themselves ahead of any trade with
referralRegistry.setReferrer(address).
Quoting#
Off-chain, the curve is constant product against a virtual reserve:
netIn = quoteIn - fee - creatorTax // fees come off the QUOTE leg
tokensOut = netIn * tokenReserve / (quoteReserve + netIn)where quoteReserve = phantomQuote + trackedQuote - quoteFeeBalance - creatorTaxBalance,
available together from getReserves().
Note getReserves() returns the virtual quote reserve, which includes the phantom
reserve. For the amount actually raised — what a progress bar should show against the
threshold — use realQuoteReserve().
Once a launch graduates the curve is closed and estimates must come from the Uniswap V4 Quoter instead. See Trading the pool.