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 USDGThe 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
- The entire position is withdrawn from the
COIN / USDGpool. - The accumulated USDG mints the coin's leveraged tracker at its live NAV.
- A new pool is opened at
COIN / TRACKER, at the same dollar price, and the whole float goes back in. - 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 coin | the migrated flag is set before anything moves |
| Only its own tracker | fixed at launch, not chosen by the caller |
| Everything goes back in | reverts if more than MIGRATION_DUST of coin is left behind |
| Never two markets at once | the old position is closed and the new one opened in the same transaction |
| Permissionless | anyone 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.