Skip to content

Outcomes & Tokens

Every market has two SPL token mints, both owned by the markets program and derived from the market PDA:

YES mint seeds = ["yes_mint", market_pda]
NO mint seeds = ["no_mint", market_pda]

Holding 1 YES token means: if this market resolves YES, the vault owes me 1 USDC. Holding 1 NO token is the same claim on the other outcome. Outcome tokens use 6 decimals, matching USDC, so raw amounts line up 1:1.

1 YES + 1 NO == 1 USDC

This is enforced by the program, not by arbitrage. Two instructions implement it:

InstructionEffect
mint_tokensDeposit n USDC into the market vault → receive n YES and n NO
merge_tokensReturn n YES and n NO → withdraw n USDC from the vault

Neither is a trade. There’s no counterparty and no price — it’s a conversion at par, available to anyone at any time while the market is open.

Three consequences worth internalising:

  1. The vault is always fully collateralised. Every outcome token in existence was minted against a dollar sitting in the vault.
  2. Selling a side you don’t hold is possible. Mint a pair, keep the side you want, sell the other.
  3. The matching engine can create liquidity. Two traders who both want to buy opposite sides are matched by minting a fresh pair from their combined collateral. See Match Types.

Because the pair is worth exactly $1, the two sides always price as complements:

price(NO) = 1 − price(YES)

So there is no meaningful difference between the YES book and the NO book — a bid for YES at $0.40 is an offer of NO at $0.60. The order manager keeps a separate book per token ID, and the aggregated view at /v1/book is the one to read if you want both sides of a market together.

The on-chain price accumulator stores everything in YES terms: a fill on the NO leg is recorded as its YES complement, so a single field describes the whole market. → CLOB Markets as Legs

Once a market is Resolved, the winning token pays 1 USDC and the losing token pays nothing.

markets::redeem winning outcome tokens → USDC, 1:1 from the market vault
markets::refund after a cancellation → collateral back, both sides

Redemption is a transaction you send yourself; it isn’t automatic and there is no deadline enforced in the program. withdraw_residual lets an admin sweep a market only once it is fully settled.

For a cancelled market, refund returns collateral against either side — the market never had a winner, so both token types are claims on the same pot.

CLOB positionParlay
Represented byFungible SPL tokens in your ATAA Parlay PDA account
TransferableYesNo
Sellable before resolutionYes, into the bookNo
Partially exitableYesNo — all or nothing
Redeemed bymarkets::redeemhigh-market-parlay::claim_parlay

A parlay is not a basket of outcome tokens. The parlay program never touches the YES/NO mints at all — it holds USDC and pays USDC. The legs are references to markets, priced once at create time.

→ How Parlays Work

Two on-chain reads gate every order you place:

  • ATA balance — do you hold what you’re offering? A BUY needs collateral; a SELL needs outcome tokens.
  • Delegate allowance — has the maker approved the program’s delegate PDA to move those tokens at settlement?
Delegate PDA seeds = ["delegate", maker]

The allowance is a standing SPL Approve. It’s what lets a maker post an order and go offline — the maker never signs the settlement transaction; the program signs for the delegate PDA instead. The order manager’s risk backend checks both over JSON-RPC on insert, and reserves the maker amount so a single balance can’t back two orders.

A missing allowance is a warning at insert time, not a rejection — but the settlement will fail on-chain. Set it before you trade:

Terminal window
cargo run -p delegate --quiet -- set --keypair ~/.config/solana/id.json --amount 1000000000