All articles
Polymarket·May 25, 2026·6 min read

How UMA Optimistic Oracle Resolution Actually Works

A senior engineer's breakdown of polymarket uma oracle resolution: proposal, liveness, disputes, DVM votes, and how bots price resolution risk.

Every Polymarket market that says "resolved" got there because a human posted a bond, nobody disputed it inside a fixed window, and a smart contract finalized the result. That human is the UMA proposer, the window is called liveness, and if you run bots on Polymarket you should treat that window as a live, tradeable state — not a formality. Most of the money left on the table around resolution comes from people who model the outcome and forget to model the machine that decides the outcome.

Here's what actually happens, step by step, and where the risk hides.

The lifecycle of a single resolution

Polymarket doesn't resolve markets itself. When a market's end date passes, the resolution question gets pushed to UMA's Optimistic Oracle (specifically the OOv2 contract on Polygon, wired through Polymarket's UmaCtfAdapter). The oracle assumes any answer is correct unless challenged — that's the "optimistic" part.

The sequence looks like this:

  1. Request. The adapter asks the oracle "what's the outcome of question X?" with an ancillaryData blob that encodes the market question, the resolution sources, and the allowed answers (usually p1=No, p2=Yes, p3=50/50 unknown).
  2. Proposal. Someone — often a bot run by an arbitrageur or by UMA-aligned actors — posts a proposed answer plus a bond (commonly 750 USDC on Polymarket markets, though the reward and bond are set per-request). This starts the liveness clock.
  3. Liveness window. For a fixed period (Polymarket typically uses a 2-hour liveness on standard markets, longer on some), anyone can dispute by matching the bond. If nobody does, the proposal is accepted and the market settles at that value.
  4. Dispute. If someone disputes, the optimistic path is dead. The question escalates to UMA's Data Verification Mechanism (DVM), where UMA token holders vote.
  5. DVM vote. Holders commit and reveal votes over a multi-day cycle (commit phase, then reveal, tied to UMA's ~48-hour voting rounds). The median of revealed votes wins. The correct side gets its bond back plus half the loser's bond; the wrong side eats the loss.

The uncomfortable truth: a market that looks "obvious" to you is only settled when that liveness timer hits zero with no dispute. Until then it's a probabilistic object.

Why liveness is the only clock that matters

Traders anchor on the event end date. Bots should anchor on the proposal timestamp, because liveness starts when the answer is proposed, not when the event ends. A market can end Sunday night and sit unproposed until Monday morning because no bot bothered to post the bond — there's no automatic proposer. That gap is pure carry: you're holding a position that's economically decided but not yet redeemable.

If you're building anything that touches settlement — an arbitrage bot that closes positions the moment a market becomes redeemable, or a strategy that fades mispriced "already decided" markets — you need to poll the oracle state directly, not the Polymarket UI. The states you care about on the UmaCtfAdapter and OOv2:

  • initialized but no proposal → market ended, no clock running yet.
  • proposed with a proposalTimestamp → liveness clock is live; expirationTimestamp = proposalTimestamp + liveness.
  • disputed → headed to the DVM; redemption is now days away, not hours.
  • settled → redeemable.

A minimal read to figure out where you stand:

req = oo_v2.functions.getRequest(requester, identifier, timestamp, ancillary_data).call()
# req.proposedPrice, req.expirationTime, req.disputer (zero addr = undisputed)
now = w3.eth.get_block("latest")["timestamp"]
if req.disputer != ZERO_ADDR:
    state = "DVM_PENDING"          # settlement in ~2-4 days
elif req.expirationTime and now >= req.expirationTime:
    state = "SETTLEABLE"           # push settle(), then redeem
elif req.expirationTime:
    secs_left = req.expirationTime - now
    state = f"LIVE_{secs_left}s"   # dispute still possible
else:
    state = "UNPROPOSED"           # no clock, pure carry risk

The SETTLEABLE state is worth flagging: after liveness expires the outcome is locked, but tokens aren't redeemable until someone calls settle(). That's often you. Bots that assume settlement is automatic sit on dead capital.

Modeling dispute risk

Not every disputable market gets disputed, and knowing which ones will is where the edge lives. Disputes cluster around a few patterns:

  • Ambiguous resolution sources. If ancillaryData names a source that's vague or that went offline, expect a dispute. Read the actual bytes; don't trust the pretty question text.
  • Proposals that contradict obvious reality. Someone proposing "No" on a market that clearly resolved "Yes" is either fat-fingering or farming a dispute bond. Either way, liveness will not run clean.
  • Close calls near the boundary condition. "Above 70,000 by Friday close" when the price is at 69,980 — those get contested.

For pricing, I treat each live proposal as a small probability of dispute p_d and a dispute cost c_d in delayed settlement (days of locked capital plus DVM tail risk). Expected redemption time becomes (1 - p_d) * liveness_remaining + p_d * dvm_delay. If your strategy needs capital velocity, a market with even a 5% dispute probability and a 3-day DVM delay has a materially worse carry profile than the headline "2 hours to settle" suggests. This math is exactly what separates a naive close-out from a good one, and it's the backbone of any resolution and dispute trading strategy that actually books the edge.

The DVM tail

Once a market hits the DVM, you're no longer trading the event — you're forecasting how UMA token holders will vote. The median mechanism means you care about the distribution of voters, not the objectively correct answer. In practice the DVM has been reliable on clear questions and messy on genuinely ambiguous ones (the several high-profile Polymarket disputes over the years all lived in that ambiguity). If you hold a position into a DVM vote, size it like you're holding a governance bet, because you are.

Practical build notes

A few things that bite people when they wire this into production:

  • Watch proposal and dispute events, not just prices. Subscribe to ProposePrice and DisputePrice logs on the OOv2 contract filtered to Polymarket's requester. Your fill logic should react within seconds of a dispute, because the moment DisputePrice fires, your effective settlement date jumps by days. Any market maker running two-sided quotes needs to pull or widen quotes on a disputed outcome instantly.
  • Decode ancillaryData at ingest. The resolution rules live there. Parsing them into structured fields at market-onboarding time lets you flag dispute-prone markets before you ever take a position.
  • Separate "priced" from "redeemable." Your PnL model should carry a market as economically settled the second liveness expires clean, but your capital model should only free the collateral once settle() succeeds and tokens redeem. Conflating the two overstates your available margin.
  • Latency matters at the edges. Getting a proposal in first, or disputing a bad proposal in time, is a mempool game on Polygon. The same order-signing and low-latency plumbing that matters on the CLOB matters here.

For higher-frequency strategies, the resolution layer interacts with your quoting layer in ways that aren't obvious until you've run into them — the CLOB market-making mechanics and your resolution-risk model have to share the same view of market state, or you'll quote into outcomes you can't cleanly exit. A spread bot that ignores which markets are near proposal will happily accumulate inventory it can't unwind for three days.

The short version: liveness windows are the real clock, disputes are a modelable event, and the DVM is a governance bet you should size accordingly. Treat resolution as a state machine you poll, not a footnote you assume.

If you want this resolution-state logic built into a system that trades and manages inventory around it correctly, that's exactly what our Polymarket arbitrage bot work is designed for.

Need a bot like this built?

We design, build and run trading bots on Solana, Hyperliquid and Polymarket.

Start a project
#Polymarket#UMA Oracle#Resolution Risk#Trading Bots#DVM