Verex
DocsCreatePortfolio

Resolution & the UMA oracle

A prediction market is only as good as its answer to “what actually happened?”. A blockchain cannot see the world, so some outside process must supply the truth. This document covers what Verex does today, and how UMA's Optimistic Oracle replaces the operator as the source of that truth.

Today: the operator reports

At resolution time the operator opens the market, selects the winning outcome, and confirms. The API calls reportPayouts on the Conditional Tokens contract, which fixes the payout vector permanently. Winning tokens become redeemable for $1; losing tokens become worthless.

This is simple, instant, and free. It is also completely trusted — every holder is relying on the operator being both honest and correct. That is acceptable for a demo with test funds and unacceptable for anything else, which is why the oracle work exists.

What “optimistic” means

An optimistic oracle inverts the usual design. Instead of asking a committee to vote on every question, it assumes the first answer is correct and only escalates when someone objects. Voting is expensive and slow, so you spend it only on the rare disputed case.

The security comes from bonds, not from trust. Proposing an answer costs a deposit; disputing one costs a deposit. Whoever turns out to be wrong loses theirs to the other. As long as the bond is larger than the profit available from lying, honesty is the rational strategy — and nothing needs to happen at all when the answer is obvious.

The flow, step by step

  1. Request. The market asks the oracle a question, encoded with UMA's YES_OR_NO_QUERY identifier — plain English text plus resolution criteria.
  2. Propose. Anyone posts an answer with a bond. In practice a bot proposes within minutes, because the reward is free money for an obvious answer.
  3. Liveness. A challenge window opens — the UMA default is 7,200 seconds (two hours). Nothing happens unless somebody objects.
  4. Settlethe normal path. Liveness expires with no dispute, the answer is final, and the proposer gets its bond back plus the reward.
  5. Disputethe rare path. A challenger posts a matching bond. The question escalates to UMA's DVM, where UMA token holders vote over roughly 48–96 hours. The loser's bond goes to the winner.

The answer is encoded as a fixed-point number: 1e18 means YES, 0 means NO, and 0.5e18 means unresolvable — used when the question was ambiguous or the event genuinely cannot be settled. Verex maps that back onto the CTF payout vector.

Bonds and the whitelist

Bonds must be posted in a currency on UMA's AddressWhitelist. Verex's own test USDC is not on it — that was the first real constraint discovered when wiring this up on Sepolia.

The chosen bond currency is Sepolia WETH, for a practical reason: it is self-service. Anyone can obtain it by sending ETH to the WETH contract's deposit() function, whereas UMA's own whitelisted test USDC has no public mint. WETH carries a small final fee (0.001) where UMA's USDC has none, which is a cost worth paying for not depending on someone else to hand out tokens.

What if a voter is malicious?

The honest answer is that this is a real risk class, not a solved problem. An optimistic oracle's guarantees rest on economics, and economics can be attacked.

  • A bad proposal is the cheap case. Anyone watching can dispute it and take the proposer's bond — the attack loses money as long as at least one honest watcher exists.
  • *A malicious unresolvable vote* is more corrosive. It does not steal a payout; it strands one, and it is easier to argue for than an outright wrong answer.
  • Governance capture is the systemic case. Because the DVM is token-weighted, an attacker holding enough voting power can ratify a false answer. The defence is that doing so destroys the value of the tokens they used to do it — a deterrent, not a guarantee.
On a testnet the shape of the risk is different: the disputes that matter are not adversarial, they are indifferent. Nobody has money riding on a Sepolia market, so nobody watches it. A dispute raised by a stranger would still be settled by real voters, but the outcome is outside the operator's control — which is why the demo path shortens liveness via setCustomLiveness and exercises the undisputed happy path.

Can the operator choose per market?

Yes — but only at creation time, never afterwards. The reason is structural rather than a matter of policy:

conditionId = keccak256(abi.encodePacked(oracle, questionId, outcomeSlotCount))

The oracle's address is hashed into the market's identity. Switching a live market to a different oracle would compute a different conditionId — a different market entirely, holding none of the original positions. So the choice between operator resolution and UMA is made when the market is created and is fixed for its lifetime.