Concepts
The mental model behind a parimutuel market.
Parimutuel, not order book
There is no matching engine and no counterparty. Every participant who stakes on the winning option shares the total pool pro‑rata to their contribution, minus fees. If you stake 100 USDC on the winning side of a 1,000 USDC pool, you receive roughly 10% of the post‑fee pool.
This has two consequences worth internalizing:
- No price. A stake is a claim on a share of the pool, not a share bought at a quoted price. Odds are implicit in the pool composition at any moment, but nothing trades.
- Early stakers aren't advantaged by price. They are advantaged only if later stakers pile into the losing option — a "discovery" advantage, not a price advantage.
Lifecycle
Every market moves through a linear state machine:
| State | Entered by | Allowed actions |
|---|---|---|
Open | creation | buyIn, whitelist edits |
Closed | closeTime elapsed | submitAdminVote, submitResolution |
ResolvedPendingFinality | submitResolution | submitDispute, finalizeMarket |
Finalized | finalizeMarket after the challenge window | redeem |
Voided | strict‑majority dispute | refund |
Closure from Open to Closed is passive — the contract treats the market as closed the first
time any function checks block.timestamp >= closeTime. No closeMarket call is needed.
Roles
- Creator. Deploys the market via the factory. Owns the whitelist and sets the creator fee. Cannot resolve (unless they are also the sole admin).
- Admin / Resolver. One or more addresses authorized to submit the outcome. In
MultiAdminmode, admins cast votes and any one of them may submit the resolution once quorum is reached. - Participant. Anyone who has staked, even 1 wei of USDC. Eligible to dispute.
- Anyone. May call
finalizeMarketonce the challenge window closes — it is intentionally permissionless so markets don't stall.
Options
Options are declared at creation: two to eight strings, each up to 50 characters. They are
referenced by uint8 index in every later call. The strings themselves are immutable — rename
through off‑chain metadata (Convex, a CMS, etc.) if you need display flexibility.
Resolution modes
Three modes, chosen at creation and immutable thereafter:
- SingleAdmin. One resolver.
admins.length === 1,quorum === 1. - MultiAdmin. 1–5 resolvers. Each casts
submitAdminVote(optionIndex); oncequorumvotes land on the same option, any admin may callsubmitResolutionto commit it. - AiOracle. Identical mechanics to
SingleAdminon‑chain, but the resolver address is held by an off‑chain AI service that fetches evidence and signs the transaction. See oracles.
Evidence
Every resolution carries an evidenceUrl string and its keccak256 hash. The hash isn't verified
against URL content on‑chain — it's a tamper‑evidence anchor so the resolver can't later swap the
artifact. Participants inspect the URL during the challenge window and dispute if it doesn't justify
the claimed outcome.
Disputes
A dispute is a single boolean vote per participant. If 2 * disputeCount > eligibleParticipantCount
at any point during the window, the market voids immediately and all stakers refund. There is no
partial rollback and no dispute resolution — it's a binary "accept or void" by the participants
who have skin in the game.
Fees
Two fees are deducted at finalization:
- Creator fee — 0–500 bps (0–5%), configurable per market.
- Platform fee — 0–500 bps, configured globally on the factory.
Combined cap is 1,000 bps (10%). Fees are only routed when a market finalizes; a voided market pays no fees.
Currency
All stakes are USDC (6 decimals). Amounts everywhere in the contract are in USDC base units —
1_000_000 is 1 USDC. This is not configurable per market.