Skip to main content
Sui-native optimistic oracle for non-price markets. Bond-backed propose/dispute, ResolverNFT-weighted vote, 30-minute auto-finalize.

Config + ledger

Both shared at publish. IDs land in .env as OO_CONFIG_ID / VOTE_LEDGER_ID.

Proposal

Lifecycle

propose<COLLATERAL>

Asserts outcome \in {1,2}, coin::value(bond) >= min_bond_micro, market.resolution_kind == RESOLUTION_OPTIMISTIC. Emits ProposalCreated.

dispute<COLLATERAL>

Asserts state == OPEN, clock.timestamp_ms < challenge_deadline_ms, coin::value(bond) >= proposer_bond.value. State to DISPUTED, vote_deadline_ms set to now + vote_window_ms. Emits ProposalDisputed.

cast_vote

Requires the caller hold a ResolverNFT with matching weight (v1 stub. The on-chain check is a TODO). Updates yes_weight / no_weight. Emits VoteCast.

finalize_auto<COLLATERAL> / finalize_vote<COLLATERAL>

Asserts state == OPEN, clock.timestamp_ms >= challenge_deadline_ms. Returns the proposer’s bond back and a zero coin for the unused disputer-bond slot; state to FINALIZED_AUTO. Returns the proposer address so the caller can transfer::public_transfer the bond back in the same PTB. finalize_vote is the post-dispute path: asserts state == DISPUTED, clock.timestamp_ms >= vote_deadline_ms. The winning side takes both bonds. The losing-side proposer/disputer’s bond is forfeited to the winner.

Frontend integration

OOPanel on EventMarketDetail exposes propose / dispute / finalize buttons with a live countdown to the deadline. State pill transitions animate via AnimatePresence. See Optimistic Oracle.

Tests

tests/oo_resolution_tests.move. State + outcome constants are distinct (placeholder; full propose-dispute-finalize harness lands post-republish).