oo_resolution.move: a Sui-native optimistic oracle with a 30-minute challenge window. Polymarket’s UMA window is 7 days.
State machine

A proposal starts OPEN. If no one disputes within the challenge window, finalize_auto closes it. If a dispute lands, ResolverNFT holders vote and finalize_vote closes it. The side with majority weight wins both bonds.
Lifecycle
1
Propose
Anyone calls
oo_resolution::propose<COLLATERAL>(market_link, outcome, bond_coin, clock, ctx) with a DUSDC bond at or above OO_MIN_BOND. If no one disputes within OO_CHALLENGE_WINDOW_MS (default 30 min), the proposal becomes the final outcome.2
Dispute (optional)
Anyone can call
dispute<COLLATERAL> with a counter-bond equal to the proposer’s. State moves to DISPUTED. A DAO vote is triggered.3
Vote (DISPUTED only)
ResolverNFT holders call cast_vote(vote_ledger, proposal, weight, vote). Each vote is weighted by the holder’s ResolverNFT weight. The vote window is OO_VOTE_WINDOW_MS (default 12 hours).4
Finalize
Two paths:
finalize_auto<COLLATERAL>. No dispute happened. Proposer wins their bond back. State moves toFINALIZED_AUTO.finalize_vote<COLLATERAL>. Vote window closed. The side with majority weight wins both bonds. State moves toFINALIZED_VOTE.
States
Outcomes
Frontend integration
EventMarketDetail renders the OOPanel whenever the binary-market registry entry has an ooMarketLinkId. Full lifecycle UI:
- Propose form (bond amount + YES / NO chips)
- Dispute form (auto-mirrors counter-outcome, min-bond clamp)
- Finalize buttons.
finalize_autowhen window closed and no dispute.finalize_voteotherwise. - Historical proposals list
- State pill (OPEN / DISPUTED / FINALIZED_AUTO / FINALIZED_VOTE) with
AnimatePresencetransitions - Live countdown to challenge or vote deadline
ResolverNFTs have been distributed yet). The panel surfaces vote weights when the window closes.
Scripts
scripts/oo-finalize.ts pre-flight-reads the proposal and prints time-remaining instead of letting the Move call abort early.
Bridge to settlement (v0.4)
The OO does not yet bridge tosettlement::mark_resolved automatically. That’s a v0.4 republish follow-up. For now, after finalize_* the resolver manually signs binary-market:resolve with the matching outcome.
