FAQ — Frequently Asked Questions#
Common questions about trading, fees, oracle behavior, and the protocol.
General#
What is Seesaw?#
Seesaw is a permissionless, non-custodial binary prediction-market protocol on Solana. See the docs landing page for a full product overview.
What is on-chain, and what depends on off-chain services?#
Solana enforces market custody, order matching, and settlement. Indexing, analytics, Pyth/Hermes oracle transport, and external-proof providers remain off-chain dependencies. An indexer or API outage must not change the protocol's rules or custody, but it can make indexed views, analytics, oracle delivery, or external-proof acquisition temporarily unavailable. See the canonical product trust boundary.
How do binary prediction markets work?#
You buy YES shares if you think a price will be UP by the end of a window, or NO shares if you think it will be DOWN. Winning shares pay 1 USDT each; losing shares pay 0. For the full mechanics see Understanding Shares and How It Works.
Trading#
How do I place an order?#
- Connect a Solana wallet (Phantom, Solflare, or Backpack).
- Pick a market — SOL/USD, BTC/USD, or ETH/USD are the seed markets at launch.
- Select YES (price UP) or NO (price DOWN).
- Enter quantity (shares) and limit price (0.01–0.99 USDT per share).
- Click Buy and approve the transaction.
Your cost is price × quantity. Buying 100 YES at 0.60 USDT requires 60 USDT
in collateral (plus a small taker fee if your order fills immediately).
What order types are available?#
| Type | Behaviour |
|---|---|
| Limit | Rests on the book at your price if not immediately matchable |
| PostOnly | Rests on the book; rejected if it would match immediately |
| ImmediateOrCancel (IOC) | Fills what it can right now; the unfilled remainder is cancelled |
IOC orders are exempt from the maker price band.
What happens if my order does not fill?#
A Limit or PostOnly order rests on the book until another trader matches it, you
cancel it, or the market's trading period ends. Resting orders that exceed their
per-order TTL (max_age_seconds) become reclaimable via ReclaimExpiredOrder.
Important: unfilled bid collateral is not automatically returned when the market closes. Cancel the order while trading is live to get it back immediately, or it is released together with your payout when you redeem after resolution. See What if I forget to claim?.
Fees#
What fees do I pay?#
Seesaw charges a taker-only, capped-linear-decay fee. Makers (resting orders) pay nothing.
fee_bps(p) = min(fee_cap_bps, decay_rate_bps × (10_000 − p) / 10_000)
With default parameters (fee_cap_bps = 200, decay_rate_bps = 400):
| Fill price | Effective taker fee |
|---|---|
| 0.00–0.50 USDT | 2.00% (capped) |
| 0.60 USDT | 1.60% |
| 0.80 USDT | 0.80% |
| 0.90 USDT | 0.40% |
| 0.95 USDT | 0.20% |
| 0.99 USDT | 0.04% |
The fee is rounded UP; payouts are rounded DOWN — both in the protocol's favor.
Where do fees go?#
Shipped fee defaults allocate four ways:
<!-- src: program/src/logic/fee.rs:168 FeeSplit4::TARGET --> <!-- F-01: update with builder fee allocation -->| Recipient | Share |
|---|---|
| Protocol treasury | 50% (routed to one of 8 treasury_recipients shards) |
| Market creator | 5% (accrues in market; claimed via ClaimCreatorFees) |
| Referrer | 5% (retained in the market until rollup; if no referrer, flows to protocol) |
| Eligible maker | 40% (credited as free quote balance after the resting-age gate) |
Ineligible maker allocation and rounding dust go to protocol. See fee constants for shipped defaults; deployed config may be retuned.
The 8-shard protocol treasury means a single key compromise drains at most 1/8 of accumulated protocol revenue. See Flow of Funds for the full accounting.
Referrals#
How does the referral program work?#
- Click a referral link or call
SetReferrer (0x21)directly. - An on-chain
ReferralAccountpermanently binds you to that first-touch referrer; the binding earns for 365 days and cannot be replaced after expiry. - Every taker fee you pay during that period retains its configured referral share (5% at shipped defaults) in
the market vault as a deferred liability. Permissionless
RollupReferralFees (0x36)later moves it to the referrer's bound treasury shard and creditsReferrerEarningsAccount.
Referrers call ClaimReferrerEarnings (0x24) to withdraw accumulated earnings
after rollup — no minimum balance or cooldown applies to the rolled-up amount.
Rollup should land before the seven-day post-resolution grace period ends.
After that deadline, permissionless position cleanup may reclassify any still
pending referral amount to market-creator fees.
Without an eligible referrer, the referral portion defaults to the protocol treasury. Your total fee is the same either way.
Settlement and Claiming#
When do markets resolve?#
After the market's duration window closes (e.g. 15 minutes for the default):
- Anyone calls
SnapshotEnd (0x04)to capture the end price from Pyth. - Anyone calls
ResolveMarket (0x05)to compare end vs. start price and record the outcome: UP if end ≥ start, DOWN otherwise (equality resolves UP). - Winners redeem for 1 USDT per share via
Redeem (0x1A).
All lifecycle cranks are permissionless — anyone can execute them. The canonical SDK exposes the instruction builders; operators can assemble them through the core SDK or keeper tooling. Reclaim-originated markets use the registered resolver service for authenticated external proofs.
What if I forget to claim after a market resolves?#
This is the most important risk to understand.
Winnings are NOT pushed to your wallet automatically. You must call Redeem.
The forfeiture timeline:
- Market resolves.
- 7 days after
resolved_at:CloseMarket (0x1E)becomes eligible. - During that 7-day window,
Redeem (0x1A)pays your claim and also releases any unfilled buy-side resting collateral from your position. - Before
CloseMarketruns, the permissionlessMarkPositionSettled (0x1C)crank pays each abandoned position's owed value directly to the owner's settlement token account. This is your safety net — third parties can trigger it on your behalf, and it pays owners, not the creator. - Expired resting orders that are reclaimed before terminal teardown use
ReclaimExpiredOrder (0x19): ordinary bid-side reclaims refund the maker minus the optional caller bounty, capped at 10 bps / 0.1 stablecoin. CloseMarketexecutes: the market is torn down. Any residual dust still in the vault (from rounding, donated tokens, or positions that could not be settled for other reasons) is swept to the market creator's stablecoin ATA. Abandoned unfilled-bid collateral that reaches the terminal-forfeit path is part of that residual creator sweep.
Safe habit: redeem every resolved market within a few days. Don't leave positions or resting orders abandoned in finished markets. See Flow of Funds for the full timeline.
What if the oracle is down at settlement time?#
If the Pyth oracle cannot supply a usable post-boundary price by
t_end + market_expiration_window_seconds (default 7 days after the
market's end time), the market transitions to Expired via
ExpireMarket (0x06). In that state:
- Both YES and NO shares redeem at 0.50 USDT each (50/50 split).
- Unfilled bid collateral is released.
- Funds are never stranded by an oracle outage.
Orders and Price Band#
Why was my order rejected?#
Several conditions can cause a resting order to be rejected:
| Error | Code | Cause |
|---|---|---|
OrderPriceOutOfBand | 0x3014 | Resting price is outside the maker price band |
PostOnlyModeActive | 0x300B | Market is in PostOnly mode; Limit and PostOnly orders are still accepted |
ProtocolPaused | 0x6001 | Protocol is paused; only settlement instructions remain available |
WouldCross | 0x3004 | A PostOnly order would immediately match |
TradingEnded | 0x1004 | Market's trading period has closed |
OrderbookFull | 0x3002 | The selected orderbook tier is full on that side |
MinRestingNotionalNotMet | 0x3013 | Remaining quantity after partial fill is below the minimum |
MaxTotalSharesExceeded | 0x300F | Order would push the market over its share cap |
Price band in detail: When both sides of the order book have resting orders, new resting orders must sit within ±1000 bps of the midpoint. When one or both sides are empty, the static bounds apply: bids must be ≥ 100 bps, asks ≤ 9900 bps. IOC orders are exempt — they never rest.
Market emergency status: Each market has an independent emergency status set
by the admin via SetMarketEmergencyStatus (0x2C):
| Status | Effect |
|---|---|
| None | Normal trading |
| PostOnly | Only PostOnly orders may rest; IOC/Limit takers blocked |
| Paused | All order placement blocked; settlement still works |
| ForceCancelOnly | New orders blocked; ForceCancelMarketOrders (0x2D) can cancel all resting orders |
Settlement instructions (Redeem, ForceClose, MarkPositionSettled, etc.)
remain available in all non-None emergency states.
Oracle#
How does Seesaw use Pyth?#
Seesaw launch markets use Pyth Pull only. The market stores the 32-byte feed ID,
and each snapshot supplies a real PriceUpdateV2 account posted by the official
Pyth Receiver after Hermes has selected the boundary update. The program checks
the feed ID, Receiver owner, verification level, freshness, and boundary witness.
The create-market instruction has no oracle-mode selector or Push compatibility fields. E2E and production setup must fail closed when a Receiver-backed update account is unavailable; synthetic or client-owned oracle accounts are invalid.
Pull mode:
- The market stores
pyth_feed = [0u8; 32](the pull indicator — no address). - At snapshot time, anyone posts an ephemeral
PriceUpdateV2produced by the official Pyth Solana Receiver program (via Pyth Hermes) to the transaction, and the program validates feed-id + owner ==config.pyth_receiver_program_id. - Pull mode makes Sampling Rule A firstness deterministic — Hermes can fetch exactly the first post-boundary price update, so there is no ambiguity about which sample qualifies.
Markets resolve UP if end ≥ start, DOWN if end < start.
For technical background see Design → Price Oracle.
Is there a planned Pyth upgrade I should know about?#
Pyth's Core upgrade is reflected in Seesaw's hard-pinned Receiver owner ID. The former ProposePythProgramId (0x30) and
ApplyPythProgramId (0x31) assignments are reserved wire holes; current
on-chain dispatch rejects both, with any payload shape, as
InvalidInstructionData.
If Pyth changes owner programs again, Seesaw must handle it as a program-upgrade event with release evidence rather than a routine on-chain config proposal.
SDK#
What SDK should I use to integrate?#
One canonical family:
Canonical SDKs (convenience; indexer/API in the read path):
- TypeScript:
@seesaw/core(@solana/kitv6) - Python:
seesaw-sdk(PyPI, solders-based) - Rust:
seesaw-sdk(crates.io)
Reclaim and generated account surface — Reclaim handles external proofs and generated readers validate account sets from RPC fail-closed:
- TypeScript:
@seesaw/core - Python:
seesaw-sdk - Rust:
seesaw-sdk
See SDK Guide for the canonical integration.
Security#
Is Seesaw audited or risk-free?#
No. The Protocol and its surrounding infrastructure may contain undiscovered bugs or vulnerabilities. Oracle data may be delayed, unavailable, stale, or incorrect; blockchain transactions may be irreversible; and network or third-party service failures may prevent timely trading or settlement. Do not use funds you cannot afford to lose, and review the Terms of Use and Security documentation before using the Services.
Is the protocol audited?#
The Seesaw on-chain program has not undergone a human third-party security audit as of the current release. Security measures in place include:
- ~1,628 unit tests and ~49 property tests (as of 2026-05-19)
- Fuzz testing (36 targets via
cargo-fuzz) - Mutation testing (
cargo-mutants) - Kani formal verification proofs
- Runtime invariant checks (solvency, no-crossed-book, conservation)
- All arithmetic uses checked operations; rounding always favors the protocol
This status will be updated when a human third-party audit is completed. Trade accordingly — smart-contract risk is real. See For Traders → Risks for the full risk disclosure.
Common Error Codes#
See Error Codes for the complete, categorized reference. Common codes you may encounter while trading are listed there alongside their causes and recovery actions.
Getting Help#
If your issue is not covered here:
- Check the Troubleshooting guide.
- Search Discord — many issues have been discussed before.
- Post in #support with: error code, transaction signature, wallet type, browser, and steps to reproduce.
- Open a GitHub issue for bugs or feature requests.