# graduation

The graduation moment is the most important state transition in basefun. This page covers exactly what happens, where the numbers come from, and what changes for everyone.

## The trigger

`BondingCurveV2._maybeGraduate()` runs at the end of every successful `_buyFor`. It checks two conditions:

```solidity
bool reserveHit = getReserveUSDC() >= GRADUATION_USDC;    // $10,000
bool soldOut    = tokensSoldFromCurve >= CURVE_SUPPLY;     // 757,500,000
if (!reserveHit && !soldOut) return;
```

Either one fires graduation. In the no-perp-PnL case the constants are tuned to hit both at the same time. With perp PnL one tends to hit first (a profitable underlying drives reserve up faster than sales push `sold`).

## The graduation atomic block

```solidity
uint256 ltBalance = lt.balanceOf(address(this));
if (ltBalance > 0) lt.redeem(ltBalance, 0);   // pull ALL remaining USDC back

graduated = true;
emit Graduated(reserve);

uint256 bal = usdc.balanceOf(address(this));
uint256 treasuryCut = bal >= GRADUATION_TREASURY_USDC ? GRADUATION_TREASURY_USDC : bal;
if (treasuryCut > 0) usdc.safeTransfer(protocolFeeRecipient, treasuryCut);
```

After this, the curve holds **(LP\_SUPPLY tokens + \~$9,700 USDC)** and `graduated = true`. Every subsequent `buy`/`sell` call reverts with `AlreadyGraduated`.

## The migration tx (separate)

Triggered by the keeper bot calling `factory.migrateToUniV2(curveAddress)`. This is a single transaction that, atomically:

{% stepper %}
{% step %}

## Withdraw everything from the curve

`curve.withdrawForGraduation(address(this))`.
{% endstep %}

{% step %}

## Cap the LP seed

* `lpUsdc = min(curveUsdc, GRADUATION_LP_USDC) = $9,700`
* `lpTokens = min(curveTokens, LP_SUPPLY) = 242.5M`
  {% endstep %}

{% step %}

## Look up the Uni V2 pair address

Creates it if it doesn't exist.
{% endstep %}

{% step %}

## V3 only: activate the FOT hook

`token.setPair(pair, true)` — activates the 1% FOT hook on this pair specifically.
{% endstep %}

{% step %}

## Approve the Uni V2 router and add liquidity

```solidity
router.addLiquidity(
    tokenAddr, usdc,
    lpTokens, lpUsdc,
    95% min, 95% min,
    0x000000000000000000000000000000000000dEaD,   // ← LP burned
    block.timestamp + 600
);
```

{% endstep %}

{% step %}

## Sweep any USDC dust to treasury

Overshoot beyond the $9,700 cap is swept to treasury.
{% endstep %}

{% step %}

## Burn any leftover unsold tokens

At `0xdead`.
{% endstep %}

{% step %}

## Emit `Migrated(token, pair, tokensIn, usdcIn)`

The LP ERC-20 tokens that `addLiquidity` returns are sent directly to the dead address — **no entity holds them, no one can withdraw the liquidity, ever**.
{% endstep %}
{% endstepper %}

## The price seed

Because we deposit exactly `(242,500,000 tokens, $9,700 USDC)`, the pair's initial spot is:

```
spot_per_token = 9_700 / 242_500_000 = $0.00004
mcap_at_seed   = 0.00004 × 1_000_000_000 = $40,000
```

That's the **post-migration market cap floor**. It's the same for every basefun token by design.

## What if the curve has more or less than expected?

The LT redemptions at graduation give back whatever USDC was in the perp at that moment. Possible outcomes:

| Scenario            | Curve USDC at migration                       | What happens                                                                                                                                                        |
| ------------------- | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Perp neutral**    | exactly $10,000 → after $300 cut, $9,700 left | Seeds at the $40k MC target. Zero dust.                                                                                                                             |
| **Perp profitable** | > $10,000 (LT NAV grew during the curve)      | $300 to treasury, $9,700 to LP, **excess swept to treasury** (small dust).                                                                                          |
| **Perp drawdown**   | < $10,000 (LT NAV shrank)                     | $300 cut still taken (or capped at balance), then `addLiquidity` proceeds with whatever is left. **LP seed lands at < $40k MC**.                                    |
| **Perp liquidated** | could be \~$0                                 | Treasury cut clamps to 0, LP seed clamps to 0. Curve effectively goes to zero and migration produces a near-empty pair. This is the disclosed risk of perp backing. |

In practice the keeper aggregates LT mints across a market, so a single bad PnL day on the underlying tanks every basefun token in that `(pair, lev, dir)` together. There's no isolation per token.

## Why $40k specifically

The post-migration MC was chosen as a **psychological round number** that's high enough to feel meaningful (compared to the \~$3.8k floor) but low enough that early Uni V2 buyers still have realistic upside.

The split between curve cap ($10k) and LP seed ($9.7k) leaves a $300 treasury reward per graduation, which scales with launch volume without taxing every individual trade more aggressively.

## What changes for the creator

Immediately at graduation:

* 0.5% creator fee on **bonding-curve** trades stops (no more curve trades).
* 0.5% creator fee on Uni V2 trades **starts** — paid in token initially, swept by the keeper into USDC and forwarded to the creator's wallet.
* Earnings remain visible on the token's Earnings tab.

What does NOT change:

* `creatorFeeRecipient` is still the same immutable address.
* Creator's existing token bag (from any buys they did) is unchanged.

## What changes for the protocol

* $300 USDC arrives in treasury.
* The curve's 0.5% protocol fee stops.
* Post-grad 0.5% protocol fee starts — same async dispatch as creator's.

## What changes for holders

* Existing bag is unchanged (just an ERC-20).
* Selling now routes through Uni V2 instead of the curve. The UI handles this transparently.
* Price discovery now comes purely from the Uni V2 pool reserves. No more perp PnL effect.

## What changes for buyers entering post-graduation

* Buy is a standard Uni V2 swap (with FOT support on V2 tokens).
* The pair is now permanent — they can be confident liquidity won't disappear (LP is burned).
* The token's price will move with Uni V2 buy/sell pressure only.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://basefun.gitbook.io/basefun-docs/graduation.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
