Resolution
How markets resolve through UMA's Optimistic Oracle — assertion, challenge, settlement, and redemption.
Markets resolve through UMA's Optimistic Oracle V3. Anyone can assert an outcome by posting a bond, and if no one disputes it within a liveness window, the assertion is accepted.
Resolution Lifecycle
| Phase | Description | Who Acts |
|---|---|---|
ACTIVE_NO_ASSERTION | Market is active, no assertion exists | Anyone can assert |
ASSERTION_PENDING | Assertion posted, liveness window running | Anyone can dispute via UMA |
ASSERTION_EXPIRED | Liveness expired without dispute | Anyone can settle |
SETTLED_NOT_REPORTED | UMA confirmed the assertion | Anyone can report to CTF |
RESOLVED | Payouts recorded in CTF | Winning token holders can redeem |
Making an Assertion
Anyone can assert a market's outcome by calling assertMarketOutcome. The asserter posts a bond — if the assertion goes undisputed, the bond is returned plus any reward. If disputed and wrong, the bond is lost.
const tx = await client.uma.assertMarketOutcome({
marketId: 42n,
outcome: 'Yes',
autoApprove: true, // auto-approves bond token if needed
});Preconditions:
- No active assertion on this market
- Caller must hold sufficient bond tokens (USDC)
- USDC approved to the Diamond contract
The outcome string must exactly match one of the market's defined outcomes (e.g., "Yes" or "No").
Challenge Period
During the liveness window, anyone can dispute an assertion by posting a counter-bond directly through UMA's Optimistic Oracle V3. Disputes are not handled by OddMaki contracts — they go through UMA's standard dispute mechanism.
- Disputer calls
disputeAssertion()on the UMA Oracle (not the Diamond) - UMA escalates the dispute to its DVM for human arbitration
- DVM voters resolve the dispute
- If upheld: assertion accepted, disputer loses bond
- If rejected: assertion rejected, asserter loses bond, a new assertion can be submitted
You can check assertion status at any time:
const details = await client.uma.getAssertionDetails(assertionId);
console.log(details.expirationTime); // Unix timestamp when liveness expires
console.log(details.canSettle); // true if liveness expired
console.log(details.isDisputed); // true if disputedSettlement
After the liveness window expires without dispute, anyone can settle the assertion:
const tx = await client.uma.settleAssertion(assertionId);Settlement triggers UMA to finalize the result. UMA synchronously calls back into the Diamond to record whether the assertion was truthful. If the assertion was rejected (via dispute), the oracle lock is cleared and a new assertion can be made.
Reporting
After settlement, the resolved outcome must be reported to the Conditional Token Framework. This records the payout vector and enables redemption.
const tx = await client.uma.reportResolution({
marketId: 42n,
outcome: 'Yes',
});The outcome parameter must exactly match the settled assertion's outcome.
Payout vectors:
| Resolved As | Payout Vector | Meaning |
|---|---|---|
"Yes" | [1, 0] | YES holders win |
"No" | [0, 1] | NO holders win |
"Invalid" | [1, 1] | Equal split — both sides redeem proportionally |
Market group cascade: If a market in a group resolves YES, all sibling markets automatically resolve as NO.
Redemption
After resolution is reported, holders of winning outcome tokens can redeem them for collateral:
const tx = await client.uma.redeemWinnings(42n);The CTF burns winning tokens and returns collateral (e.g., USDC). Partial redemptions are supported — you don't have to redeem all at once.
You can check resolution status before redeeming:
const status = await client.uma.getResolutionStatus(42n);
console.log(status.resolved); // boolean
console.log(status.winningOutcome); // "YES" | "NO" | "INVALID" | null
console.log(status.payouts); // [1n, 0n]Dispute Handling
If an assertion is disputed and rejected by UMA's DVM, the oracle lock is cleared. A new assertion can then be submitted — the market doesn't get stuck. There is no admin override or emergency resolution mechanism; resolution is fully governed by the UMA Oracle lifecycle.
Key edge cases:
- Expired but unsettled: An expired assertion stays pending until someone calls
settleAssertion()— there's no auto-settlement - No assertion: A market with no assertion stays active indefinitely until someone posts one
- Double assertion prevention: Only one assertion can be active per market at a time
What's Next
- Oracle Settings → — configure bond, reward, and liveness
- Token Mechanics → — how outcome tokens and redemption work
- Creating Markets → — market creation parameters