IDecentralizedOracle Interface
Complete Solidity interface for integrating with the main DecentralizedOracle contract on BSC Mainnet.
Contract Address
DecentralizedOracle: 0xFA4595F636887CA28FCA3260486e44fdcc8c8A71 (BSC Mainnet)
View on BSCScan
Overview
The DecentralizedOracle is the main oracle contract for FarmTruth, using token-weighted voting with tie-breaking mechanisms and automated state management. It serves as the final arbiter for disputed OptimisticOracle queries.
Key Features:
- Token-Weighted Voting: Vote power proportional to token stake
- Tie-Breaking: Automatic period extensions when tied
- Inactivity Slashing: Creator deposits slashed if no votes after ~18 hours
- Flexible Options: Support for 2-255 voting options
- JSON Metadata: Rich metadata support for query context
Economic Parameters
Parameters are controlled by the Governance contract:
| Parameter | Default Value | Description |
|---|---|---|
proposalCreationDeposit | 100,000 tokens | Required deposit to create a query |
votingPeriod | 115,200 blocks | ~1 day voting period |
tieExtensionPeriod | 28,800 blocks | ~6 hours extension for ties |
quorumPercentage | 10% | Minimum participation for governance |
Complete Interface
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "./IGovernance.sol";
/**
* @title IDecentralizedOracle
* @notice Interface for the DecentralizedOracle contract
* @dev Deployed at: 0xFA4595F636887CA28FCA3260486e44fdcc8c8A71 (BSC Mainnet)
*
* This is the main oracle contract for FarmTruth, using token-weighted voting
* with tie-breaking mechanisms and automated state management.
*
* @custom:see contracts/FarmTruth.sol
*/
interface IDecentralizedOracle {
// ============ Events ============
/**
* @notice Emitted when a new query is created
* @param queryId The unique identifier for the query
* @param creator Address that created the query
* @param question The question text
* @param totalOptions Number of voting options
* @param startBlock Block when voting starts
*/
event QueryCreated(
uint256 indexed queryId,
address indexed creator,
string question,
uint8 totalOptions,
uint256 startBlock
);
/**
* @notice Emitted when a vote is cast on a query
* @param queryId The query identifier
* @param voter Address that cast the vote
* @param answerHash Hash of the selected answer
* @param selectedOptions Array of option indices voted for
* @param collateral Amount of tokens staked
*/
event VoteCast(uint256 indexed queryId, address indexed voter, bytes32 answerHash, uint8[] selectedOptions, uint256 collateral);
/**
* @notice Emitted when a query is resolved
* @param queryId The query identifier
* @param winningAnswerHash Hash of the winning answer
* @param winningOptions Array of winning option indices
* @param totalPot Total reward pool for winners
*/
event QueryResolved(uint256 indexed queryId, bytes32 winningAnswerHash, uint8[] winningOptions, uint256 totalPot);
/**
* @notice Emitted when voting period is extended due to a tie
* @param queryId The query identifier
* @param newEndBlock New end block after extension
* @param uniqueWinners Number of tied winners
*/
event VotingExtended(uint256 indexed queryId, uint256 newEndBlock, uint256 uniqueWinners);
/**
* @notice Emitted when a voter claims their rewards
* @param queryId The query identifier
* @param voter Address receiving rewards
* @param reward Amount of tokens received
*/
event RewardsClaimed(uint256 indexed queryId, address indexed voter, uint256 reward);
/**
* @notice Emitted when a query creator's deposit is slashed for inactivity
* @param queryId The query identifier
* @param creator Address of query creator
* @param amount Amount slashed
*/
event QuerySlashed(uint256 indexed queryId, address indexed creator, uint256 amount);
// ============ State Variables ============
/**
* @notice Maximum number of options allowed per query
*/
function MAX_OPTIONS() external view returns (uint8);
/**
* @notice Minimum number of options required per query
*/
function MIN_OPTIONS() external view returns (uint8);
/**
* @notice Total number of queries created
*/
function queryCount() external view returns (uint256);
/**
* @notice Reference to the Governance contract
*/
function governance() external view returns (IGovernance);
/**
* @notice Threshold for considering a query inactive (default: 86,400 blocks ~18 hours)
*/
function inactivityThreshold() external view returns (uint256);
/**
* @notice Total number of votes cast across all queries
*/
function totalVotes() external view returns (uint256);
// ============ Core Functions ============
/**
* @notice Create a new oracle query
* @dev Requires approval for proposalCreationDeposit tokens
* @param startBlock Block number when voting should start (auto-adjusted if in past)
* @param question The question to ask
* @param metadata JSON metadata with additional info (e.g., options array)
* @param totalOptions Number of voting options (2-255)
* @return queryId The unique identifier for the created query
*/
function createQuery(
uint256 startBlock,
string memory question,
string memory metadata,
uint8 totalOptions
) external returns (uint256);
/**
* @notice Cast a vote on an active query
* @dev Requires token approval for collateral amount
* @param queryId The query to vote on
* @param selectedOptions Array of option indices to vote for
* @param collateral Amount of tokens to stake on this vote
*/
function vote(
uint256 queryId,
uint8[] memory selectedOptions,
uint256 collateral
) external;
/**
* @notice Resolve a query after voting period ends
* @dev Can be called by anyone once conditions are met
* @param queryId The query to resolve
*/
function resolveQuery(uint256 queryId) external;
/**
* @notice Claim rewards for a winning vote
* @dev Only winners can claim, proportional to their stake
* @param queryId The query to claim rewards from
*/
function claimReward(uint256 queryId) external;
// ============ View Functions ============
/**
* @notice Get comprehensive details for a query
* @param queryId The query identifier
* @return creator Address that created the query
* @return startBlock Block when voting starts
* @return originalEndBlock Original end block
* @return currentEndBlock Current end block (may be extended)
* @return question The question text
* @return metadata JSON metadata string
* @return totalOptions Number of voting options
* @return resolved Whether query is resolved
* @return winningOptions Array of winning option indices
* @return totalCollateral Total tokens staked
* @return totalWinningCollateral Tokens staked on winning answer
* @return totalPot Total reward pool
* @return createdAt Timestamp when created
* @return lastVoteBlock Block of most recent vote
* @return inTieExtension Whether in tie extension period
* @return canBeResolved Whether query can currently be resolved
*/
function getQueryDetails(uint256 queryId) external view returns (
address creator,
uint256 startBlock,
uint256 originalEndBlock,
uint256 currentEndBlock,
string memory question,
string memory metadata,
uint8 totalOptions,
bool resolved,
uint8[] memory winningOptions,
uint256 totalCollateral,
uint256 totalWinningCollateral,
uint256 totalPot,
uint256 createdAt,
uint256 lastVoteBlock,
bool inTieExtension,
bool canBeResolved
);
}
Usage in Your Contract
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "./IDecentralizedOracle.sol";
import "./IGovernance.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
contract MyOracleIntegration {
IDecentralizedOracle public immutable oracle;
IERC20 public immutable token;
constructor(address _oracle) {
oracle = IDecentralizedOracle(_oracle);
// Get token address from governance
IGovernance governance = oracle.governance();
token = governance.governanceToken();
// Approve unlimited spending
token.approve(_oracle, type(uint256).max);
}
/// @notice Create a query with JSON metadata
function createQueryWithMetadata(
uint256 startBlock,
string calldata question,
string[] calldata options
) external returns (uint256) {
// Build JSON metadata
string memory metadata = string(abi.encodePacked(
'{"options":["',
options[0],
'","',
options[1],
'"]}'
));
return oracle.createQuery(
startBlock,
question,
metadata,
uint8(options.length)
);
}
/// @notice Vote on a query
function voteOnQuery(
uint256 queryId,
uint8 optionIndex,
uint256 collateral
) external {
uint8[] memory selectedOptions = new uint8[](1);
selectedOptions[0] = optionIndex;
oracle.vote(queryId, selectedOptions, collateral);
}
/// @notice Check if query can be resolved
function checkResolvable(uint256 queryId) external view returns (bool) {
(
,,,,,,,, // Skip first 8 fields
,,,,,, // Skip next 6 fields
bool canBeResolved
) = oracle.getQueryDetails(queryId);
return canBeResolved;
}
}
Query States
Queries progress through different states managed by EnumerableSets:
- Pending: Created but voting hasn't started yet
- Active: Currently accepting votes
- Past: Resolved or expired
Tie-Breaking Mechanism
When a query resolves with multiple answers having equal top weight:
- Voting period extends by
tieExtensionPeriod(~6 hours) - Additional votes can break the tie
- Extension can repeat multiple times if ties persist
- Eventually resolves with the winning answer(s)
Inactivity Slashing
If a query receives no votes within inactivityThreshold (~18 hours):
- Anyone can call
slashInactiveQuery(queryId) - Creator's deposit is burned
- Query is marked as resolved with no winner
See Also
- Main Oracle Solidity Integration - Integration guide
- Create Queries - Query creation guide
- Vote & Resolve - Voting mechanics
- IGovernance - Governance interface
- IOptimisticOracle - Optimistic oracle interface
Source Code
The canonical source code for this interface is located at:
- Repository:
contracts/IDecentralizedOracle.sol - Deployed: 0xFA4595F636887CA28FCA3260486e44fdcc8c8A71
Back to Interfaces Overview | Documentation Home