SBET Protocol / Version 2

SBET V2 Protocol Overview

SBET V2 is the second-generation settlement and dispute architecture for the SBET sports-betting and prediction-market protocol. It replaces the old one-shot finalization model with an explicit match state machine, a VRF-selected grader panel, bond-escalation disputes, dedicated custody, and tiered pause controls designed for real operations on EVM L2.

Status: Pre-deployment Target networks: Base and Arbitrum Updated: 2026-04-08
9
Primary Contracts
15
Locked Decisions
13 / 9
Panel / Quorum
$225k
Per-Match Cap
3
Pause Tiers
Who this page is for: integrators, technical due-diligence readers, auditors, grader operators, and product teams building on SBET. This is a narrative overview of the V2 protocol set. The raw engineering sources live under /docs/protocol-v2/.

What V2 Is

V2 is not an incremental feature patch on top of the legacy SBET stack. It is a fresh deployment model with explicit contract boundaries, explicit authority boundaries, and a deterministic lifecycle for every match: registration, betting, outcome proposal, challenge, dispute, finalization or void, and payout or refund.

What Changed
  • Two immutable pool regimes per match: SIGNED_POSITION and PARIMUTUEL.
  • Two-phase settlement: Open → Proposed → Finalized instead of immediate one-shot finalization.
  • VRF-drawn grader panels with per-match Merkle commitments.
  • Bond-escalation disputes with a 5-of-9 arbiter as the final court.
  • Dedicated treasury custody, gasless auto-claim, and slash routing.
  • LMSR prediction market AMM with autonomous payouts — keepers push winnings to holders.
  • Domain-separated prediction market IDs prevent namespace collision with sportsbook matches.
Why It Matters
  • Core no longer mixes match logic with token custody.
  • The protocol can slow down contentious outcomes without slowing down clean ones.
  • Users can trace the exact state of a match and what can happen next.
  • Attack profit is bounded by explicit caps tied to grader collateral.
  • Operational failure modes are isolated by match, category, or global pause scope.

The 13 Locked Architectural Decisions

The V2 source tree is organized around thirteen non-negotiable decisions. These are the design anchors that explain the shape of the contracts, the economics, and the governance surface.

# Decision V2 Rule Why It Exists
1 Dynamic challenge windows 90s / 15m / 2h / 4h based on consensus quality Fast, obvious matches finalize quickly; contentious ones stay challengeable longer.
2 Two-phase finalization Open → Proposed → Finalized|Disputed|Voided Separates grader attestation from locked outcome.
3 Grader collateral floor $25k SBET minimum stake per grader Colluding graders must risk capital to influence outcomes.
4 Per-match payout cap + slash split ABSOLUTE_CAP = 225_000e18, slash = 50/20/20/10 Single-match loss is bounded and challenger incentives stay positive.
5 Arbiter final court 5-of-9 Safe multisig Emergency override exists, but no single signer can decide outcomes.
6 Three-tier pause Match, category, and global pause layers Incidents can be isolated instead of freezing the whole protocol by default.
7 Bond-escalation disputes 1% TVL initial bond, 2× escalation, max 3 rounds Attackers pay to delay resolution; honest challengers have a reason to act.
8 Gasless auto-claim ERC-2771 meta-tx via immutable forwarder Winners can get paid without manual gas management.
9 Void refund semantics Void always returns principal plus fee rebate path Cancelled or broken matches should not strand user funds.
10 AI grader escalation Confidence-based, multi-stage off-chain grading stack Confidence feeds directly into challenge-window sizing.
11 Explicit void reasons NATURAL, PROTOCOL, DISPUTE Every void has a distinct audit trail and recovery path.
12 VRF-selected grader panel Default panel size 13, quorum 9 Prevents targeted grader selection and tolerates four dropouts.
13 Hybrid payout model Binary signed positions + N-outcome parimutuel pools Sportsbook-style markets and community pools can share one core stack.
14 Prediction market domain separation coreMatchId = keccak256(PREDICTION_DOMAIN, marketId) Prediction markets and sportsbook matches cannot collide in Core's namespace.
15 LMSR AMM with autonomous payouts Push-based payouts via redeemFor and batchRedeemFor Users receive winnings without manual claiming. Failure isolation prevents one bad transfer from blocking others.

Protocol Topology

SBET V2 is decomposed into dedicated contracts. Core owns state transitions, Treasury owns user funds, DisputeManager owns the bond ladder, GraderRegistry owns grader collateral, GuardianCouncil owns protocol-wide pause authority, and StakerRewards owns reward accounting.

match lifecycle SBETCoreV2 match registry • bet accounting • finalize • void • lock custody SBETTreasuryV2 receiveStake • releasePayout • refundVoid • autoClaim dispute court DisputeManager bond ladder • deadlines • claimByDefault • arbiter resolve reward sink SBETStakerRewards pull-based reward accounting for slash and auto-claim fees grader collateral GraderRegistryV2 stake floor • submitGrade • confidence • slash sink pause authority GuardianCouncil category pause • global pause • unpause timelock prediction market layer PredictionMarketV2 lifecycle + metadata + resolution sync + keeper orchestration PredictionAMMV2 LMSR pricing + ERC-1155 shares + autonomous payouts stake / payout boundary openDispute / resolveDispute slashWithChallenger pauseTierOf() registerMatch AMM fees to treasury
Figure 1 — Core coordinates the lifecycle. Custody, dispute, grader collateral, pause powers, and prediction market pricing live in separate contracts.

Contract Set and Boundaries

Contract Approx. Lines Primary Responsibility Critical Boundary
SBETCoreV2 923 Match registry, pool accounting, propose/finalize/dispute/void transitions Never holds user custody directly.
SBETTreasuryV2 435 Stake custody, payouts, void refunds, auto-claim, slash distribution Only contracts with CORE_ROLE or registry roles can move funds.
GraderRegistryV2 359 Grader stake, lifecycle, grade submission, confidence aggregation Sole custodian of grader collateral.
DisputeManager 424 Initial bond calculation, escalation rounds, deadlines, arbiter outcome Owns the dispute bond book and winner-take-all dispute pot.
GuardianCouncil 313 Category pause, global pause, unpause timelock Controls pause state, not match outcomes or custody.
SBETStakerRewards 293 Pull-based reward accumulation for slash flows and auto-claim fees Reward sink, not match logic.
PredictionMarketV2 728 Prediction market lifecycle, metadata, resolution sync, keeper orchestration Registers markets as Core matches. Does not hold user custody.
PredictionAMMV2 991 LMSR pricing, ERC-1155 shares, autonomous payouts, fee routing to Treasury Holds trading collateral directly. Fees route to Treasury.
ChallengeWindowLib + SignedPositionLib 230 Pure math for timing tiers and V1-parity signed-position payout math No storage, no external calls.
Pre-deployment note: the documentation source currently states that VRF wiring is still in a pre-production form. The build uses a privileged VRF_FULFILLER_ROLE relay for seeding, and production deployment is expected to replace that path with the real coordinator callback.

How a Match Moves Through V2

Every V2 match progresses through a deterministic state graph. Pool type is immutable, but state changes are explicit and role- or time-gated. This is the core difference from the older architecture: a match does not simply "finalize". It enters a proposed state, becomes challengeable, may escalate into dispute, and only then exits into payout or refund conditions.

None unused matchId Open accepting bets Proposed challenge window active Disputed bond ladder running Finalized claims enabled Voided refunds registerMatch proposeOutcome openDispute finalize resolveDispute(void) claim* arbiter override can force Finalized from Open / Proposed / Disputed
Figure 2 — State moves only forward. Pool type is fixed at registration; only match state changes.

State Transitions

From → To Function Caller Key Guard
None → Open registerMatch MATCH_REGISTRAR_ROLE Commits PoolType, panel root, panel size, and quorum immutably.
Open → Proposed proposeOutcome GRADER_AGGREGATOR_ROLE Requires quorum and computes unlockAt from the challenge tier.
Proposed → Finalized finalize Permissionless Challenge window must have elapsed and no pause tier may block the action.
Proposed → Disputed openDispute Permissionless + bond Must happen before unlockAt; challenger approves DisputeManager.
Disputed → Finalized|Voided resolveDispute DisputeManager Called after default judgment or arbiter ruling.
Open|Proposed|Disputed → Finalized overrideOutcome ARBITER_ROLE Emergency override for irreducible off-chain incidents.
Open|Proposed → Voided voidMatch GOVERNANCE_ROLE Only NATURAL or PROTOCOL reasons; dispute voids must flow through DisputeManager.
Finalized → payout claimParimutuel / claimSignedPosition Bettor Claim path depends on pool type.
Voided → refund claimVoidRefund Bettor Refund path depends on pool type and stored position.

Challenge Window Tiers

V2 does not use one fixed delay for every match. The window is chosen from four tiers depending on dissent count, quorum quality, AI confidence, and source agreement.

Tier Duration Trigger
Fast 90 seconds Unanimous panel, confidenceBps ≥ 9500, and at least two independent agreeing sources.
QuorumClean 15 minutes Quorum reached, zero dissent, but not strong enough for fast-path.
OneDissent 2 hours Exactly one grader dissents.
Contentious 4 hours Two or more dissents or confidence below 60%.
function computeTier(
    uint256 n,
    uint256 m,
    uint256 signers,
    uint256 dissents,
    uint16 confidenceBps,
    uint8 sourceAgreement
) internal pure returns (Tier tier, uint32 windowSeconds);

Settlement Models

V2 supports two immutable accounting regimes. This is one of the largest conceptual changes from V1: the core can serve both sportsbook-like binary exposure and pot-based community pools, while keeping payout logic explicit per match.

Dimension SIGNED_POSITION PARIMUTUEL
Outcome count Binary only; numOutcomes == 2 enforced at registration Two or more outcomes
Typical use Sportsbook-style back/lay or long/short exposure Multi-outcome pools and prediction markets
User behavior A single user may hold both long and short on the same match A user may only build one outcome position per match
Exposure cap max(longPool, shortPool) totalAccepted
Claim function claimSignedPosition claimParimutuel
Void refund longPos + shortPos User stake on the match

Payout Math

// Signed-position payout (V1 parity)
payoff_long  = longPos  * finalPrice / MAX_PRICE;
payoff_short = shortPos * (MAX_PRICE - finalPrice) / MAX_PRICE;
finalPrice   = outcome * MAX_PRICE / (numOutcomes - 1);

// Parimutuel payout
payout = userStake * totalAccepted / winningOutcomeStake;
Important: signed-position math was preserved deliberately for compatibility. V2 changes architecture and control flow much more than it changes the binary payout surface.

Prediction Markets (LMSR AMM)

V2 includes a dedicated prediction market layer built on top of Core. PredictionMarketV2 manages the market lifecycle and metadata. PredictionAMMV2 provides LMSR (Logarithmic Market Scoring Rule) pricing with ERC-1155 outcome shares, autonomous payouts, and fee routing to Treasury.

LMSR Pricing

The AMM uses Hanson's LMSR with PRBMath SD59x18 fixed-point arithmetic. The b parameter controls market depth. A higher b means more liquidity and tighter spreads; a lower b means prices move faster with each trade.

The minimum safe b parameter is 1e18 (enforced in seedLiquidity). For production pools, SAFE_RECOMMENDED_B = 1000e18 provides a large safety margin against PRBMath exp() overflow.

// Symmetric fee formula (Polymarket pattern)
// fee = totalFeeBps * min(price, MAX_PRICE - price) * amount / (MAX_PRICE * BPS_DENOM)
// Near 50/50 price: full fee. Near certainty: fee approaches 0.
// Minimum fee floor: at least 1 wei when amount > 0 and fees configured.

Autonomous Payouts

Prediction markets use a push-based payout model. Users do not need to manually claim winnings. Keeper bots detect Core finalization and push payouts:

  1. Keeper calls syncAndDistribute(marketId, holders[]) on PredictionMarketV2.
  2. Market syncs the resolution from Core (idempotent, safe to call multiple times).
  3. AMM iterates holders, burns their winning ERC-1155 shares, and transfers pro-rata collateral.
  4. If one holder's transfer fails, the batch continues. Failed holders can redeem individually later.

The same pattern works for voided markets via syncAndRefund, where all outcomes are refundable pro-rata.

Domain Separation

Prediction market IDs are namespaced to avoid collision with sportsbook match IDs in Core. The formula coreMatchId = keccak256(PREDICTION_DOMAIN, marketId) is deterministic and requires no coordination between sportsbook and prediction market registrars.

Security Hardening

PredictionAMMV2 (991 lines) underwent a dedicated security review. Five P0 critical fixes were applied:

Fix Vulnerability Remediation
P0-1 LMSR exp() overflow with small b Minimum b ≥ 1e18 enforced at pool seeding.
P0-2 Fee-on-transfer token accounting drift Balance-before/after check on every collateral transfer. Reverts if received < amount.
P0-3 Sell fee on stale pre-trade price (sandwich vector) Fees computed on average of pre-trade and post-trade price.
P0-4 Pro-rata snapshot drift on burn Lazy-init snapshot of winning shares / grand total on first call.
P0-5 CEI violation in sell (state before burn) Burn ERC-1155 shares first, then update pool state.

Additionally, the AMM's reference to PredictionMarketV2 is now governance-settable with a 48-hour timelock (HIGH-1 fix), and 20 Echidna invariant properties validated pool solvency, fee bounds, and redemption fairness. Echidna found and we fixed a zero-fee LMSR rounding arbitrage; sell payouts now round down.

Test coverage: 307 Foundry tests (including 6 fuzz tests), 20 Echidna invariant properties, 97 indexer pytest, 23 dapp vitest. Slither static analysis clean.

Disputes and Pause Architecture

Disputes in V2 are their own protocol subsystem. A dispute is not an informal challenge flag; it is a capitalized, deadline-driven ladder that eventually resolves through an arbiter ruling. Separately, pause logic is split into match, category, and global layers so operations can isolate damage instead of toggling one giant kill switch.

Round 0 challenger posts initial bond 1% TVL, clamped to $5k-$50k Round 1 defender responds with 2× bond 24h response window Round 2 challenger responds with 4× bond 24h response window Round 3 defender responds with 8× bond then state moves to arbiter Arbiter 5-of-9 Safe awaiting defender awaiting challenger awaiting defender winner or default propagates to Core
Figure 3 — The bond ladder prices delay and noise. Only disputes that survive three rounds reach the arbiter multisig.

Dispute Bond Escalation

Round Who must respond New bond posted Cumulative pot
0 Challenger opens dispute 1× initial bond
1 Defender 2× initial bond
2 Challenger 4× initial bond
3 Defender 8× initial bond 15×
initialBond = max(5_000e18, min(50_000e18, matchTvl * 100 / 10_000));

Pause Tiers

Tier Quorum / Trigger Max Duration Purpose
Match Anyone with 1_000e18 SBET lock bond 24 hours Permissionless response to a single anomalous match.
Category 3-of-5 guardian quorum 72 hours Sport- or league-wide integrity incident.
Global 5-of-9 guardian quorum 14 days Protocol-wide emergency with a 72-hour unpause timelock.
Operational detail: pause blocks new betting, new position opening, proposal, and finalization. It does not block claim paths once a match is finalized or voided. That distinction matters: users should still be able to exit resolved risk during an incident.

Economic Security Model

V2 ties the maximum stealable value on a match to the collateral at risk from the grading quorum. The protocol is trying to make dishonest resolution economically irrational, not merely socially discouraged.

Core Invariants

Invariant Meaning
Cap invariant Parimutuel matches cap totalAccepted; signed-position matches cap max(longPool, shortPool).
Collateralization invariant perMatchPayoutCap() ≤ graderStakeFloor × quorumM.
Slash split invariant 50% challenger / 20% treasury / 20% stakers / 10% bounty = 100%.
State monotonicity No external function should move match state backward.
Immutable pool type PoolType is written at registration and never mutated.
Dispute uniqueness Only one live dispute may exist for a given match at a time.

Cap and Collateral

uint256 public constant ABSOLUTE_CAP = 225_000e18;

function perMatchPayoutCap() public view returns (uint256) {
    uint256 floor_ = GRADERS.graderStakeFloor();
    uint256 candidate = floor_ * _quorumM;
    return candidate < ABSOLUTE_CAP ? candidate : ABSOLUTE_CAP;
}

With the default stake floor of 25_000e18 SBET and quorum 9, the quorum's combined collateral equals the cap: $225k. That is the core security claim. A malicious quorum should always have at least as much at risk as it could steal from one match.

Worked Attack Scenarios

Scenario Attacker Goal Why Loss Is Bounded
9-of-13 grader collusion Finalize the wrong outcome and steal user payouts Cap is bounded at $225k while the colluding quorum risks $225k of grader stake before dispute bonds and slash routing.
Fast-tier challenge race Exploit the 90-second window before bots or watchers react Opening a dispute costs at least $5k; any honest watcher can interrupt finalization and kick the match into the dispute ladder.
Griefing dispute on a large match Delay claims without a real case Initial bond is capped at $50k and escalates 2× per round; missing a deadline forfeits all posted capital.
Malicious match-lock spam Freeze many matches cheaply Each lock costs 1,000 SBET, expires in 24h, and may be slashed by governance if malicious.
VRF fallback miner influence Bias fallback panel selection Fallback is bounded to a liveness path, flagged by events, and still constrained by dispute economics and the cap invariant.

Treasury Hardening (V2.1)

SBETTreasuryV2 enforces a per-match deposit/release ledger that prevents cross-match drainage, double-claims, and over-release. Every payout path is checked against what was actually deposited for that specific match.

Mechanism Implementation What It Prevents
Per-match ledger matchDeposited[matchId][token] and matchReleased[matchId][token] track inflows and outflows per match. Cross-match drainage: funds deposited for match A cannot be released against match B.
Outflow invariant released + amount <= deposited enforced on every payout path (releasePayout, refundVoid, autoClaim). Over-release and double-claims. Reverts with OutflowExceedsDeposit.
CEI-compliant inflow Effects (ledger update + event) execute before interactions (safeTransferFrom). Reentrancy vectors on the deposit path.
Role locking lockCriticalRoles() is a one-shot, irreversible freeze of CORE_ROLE, GRADER_REGISTRY_ROLE, and DISPUTE_MANAGER_ROLE after deployment wiring. Admin key theft post-lock cannot re-grant fund-moving roles.
Token validation addAllowedToken checks code size and probes totalSupply() as an ERC-20 sanity gate. Adding EOAs or non-ERC-20 addresses to the settlement token allowlist.
// Outflow invariant — enforced on every payout path
uint256 alreadyReleased = matchReleased[matchId][token];
if (alreadyReleased + amount > matchDeposited[matchId][token])
    revert OutflowExceedsDeposit(matchId, token, amount);
matchReleased[matchId][token] = alreadyReleased + amount;

// One-shot role lock — irreversible after deployment wiring
function lockCriticalRoles() external onlyRole(GOVERNANCE_ROLE);
// Sets rolesLocked = true. All subsequent grantRole / revokeRole
// for CORE_ROLE, GRADER_REGISTRY_ROLE, DISPUTE_MANAGER_ROLE revert.

Match Expiry

Every match can have a deadline. If a match passes its deadline without finalization, anyone can expire it. This prevents stale matches from locking user funds indefinitely.

Function Caller Behavior
setMatchDeadline(matchId, deadline) MATCH_REGISTRAR_ROLE Sets the deadline (uint32 timestamp). On-chain guard: deadline >= block.timestamp + 30 minutes prevents instant-void from a compromised key.
expireMatch(matchId) Permissionless Callable by anyone after the deadline if the match is still Open or Proposed. Transitions the match to Voided.
setDefaultMatchTTL(ttl) GOVERNANCE_ROLE Governance-tunable default time-to-live. Bounded: 1 hour minimum, 90 days maximum, 48 hours default.
claimVoidRefund(matchId, token) Bettor Returns principal + fees after expiry-triggered void, same as any other void path.

Events: MatchDeadlineSet(matchId, deadline), MatchExpired(matchId). The deadline field on MatchInfo starts at 0 (unset). The indexer's deadline keeper sets deadlines based on actual match schedules via setMatchDeadline.

Defense-in-Depth Properties

V2 layers multiple independent security mechanisms. Compromise of one subsystem should not cascade into fund loss.

Property How It Works
Treasury validates independently Treasury enforces the outflow invariant regardless of what Core requests. Even a compromised Core cannot release more than was deposited for a given match.
Role locking survives key theft After lockCriticalRoles(), admin key theft cannot re-grant CORE_ROLE, GRADER_REGISTRY_ROLE, or DISPUTE_MANAGER_ROLE. The lock is one-shot and irreversible.
Deadline guard A compromised MATCH_REGISTRAR_ROLE cannot set an instant-expiry deadline. The minimum lead time (MIN_DEADLINE_LEAD = 30 minutes) ensures observers have time to react.
TOCTOU guard On-chain state is re-checked before AI-derived grade signing. The grader aggregator verifies match state at submission time, not at grade computation time.
Fee-on-transfer unsupported by design The CEI pattern with no balance-delta measurement means fee-on-transfer tokens are explicitly unsupported. This removes an entire class of accounting drift vulnerabilities.

Roles and Authority

V2 intentionally decomposes authority. Graders attest. Guardians pause. The arbiter resolves irreducible disputes. Treasury enforces custody by role. Governance still exists, but no single role should simultaneously control grading, dispute judgment, and user funds.

Role Lives On Primary Powers
GOVERNANCE_ROLE Core, Treasury, Registry, Council Void matches, tune protocol parameters, assign critical pointers, pause Treasury, manage stake floor and fee settings.
MATCH_REGISTRAR_ROLE Core Registers matches and seals per-match immutable parameters.
GRADER_AGGREGATOR_ROLE Core Proposes outcomes into the challenge window.
VRF_FULFILLER_ROLE Core Pre-deployment seed fulfillment path until the live coordinator callback is wired.
ARBITER_ROLE Core / DisputeManager 5-of-9 Safe emergency override and final dispute resolution path.
Guardian quorums GuardianCouncil Category and global pause management, including the global unpause timelock.
CORE_ROLE Treasury Allows Core to hold stakes, release payouts, issue void refunds, and trigger auto-claim.
GRADER_REGISTRY_ROLE Treasury Allows slash distributions to flow from registry into Treasury accounting.
TOKEN_MANAGER_ROLE Treasury Manages the settlement-token allowlist.

Operator and User Flows

The protocol is easiest to understand when you follow concrete flows. The important implementation detail is that approvals go to different contracts depending on the action.

Approval Cheat Sheet

Action Approve This Contract Why
placeBet / openSignedPosition SBETTreasuryV2 Treasury pulls the user stake via safeTransferFrom.
openDispute DisputeManager The dispute contract, not Core, pulls the initial bond.
respond DisputeManager Round bonds are held by the dispute contract.
lockMatch SBETCoreV2 Core holds the 1,000 SBET match-lock bond.
Grader register / increaseStake GraderRegistryV2 Registry is the sole custodian of grader collateral.
Stake in rewards SBETStakerRewards Reward contract holds staked SBET directly.
createMarket (liquidity) PredictionMarketV2 Market transfers collateral to the AMM for LMSR seeding.
buy (prediction shares) PredictionAMMV2 AMM holds trading collateral directly for LMSR pricing.

Flow Summary

  1. Place a parimutuel bet: approve Treasury, call placeBet, and watch for BetPlaced plus Treasury custody events.
  2. Open a signed position: approve Treasury, call openSignedPosition, and remember the cap applies to directional exposure, not the sum of both sides.
  3. Watch a match finalize: track OutcomeProposed, read unlockAt, then either wait for a relayer or permissionlessly call finalize.
  4. Open or answer a dispute: approve DisputeManager, post the required round bond, and be prepared for a 24-hour response window at each stage.
  5. Claim payout or refund: use the claim function that matches the pool type, or claimVoidRefund if the match was voided.
  6. Opt into gasless auto-claim: set Treasury auto-claim opt-in and accept the default fee path of 2% for SBET or 3.5% for other tokens.
  7. Create a prediction market: approve Treasury for the Core bond, approve PredictionMarketV2 for initial liquidity, call createMarket.
  8. Trade prediction shares: approve PredictionAMMV2, call buy or sell. LMSR pricing with symmetric fees.
  9. Redeem prediction winnings: either call redeem manually after syncResolution, or wait for a keeper to push payouts via syncAndDistribute.
// Example: parimutuel bet
await usdc.approve(treasuryAddress, parseUnits("100", 6));
await sbetCore.placeBet(matchId, 0, usdcAddress, parseUnits("100", 6));

// Example: open dispute
await sbet.approve(disputeManagerAddress, parseEther("5000"));
await sbetCore.openDispute(matchId, 1);

From V1 to V2

V2 is a fresh-start deployment, not an in-place upgrade. V1 keeps operating for existing positions; V2 introduces a new contract set, new addresses, new match identifiers, and a new trust model.

V1 vs V2 at a Glance

Area V1 V2 Why V2 Is Better
Match model Looser market wrappers and indirect settlement objects One canonical MatchInfo per match Cleaner indexing, cleaner state, fewer hidden assumptions.
Finalization Single-phase or administrative finalization Proposed state plus explicit challenge and dispute path Users can observe a match becoming final instead of trusting a one-shot resolution.
Oracle / graders Static grader model VRF-selected panel with quorum and dissent accounting Harder to target and easier to reason about disagreement.
Disputes Thinner, more administrative flow Bond-escalation machine with deadlines and arbiter resolution Delay and fraud become explicit capital costs.
Custody Broader treasury / monolith responsibilities Dedicated Treasury with role-gated fund movement Match logic and user custody are separated.
Pausing Blunter pause model Match, category, global tiers Incidents can be contained instead of broad-freezing all activity.
User fairness Less explicit void economics Void semantics and fee-rebate path encoded into the lifecycle Better recovery path when a market cannot resolve cleanly.

Migration Rules

  • Existing V1 positions remain governed by V1 settlement paths.
  • There is no forced migration and no treasury merge at V2 launch.
  • V2 is a fresh-start deployment with a new set of contracts and new match IDs.
  • Governance may eventually stop creating new V1 matches, but old V1 positions continue to settle under V1 rules.

Ship-Blocking Problems Addressed in V2

Bug Fix V1 / Early-Draft Problem V2 Resolution
Split-outcome staking Parimutuel semantics could be broken if a bettor built positions on multiple outcomes. ExistingPositionDifferentOutcome blocks multi-outcome self-hedging in parimutuel pools.
SBET token bootstrapping Dynamic token lookups created circular dependency and mutation risk. SBET_TOKEN is wired as an immutable constructor dependency.
Panel-size sourcing An early draft risked computing challenge tiers with signer count as panel size. MatchInfo.panelSize is the source of truth for N in M-of-N.
Per-match cap semantics No explicit cap discipline and no distinction between pot size and directional exposure. Parimutuel uses totalAccepted; signed-position uses max(longPool, shortPool).

Deep Dives and Downloads

This page is the narrative overview. The engineering source documents go deeper into contract APIs, attack scenarios, operator requirements, and migration details.

Current status (2026-04-08): all 6 V2 Core contracts are deployed to Sepolia with Treasury hardening (per-match ledger, outflow invariant, role locking) and match expiry (deadline-based permissionless void). AI match verification is live on the indexer with multi-source deterministic resolution and confidence-gated AI tiebreaker. PredictionMarketV2 and PredictionAMMV2 are code-complete and security-hardened (5 P0 fixes, 20 Echidna invariants, Slither clean) but not yet deployed. V1 has been removed from the dapp — zero V1 ABI imports remain in production code. Audit work is scheduled for Q2 2026. Open follow-up items: on-chain arbiter vote visibility, dispute-pot distribution consistency, grader slashing hooks on arbiter ruling, and final fee-rebate lock-in for claimVoidRefund.