Curve arithmetic and trading
Source: curve.move, launch.move, and fees.move. Use integer arithmetic; floating-point previews lose atomic-unit accuracy.
Reserves and price
Section titled “Reserves and price”Let D = 10_000, M = meme_reserve, V = virtual_quote, Q = real_quote_reserve, T = graduation_target, fq = quote_fee_bps, fm = meme_fee_bps, and s = sell_burn_bps. Rates below mean their integer BPS values. The curve prices against (V + Q) * M, with output rounded down; fees and burn round up. Rounding can increase the product. V is never deposited or withdrawn.
spot_price_atoms = (V + Q) / Mspot_price_whole = spot_price_atoms * 10^meme_decimals / 10^quote_decimalsprogress = Q / TThese display values are rational ratios: retain numerator and denominator or use decimal formatting. Do not perform truncating integer division before decimal scaling. Multiplying whole-token price by the current whole-token supply gives a current-supply valuation. Multiplying by the original billion-token supply gives an original-supply valuation; disposal at migration can make these differ. Neither is an executable quote.
For q quote atoms supplied, first cap gross input:
R = T - Qif q - ceil(q * fq / D) <= R: g = qelse: g = ceil(R * D / (D - fq))refund = q - g
quote_fee = ceil(g * fq / D)n = g - quote_feegross_meme = floor(M * n / (V + Q + n))meme_fee = ceil(gross_meme * fm / D)net_meme = gross_meme - meme_feeAn accepted trade changes Q to Q + n and M to M - gross_meme. A target-reaching buy sets MigrationReady. The cap reaches the remaining net quote amount exactly; the virtual reserve does not count.
launch::buy(launch, package_version, runtime_config, quote_coin, min_meme_out) returns (Coin<Meme>, Coin<Quote>): net output and excess-input refund. Consume both, including zero coins. Only Live permits buys. A nonterminal zero-output buy aborts with EZeroTradeOutput. A terminal zero-output buy succeeds only if min_meme_out is zero; a positive minimum aborts with ESlippageExceeded.
For m input token atoms:
meme_fee = ceil(m * fm / D)burn = ceil((m - meme_fee) * s / D)x = m - meme_fee - burngross_quote = floor((V + Q) * x / (M + x))quote_fee = ceil(gross_quote * fq / D)net_quote = gross_quote - quote_feeAn accepted sell changes M to M + x, Q to Q - gross_quote, and adds burn to pending_burn. It must be funded by the real quote balance; virtual reserves provide no payout liquidity. A balance failure reverts the transaction.
launch::sell(launch, package_version, runtime_config, meme_coin, min_quote_out) returns one Coin<Quote>. It requires Live and public_start_ms to be set. Zero net output aborts; output below the minimum aborts. Sell burn is separate from both asset fees and is disposed of only at migration.
Fee splits
Section titled “Fee splits”Each trade-fee asset splits using live RuntimeConfig.protocol_fee_share_bps, p:
protocol = ceil(fee * p / D)creator = fee - protocolFees accrue in the launch. Each launch’s fq and fm are immutable snapshots, each bounded at 1,000 BPS; Blast can change p from 0 to 10,000 BPS without a delay for later trades. A named partner takes its cut of Blast’s balances at payout time, not an extra fee during the trade.
For example, with M=1_000_000, V=100_000, Q=0, T=100_000, fq=fm=100, a buy supplying 10_000 quote atoms uses them all: quote fee 100, net quote 9_900, gross tokens 90_081, token fee 901, net tokens 89_180. This example uses atoms and is not a configured launch or a price promise.
Opening-round calls
Section titled “Opening-round calls”join_opening_round accepts a non-zero Coin<Quote> before public_start_ms + opening_round_ms; repeated bids accumulate under OpeningRoundBidKey(sender). The creator can join before sharing. No ordinary trade or withdrawal is available in OpeningRound.
At or after the end, anyone calls settle_opening_round once. It changes the state to Live and runs the pot through the buy arithmetic with minimum output zero. If zero tokens would be delivered without reaching the target, it retains the whole pot for refund; a target-reaching pot can be charged despite zero token output. Settlement may immediately produce MigrationReady.
deliver_opening_round(launch, package_version, bidder) removes that address’s bid and pays it directly. For remaining balances B_m, B_q, remaining bid total B, and this bid b, delivery pays floor(B_m*b/B) and floor(B_q*b/B), then subtracts the bid and payouts. The last delivery takes the remainder. Delivery works in every later lifecycle, including Migrated.
Learn and experiment
Section titled “Learn and experiment”The pricing walkthrough derives the constant-product equation step by step. The builder applies these atomic-unit rules to configurable plans, trade examples and LP-fee routing; its rates are examples, not live policy.