IOptimisticOracle Interface
Complete Solidity interface for integrating with the OptimisticOracle contract on BSC Mainnet.
Contract Address
OptimisticOracle: 0xA83689161DFa9d5992fBa658d3148C6f72E1419E (BSC Mainnet)
View on BSCScan
Overview
The OptimisticOracle provides fast, low-cost oracle resolution through an optimistic mechanism with dispute escalation to the main DecentralizedOracle.
Key Features:
- Fast Resolution: Queries resolve in ~1.5 hours if undisputed
- Economic Security: 1M token collateral for proposals and disputes
- Dispute Escalation: Automatic escalation to DecentralizedOracle when disputed
- "Not Clear Yet" Handling: Queries can be reset if resolution is premature
Query Lifecycle:
Awaiting → Proposed → [Disputed →] Resolved
(1.5h) (escalate)
Economic Parameters
| Parameter | Value | Description |
|---|---|---|
CREATION_COST | 30,000 tokens | Cost to create a query (20k reward, 10k burned) |
PROPOSAL_COLLATERAL | 1,000,000 tokens | Collateral to propose an answer |
DISPUTE_COLLATERAL | 1,000,000 tokens | Collateral to dispute a proposal |
DISPUTE_WINDOW | 7,200 blocks | ~1.5 hours at 0.75s/block (BSC) |
MAIN_ORACLE_FUNDING | 100,000 tokens | Deducted from loser's collateral |
PROPOSER_REWARD | 20,000 tokens | Reward for correct resolution |
Complete Interface
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
/**
* @title IOptimisticOracle
* @notice Interface for the OptimisticOracle contract - a permissionless optimistic oracle with dispute mechanism
* @dev Deployed at: 0xA83689161DFa9d5992fBa658d3148C6f72E1419E (BSC Mainnet)
*
* This oracle allows fast, low-cost resolution of queries through an optimistic mechanism:
* 1. Anyone can create a query with string options (pays 30k tokens)
* 2. Anyone can propose an answer (locks 1M tokens as collateral)
* 3. Anyone can dispute within ~1.5 hours (locks 1M tokens)
* 4. If disputed, escalates to main DecentralizedOracle for resolution
* 5. Winner receives collateral + 900k from loser + 20k reward
*
* Query lifecycle: Awaiting -> Proposed -> [Disputed ->] Resolved
*
* Special handling:
* - Options use standard 0-based indexing (0 to N-1)
* - Empty array means "No correct choice"
* - When disputed, main oracle adds "Not clear yet" as option N
* - If resolved as "Not clear yet", query resets to Awaiting state
*
* @custom:see contracts/OptimisticOracle.sol
*/
interface IOptimisticOracle {
// ============ Enums ============
/**
* @notice Possible states for an optimistic query
* @param Awaiting Waiting for someone to propose an answer
* @param Proposed Answer proposed, dispute window open
* @param Disputed Answer disputed, awaiting main oracle resolution
* @param Resolved Final answer determined
*/
enum QueryState { Awaiting, Proposed, Disputed, Resolved }
// ============ Events ============
/**
* @notice Emitted when a new optimistic query is created
* @param queryId The unique identifier for the query
* @param creator Address that created the query
* @param question The question text
* @param optionsCount Number of options provided
*/
event OptimisticQueryCreated(uint256 indexed queryId, address indexed creator, string question, uint256 optionsCount);
/**
* @notice Emitted when an answer is proposed for a query
* @param queryId The query identifier
* @param proposer Address that proposed the answer
* @param answer Array of option indices (empty for "no correct choice")
*/
event AnswerProposed(uint256 indexed queryId, address indexed proposer, uint8[] answer);
/**
* @notice Emitted when a proposed answer is disputed
* @param queryId The query identifier
* @param challenger Address that disputed the answer
* @param mainOracleQueryId The ID of the escalated query in the main oracle
* @param asNotClear True if disputing as "not clear yet"
*/
event AnswerDisputed(uint256 indexed queryId, address indexed challenger, uint256 mainOracleQueryId, bool asNotClear);
/**
* @notice Emitted when a query is resolved
* @param queryId The query identifier
* @param finalAnswer Array of winning option indices
* @param isNotClearYet True if resolved as "not clear yet" (query reset to Awaiting)
*/
event QueryResolved(uint256 indexed queryId, uint8[] finalAnswer, bool isNotClearYet);
/**
* @notice Emitted when a query is reset to Awaiting state (after "not clear yet" resolution)
* @param queryId The query identifier
*/
event QueryResetToAwaiting(uint256 indexed queryId);
/**
* @notice Emitted when rewards are claimed by a participant
* @param queryId The query identifier
* @param recipient Address receiving the rewards
* @param amount Amount of tokens received
*/
event RewardsClaimed(uint256 indexed queryId, address indexed recipient, uint256 amount);
// ============ Constants ============
/**
* @notice Cost to create a new query (30,000 tokens)
* @dev Depositor gets 10k burned, winner gets 20k as reward
*/
function CREATION_COST() external view returns (uint256);
/**
* @notice Collateral required to propose an answer (1,000,000 tokens)
*/
function PROPOSAL_COLLATERAL() external view returns (uint256);
/**
* @notice Collateral required to dispute an answer (1,000,000 tokens)
*/
function DISPUTE_COLLATERAL() external view returns (uint256);
/**
* @notice Dispute window duration in blocks (~1.5 hours at 0.75s/block)
*/
function DISPUTE_WINDOW() external view returns (uint256);
/**
* @notice Reward paid to final resolver from creation deposit (20,000 tokens)
*/
function PROPOSER_REWARD() external view returns (uint256);
/**
* @notice Amount deducted from loser's collateral to fund main oracle query (100,000 tokens)
*/
function MAIN_ORACLE_FUNDING() external view returns (uint256);
/**
* @notice Maximum regular option index (254)
* @dev Index 255 is reserved for internal use
*/
function MAX_REGULAR_OPTION() external view returns (uint8);
/**
* @notice Burn address for unused creation deposit (0x000000000000000000000000000000000000dEaD)
*/
function BURN_ADDRESS() external view returns (address);
// ============ State Variables ============
/**
* @notice Total number of queries created
*/
function queryCount() external view returns (uint256);
/**
* @notice The ERC20 token used for collateral and rewards
* @return Address of the ERC20 token contract
*/
function token() external view returns (address);
/**
* @notice The main DecentralizedOracle used for dispute resolution
* @return Address of the DecentralizedOracle contract
*/
function mainOracle() external view returns (address);
// ============ Core Functions ============
/**
* @notice Create a new optimistic query with string options
* @dev Requires approval for CREATION_COST tokens
* @param question The question to ask
* @param options Array of option strings (2-254 options required)
* @return queryId The unique identifier for the created query
*/
function createQuery(string memory question, string[] memory options) external returns (uint256);
/**
* @notice Propose an answer to a query
* @dev Requires approval for PROPOSAL_COLLATERAL tokens
* @dev Query must be in Awaiting state
* @param queryId The query ID
* @param selectedOptions Array of option indices (can be empty for "no correct choice")
*/
function proposeAnswer(uint256 queryId, uint8[] memory selectedOptions) external;
/**
* @notice Dispute a proposed answer
* @dev Requires approval for DISPUTE_COLLATERAL tokens
* @dev Query must be in Proposed state and within dispute window
* @dev Escalates to main oracle with "Not clear yet" added as option N
* @param queryId The query ID
* @param disputeAsNotClear If true, dispute as "not clear yet"
*/
function dispute(uint256 queryId, bool disputeAsNotClear) external;
/**
* @notice Resolve a query after dispute window passes without dispute
* @dev Query must be in Proposed state and dispute window must be closed
* @dev Proposer receives collateral + 20k reward, 10k burned
* @param queryId The query ID
*/
function resolveUndisputed(uint256 queryId) external;
/**
* @notice Resolve a disputed query after main oracle resolves
* @dev Query must be in Disputed state and main oracle must be resolved
* @dev If "not clear yet", challenger compensated, query reset to Awaiting
* @dev Otherwise, winner receives collateral + 900k from loser + 20k reward
* @param queryId The query ID
*/
function resolveDisputed(uint256 queryId) external;
// ============ View Functions ============
/**
* @notice Get the answer for a resolved query
* @dev Reverts if query is not resolved
* @param queryId The query ID
* @return answer Array of option indices (can be empty for "no correct choice")
*/
function getAnswer(uint256 queryId) external view returns (uint8[] memory);
/**
* @notice Get the current state of a query
* @param queryId The query ID
* @return state The current state (Awaiting, Proposed, Disputed, or Resolved)
*/
function getQueryState(uint256 queryId) external view returns (QueryState);
/**
* @notice Get full details for a query
* @param queryId The query ID
* @return creator Address that created the query
* @return question The question text
* @return options Array of option strings
* @return createdAt Block timestamp when created
* @return state Current query state
* @return proposer Address that proposed answer (if any)
* @return proposedAnswer Proposed option indices
* @return proposalBlock Block number when proposed
* @return disputed Whether the query has been disputed
* @return challenger Address that disputed (if any)
* @return mainOracleQueryId Main oracle query ID (if disputed)
* @return resolved Whether the query is resolved
* @return finalAnswer Final winning option indices
* @return isNotClearYet Whether resolved as "not clear yet"
*/
function getQueryDetails(uint256 queryId) external view returns (
address creator,
string memory question,
string[] memory options,
uint256 createdAt,
QueryState state,
address proposer,
uint8[] memory proposedAnswer,
uint256 proposalBlock,
bool disputed,
address challenger,
uint256 mainOracleQueryId,
bool resolved,
uint8[] memory finalAnswer,
bool isNotClearYet
);
/**
* @notice Get remaining blocks in dispute window
* @param queryId The query ID
* @return remaining Blocks remaining (0 if window closed or not applicable)
*/
function getDisputeWindowRemaining(uint256 queryId) external view returns (uint256);
/**
* @notice Check if a query can currently be disputed
* @param queryId The query ID
* @return canDispute True if query is in Proposed state and within dispute window
*/
function canDispute(uint256 queryId) external view returns (bool);
/**
* @notice Get paginated list of queries filtered by state
* @param state Filter by this state
* @param offset Starting index in the filtered results
* @param limit Maximum number of results to return
* @return queryIds Array of query IDs matching the criteria
*/
function getQueriesByState(QueryState state, uint256 offset, uint256 limit)
external
view
returns (uint256[] memory queryIds);
}
Usage in Your Contract
Copy the interface above into your project, or import it directly:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "./IOptimisticOracle.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
contract MyContract {
IOptimisticOracle public immutable oracle;
IERC20 public immutable token;
constructor(address _oracle, address _token) {
oracle = IOptimisticOracle(_oracle);
token = IERC20(_token);
// Approve unlimited spending for convenience
token.approve(_oracle, type(uint256).max);
}
function createQuery(
string calldata question,
string[] calldata options
) external returns (uint256) {
// Ensure contract has 30k tokens
require(token.balanceOf(address(this)) >= oracle.CREATION_COST(), "Insufficient balance");
return oracle.createQuery(question, options);
}
}
See Also
- Solidity Integration Guide - Detailed integration examples
- Create Queries - Query creation guide
- Propose & Dispute - Proposal and dispute mechanics
- IDecentralizedOracle - Main oracle interface (for disputes)
- IGovernance - Governance interface
Source Code
The canonical source code for this interface is located at:
- Repository:
contracts/IOptimisticOracle.sol - Deployed: 0xA83689161DFa9d5992fBa658d3148C6f72E1419E
Back to Interfaces Overview | Documentation Home