Fees
GoMarket charges fees in two unrelated places: on CLOB trades, and on winning parlay payouts. The mechanics are different in each.
CLOB trading fees
Section titled “CLOB trading fees”Fees are charged on the taker asset — the asset flowing from taker to maker — and accrue to a per-mint fee vault PDA.
Fee vault seeds = ["fee_vault", mint]| Maker’s side | Taker pays the maker | Fee taken in |
|---|---|---|
| BUY | outcome tokens | outcome tokens |
| SELL | collateral | collateral |
The formula
Section titled “The formula”price = calculate_price(maker_amount, taker_amount, side);min_price = min(price, ONE - price);
match side { Side::Buy => (fee_rate_bps * min_price * outcome_tokens) / (price * BPS_DIVISOR), Side::Sell => (fee_rate_bps * outcome_tokens / BPS_DIVISOR) * min_price / ONE,}The min(price, 1 − price) term is the important part. It scales the fee by
how far the price is from a certainty, so the effective rate is highest at
$0.50 and falls toward zero at the extremes.
| YES price | min_price | Relative fee |
|---|---|---|
| $0.50 | 0.50 | maximum |
| $0.20 or $0.80 | 0.20 | 40% of max |
| $0.05 or $0.95 | 0.05 | 10% of max |
A trader buying a 3¢ longshot is risking 3¢ to make 97¢. Charging them the
same percentage as someone trading a coin flip would be a far larger share of
their actual risk. Scaling by min(p, 1−p) keeps the fee proportional to the
value at stake rather than to the notional.
Who pays
Section titled “Who pays”Takers pay; makers don’t. The validator enforces this at insert: an order
that is marketable on arrival must carry at least the taker fee rate in
feeRateBps, or it’s rejected. A resting order that is later taken doesn’t
pay — it was the maker on that fill.
So feeRateBps on your order is not optional decoration. Set it correctly for
the role your order will play, or the insert fails.
The on-chain handler independently validates fee <= taking, so a malformed
fee rate cannot consume the entire payment.
Parlay fees
Section titled “Parlay fees”A parlay’s fee is charged on the gross potential payout, at claim time, and only on a winning slip.
fee = floor(potential_payout × fee_bps_at_create / 10_000)fee = min(fee, potential_payout)net = potential_payout − feeThree properties:
- No fee on the stake. Placing a parlay costs exactly your stake.
- No fee on a loss. You lose the stake, nothing more.
- The rate is snapshotted at create time.
fee_bps_at_createis written into theParlayaccount when you place it and read back at claim. An adminupdate_configbetween those two moments cannot change what you pay.
The cap is 10% (fee_bps ≤ 1000), enforced at initialize and on every
update_config.
At claim, the vault pays net to the user and fee to config.treasury in
the same transaction.
Worked example
Section titled “Worked example”stake $10legs 3, at 50% / 40% / 25%combined 0.05potential_payout $200fee_bps_at_create 200 (2%)
fee = floor(200_000_000 × 200 / 10_000) = 4_000_000 → $4net = $200 − $4 = $196Where fees go
Section titled “Where fees go”| Source | Destination |
|---|---|
| CLOB trade fees | Per-mint fee vault PDA, ["fee_vault", mint] |
| Parlay fees | config.treasury token account |
Both are on-chain accounts controlled by the program’s admin authority, which in production is a Squads multisig.
Costs that aren’t fees
Section titled “Costs that aren’t fees”| Cost | Notes |
|---|---|
| Solana transaction fees | Paid by the executor for CLOB settlement; paid by you for parlay instructions |
| Priority fees | The executor escalates these on retries |
| Mint / merge | No fee — a par conversion, not a trade |
| Redeem / refund | No protocol fee |
| Cancelling an order | Free; off-chain only |
| Spread | Not a fee, but usually your largest real cost on a thin book |