How it works.

Written for skeptics. No hand-waving.

Even betting

Traditional sportsbooks build an overround into every line — they price both sides to pay out less than 100 cents on the dollar. The margin is silent and structural.

Even Steven is parimutuel: every dollar staked on the losing side goes to the winning side. No house pool. No overround. Winners split 100% of losers' stakes.

At a liquid market — equal money on both sides — a $100 stake returns $200 gross on a win. 1:1 payout. The house was the hidden cost. We removed it.

The fee, honestly.

There is one fee: 2% of your stake, charged once at bet placement. It never touches the pool.

Stake$100.00
Fee (2%)$2.00
Total cost$102.00
Gross payout at liquidity~$200.00
Net profit~$98.00

The 2% is set in the contract as FEE_PERCENT = 200 (200 basis points). It is immutable per deployed market — it cannot be changed after the contract is live. There is no settlement fee. No claim fee. No surprises.

What you actually pay.

Every prediction market advertises a low fee. None of them tell you the full cost — because the full cost is the house, and the house is the business.

On an order book you pay three things every trade: the taker fee (the number they advertise), the overround (both sides sum past 100¢ and you pay the gap), and slippage (your order eats the book at progressively worse prices). Rename those three and you have a bookie — the vig, the spread, the line move. They are invisible, variable, and depth-dependent, and they are exactly the margins the house has always taken. Moving them on-chain did not remove them; it hid them in the microstructure.

Even Steven has none of them. No order book means no overround and no slippage. You pay one thing: a flat 2% protocol fee on your stake, charged the moment you place the bet.

scroll →

PlatformTotalDepthFeeOverSlipSettle
Even Steven2.00%Any2.00%0%0%0%
Polymarket US~4.9%Liquid2.50%~2%~0.4%0%
Polymarket Global~4.7%Liquid0.75%~2%~0.4%0%
Kalshi~8.0%Liquid3.50%~2%~0.5%2.00%
Polymarket US~7–8%Medium2.50%~4%~0.8%0%
Kalshi~12–15%Medium3.50%~3–4%~1%2.00%
Polymarket~17–20%+Illiquid0.75–2.50%~9%+~3.5%+0%

Friction = (fair profit − actual profit) ÷ stake × 100, on a winning $100 bet at ~50% probability. Every cost component is included: fees, overround, slippage, settlement charges. Nothing hidden.

Source: April 2026 live platform screenshots + published fee schedules (polymarketexchange.com/fees-hours.html, kalshi.com/fee-schedule). Overround measured as sum of buy-side ask prices for all outcomes on the same market. Self-check: open any sports market on Polymarket or Kalshi, add both sides' ask prices, compare to 100¢. The gap is the overround on top of the advertised fee.

Why Even Steven wins on friction

Polymarket Global advertises 0.75% for sports. Our fee is 2.00%. On a single-cell comparison we look more expensive. On total friction we win every row.

  1. No order book = no overround. When you buy "Yes" on one side and someone buys "Yes" on the other, the two prices sum to more than $1.00. That excess — typically 1–9¢ depending on liquidity — goes to market makers. On Even Steven, pools sum to exactly 100% of stakes by construction. There is no gap because there is no order book and no market maker.
  2. Flat fee regardless of size = no slippage. A $10,000 bet on Polymarket walks the order book from 50¢ to 51¢ as it fills. On Even Steven, a $10,000 bet and a $100 bet pay the same 2% friction. The pool absorbs any size at the current Z line — no book to walk, no price impact.
  3. Flat friction across every market. Tuesday MLS, Sunday NFL, niche hockey props — Even Steven charges 2.00% on all of them. On Polymarket, liquid NFL markets show ~5% friction while illiquid props show 20%+. Agents betting on long-tail markets — the majority of sports events by count — face dramatically higher costs on order book platforms.
  4. The fee cannot be raised on you. Polymarket raised fees three times in 2026: crypto in January, sports in February, eight more categories in March. FEE_PERCENT is set at deployment and is immutable. A strategy backtested at 2% friction stays at 2% friction across every market, every time period.

Trustless settlement.

Game results are submitted to UMA's Optimistic Oracle V3 via assertTruth(). UMA's optimistic model assumes the assertion is correct unless someone disputes it with a bond during the ~2-hour liveness window.

The dispute window is a feature, not a bug: anyone with evidence the result is wrong can challenge it on-chain. If unchallenged, it finalizes automatically and payouts open.

The owner cannot override outcomes. settle() was removed entirely in v1.8. Finality is enforced in code, not promised in docs.

No owner override.

Once a market is deployed, the owner cannot pause it, cancel it arbitrarily, or change the fee. The only cancellation path is if settlement fails for 7 days, at which point anyone can call triggerRefund() — your stake is returned in full.

The same logic governs legitimate cancellations (e.g., a game that does not take place): if a game is cancelled, your stake is refunded in full. The 2% fee paid at placement is not refunded — it was already collected when you bet. 90-day claim window.

Verify everything.

  • Factory contract on BaseScan — source verified, immutable.
  • GitHub (MIT license) — all contract code is public.
  • Five audit rounds (Claude Opus, March–June 2026). All critical and high findings resolved. Not a formal third-party audit.
  • getMarketEV(stake, side) — call it yourself on any live market to check the math. Payout numbers in this app come directly from this function.

Edge cases.

Unbalanced pools
Early in a market's life, one side may have more money than the other. Payouts float until the pools balance. Your line and payout estimate are shown at bet time via getMarketEV — they lock the moment you confirm the transaction.
Protocol seed
Each market is seeded with 1 USDC per side at deployment. This ensures getMarketEV returns a meaningful number even before any bets are placed.
Cancellation
If a game is cancelled, your stake is refunded in full. The 2% fee paid at placement is not refunded — it was already collected when you bet. 90-day claim window.
7-day settlement backstop
If a closed market goes 7 days without a settlement assertion, any wallet can call triggerRefund(). Your stake is refunded in full. The 2% fee paid at placement is not refunded — it was already collected when you bet. Designed to protect bettors if a settlement bot fails.

Your funds can't get stuck.

Three recovery paths exist as structural guarantees in the contract. Every path ends in a payout or a stake refund. Nothing can be permanently locked.

  1. 1

    Settlement → claim

    Normal path. Game ends, anyone calls requestSettlement(finalSpread) with a USDC bond. After the 2-hour UMA liveness window, executeSettlement() finalizes. Winners call claimAllPayouts(). 90-day claim window post-settlement.

  2. 2

    triggerRefund() — anyone after 7 days

    If a closed market goes 7 days without a settlement assertion, any wallet can call triggerRefund(). Full stake returned; the 2% placement fee is not refunded (it left the contract when you bet). Use canTriggerRefund() to check availability.

  3. 3

    sweepUnclaimed() — protocol after 90 days

    After 90 days post-settlement or cancellation, any unclaimed funds are swept to the protocol wallet. Bettors have 90 days to claim — sufficient for any automated agent. The sweep is a hygiene function, not a trap: you have a 90-day window before it applies.

Source: SportsbookMarket.sol cancelMarket(), triggerRefund(), sweepUnclaimed()

Verified contracts.

Base Mainnet — source verified on BaseScan, Exact Match.

ContractAddress
SportsbookFactory v1.30x9E9C769a8a8027
SportsbookFactory v1.2 (retired)0x08BA562416E214
USDC (Circle)0x833589fCA02913
UMA OOV30x2aBf1Bd7AF500c

Deploy tx: 0x2ec96b82ced224a4

Base Sepolia (testnet)

SportsbookMarket (reference)0xF536a69C158AC2
USDC (Circle testnet)0x036cbd533dcf7e
UMA OOV30x0F7fC5E6388deE

Markets deploy per game via the factory. Use getOpenMarkets() to discover active markets.

Annex

For developers & agents.

Even Steven is designed for AI agents. Every market exposes machine-readable state through view functions. No UI required. Full reference: AGENTS.md on GitHub.

Quick Start

javascript
// 1. Find open markets
const markets = await factory.getOpenMarkets();

// 2. Evaluate a market (payouts are gross of the 2% placement fee)
const [gameId, z, gPool, lePool, tPool, isOpen] = await market.getMarketState();
const [currentPayout, liquidPayout, impliedVig] = await market.getMarketEV(stake, greaterThan);

// 3. Approve and bet (the contract pulls stake + 2% fee)
await usdc.approve(marketAddress, ethers.MaxUint256);
await market.placeBet(greaterThan, stake);

// 4. Claim after settlement
await market.claimAllPayouts();

Discovery

solidity
// Find all open markets
address[] memory markets = factory.getOpenMarkets();

// Get full snapshot of a market
(
    string memory gameId,
    bool isOpen,
    bool isSettled,
    bool isCanceled,
    int256 currentZ,
    uint256 totalPool,
    int256 spreadMax,
    int256 spreadMin,
    uint256 feePercent,
    bool refundAvailable
) = factory.getMarketInfo(marketAddress);

// Look up a market by game ID (public mapping getter)
address market = factory.marketByGameId("NFL-2026-01-15-HOME-Chiefs-AWAY-49ers");

Pre-bet evaluation

solidity
// Get current state
(
    string memory gameId,
    int256 z,          // current Z line, 4-decimal: -35000 = -3.5
    uint256 gPool,     // stakes on greaterThan side
    uint256 lePool,    // stakes on lessEqual side
    uint256 tPool,     // total pool (stakes only, fees never enter)
    bool isOpen,
    bool isSettled
) = market.getMarketState();

// Evaluate EV before betting (payouts are gross of the 2% placement fee)
(
    uint256 currentPayout,  // gross return at current pool state
    uint256 liquidPayout,   // gross return at balanced pools (~$200 on $100 stake)
    uint256 impliedVig      // protocol fee in bps — 200 = 2%
) = market.getMarketEV(stake, greaterThan);

// Kelly criterion note:
// liquidPayout / stake = gross multiplier at liquidity (~2.0)
// True cost basis     = stake * (1 + impliedVig / 10000)  // 2% fee on stake
// Opportunity check   : currentPayout > liquidPayout → early imbalance favors you
// Net EV              = (probability * currentPayout) - stake - (stake * impliedVig / 10000)

Approve and bet

solidity
// Always use max approval — Circle USDC on Base rejects exact-amount approvals.
// Max approval covers stake + 2% fee in one go.
usdc.approve(marketAddress, type(uint256).max);

// greaterThan = true  → betting finalSpread * 10000 > lockedZ
// greaterThan = false → betting finalSpread * 10000 <= lockedZ
market.placeBet(greaterThan, stake); // minimum 1 USDC = 1_000_000

Claim

solidity
// After MarketSettled event fires:
market.claimAllPayouts(); // claims all your bets in one transaction

// Or claim a specific bet by ID:
market.claimPayout(betId);

// 90-day claim window — after that, sweepUnclaimed() moves funds to the protocol

Full function reference, strategy notes, and event subscriptions: AGENTS.md. Protocol version: v1.8.1. Audited by Claude Opus, five rounds, March–June 2026.