MECHANICS / GRADUATION

Graduation to Uniswap V4

Deliberately two phases, so a failed pool seed can never strand a curve's reserves. The curve already holds the asset its pool will use, so graduation converts nothing, needs no router and needs no oracle.

Phase 1 — graduate(token)

  • Permissionless. Checks the curve is ready, then runs the seed preflight through AgiV2GraduationGuard before anything irreversible happens.
  • Sweeps pending fees, halts the curve and moves its quote and token reserves into the factory. The factory records what it actually received, not what the curve said it sent, so an under-delivering asset cannot draw the shortfall from other launches' escrowed balances.
  • Because it is purely internal bookkeeping, the curve calls it automatically from inside the buy that crosses the threshold. If that inner call fails, it is swallowed (AutoGraduationFailed) so a graduation problem cannot take the crossing buy down with it.
  • The launch moves to phase Swept.

Phase 2 — createGraduatedPool(token)

  • Permissionless and retryable: the launch stays in Swept until a seed succeeds, so a transient failure never strands anything.
  • Only the token amount that preserves the curve's terminal price is seeded: poolTokens = sweptTokens × sweptQuote / (sweptQuote + phantomQuote). The remainder — the part that backed the phantom reserve — is permanently locked in AgiV2LaunchLocker and never circulates (GraduationTokensPermanentlyLocked).
  • The pool is initialized at the price those two amounts imply, registered with AgiV2MemeHook, and a full-range position is minted directly to the locker by AgiV2GraduationExecutor, which exists only to keep the factory under the 24 KB contract size limit.
  • The launch moves to PoolCreated. From then on the hook charges the fee and the escrow pays it out.
  • In practice our robot sends this call and pays its gas (see Operations). The call stays permissionless: if the robot is down, anyone can send it and the result is identical.

The guard

AgiV2GraduationGuard is a stateless preflight that models the rejections of the real mint: the seed amounts against V4's signed int128 bound (the PositionManager's ABI takes uint128, so an amount in between passes every field check and still reverts inside core), the derived square-root price against V4's own limits, and the full-range liquidity against zero. It exists because phase one is irreversible: a seed that passes here and reverts inside V4 would leave a launch permanently unseedable.

When it goes wrong

forceSweptGraduation
Owner-only, and only for a launch the preflight genuinely refuses. While a seed is still viable it reverts with GraduationStillViable, so it cannot be used to take a healthy launch's reserves instead of seeding its pool.
rescueSweptGraduation
Owner-only, and only 7 days after the sweep. Releases the reserves whole to one address for off-chain distribution, for the case where the quote asset became fee-on-transfer, rebasing or blocklisting after approval and can therefore never satisfy the exact transfer the seed needs. Seeding stays permissionless during the whole wait: anyone can end the window early and permanently by calling createGraduatedPool. The phase becomes Rescued, which is terminal.
rescueCurveFees
Owner-only. Pays a still-trading launch's pending fees directly to the protocol and creator, bypassing the escrow, for a quote asset that has stopped delivering there. It is also the only way to unwedge such a launch's graduation, since graduate sweeps fees before handing over reserves.