How a launch works
The short version#
deployer ─▶ LaunchLab initialize_with_token2022
creator = the Stags policy PDA
quote = a tokenized stock
▼
the pool trades, StonkFun collects the whole 1% fee
▼
StonkFun forwards the creator's share, off chain,
into ATA(creator, quote_mint) = the policy's quote_escrow
▼
anyone ─▶ route ─▶ protocol cut, bankroll share, LP share
anyone ─▶ compound_lp, sweep_profit, buyback_and_burn, burn_base_legEvery money instruction after the launch is permissionless, with two exceptions that are named on the instruction reference. There is no privileged keeper. If the one running stops, anybody can call the same instruction with the same result.
The check matters because whoever the pool names as creator receives every fee the launch ever earns, and a policy pointing at the wrong pool would look perfectly healthy from the outside.
1. The pool#
The launch is a Raydium LaunchLab pool created with initialize_with_token2022. That instruction takes a creator, described by Raydium as "the wallet fees are forwarded to". Stags passes the policy PDA there, so creator fees accrue to a program-derived address from the first trade. There is nothing to register afterwards and no wallet in the path.
The quote asset is one of StonkFun's launchable pairs, which are dominated by tokenized stocks. See quote assets and pairs for which of those pairs can actually be used, because not all of them can.
2. The policy account#
In the same flow the deployer calls init_policy. This creates the Policy account at seeds ["policy", mint] and, with it, four token accounts owned by that PDA and one associated token account for the fee key. The policy records the splits, the mode, the model, the risk setting, the target asset and the leverage cap, plus three keys: the authority, the agent and the guardian.
It proves the fee stream rather than assuming it#
init_policy takes the LaunchLab pool account and refuses to create a policy that is not actually the pool's creator. Whoever the pool names as creator receives every fee the launch ever earns, so a policy pointing at the wrong pool could never be paid, and it would look perfectly healthy from the outside.
Five things are established before a single field is trusted:
- the account sits at the address LaunchLab would have derived for this pair,
["pool", base_mint, quote_mint]; - it is owned by the pinned
launchlab_program; - it is long enough to hold the struct;
- it carries LaunchLab's own
PoolStatediscriminator; - the base and quote mints read back out of it match the pair, which is belt and braces on top of the seeds.
Only then is creator read, and it must equal the policy address. Anything else fails with NotTheLaunchPool or PoolCreatorNotPolicy. Three field offsets are read out of the account directly rather than pulling in Raydium's crate, and they were confirmed against a real mainnet pool.
3. The Fee Key NFT, which turns out not to exist here#
The program was built expecting LaunchLab's claim to be gated by a per-launch Fee Key NFT, so init_policy creates fee_key_account, an associated token account for fee_key_mint owned by the policy PDA, and no instruction in the program ever debits it.
discriminator [26, 97, 138, 203, 132, 171, 141, 252]
0 creator signer, writable
1 fee_vault_authority PDA["creator_fee_vault_auth_seed"]
2 creator_fee_vault PDA[creator, quote_mint] writable
3 recipient_token_account ATA(creator, token_program, quote_mint) writable
4 quote_mint
5 token_program
6 system_program
7 associated_token_program4. How the fee arrives, and routing#
The program keeps two escrows, a quote leg and a base leg, and handles them differently:
- The quote leg, which is the stock, is money. It lands in
quote_escrowand is split byroute. - The base leg, which is the launched token, is already the thing holders want destroyed, so it needs no swap. It lands in
base_escrowand is burned byburn_base_legor bybuyback_and_burn.
What a launch costs#
About 0.0176 SOL, and that figure is decoded from a real StonkFun launch on mainnet rather than estimated. It answers a question worth answering out loud, because the number people expect is much larger.
| Side | Item | SOL |
|---|---|---|
| LaunchLab | the base mint | 0.002718 |
| LaunchLab | the pool state | 0.002830 |
| LaunchLab | quote vault | 0.001488 |
| LaunchLab | base vault | 0.001488 |
| LaunchLab | network fee | 0.000040 |
| LaunchLab total | 0.008564 | |
| Stags | the policy account | 0.002682 |
| Stags | four token accounts | 0.006238 |
| Stags | mint and metadata | 0.002682 |
| Stags | two signatures | 0.000010 |
| Stags total | 0.011613 |
The two subtotals do not simply add: the mint appears on both sides, because LaunchLab creates it. The honest total is about 0.0176 SOL per launch. LaunchLab's side was decoded from the newest live launch at the time of reading, mint 5JcJTPz7XAeV75iocd2D32oyFpTrtnt752eXFRikA8TE; the Stags side was read live by the preflight script. Rent moves, so re-read it rather than trusting this table.
What the deployer decides#
These are the arguments to init_policy, in order. Everything else about a launch is either LaunchLab's or the protocol's.
Model account only when the mode is Agent, and the model must be enabled. Meaningless in Passive mode.to_bankroll_bps may not exceed the protocol's max_bankroll_bps ceiling.max_risk. See risk, origins and asset classes.passive_deploy refuses any venue account whose asset_mint is not this exact key.MAX_LEVERAGE = 5 at the point it is written, and again on every remote equity attestation.Three keys are also recorded from the accounts passed in: authority (the deployer, who can change an unlocked policy), agent (which may move funds only to pre-registered venues) and guardian (which may pause and may not unpause). The agent and guardian are recorded as raw keys and are not checked at launch, so they may be addresses the deployer does not control yet.
The accounts a launch creates#
All five token accounts are associated token accounts, not bespoke PDAs. That is a deliberate change, and the reason is on what is not built yet: the on-chain associated token program sizes an account against the live Token-2022 program, which is what lets a policy be created against a real tokenized stock at all.
| Account | Derivation | Holds |
|---|---|---|
| Policy | ["policy", mint] | The splits, mode, model, risk, target, counters and the three keys |
| quote_escrow | ATA(policy, quote_mint) | Quote fees awaiting route, and the LP share awaiting compound_lp |
| base_escrow | ATA(policy, base_mint) | Base fees, and bought-back tokens, both awaiting the burn |
| bankroll | ATA(bankroll_auth, quote_mint) | The vault itself, in the quote mint |
| holder_rewards | ATA(holder_auth, quote_mint) | Profit staged for buyback, spendable only by buyback_and_burn |
| fee_key_account | ATA(fee_key_auth, fee_key_mint) | The fee key account. Never debited. |
Each *_auth is a program address at ["<name>_auth", policy]. Three of them are needed because only one associated token account can exist per owner and mint, and the three quote-side accounts would otherwise collide on a single address.
Every quote-denominated account belongs to one policy's own quote_mint. There is no protocol-wide quote mint, because every launch pairs a different stock.
Why no StonkFun integration is needed#
StonkFun is not an AMM. It is a front end and adoption layer over LaunchLab. In its own words, you can skip it entirely and construct the launch yourself against LaunchLab with your own mint keypair and your own instructions, and still get everything the platform does around a launch. It scans pools carrying its platform id every minute and adopts the ones it has no record of, and an adopted launch is indistinguishable from an API-created one.
So Stags builds the LaunchLab initialize itself and bakes in the platform id. No key, no signup, no business relationship.
| Field | Address |
|---|---|
| LaunchLab program | LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj |
| GlobalConfig | B7ctMMdGvy46Am56myTtzfkNzt9kWZVTNGM2BWrJ9adg |
| Platform id, standard | 4E876qZTE9FJMrBzgVtBrSrzz2TLivB5Y5QXPjB4gZL7 |
| Platform id, reward | 6BwHHDg3u1854jC8PDLXvR4spTcLNaoBxLJNGC4nTESt |
| Curve rule, standard | QYZp1YzqEHU67ngXphF9LAkxkxWGvpWEv3rXh4yDbWA |
| Curve rule, reward | 7MNLMFMmFVhN9Z3sj51QZso28oD2Ta3zDPwNAmfrs2vk |
| Pool PDA | ["pool", base_mint, quote_mint] |
Read from StonkFun's developer documentation and its open API on 2026-09-22, quoting the SPYX pair. The pool PDA is confirmed twice independently: LaunchLab's own IDL declares exactly those seeds on initialize, initialize_v2, initialize_with_token_2022 and migrate_to_cpswap, and the derivation reproduces the pool address StonkFun reports for 25 of 25 live launches. No pool address needs storing: the two mints already on the Policy are enough.
The curve, as StonkFun configures it#
| Field | Value |
|---|---|
| Curve | ConstantCurve, migrates to Raydium CPMM |
| Base decimals | 6 |
| Base supply | 1000000000000000 |
| totalSellA | 793100000000000 |
| Opening market cap | $3,305 |
| Graduation market cap | $48,567 |
| Implied run | 14.69x |
| Reward tax tiers | 100 or 300 bps, and only those |
Read 2026-09-22 against the SPYX pair. These are StonkFun's numbers, not ours: Stags does not choose the curve.
How much of a trade reaches the policy#
Two fields decide the mechanism, and they are separate rather than one list of three types. launchpad is launchlab here, or raydium for the older locked-position type with its Fee Key NFT, and mode is standard or reward. A Stags launch is launchlab, standard: no creator position, and StonkFun forwards the creator's share itself. Reward mode has no creator fee at all.
The on-chain fee fields are consistent with that and are worth showing, because they look at first glance like the creator is paid nothing. Both live platform configs, decoded from mainnet on 2026-09-22:
| Field | Standard config | Reward config |
|---|---|---|
creator_fee_rate | 0 | 0 |
fee_rate | 10000 (1%, StonkFun's own cut) | 10000 |
creator_scale | 0 | 0 |
platform_scale | 1000000 (100% to StonkFun) | 1000000 |
burn_scale | 0 | 0 |
Every creator fee vault behind all 25 live launches reads exactly 0, and a mainnet claim simulation fails inside LaunchLab's own handler with nothing to transfer.
That is exactly what you would expect when the platform takes the whole 1% at the protocol level and then forwards the creator's share itself. The creator fee vaults are empty because that path is not the one in use, not because nobody is paid, and on every one of the five forwarded launches watched the vault read zero while credits arrived. The practical consequence for this program is that route, not claim_fees, is the instruction that does the work.
StonkFun reward mode: a 100 or 300 bps TRANSFER TAX on the mint,
collected by StonkFun's own withhold authority,
and distributed by them on their reward cycle.
Stags: profit from the bankroll buys the token back
and burns it. Nothing is paid to a wallet.Both can run on the same launch. They are different streams from different sources, and this documentation never calls them the same thing.