How it works
This page follows one stock from listing to a fill, naming the instruction that does each step.
1. Listing a stock
- The notice authority calls
floor_notice::file_notice(issuer_sponsored, notice_sent_at)for the mint. For an issuer-sponsored tokennotice_sent_atis stored as 0 and trading may open at once. For a third-party token the date must be positive and not in the future; the record opens atnotice_sent_at + 30 days. - The caps authority calls
floor_caps::list_symbol(symbol, tier, decimals). The symbol is the ticker as up to 12 bytes;tieris 1 or 2;decimalsare the stock mint's (at most 12). The tier's symbol count, less any symbols reserved for affiliates withset_reserved, must have room, or the call fails withSymbolLimit. There is no grace: the listing is refused, not recorded. - A keeper set posts the prior month's ADV with
floor_caps::post_adv(month, adv_shares). Until the prior month's ADV is on record,record_executionfails withNoPriorMonthAdvand the stock cannot trade. - The halt authority opens the symbol's halt record with
floor_halt::open_symbol(symbol). - The venue authority registers the quote mint once with
floor_venue::register_quote(kind)(PaymentStablecoin,TokenizedMoneyMarketFundorTokenizedStock) and then opens the pair withfloor_venue::create_pool(symbol).create_poolchecks that the stock mint is Token-2022 with an issuer gate: a transfer hook program, or accounts frozen by default plus a freeze authority, which is how FWDI and GLXY are issued (NoIssuerGateotherwise), that the symbol is listed in the caps program (SymbolNotListed) and that the listing's decimals match the mint (DecimalsMismatch).
2. Admitting a wallet
The venue authority calls floor_venue::admit(wallet), which creates the wallet's Participant record with admitted = true. set_admitted(false) revokes it and set_admitted(true) readmits it; each change emits ParticipantChanged. Every swap, deposit and withdrawal requires the signer's Participant to be admitted (NotAdmitted). The issuer's own allowlist is enforced separately by the mint: FWDI and GLXY accounts are frozen by default and only the ones Superstate's transfer agent has thawed can send or receive.
3. Providing liquidity
add_liquidity(max_stock, max_quote, min_lp) deposits both sides in the pool's current ratio (math::deposit picks the amounts that fit inside both maxima) and mints LP units from the pool's LP mint (6 decimals). remove_liquidity(lp, min_stock, min_quote) burns LP units and pays out the pro-rata share of both reserves. Reserves exclude the venue's accrued fee share, so an LP's claim is on everything else in the vaults, fees earned included. Both instructions emit LiquidityChanged.
4. A fill
swap(stock_to_quote, amount_in, min_out) runs these checks in order:
- the venue is not paused (
VenuePaused) and the pool is not paused (PoolPaused); - the symbol's
HaltState.haltedis false (Halted); - the mint's
IssuerNotice.trading_open(now)is true: issuer-sponsored, or past day 30 with no objection (NoticeNotOpen); - the quote:
math::quote(reserve_in, reserve_out, amount_in, fee_bps, venue_share_bps)takes the fee from the input, rounds it up, splits off the venue's share, and prices the rest on the constant product;amount_outmust reachmin_out(Slippage), and a quote that would empty a reserve is refused (BadQuote); - the CPI into
floor_caps::record_execution(stock_amount), signed by the venue PDA:used + fill <= cap(ExceedsMonthlyCap), and past 90 percent of the cap a single fill may be at most 1 percent of it (Throttled); the stock leg is what is counted, whichever direction the trade goes; - the two transfers, in through the user's signature and out through the pool PDA, both through the mint's own token program so its extensions apply (a frozen account rejects the transfer; the test mint's hook runs);
- the venue's fee share is added to
pool.venue_fee_stockorpool.venue_fee_quote, and aFillevent is emitted with both amounts, both fees, both reserves after the trade, the slot and the time.
Worked example from the program's own test: reserves 1,000,000 in and 1,000,000 out, amount_in 1,001, fee 30 bps, venue share 20 percent. Fee = 1,001 × 30 / 10,000 = 3.003, rounded up to 4. Venue fee = 4 × 2,000 / 10,000 = 0.8, rounded down to 0. Net input 997, output 1,000,000 × 997 / 1,000,997 = 996.
5. The cap month
record_execution resets the counter when the calendar month changes (month_index(now)), so a fresh month starts at zero executed shares. The cap in token units is adv_shares × cap_bps / 10,000 × 10^decimals. The constants are TIER1_CAP_BPS = 25, TIER2_CAP_BPS = 250, THROTTLE_FROM_BPS = 9,000, THROTTLE_FILL_BPS = 100.
For FWDI, September 2026 ADV on Nasdaq was 2,273,683 shares over 21 sessions, so October's Tier 1 cap is 5,684 shares.
6. A halt
A keeper calls floor_halt::post(halted, seq). When the threshold is reached, HaltState.halted flips, since is set and HaltChanged is emitted; that event is the participant notice the order asks for. Every later swap fails with Halted until a resume event is applied the same way.
7. A breach
If a prior-month ADV is revised downward after fills have already happened, and this month's executed shares now exceed the new cap, post_adv calls breach. The caps authority can also call declare_breach when a breach is found off chain. The first breach is recorded; each later breach sets paused_until three calendar months ahead (BREACH_PAUSE_MONTHS = 3) and swaps fail with BreachPause until then. set_paused is the voluntary pause the order allows as a stock nears its cap.
8. The tape
Every Fill event is indexed and served as JSON for the last 30 days in USD, refreshed within 10 minutes. Before launch the tape is empty; the landing page says so rather than showing invented prints.