Files
pumpfun-bonkfun-bot_github/docs/launchlab-protocol.md
T
b5d0fd7761 feat(trading): sell a held coin after its bonding curve graduates (#237)
A graduated curve takes no trades. Curve managers now report it and refuse a
price, and the trader prices and sells through the platform's post-graduation
market: the canonical PumpSwap pool for pump.fun, the Raydium CPMM pool for
LaunchLab. Both pools are derived from the mint.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 22:29:08 +02:00

5.2 KiB

Raydium LaunchLab: letsbonk.fun and StonkFun

Both platforms are pools on one program, Raydium LaunchLab (LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj). The shared code is src/platforms/launchlab/; platforms/letsbonk/ and platforms/stonkfun/ only name their platform configs. The IDL is idl/raydium_launchlab_idl.json, pulled from the program's on-chain IDL account.

Platforms are platform configs

A launchpad on LaunchLab is the set of PlatformConfig accounts its pools are created under. Every launch and every trade names one, at account 3.

Platform Platform configs
letsbonk.fun 5thqcDwKp5QQ8US4XRMoseGeGbmLKMmoKZmS6zHrQAsA
StonkFun, standard 4E876qZTE9FJMrBzgVtBrSrzz2TLivB5Y5QXPjB4gZL7
StonkFun, reward 6BwHHDg3u1854jC8PDLXvR4spTcLNaoBxLJNGC4nTESt

The geyser and blocks listeners subscribe on these accounts, not on the program (EventParser.get_stream_filter_accounts), so other launchpads on LaunchLab stay out of the stream. Two platforms on one program also mean nothing may key a lookup by program id alone.

Launches

StonkFun launches are initialize_with_token_2022, as legacy, v0 and v1 transactions, sometimes issued by a router as an inner instruction. Read accounts by IDL name: payer is 0 and creator is 1, and the pool's creator — which keys the creator fee vault — is the creator account, not the payer. The quote mint is account 7 and its token program account 11. The transfer fee is the transfer_fee_extension_param argument.

Everything a buy needs is in the instruction, so the parsers set state_from_event. The program's PoolCreateEvent carries no base mint, quote mint or platform config, which is why there is no logs listener for LaunchLab.

Trades

buy_exact_in and sell_exact_in take the IDL's 15 accounts, then three the program reads positionally: the system program, the platform fee vault PDA([platform_config, quote_mint]) and the creator fee vault PDA([creator, quote_mint]). The pool is PDA(["pool", base_mint, quote_mint]). Every one of these is keyed by the pool's quote mint.

  • buy_exact_in spends all of amount_in. The trader hands an exact-in builder the configured amount, unpadded (spends_exact_amount_in).
  • Price is (virtual_quote + real_quote) / (virtual_base - real_base). The virtual reserves are fixed at launch. Pricing off them alone returns the launch price forever, and take-profit and stop-loss never fire.
  • Fees: trade_fee_rate (GlobalConfig) + fee_rate + creator_fee_rate (PlatformConfig), in parts per million, read live by the program. A buy pays them from its input and a sell from its output, rounded up. Curve outputs round down. platforms/launchlab/curve_math.py reproduces both to the unit.

Quote assets

The launcher picks the quote: SOL, an xStock, another coin. A SOL-quoted trade settles through a throwaway wrapped-SOL account opened and closed in the same transaction. Any other quote is paid from, and paid into, the wallet's own account for that mint. The bot never buys a quote asset, so the balance must already be there, and a sell leaves the proceeds in that asset. The quote's token program comes from the launch instruction. xStocks are Token-2022 mints.

xStocks carry a pause switch, a permanent delegate, a scaled UI amount and a transfer-hook extension with no program set. If the issuer sets a hook program, every transfer needs that program's extra accounts, and the builder does not pass them.

Transfer fees

StonkFun reward coins are Token-2022 mints with a 1% or 3% transfer fee.

  • A buy delivers its output less the fee, and minimum_amount_out is checked against what arrives. A floor computed without the fee reverts 6004.
  • A sell sends its amount and the pool trades on what arrives, less the fee.
  • The fee is withheld inside the receiving account: the bot's own account, on a buy. Token-2022 refuses to close an account holding withheld fees (0x23), so cleanup runs the permissionless HarvestWithheldTokensToMint first. Standard coins' mints have no transfer-fee extension, and harvesting against one fails, so only harvest when the account holds withheld fees.

Graduation

When a curve raises its target, Raydium's migrate wallet moves it to a pool, and the curve takes no more trades. PoolState.status is 1 while it waits and 2 once migrated; a migrated pool keeps its final reserves, so the curve manager reports graduated and calculate_price raises rather than return a frozen price.

migrate_type 1 means Raydium CPMM, which is where every StonkFun coin goes. The CPMM pool is PDA(["pool", amm_config, token_0, token_1]) under the CPMM program, with amm_config the platform's PlatformConfig.cpswap_config and the two mints ordered by their bytes, so it is derived, never searched for. A sell is swap_base_input, 13 accounts; the creator fee accrues inside the pool and adds none. Price is the vault balances less the protocol, fund and creator fees still sitting in them. migrate_type 0, Raydium AMM v4, has no market in the bot; a coin there is reported, not sold.

Verifiers

verify_launchlab_trades, verify_launchlab_launch_parsing, verify_cleanup_harvests_withheld_fees and verify_sell_after_graduation cover all of the above against captured mainnet transactions.