op::graduate message to the curve. tonch operates a keeper that does this automatically within seconds of the threshold being crossed; the keeper is just a convenience and isn’t required.
Trigger conditions
Theop::graduate handler runs these guards before doing anything:
graduation_state < state::graduated— not already graduated.real_ton >= graduation_ton_target— the curve has actually reached 1,000 TON.msg_value >= min_graduate_gas_reserve— the trigger transaction has enough gas to cover the migration messages.
The migration sequence
A successfulop::graduate runs these steps atomically in a single transaction:
1. Treasury cut
The contract computes:- Long-term protocol operating costs.
- Liquidity bootstrap funds for ecosystem partnerships.
- Future development of tonch’s contracts and frontend.
2. Pool seed split
The remainingreal_ton - treasury_cut (≈ 900 TON) is the pool seed TON. Combined with the 200M reserved Jettons (the AMM reserve allocation), this is what funds the DeDust pool:
3. Burn unsold curve supply
Any Jettons still held by the curve beyond the AMM reserve are leftover from the curve’s asymptotic shape (typically ~23M of the 800M for-sale supply). These get burned viaop::jetton_burn:
4. DeDust native vault deposit
The curve sends the pool seed TON to DeDust’s native (TON) vault with adeposit_liquidity payload that names the future pool’s two assets and the minimum LP amount (set to 1, accepting any LP).
5. DeDust Jetton vault deposit
The curve sends the 200M Jettons to DeDust’s per-Jetton vault with a TEP-74 transfer carrying adeposit_liquidity forward payload. The forward payload tells DeDust to credit the deposit to the same liquidity-deposit address as the native deposit in step 4.
6. LP minting and routing
DeDust’s pool contract receives both deposits, computes the LP supply to mint, and sends the LP Jettons back to the depositor — which is the curve. The curve’stransfer_notification handler recognizes the LP Jetton and forwards it to the LP locker contract.
7. State transition
The curve’s state transitions tostate::graduated. From this point:
- Buys and sells are rejected.
- The
op::sweep_feesopcode (deployer-only) becomes claimable by the original deployer for any accumulated curve fees. - The Jetton master continues to function normally for transfers among holders.
Why so many steps in one transaction
Each step uses TON’s actor-model message passing — sending a message to another contract that processes asynchronously. The graduation transaction sends all the messages in one go, but they execute across multiple chain blocks. This means:- The whole sequence finalizes over ~3–10 blocks (~1–10 seconds depending on TON validator timing).
- The frontend’s “graduating” state lasts until DeDust returns the LP Jettons to the curve and the curve forwards them to the locker.
- A graduation can stall if any single message bounces — for instance, if DeDust’s pool is mid-deploy and not yet ready to accept deposits. The keeper retries on failure.
What the deployer gets
Two things flow back to the deployer at graduation:- Accumulated curve fees — the 1% per-trade fees collected during the curve phase. Claimable via
op::sweep_feesby the original deployer’s address. For a curve that filled in moderate volume, this is roughly 1% of 1,000 TON ≈ 10 TON. - Their dev-buy holdings — if the deployer dev-bought, those Jettons are in the deployer’s wallet from the moment of the dev-buy. They are not affected by graduation.
Verification
Once graduation completes, you can verify the final state by reading the curve contract on Tonviewer:get_curve_statereturns the current state (should begraduated).- The curve’s TON balance should be near zero (only gas dust).
- The curve’s Jetton balance should be zero.
- The DeDust pool should hold the 900 TON + 200M Jetton reserves.
- The LP locker’s Jetton balance should match the LP supply minted by DeDust.