Each market is deployed as a minimal proxy clone of a single implementation contract. This is dramatically cheaper than deploying full contracts:
Approach
Gas Cost
Full contract deploy
~2,000,000
EIP-1167 clone
~440,000
The factory deploys a lightweight proxy (~45 bytes) that delegates all calls to the implementation. Each clone has its own storage but shares the implementation's code.
Contract Interactions
State Machine
Each market follows a linear state progression:
State
Description
Transitions
Open
Accepting bets. Starts at creation.
→ Closed (when tradingEnd reached)
Closed
Betting stopped, awaiting resolution.
→ Resolved or → Cancelled
Resolved
Winner determined, payouts available.
Terminal state.
Cancelled
Refunds available.
Terminal state.
Note: The state variable stores the base state, but getCurrentState() computes the effective state based on timestamps. For example, an Open market past its tradingEnd is effectively Closed even if state hasn't been updated on-chain.
Key Design Decisions
Parimutuel over Orderbook
An orderbook requires matching engines and complex liquidity management. The parimutuel model is simpler: all bets pool together, winners split proportionally. Perfect for an MVP.
Trading Deadline at Halfway
Betting stops at the halfway point of the market duration (2.5 minutes for a 5-minute market). This prevents last-second bets that could exploit price movements already visible in the mempool.
Fee on Winnings Only
The 3% protocol fee is charged on the winning pool, not the total pool. This means losers lose exactly what they bet — no additional fee on top.
Permissionless Resolution
Anyone can call resolve() after expiry, not just the admin. This makes the system more trustless — if the keeper goes down, any user can resolve markets.