Architecture
Four programs share the work. The venue program owns money and executes trades; the other three hold facts the venue reads before it lets a trade through. Two of those facts come from off chain through keeper sets.
The programs
floor_venue (3vkpdUbz...) floor_halt (hZWUysrR...)
Venue seeds ["venue"] HaltConfig seeds ["config"]
Participant seeds ["participant", wallet] HaltState seeds ["halt", symbol]
QuoteAsset seeds ["quote", mint]
Pool seeds ["pool", stock_mint, quote_mint]
floor_caps (riN4V5uU...)
floor_notice (4MLRiWbL...) CapsConfig seeds ["config"]
NoticeConfig seeds ["config"] SymbolCap seeds ["cap", symbol]
IssuerNotice seeds ["notice", mint]
swap in floor_venue takes the pool, the symbol's HaltState, the mint's IssuerNotice, the symbol's SymbolCap and the caps CapsConfig as accounts, checks them in that order, then calls floor_caps::record_execution by CPI signed with the venue PDA. The caps config stores that PDA as its recorder; no other signer can count shares.
One of each
Every object that must be unique is a PDA whose seeds are the thing it is unique for:
- one
Poolper (stock mint, quote mint): seeds["pool", stock_mint, quote_mint]; - one
SymbolCapper symbol:["cap", symbol], where the symbol is a 12-byte padded ticker; - one
HaltStateper symbol:["halt", symbol]; - one
IssuerNoticeper mint:["notice", mint]; - one
Participantper wallet and oneQuoteAssetper mint.
A second pool for the same pair, or a second notice for the same mint, cannot be created because the address is already in use.
Keeper feeds
Two facts cannot be computed on chain: whether the primary exchange has halted a stock, and the stock's prior-month consolidated average daily volume. Both arrive through keeper sets with the same shape:
- a config holds up to 16 keeper keys and a
threshold(1 to the keeper count), plus akeeper_epochthat increments on every change to the set; votes cast under an older epoch are void; - a keeper proposes a value for the next sequence (halt) or for a month (ADV); the first vote opens the proposal, later votes must match it or fail with
ProposalMismatch; a keeper cannot vote twice (AlreadyVoted); - when the votes reach the threshold the value is applied and an event is emitted (
HaltChanged,AdvPosted).
Halt events carry a sequence number and must arrive in order (seq == applied seq + 1, else StaleSequence), and a vote that would not change the state is refused (NoChange). ADV can only be posted for a month that has ended (MonthNotOver) and never for a month older than the one on record (OlderMonth). A revision of the prior month's ADV that leaves this month's executed shares above the new cap triggers breach at once.
Sources the keepers read: Nasdaq Trader's trade halts feed and CTA notices for halts; the NYSE Consolidated Volume Summary for ADV. The venue board on the landing page reads Nasdaq's public endpoints for the same facts so a visitor can compare.
Trust model
| Authority | Held by | Can do | Cannot do |
|---|---|---|---|
| Venue authority | multisig | set fees up to 10 percent, set the fee recipient, pause the venue or a pool, admit and revoke participants, register quote assets, create pools | take user funds, mint stock, change a pool's mints, skip a halt or cap check |
| Halt authority | multisig | set the keeper set and threshold | post a halt directly |
| Caps authority | multisig | set keepers, list symbols, set reserved symbol counts for affiliates, pause a symbol voluntarily, declare a breach | change the cap percentages or the throttle (constants in code), record executions |
| Notice authority | multisig | file a notice, record an objection inside the window | lift an objection, shorten the 30 days |
| Keepers | operator-run and third-party signers | vote on halt state and monthly ADV | apply anything alone when the threshold is above one |
| Upgrade authority | the deployer until a multisig takes it | upgrade the programs | nothing else; it is disclosed on the disclosures page |
The app and the site
The Next.js site serves the landing page, the docs and /app. /app reads the four programs through /api/rpc, a relay that forwards a fixed list of read and send methods to a keyed RPC provider. Before launch the app runs in preview: live mainnet accounts, every input and quote working, transaction buttons replaced by "Opens at launch". The landing's board reads /api/board, which gathers Nasdaq last sale, market status, daily volumes and the halt feed, plus Jupiter prices for the Superstate mints.