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

How UMA's Optimistic Oracle Actually Resolves Polymarket Markets

How UMA's Optimistic Oracle resolves Polymarket markets: proposal bonds, the 2-hour liveness window, DVM escalation, and failure modes.

What "optimistic" actually means here

UMA's Optimistic Oracle doesn't know anything. It has no data feed, no API call to an outcome database, no oracle nodes checking a scoreboard. Instead it runs on a simple economic bet: assume the first answer someone proposes is correct, give everyone a window to prove it wrong, and only pay attention to real-world truth if somebody's willing to put money behind a challenge. That's the whole trick, and it's why Polymarket runs on it instead of a Chainlink-style push feed — most binary event outcomes (elections, sports, "will X ship by Y date") have no clean on-chain data source, so you need a mechanism that can absorb arbitrary human judgment without a committee voting on every single market by default.

Every Polymarket market is backed by a conditional token pair minted through Gnosis's conditional tokens framework — YES and NO shares tied to a single question ID. UMA's job is narrow: decide what number that question ID resolves to (0, 1, or 0.5 for a genuine tie/ambiguous case) so the CTF contract can let holders redeem the winning side for $1 and the losing side for $0.

The three-stage lifecycle

Stage 1 — proposal and bond

Once a market's event window closes, anyone can call the resolution function on Polymarket's UMA adapter contract (the UmaCtfAdapter). This submits a price request to the Optimistic Oracle. A proposer — usually a bot, sometimes Polymarket's own infrastructure, sometimes an independent keeper chasing the reward — then posts the answer along with a bond, historically around 750 USDC on top of a smaller UMA final fee. That bond is the entire security model. It's not "trust me," it's "I'm willing to lose 750 USDC if I'm wrong."

Stage 2 — the liveness window

Once proposed, the answer sits in a challenge period, typically two hours for Polymarket's adapter. During liveness, the proposed price is visible on-chain but not final — this matters a lot for bots. If your spread bot or pricing engine reads the OO's proposed price and treats it as settled, you will occasionally get burned, because a proposed price can and does get overturned. Treat anything inside the liveness window as "probably true, not yet true."

If nobody disputes before the window closes, the price is finalized automatically and the adapter settles the market. This is the fast path — most markets resolve this way, in under two and a half hours from close.

Stage 3 — escalation to the DVM

If someone disputes, they have to post a matching bond. The request now leaves the Optimistic Oracle entirely and gets kicked to UMA's Data Verification Mechanism — a token-weighted commit-reveal vote among UMA stakers. This is where "optimistic" stops and "slow" starts. DVM voting runs on fixed daily UTC cycles, and a vote takes a minimum of 48 hours to complete a commit-and-reveal round. If your dispute lands close to the daily cutoff, it misses that cycle and rolls into the next one, which means real-world resolution time for a disputed market can stretch past 72–96 hours. UMA token holders commit a hashed vote, reveal it after the commit window closes, and the majority-weighted outcome wins. Voters who sided with the majority split rewards drawn partly from the losing bond; voters on the wrong side get a portion of their staked UMA slashed. That's the incentive that's supposed to make honest voting the dominant strategy — in practice it mostly works because disputing a genuinely correct answer is expensive and slow, so it filters out casual griefing, though not all of it.

A worked example

Say there's a market: "Will the Fed cut rates by 25bps at the March meeting?" The FOMC announces a cut at 2:00pm ET.

  1. At 2:05pm, a keeper bot calls requestResolution, which fires a price request to the OO.
  2. At 2:07pm, the same bot (or a competing one) proposes price = 1 (YES), posting the 750 USDC bond.
  3. Liveness clock starts: the price shows as 1 on-chain but is flagged "proposed, not final." A naive scraper reading the contract state would see YES at 100% two hours before it's actually locked in.
  4. No one disputes — the outcome is unambiguous, verifiable from a Fed press release. At 4:07pm, liveness expires, the OO finalizes price = 1, and the CTF adapter settles the market. Total time: two hours.
  5. Contrast that with a market like "Will Candidate X concede by end of day?" — genuinely disputable on timing or intent. A disputer posts a matching bond at 3:50pm, ten minutes before liveness would have expired. Now it's in DVM limbo. If that's past the daily UTC vote cutoff, the earliest resolution is roughly 48–72 hours out, and the market's shares keep trading the whole time on residual uncertainty.

A rough state machine your bot should track, reading straight off the adapter/OO contracts:

// pseudo-code, ethers.js style
const state = await oo.getState(requester, identifier, timestamp, ancillaryData);

switch (state) {
  case State.Proposed:
    // price exists but is inside liveness — treat as provisional
    return { finalized: false, impliedPrice: proposal.price, risk: "reversible" };
  case State.Disputed:
    // now in DVM queue — expect 48h+ before resolution
    return { finalized: false, impliedPrice: null, risk: "long-dispute" };
  case State.Settled:
    return { finalized: true, impliedPrice: settledPrice, risk: "none" };
  default:
    return { finalized: false, impliedPrice: null, risk: "unresolved" };
}

Failure modes bots actually have to handle

  • Reading proposed-but-unsettled prices as truth. The most common bug in homegrown resolution watchers. Always gate on Settled state, not Proposed.
  • Bond griefing. A well-funded actor disputes a correct answer purely to delay settlement and force a DVM round, locking up capital in the market for days. It costs them the bond risk but can be worth it if it lets them exit a losing position at a better price before the truth is locked in.
  • Cycle-boundary timing. Two disputes filed ten minutes apart can resolve a day apart depending on which side of the UTC cutoff they land on. If you're running a market-making strategy around resolution-adjacent markets, this variance in time-to-finality needs its own risk model, not a fixed timer.
  • Ambiguous ancillary data. The question text (ancillary data) proposers and voters read is sometimes looser than traders assumed when pricing the market. This is the actual root cause behind most controversial UMA votes on Polymarket — not oracle failure, but underspecified questions.
  • Early or premature proposals. The adapter reverts proposals submitted before a market's expected end timestamp, but timezone or off-by-one errors in scraping event schedules still trip up naive bots trying to front-run resolution.

If you're building anything that reacts to Polymarket outcomes in real time — arbitrage between correlated markets, copy-trading resolution-sensitive positions, or news-driven execution — the oracle lifecycle isn't a background detail, it's the thing that determines whether your fills are real. It's the same reason comparing Polymarket's CLOB against AMM-style prediction markets or weighing Polymarket against Kalshi for algorithmic trading always comes back to settlement mechanics, not just liquidity depth.

We build the resolution-state tracking directly into execution logic rather than bolting it on after — if you're chasing cross-market pricing gaps around event close, take a look at our Polymarket arbitrage bot build.

Need a bot like this built?

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

Start a project
#Polymarket#UMA#Optimistic Oracle#smart contracts#trading bots