Launch vault
This supersedes the launch-vault section of the Tender programs' own docs, which predates the strike ladder, the stake slider, the size-cap changes, the $1M cutoff, auto-exercise, calls before bonding, the $100K/$150K hourly strikes and the per-wallet cap.
launch(name, symbol, uri, beneficiary, max_sol_cost, stake_bps)
- Refuses
stake_bpsoutside 500..=1000 (BadStake) and bad metadata lengths. - pump.fun
create_v2with the creator PDA["creator", mint]as creator, thenbuy_v2ofPUMP_SUPPLY x stake_bps / 10,000tokens, paid by the launcher (platform mode) or drawn from the backer pool (backer mode). Cost must not exceedmax_sol_cost(Slippage). - Records stake, stake cost, graduation price, supply, status LAUNCHED.
- Needs an address lookup table (legacy size exceeds 1,232 bytes).
open_calls
Anyone, once, while the coin is still on its curve (status LAUNCHED, curve not complete, curve
creator = creator PDA, no collection yet; CallsOpen otherwise). Creates the calls collection
(same A-07 handling as activate) and seeds H at the curve spot. The launch flow sends it right
after launch; the keeper's openCalls job is a safety net.
activate
Requires a complete curve and the canonical PumpSwap pool with the creator PDA as coin creator.
If pump.fun's boost vault still holds SOL, the first call arms activation and returns; a later
call proceeds once BOOST_MAX_WAIT (30 min) has passed or the boost is empty (fix for SEC-A
A-03). Creates the calls collection unless open_calls already did (moving any stray lamports
out first, fix A-07). Seeds H at the graduation price.
buy(tenor, amount, max_premium, strike_usd)
- Status ACTIVE, or LAUNCHED with calls opened (before bonding); account checks. After activation sales are open only while the curve creator and pool coin creator are still the creator PDA. Before bonding the pool accounts are the canonical pool's address (the pool does not exist yet).
- Reference: spot (before bonding the curve's virtual reserves, after it PumpSwap reserves incl.
virtual quote) and H slewed to now;
p_ref = max(spot, H[tenor]). - Lowest rung:
ceil_100K(max(1.5 x ref_mcap, $200K)). Strike:strike_usd(0 = lowest) must be a whole $100K from the lowest to 9 steps above, or, hourly only, $100K or $150K if at least1.5 x ref_mcap(BadStrike). - Refuse if
ref_mcap >= $1M(McapCeiling), or spot is at or above the strike. - Size limits (Y0 units): fill 5%; rolling hour 2.5% unless 1.5 x ref_mcap <= $200K (pinned);
day and live
48% x stake / 10%; thin pool 25% of live base (before bonding: of the curve's real tokens). Per wallet: at mostWALLET_CAP(2M tokens) of open calls per coin, tracked in the PDA["wallet", vault, buyer](8 expiry slots, created at the buyer's cost), passed as the 17th remaining account (WalletLimit). - Premium:
ceil(low x size x 13.9% / supply)thenceil(that x low / k), converted to SOL at Pyth; must be at mostmax_premium. 0.5% to the treasury, rest to the creator PDA (measured; the treasury's own fee is skipped if it is the buyer). - The series must be the canonical engine series for (mint, wSOL, strike, expiry, call, tier A, writer = creator PDA, pool, USD strike unit) (fix A-01), created if absent. The pool is the canonical pool before and after bonding, so pre-bond series cash out on it after migration.
- After activation: half the net premium buys the token on PumpSwap; cover from inventory;
shortfall bought in the same swap with vault SOL, backers lend the rest, bounded by
COVER_BAND_BPS(fix A-05). Before bonding: cover from the stake only (NotCoveredPreBond), and the premium's token share stays in the vault as SOL. - Engine
write; LONG to the position escrow; Metaplex Core asset minted with 18 attributes; sale recorded in the hourly buckets and live slots.
auto_cash_out
Same accounts as cash_out_position with the keeper (AUTO_EXERCISER) as holder and the
asset's owner as the one remaining account; only in the last AUTO_WINDOW (600 s) before expiry.
Proceeds and rents go to the owner; the NFT is burned by the collection's permanent burn
delegate; the keeper takes nothing. Out of the money the engine's minimum proceeds refuses it.
exercise_position / cash_out_position
Both bind the passed series and escrow to the NFT's own attributes (fix A-02) and require
now < expiry. Exercise: holder pays the strike in SOL at Pyth, receives the tokens; the asset
stays as a receipt with status Exercised. Cash-out: engine exercise_cashless_pump sells the
escrowed tokens into PumpSwap (at most its real SOL), keeps the strike, pays the rest, burns
the asset.
settle_expired, close_position_nft
After expiry anyone settles the vault's SHORT: unexercised tokens return to inventory, strikes paid return as wSOL. Expired or exercised NFTs can be closed.
collect_fees
Collects pump.fun and PumpSwap creator fees. The vault's known SOL (sol_known) is tracked
across every handler so fees collected by others are not mistaken for its own cash (fix C-01).
Split: backers' share, backer debt, then (nothing owed) a 0.25 SOL reserve and the beneficiary.
unwind_stake, burn_leftover, write_off, poke
Stall rule after 72 h without graduation; burn leftover stake after 7 days without sales
(nothing owed); backstop write-off after 7 quiet days; poke updates H.
