> ## Documentation Index
> Fetch the complete documentation index at: https://docs.darkpool.fun/llms.txt
> Use this file to discover all available pages before exploring further.

# oo_resolution

> Optimistic oracle: propose, dispute, vote, finalize.

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

## Config + ledger

```move theme={"system"}
public struct OOConfig has key {
    id: UID,
    min_bond_micro: u64,             // OO_MIN_BOND
    challenge_window_ms: u64,        // 30 min default
    vote_window_ms: u64,             // 12 hr default
}

public struct VoteLedger has key {
    id: UID,
    /// per (proposal, voter) -> {weight, vote}
    votes: Table<vector<u8>, VoteRecord>,
}
```

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

## Proposal

```move theme={"system"}
public struct Proposal<phantom COLLATERAL> has key {
    id: UID,
    market_link_id: ID,
    state: u8,                       // OPEN | DISPUTED | FINALIZED_AUTO | FINALIZED_VOTE
    proposer: address,
    disputer: address,                // 0x0 sentinel if not disputed
    proposed_outcome: u8,            // YES | NO
    proposer_bond: Balance<COLLATERAL>,
    disputer_bond: Balance<COLLATERAL>,
    challenge_deadline_ms: u64,
    vote_deadline_ms: u64,            // 0 until disputed
    yes_weight: u64,
    no_weight: u64,
    final_outcome: u8,                // 0 if not finalized
}
```

## Lifecycle

### `propose<COLLATERAL>`

```move theme={"system"}
public fun propose<COLLATERAL>(
    config: &OOConfig,
    market_link: &MarketLink,
    outcome: u8,                        // 1 = YES, 2 = NO
    bond: Coin<COLLATERAL>,
    clock: &Clock,
    ctx: &mut TxContext,
): Proposal<COLLATERAL>
```

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

### `dispute<COLLATERAL>`

```move theme={"system"}
public fun dispute<COLLATERAL>(
    proposal: &mut Proposal<COLLATERAL>,
    config: &OOConfig,
    bond: Coin<COLLATERAL>,
    clock: &Clock,
    ctx: &mut TxContext,
)
```

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`

```move theme={"system"}
public fun cast_vote<COLLATERAL>(
    proposal: &mut Proposal<COLLATERAL>,
    ledger: &mut VoteLedger,
    weight: u64,
    vote: u8,                       // 1 = YES, 2 = NO
    clock: &Clock,
    ctx: &mut TxContext,
)
```

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>`

```move theme={"system"}
public fun finalize_auto<COLLATERAL>(
    proposal: &mut Proposal<COLLATERAL>,
    clock: &Clock,
    ctx: &mut TxContext,
): (Coin<COLLATERAL>, Coin<COLLATERAL>, address)
```

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](/concepts/optimistic-oracle).

## Tests

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