Skip to main content

GMD Oracle

Intro

GMD Oracle is a centralized oracle providing timely and accurate feed of event outcomes on Optimism network. GMD Oracle focuses on serving events for sports-oriented prediction markets. Only approved proposers can create events and propose outcomes to those events. But community can also actively participate in the Oracle bounty program and help ensure oracle's integrity. GMD Oracle setup offers advantages over fully decentralized oracles - it provides a clear point of responsibility, reducing ambiguity in the event of disputes or errors.

Oracle Services

In the operation of a centralized oracle the integrity and fairness of data dissemination are critical to sustaining long-term business viability and user trust. As the entity responsible for publishing event outcomes, the Oracle provider has a vested interest in ensuring the highest standards of accuracy and reliability.

Official Sources

The GMD Oracle relies exclusively on official sources to determine and validate event outcomes. For sporting events, this means referencing authoritative media outlets, league websites, and governing bodies — such as nba.com for NBA games. Only events with clear, verifiable outcomes are supported. Relying on official and widely accepted information, minimizes ambiguity and reinforces trust in the oracle’s data feed.

Dispute Mechanism as a Safeguard

The Oracle’s dispute mechanism is designed to ensure that event outcomes are resolved fairly, transparently, and with strong community involvement. Resolution is protected through a multi-round process that invites community participation and rewards vigilant members - the community effectively becomes the auditor of outcomes. If disagreements persist, the process escalates into longer review periods, giving the proposer and the community more time to verify facts with official sources.

Market Trust and Incentives

A centralized oracle provider derives revenue from ongoing participation in the prediction market ecosystem and operates in a competitive environment where credibility is a key determinant of success. Any deviation from impartial reporting would result in reputational damage and loss of users. Conversely, maintaining an uncompromised track record of fair adjudication enhances the oracle’s credibility, thereby building long-term relationships with market participants.


Event Resolution

Gameday Events are described by name and description hash, with description itself stored off-chain. Name and description must clearly and unambiguously identify and describe the real world event that is being represented on-chain.

Gameday Oracle supports categorical and scalar event outcomes. Events with a known set of possible outcomes are usually CATEGORICAL, whereas events such as price, points differential, are SCALAR.

Categorical Event examples:

  • Event name: Lakers v Nuggets 2025-11-20

  • Event description: NBA 2025/2026 regular season round 1 game between Lakers and Nuggets @Crypto.com Arena. Scheduled start: 2025-11-20 20:00 UTC. Outcome sources: nba.com

If an actual event is canceled and not re-scheduled, event can resolve to CANCELED state. Similarly, if event outcome is inconclusive, event may resolve to VOIDED state.


Proposals and Disputes

Round 1

  • Once Event has ended, Approved Proposer may submit Event Outcome Proposal to the Oracle by posting GMD Token bond via Staking Pool.

  • For a pre-set amount of time, usually, 15 minutes to 3 hours, other Staking Pool participants can dispute the Proposal as incorrect. In doing so disputers must post a fraction of the Proposer's bond.

  • If dispute window closes with zero disputers, proposer may assert the proposed outcome as final.

Round 2

  • If proposal is disputed, proposer must now re-asses the proposed outcome for correctness, and submit another proposal by posting a bond.

  • If dispute window closes with zero disputers, proposer may assert the proposed outcome as final:

    • If initial proposal is the same as second proposal, disputers loses posted bond.

    • However, if second proposal is different, disputers receive Proposer's bond.

Round 3

  • If second proposal is disputed as well, Event resolution is time-locked for 7 days. During this time, Proposer must evaluate the available information, consult official sources and community regarding the final resolution.

  • After time-lock expires, Proposer may unilateraly propose and assert the final outcome.

    • If final outcome is different than disputed proposal, first and second round disputers receive Proposer's bond.

Resolution flowchart

Oracle Interface

interface IGMDOracle {
error UnauthorizedProposer(address proposer);
error EventNotFound(bytes32 id);

event EventAdded(bytes32 _id, string _name, uint256 _bond, uint256 _end_time);

event EventOutcomeProposed(
bytes32 _id, EventLib.OutcomeType _type, int256[] _outcome, uint256 _amount, uint256 _round
);

event EventProposalDisputed(
bytes32 _id, address _disputer, EventLib.OutcomeType _type, int256[] _outcome, uint256 _amount, uint256 _round
);

event EventOutcomeAsserted(
bytes32 _id, EventLib.OutcomeType _type, int256[] _outcome, uint256 _amount, uint256 _round
);

function add_event(EventLib.Event memory _event) external;

function propose_outcome(EventLib.EventOutcomeProposal memory _proposal) external;

function dispute_proposal(bytes32 _eventId) external;

function getEventOutcome(bytes32 _eventId) external view returns (EventLib.EventOutcome memory);

function getEvent(bytes32 _eventId) external view returns (EventLib.Event memory);

}

Eventlib.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

library EventLib {
error EventNotFound(bytes32 id);
error ProposalNotFound(uint8 round);

enum OutcomeType {
UNRESOLVED,
DELAYED,
CATEGORICAL,
SCALAR,
CANCELLED,
VOIDED
}

struct EventOutcome {
OutcomeType outcomeType;
int256[] outcome;
bool isFinal;
bool isDisputed;
}

struct EventOutcomeProposal {
bytes32 id; // event identifier
address proposer; // proposer of the outcome
EventOutcome outcome; // proposed outcome
uint256 bond; // bond amount posted with the proposal
bool isDisputed;
address[] disputers;
uint8 round;
}

struct Event {
bytes32 id; // event identifier
string name; // descriptive name of the event
bytes32 description; // keccak256 hash of event details
uint256 endTime; // end time of the event
uint256 bond; // bond amount required to dispute the outcome
uint256 nDisputers; // number of disputers
uint256 bondMultiplier; // bond multiplier for proposers
OutcomeType outcomeType; // categorical, scalar
string[] candidateOutcomes; // possible outcomes of the event. Empty for scalar events
uint256 numberOfOutcomes; // pre-determined number of outcomes for categorical events
EventOutcomeProposal[] proposals; // outcome proposals
bool isSettled; // flag indicating if the event is settled
EventOutcome settledOutcome; // final outcome of the event
uint256 disputeEnds; // timestamp after which no more disputes are allowed
uint256 assertEnds; // timestamp after which assert is allowed
uint256 assertDuration; // assertion lock period (activated by second dispute)
uint256 disputeDuration; // period after proposal for which dispute is allowed
uint256 staleDuration; // timestamp after which non-asserted events can be asserted as inconclusive
uint8 round; // outcome resolution round
}
}