PerpFun
Connect wallet

The bond

The moment a coin stops being backed by dollars and starts being backed by a leveraged position on a real stock.


The threshold

Once a coin's own pool has accumulated bondBackingUsd of USDG, it is eligible. That value is immutable on the launcher and public — read it rather than trusting a number written on a website:

MemeLauncherV3.bondBackingUsd()      →  the threshold, in USDG

The coin page shows the same figure as a market cap, because that is the number a buyer can actually watch approach. The two are the same statement — see Reading a coin page for why the supply cancels out of that conversion entirely.

Anyone can trigger it

bondAndMigrate is permissionless. Nobody decides whether a coin bonds — the threshold does. The only thing a caller contributes is the gas.

That is deliberate. A migration that depended on us running a bot would be a migration that stops when our bot stops.

What happens, in one transaction

  1. The entire position is withdrawn from the COIN / USDG pool.
  2. The accumulated USDG mints the coin's leveraged tracker at its live NAV.
  3. A new pool is opened at COIN / TRACKER, at the same dollar price, and the whole float goes back in.
  4. The new position NFT is locked in the same locker, under the same rules.

Holders do nothing. Their tokens never move, their balances do not change, and the dollar price of the coin is the same on both sides of the transaction. What changes is what stands behind it.

The price, carried across

The new pool has to open at the same value in dollars, but its quote is now worth NAV rather than one dollar, and its decimals differ. The rescale is done on the square root — never by squaring a sqrtPriceX96, which overflows a uint256 since (2^160)^2 = 2^320:

sqrt(P') = sqrt(P) · sqrt( 10^(18 − dq) · 10^18 / NAV )

What the contract guarantees

Once per cointhe migrated flag is set before anything moves
Only its own trackerfixed at launch, not chosen by the caller
Everything goes back inreverts if more than MIGRATION_DUST of coin is left behind
Never two markets at oncethe old position is closed and the new one opened in the same transaction
Permissionlessanyone pays the gas; nobody grants permission

Where the lower bound comes from

The new position's range is derived from the amounts actually withdrawn and rounded up, not carried over from the old pool.

That is not a detail. Carrying the old lower tick and flooring it widens the band beneath the current price, which means the position needs dollars it does not have to fill the space underneath — and the deposit strands coin. We shipped that bug, it reverted a live bond with MigrationWouldStrandLiquidity, and the fix is pinned by a fork test that replays the exact failure.