Assertion lifecycle

An assertion goes through a predictable sequence from the moment a game is marked final to the moment a consumer can safely grade markets against it. Each step is deterministic and leaves a verifiable artifact.

Step 1 — Game completion detection

The relayer polls the stats provider's scores endpoint on a short interval. When a game transitions from an in-progress status to final, the game is queued for settlement. The transition is the trigger; the relayer does not settle based on elapsed time or on the scoreboard matching some expected pattern.

Games that are postponed, suspended, or cancelled never reach final and are not queued. DNP and edge cases covers what happens in those situations. Explicit GAME_VOID assertions for cancelled games are part of the contract design, but are not live in the current beta posting path.

Step 2 — Volatility assessment

The relayer analyzes the play-by-play data for the game and computes a volatility signal per market cell — (player, market_key) pair. Each cell receives one of CLEAN, LOW, MEDIUM, HIGH, or CRITICAL based on the structural features of the play-by-play that affect that specific market: fielding errors elevating hit-related markets, 2-out errors that extend innings elevating pitcher workload markets, and so on. Cells in the same game can carry different signals.

The signal is computed deterministically from the play-by-play data. No operator discretion is involved.

Step 3 — Baseline snapshot

The relayer captures the proposed set of values for the assertion. For CLEAN cells, this happens at T+15 minutes after game final. For any other signal, it happens at T+75 minutes — a delay long enough for most league-side stat corrections to land in the primary feed before the snapshot is taken.

The internal validation gate runs against the baseline. Any uncertain value is blocked and routed to review rather than asserted automatically. Other cells in the same game can still proceed.

Step 4 — Preclose snapshot and drift handling

A second snapshot is taken later. The interval depends on the cell's signal: 0 for CLEAN (the baseline doubles as the preclose), about 1.5 hours after baseline for LOW, 3.5 for MEDIUM, 5.5 for HIGH, and 11.5 for CRITICAL.

If the preclose values match the baseline, the data is confirmed stable and the cell proceeds to evidence archival. If they differ, the relayer takes a fresh baseline, recomputes the cell's volatility signal — which can ratchet upward as new revision indicators appear, but never downward — and restarts the preclose timer at the new signal's window.

Each cell has a hard cap measured from game final: CLEAN at 2 hours, LOW at 6, MEDIUM at 12, and HIGH plus CRITICAL at 18. A cell that exhausts its cap is moved to manual review rather than asserted automatically.

Step 5 — Evidence archival

For each game, evidence bundles contain the official source response, the full play-by-play data, and the volatility report. Each upload is tagged with App-Name: PropsOracle, the league code, the source identifier, the volatility signal bucket, the league's internal game ID, and the bucket label, so the bundle is discoverable via Arweave's GraphQL gateway. The returned Arweave transaction ID is included in the assertion payload as arweave_evidence_tx.

A game can have one evidence bundle per signal bucket present: the CLEAN bundle is captured at the T+15min snapshot, while each non-CLEAN bucket references the evidence captured for that bucket's assertion-time preclose state.

Step 6 — UMA assertion

The relayer compiles a MARKET_RESOLUTIONS claim for each signal bucket present in the game. The claim is described in Assertion schema. It is posted to UMA's OOV3 on Polygon with the required USDC.e bond and a short formal liveness value (15 minutes by default; 2 hours as a fallback if UMA's MOOV2 whitelist requires it). The returned assertionId is stored by UMA OOV3 and tracked by the relayer's assertion queue; MARKET_RESOLUTIONS intentionally does not write to the EventRegistry because a single game can produce multiple bucketed assertions.

The assertion's callbackRecipient is set to the Props Oracle adapter, so UMA will call it on settlement. For MARKET_RESOLUTIONS, the adapter callback does not finalize an EventRegistry stream; consumers read the relevant UMA assertion result directly.

A game produces between 1 and 5 MARKET_RESOLUTIONS assertions, one per signal bucket present.

Step 7 — UMA window

Each assertion is live for the formal liveness period. Any party can dispute by posting a counter-bond. No dispute during the window means the assertion is eligible for finalization at the end of it. A dispute sends the question to UMA DVM and the finalization timeline extends to the DVM's vote cycle (typically 48–96 hours). Challenge and disputes covers this branch.

In practice, disputes are extremely rare. The internal validation phase has already confirmed stability before posting; the UMA window exists as a formal anchor, not as the primary verification mechanism.

Step 8 — Finalization

When the UMA window closes with no dispute, or when a dispute resolves in the asserter's favor, UMA marks the assertion truthful and invokes the Props Oracle adapter callback. For MARKET_RESOLUTIONS, the adapter does not write to the EventRegistry; consumers reading UMA OOV3 now see the assertion as safe to grade against.

If a dispute resolves against the asserter, UMA marks that assertion untruthful. The assertion is effectively withdrawn; any party, including the original relayer, can repost a corrected assertion under the same canonical event ID after going through a fresh validation cycle.