// SPDX-License-Identifier: MIT pragma solidity >=0.8.0 <0.9.0; contract OptimisticOracle { //////////////// /// Enums ////// //////////////// enum State { Invalid, Asserted, Proposed, Disputed, Settled, Expired } ///////////////// /// Errors ////// ///////////////// error AssertionNotFound(); error AssertionProposed(); error InvalidValue(); error InvalidTime(); error ProposalDisputed(); error NotProposedAssertion(); error AlreadyClaimed(); error AlreadySettled(); error AwaitingDecider(); error NotDisputedAssertion(); error OnlyDecider(); error OnlyOwner(); error TransferFailed(); ////////////////////// /// State Variables // ////////////////////// struct EventAssertion { address asserter; address proposer; address disputer; bool proposedOutcome; bool resolvedOutcome; uint256 reward; uint256 bond; uint256 startTime; uint256 endTime; bool claimed; address winner; string description; } uint256 public constant MINIMUM_ASSERTION_WINDOW = 3 minutes; uint256 public constant DISPUTE_WINDOW = 3 minutes; address public decider; address public owner; uint256 public nextAssertionId = 1; mapping(uint256 => EventAssertion) public assertions; //////////////// /// Events ///// //////////////// event EventAsserted(uint256 assertionId, address asserter, string description, uint256 reward); event OutcomeProposed(uint256 assertionId, address proposer, bool outcome); event OutcomeDisputed(uint256 assertionId, address disputer); event AssertionSettled(uint256 assertionId, bool outcome, address winner); event DeciderUpdated(address oldDecider, address newDecider); event RewardClaimed(uint256 assertionId, address winner, uint256 amount); event RefundClaimed(uint256 assertionId, address asserter, uint256 amount); /////////////////// /// Modifiers ///// /////////////////// /** * @notice Modifier to restrict function access to the designated decider * @dev Ensures only the decider can settle disputed assertions */ modifier onlyDecider() { if (msg.sender != decider) revert OnlyDecider(); _; } /** * @notice Modifier to restrict function access to the contract owner * @dev Ensures only the owner can update critical contract parameters */ modifier onlyOwner() { if (msg.sender != owner) revert OnlyOwner(); _; } /////////////////// /// Constructor /// /////////////////// constructor(address _decider) { decider = _decider; owner = msg.sender; } /////////////////// /// Functions ///// /////////////////// /** * @notice Updates the decider address (only contract owner) * @dev Changes the address authorized to settle disputed assertions. * Emits DeciderUpdated event with old and new addresses. * @param _decider The new address that will act as decider for disputed assertions */ function setDecider(address _decider) external onlyOwner { address oldDecider = address(decider); decider = _decider; emit DeciderUpdated(oldDecider, _decider); } /** * @notice Returns the complete assertion details for a given assertion ID * @dev Provides access to all fields of the EventAssertion struct * @param assertionId The unique identifier of the assertion to retrieve * @return The complete EventAssertion struct containing all assertion data */ function getAssertion(uint256 assertionId) external view returns (EventAssertion memory) { return assertions[assertionId]; } /** * @notice Creates a new assertion about an event with a true/false outcome * @dev Requires ETH payment as reward for correct proposers. Bond requirement is 2x the reward. * Sets default timestamps if not provided. Validates timing requirements. * @param description Human-readable description of the event (e.g. "Did X happen by time Y?") * @param startTime When proposals can begin (0 for current block timestamp) * @param endTime When the assertion expires (0 for startTime + minimum window) * @return The unique assertion ID for the newly created assertion */ function assertEvent( string memory description, uint256 startTime, uint256 endTime ) external payable returns (uint256) {} /** * @notice Proposes the outcome (true or false) for an asserted event * @dev Requires bonding ETH equal to 2x the original reward. Sets dispute window deadline. * Can only be called once per assertion and within the assertion time window. * @param assertionId The unique identifier of the assertion to propose an outcome for * @param outcome The proposed boolean outcome (true or false) for the event */ function proposeOutcome(uint256 assertionId, bool outcome) external payable {} /** * @notice Disputes a proposed outcome by bonding ETH * @dev Requires bonding ETH equal to the bond amount. Can only dispute once per assertion * and must be within the dispute window after proposal. * @param assertionId The unique identifier of the assertion to dispute */ function disputeOutcome(uint256 assertionId) external payable {} /** * @notice Claims reward for undisputed assertions after dispute window expires * @dev Anyone can trigger this function. Transfers reward + bond to the proposer. * Can only be called after dispute window has passed without disputes. * @param assertionId The unique identifier of the assertion to claim rewards for */ function claimUndisputedReward(uint256 assertionId) external {} /** * @notice Claims reward for disputed assertions after decider settlement * @dev Anyone can trigger this function. Pays decider fee and transfers remaining rewards to winner. * Can only be called after decider has settled the dispute. * @param assertionId The unique identifier of the disputed assertion to claim rewards for */ function claimDisputedReward(uint256 assertionId) external {} /** * @notice Claims refund for assertions that receive no proposals before deadline * @dev Anyone can trigger this function. Returns the original reward to the asserter. * Can only be called after assertion deadline has passed without any proposals. * @param assertionId The unique identifier of the expired assertion to claim refund for */ function claimRefund(uint256 assertionId) external {} /** * @notice Resolves disputed assertions by determining the correct outcome (only decider) * @dev Sets the resolved outcome and determines winner based on proposal accuracy. * @param assertionId The unique identifier of the disputed assertion to settle * @param resolvedOutcome The decider's determination of the true outcome */ function settleAssertion(uint256 assertionId, bool resolvedOutcome) external onlyDecider {} /** * @notice Returns the current state of an assertion based on its lifecycle stage * @dev Evaluates assertion progress through states: Invalid, Asserted, Proposed, Disputed, Settled, Expired * @param assertionId The unique identifier of the assertion to check state for * @return The current State enum value representing the assertion's status */ function getState(uint256 assertionId) external view returns (State) {} /** * @notice Returns the final resolved outcome of a settled assertion * @dev For undisputed assertions, returns the proposed outcome after dispute window. * For disputed assertions, returns the decider's resolved outcome. * @param assertionId The unique identifier of the assertion to get resolution for * @return The final boolean outcome of the assertion */ function getResolution(uint256 assertionId) external view returns (bool) {} }