This contract implements the erc20 related functionality for the Oracly Protocol’s decentralized prediction game. It allows bettors to participate in prediction rounds, manages the lifecycle of each round, integrates with Chainlink to obtain price data, and determines round outcomes based on price movements. The contract also handles bettor payouts, refunds, and manages reward distributions via external contracts.
Contract for the Oracly Protocol’s decentralized prediction game. Manages prediction rounds, integrates with Chainlink for price data, determines round outcomes, and handles bettor payouts and refunds.
address STAKING_CONTRACT
Address of the staking contract used for distributing staking rewards.
This address should point to a valid smart contract. It is used to manage staking rewards in the Oracly protocol. The contract must implement the expected staking interface to ensure proper reward distribution.
address MENTORING_CONTRACT
Address of the mentoring contract used for distributing mentor rewards.
This address must be a smart contract. It handles the distribution of mentor rewards, and interacts with the core protocol to facilitate appropriate rewards based on mentoring actions.
address DISTRIBUTOR_EOA
Externally Owned Account (EOA) address used as a backup for reward distribution in case the main contracts encounter issues.
This address must be an EOA (not a contract). It serves as a backup to handle reward distributions manually if either the staking or mentoring contract fails and is bypassed.
constructor(address distributorEOA_address, address stakingContract_address, address mentoringContract_address, address metaoraclyContract_address) public
Constructor to initialize the reward distributors and related contracts.
Validates the addresses for staking and mentoring contracts to ensure they are contracts and not EOAs.
Also validates that the distributorEOA_address
is an EOA and not a contract.
Name | Type | Description |
---|---|---|
distributorEOA_address | address | Address of the EOA used as a backup for reward distribution. |
stakingContract_address | address | Address of the staking contract for staking rewards. |
mentoringContract_address | address | Address of the mentoring contract for mentor rewards. |
metaoraclyContract_address | address | Address of the MetaOracly contract that handles oracle game data. |
function resolve(bytes32 roundid, uint80 exitPriceid) external
Resolves a prediction round by validating the Exit Price ID and determining the outcome.
This function resolves a prediction round, ensuring that the provided priceid corresponds to a valid Exit Price from the price feed.
- The function is protected against re-entrancy attacks via nonReentrant
modifier.
- It is restricted to off-chain callers EOA using the onlyOffChainCallable
modifier.
Emits:
- RoundResolvedNoContest
: If the round concludes with a “No Contest” outcome.
- RoundResolved
: If the round ends with a valid outcome: Down, Up, or Zero.
Name | Type | Description |
---|---|---|
roundid | bytes32 | The ID of the round that needs to be resolved. |
exitPriceid | uint80 | The ID of the Exit Price that is used to determine the final outcome of the round. |
function resolve4withdraw(bytes32 roundid, bytes32 predictionid, address erc20, uint80 exitPriceid) external
Resolves a prediction round and processes the withdrawal of the payout.
This function first resolves the specified round and prediction, based on the provided Exit Price.
It then facilitates the withdrawal of the payout in the specified ERC20 token.
- The function is protected against re-entrancy attacks via nonReentrant
modifier.
- It is restricted to off-chain callers EOA using the onlyOffChainCallable
modifier.
Emits:
- RoundResolvedNoContest
: If the round concludes with a “No Contest” outcome.
- RoundResolved
: If the round ends with a valid outcome: Down, Up, or Zero.
- FATAL_EVENT_INSUFFICIENT_PRIZEPOOL
if there are insufficient funds in the prize pool.
- PredictionClaimed
event emitted when a bettor claims the payout for prediction.
- RoundPrizepoolReleased
event on a successful prize pool release.
- RoundArchived
event once the round is archived.
- MentorsRewardDistributedViaContract
when mentor commission is successfully distributed via contract.
- MentorsRewardDistributedViaEOA
when mentor commission is distributed via EOA due to a fallback.
- StakersRewardDistributedViaContract
when staker commission is successfully distributed via contract.
- StakersRewardDistributedViaEOA
when staker commission is distributed via EOA due to a fallback.
Name | Type | Description |
---|---|---|
roundid | bytes32 | The ID of the prediction round to resolve. |
predictionid | bytes32 | The ID of the specific prediction within the round. |
erc20 | address | The address of the ERC20 token contract used for the withdrawal. |
exitPriceid | uint80 | The ID of the price point (exit price) used to resolve the prediction. |
function withdraw(bytes32 roundid, bytes32 predictionid, address erc20) external
Claims a payout based on the result of a prediction in a specific round, using the specified ERC20 token for withdrawal.
This function allows off-chain callers EOA to withdraw winnings from a prediction in a specific round, denominated in a given ERC20 token.
- The function is protected against re-entrancy attacks via nonReentrant
modifier.
- It is restricted to off-chain callers EOA using the onlyOffChainCallable
modifier.
Emits:
- FATAL_EVENT_INSUFFICIENT_PRIZEPOOL
if there are insufficient funds in the prize pool.
- MentorsRewardDistributedViaContract
when mentor commission is successfully distributed via contract.
- MentorsRewardDistributedViaEOA
when mentor commission is distributed via EOA due to a fallback.
- StakersRewardDistributedViaContract
when staker commission is successfully distributed via contract.
- StakersRewardDistributedViaEOA
when staker commission is distributed via EOA due to a fallback.
- PredictionClaimed
event emitted when a bettor claims the payout for prediction.
- RoundPrizepoolReleased
event on a successful prize pool release.
- RoundArchived
event once the round is archived.
Name | Type | Description |
---|---|---|
roundid | bytes32 | The ID of the round in which the prediction was made. |
predictionid | bytes32 | The ID of the specific prediction to claim the payout for. |
erc20 | address | The address of the ERC20 token to be used for the payout withdrawal. |
function placePrediction(uint256 amount, uint8 position, bytes32 gameid, bytes32 roundid) external
Places a prediction on the specified game and round.
This function allows off-chain callers EOA to place a prediction on a game round by depositing a certain amount of ERC20 tokens.
The bettor predicts an outcome (Down, Up, or Zero) for the given game and round.
Requirements:
- The amount
must be greater than zero.
- The position
must be one of the valid values (1 for Down, 2 for Up, 3 for Zero).
- The function is protected against re-entrancy attacks via nonReentrant
modifier.
- It is restricted to off-chain callers EOA using the onlyOffChainCallable
modifier.
Emits:
- RoundCreated
event upon successful creation of the round.
- RoundPrizepoolAdd
event to signal that the prize pool has been updated.
- PredictionCreated
event if a new prediction is created.
- IncreasePredictionDeposit
event if the bettor’s prediction is updated.
Name | Type | Description |
---|---|---|
amount | uint256 | The amount of ERC20 tokens the bettor deposits to place the prediction. |
position | uint8 | The predicted outcome for the game round. Valid values: (1 for Down, 2 for Up, 3 for Zero) |
gameid | bytes32 | The ID of the game where the prediction is being placed. |
roundid | bytes32 | The ID of the specific round within the game. |
modifier onlyOffChainCallable()
Restricts function execution to external accounts (EOA) only.
This modifier ensures that only EOAs (Externally Owned Accounts) can call functions protected by this modifier, preventing contracts from executing such functions.
The check is performed by verifying that the caller has no code associated with it (not a contract) and by comparing tx.origin
with _msgSender()
.
event FATAL_EVENT_INSUFFICIENT_PRIZEPOOL(address bettor, address erc20, uint256 balance, uint256 payout, uint256 commission)
Emitted when the contract’s prize pool is insufficient to cover both a bettor’s payout and the commission. This event signals a critical failure that effectively prevents the specified ERC20 token from being used as the deposit token for further predictions.
This is a fatal event that indicates the current prize pool cannot satisfy the requested payout and commission amounts.
Name | Type | Description |
---|---|---|
bettor | address | The address of the bettor attempting to withdraw the funds. |
erc20 | address | The ERC20 token involved in the payout and commission transaction. |
balance | uint256 | The current balance of the ERC20 token held in the contract. |
payout | uint256 | The payout amount requested by the bettor. |
commission | uint256 | The commission amount that is due to the contract. |
event MentorsRewardDistributedViaContract(address distributor, address bettor, address erc20, uint256 amount)
This event is emitted when a mentor’s reward is distributed via a smart contract.
This event captures the distribution of rewards to mentors based on the bettor’s activity. It logs the distributor (the smart contract handling the distribution), the bettor (the bettor whose activity triggered the reward), the ERC20 token used, and the reward amount.
Name | Type | Description |
---|---|---|
distributor | address | The address of the contract that is distributing the reward. |
bettor | address | The address of the bettor who generated the mentor’s reward. |
erc20 | address | The address of the ERC20 token contract used for distributing the reward. |
amount | uint256 | The amount of the reward in the ERC20 token. |
event MentorsRewardDistributedViaEOA(address distributor, address bettor, address erc20, uint256 amount)
Emitted when a mentor’s reward is distributed using an Externally Owned Account (EOA). This happens as a fallback mechanism when direct distribution through smart contracts is not possible.
This event is triggered whenever the mentor’s reward is sent via an EOA, in scenarios where automated reward distribution through the smart contract system fails and is bypassed. The mentor’s reward is distributed using an ERC20 token.
Name | Type | Description |
---|---|---|
distributor | address | The address of the EOA responsible for distributing the reward to the mentor. |
bettor | address | The address of the bettor whose activity generated the reward for the mentor. |
erc20 | address | The address of the ERC20 token contract used to transfer the reward. |
amount | uint256 | The amount of ERC20 tokens that are distributed as the reward. |
event StakersRewardDistributedViaContract(address distributor, address bettor, address erc20, uint256 amount)
Emitted when a staker’s reward is distributed through a contract.
This event logs the details of a reward distribution to stakers initiated by a contract.
Name | Type | Description |
---|---|---|
distributor | address | The address of the contract responsible for distributing the reward. |
bettor | address | The address of the bettor whose actions generated the reward for the stakers. |
erc20 | address | The ERC20 token used for the reward distribution. |
amount | uint256 | The total amount of the ERC20 reward distributed. |
event StakersRewardDistributedViaEOA(address distributor, address bettor, address erc20, uint256 amount)
Emitted when a staker’s reward is distributed via an Externally Owned Account (EOA). This event acts as a fallback mechanism when the reward distribution does not go through the primary method, triggering the involvement of an EOA.
This event provides a backup solution in cases where a direct reward transfer to the staking contract fails and is bypassed, allowing the reward to be manually handled by the EOA.
Name | Type | Description |
---|---|---|
distributor | address | The address of the EOA responsible for distributing the reward. |
bettor | address | The address of the bettor whose actions resulted in the reward. |
erc20 | address | The address of the ERC20 token used to pay out the reward. |
amount | uint256 | The amount of tokens (in the ERC20 standard) distributed as the reward. |
Core contract for handling prediction games, managing rounds, and calculating payouts.
Provides essential logic for creating and managing prediction rounds, fetching price data, determining outcomes, and distributing prize pools. This contract is abstract and should be inherited by other contracts like OraclyV1, which will handle bettor interactions and protocol logic. Key functionalities: - Creation of new prediction rounds. - Fetching and validation of price data from oracles. - Determination of winners based on price movements. - Calculation and distribution of prize pools among winning participants. Note: This contract integrated with secure price oracles like Chainlink for price feeds.
uint8 VIGORISH_PERCENT
The percentage taken as commission for stakers and mentors from the prize.
Vigorish is a commission applied to the prize. It is set as a constant 1%.
mapping(bytes32 => struct Prediction) _predictions
Mapping to store predictions for each round.
Maps a round ID (bytes32) to a specific Prediction object. This stores the predictions made by bettors for a particular round.
mapping(bytes32 => struct Round) _rounds
Mapping to store round information.
Maps a round ID (bytes32) to a specific Round object that holds all the relevant information for the round, such as start time, end time, and other metadata.
mapping(address => bool) __FATAL_INSUFFICIENT_PRIZEPOOL_ERROR__
Tracks ERC20 tokens that have triggered a fatal error due to insufficient funds in the prize pool.
This mapping stores a boolean flag for each ERC20 token address.
When the flag is set to true, it indicates that the corresponding token’s prize pool has insufficient funds, causing a fatal error.
Mapping:
- address
: The address of the ERC20 token contract.
- bool
: A flag where true
indicates a fatal insufficient prize pool error for that token.
address METAORACLY_CONTRACT
Immutable address of the MetaOracly contract, which serves as a registry of all games within the Oracly protocol.
This immutable variable stores the address of the MetaOracly contract. Once set, it cannot be modified, ensuring the integrity of the contract registry across the protocol. This contract registry allows interaction with all possible games on the protocol.
constructor(address metaoracly_address) internal
Initializes the OraclyV1Core contract by setting the MetaOracly contract address.
This constructor is essential as the MetaOracly contract acts as the source for retrieving game data, price feeds, and other relevant information critical to the OraclyV1Core functionality.
Name | Type | Description |
---|---|---|
metaoracly_address | address | The address of the MetaOracly contract that serves as the data provider for the game. |
function getPrediction(bytes32 predictionid) external view returns (struct Prediction prediction)
Fetches a specific Prediction
based on the provided prediction ID.
Returns a Prediction
struct that contains details about the prediction.
Useful for retrieving prediction information like the predicted outcome, amount deposited, and bettor details.
Name | Type | Description |
---|---|---|
predictionid | bytes32 | The unique ID of the prediction to retrieve. |
Name | Type | Description |
---|---|---|
prediction | struct Prediction | A Prediction struct containing details such as the prediction position, bettor, and deposited amount. |
function getRound(bytes32 roundid) external view returns (struct Round round, uint256[4] prizepools, uint256[4] bettors, uint256[4] predictions)
Retrieves details about a specific prediction round.
This function provides detailed information about a given round, including:
- Round data (Round
memory)
- Total prize pools for the round and individual outcomes [Total, Down, Up, Zero] (uint[4]
)
- Total number of bettors for the round and individual outcomes [Total, Down, Up, Zero] (uint[4]
)
- Total number of predictions for the round and individual outcomes [Total, Down, Up, Zero] (uint[4]
)
Requirements:
- The roundid
must be valid and correspond to an existing round.
Name | Type | Description |
---|---|---|
roundid | bytes32 | The unique identifier of the prediction round. |
Name | Type | Description |
---|---|---|
round | struct Round | Information about the round as a Round struct. |
prizepools | uint256[4] | Array of four uint values: [0]: Total deposited amount in the ERC20 token. [1]: Deposited amount for the Down outcome. [2]: Deposited amount for the Up outcome. [3]: Deposited amount for the Zero outcome. |
bettors | uint256[4] | Array of four uint values: [0]: Total number of participants in the round. [1]: Number of participants who predicted Down. [2]: Number of participants who predicted Up. [3]: Number of participants who predicted Zero. |
predictions | uint256[4] | Array of four uint values: [0]: Total number of predictions made. [1]: Number of predictions for Down. [2]: Number of predictions for Up. [3]: Number of predictions for Zero. |
function getGameRounds(bytes32 gameid, uint256 offset) external view returns (bytes32[] roundids, uint256 size)
Retrieves a paginated list of Round IDs for a specified game. This function is useful for fetching game round IDs in batches.
This function returns an array of round IDs and the total number of rounds associated with the given game. The returned array contains at most 20 round IDs starting from the specified offset to support pagination.
Name | Type | Description |
---|---|---|
gameid | bytes32 | The unique identifier for the game. |
offset | uint256 | The starting index from which round IDs will be fetched (for pagination). |
Name | Type | Description |
---|---|---|
roundids | bytes32[] | An array of up to 20 round IDs starting from the given offset. |
size | uint256 | The total number of rounds in the game, which is helpful for paginating through all rounds. |
function getRoundPredictions(bytes32 roundid, uint8 position, uint256 offset) external view returns (struct Prediction[] predictions, uint256 size)
Retrieves a paginated list of predictions for a specific round and position.
Returns up to 20 Prediction
structs starting from the specified offset
.
If position
is set to 0, predictions for all positions are retrieved.
Also returns the total number of predictions matching the criteria.
Name | Type | Description |
---|---|---|
roundid | bytes32 | The unique identifier for the round to retrieve predictions from. |
position | uint8 | The prediction position to filter by (1 for Down, 2 for Up, 3 for Zero). A value of 0 retrieves predictions for all positions. |
offset | uint256 | The starting index for pagination. Use this to fetch predictions in batches. |
Name | Type | Description |
---|---|---|
predictions | struct Prediction[] | An array of Prediction structs representing the matching predictions. |
size | uint256 | The total number of predictions available for the specified round and position. |
function getBettorPredictions(address bettor, uint8 position, uint256 offset) external view returns (struct Prediction[] predictions, uint256 size)
Retrieves a paginated list of a bettor’s predictions for a specific position.
Returns up to 20 Prediction
structs starting from the specified offset
.
If position
is set to 0, predictions for all positions are retrieved.
Also returns the total number of predictions matching the criteria.
Name | Type | Description |
---|---|---|
bettor | address | The address of the bettor whose predictions are being queried. |
position | uint8 | The predicted outcome (1 for Down, 2 for Up, 3 for Zero). A value of 0 retrieves predictions for all positions. |
offset | uint256 | The starting index for pagination of the results. |
Name | Type | Description |
---|---|---|
predictions | struct Prediction[] | An array of Prediction structs limited to 20 entries. |
size | uint256 | The total number of predictions for the bettor and specified position. |
function isBettorInRound(address bettor, bytes32 roundid) external view returns (bool inround)
Checks whether a specific bettor has participated in a given round. This function is used to verify if the bettor has placed a prediction in the provided round.
This function checks participation in a specific prediction round using the bettor’s address and the unique round ID.
Name | Type | Description |
---|---|---|
bettor | address | The address of the bettor to check for participation. |
roundid | bytes32 | The unique identifier of the round. |
Name | Type | Description |
---|---|---|
inround | bool | true if the bettor participated in the round, false otherwise. |
function getBettor(address bettor, address erc20) external view returns (address bettorid, uint256[4] predictions, uint256[4] deposits, uint256[4] payouts)
Retrieves information about a specific bettor’s activity for a given ERC20 token.
This function provides detailed information about the bettor’s predictions, including:
- Bettor’s address (bettorid
) if found.
- Total number of predictions and individual outcomes [Total, Up, Down, Zero] (uint[4]
).
- Total deposited amounts for predictions and individual outcomes [Total, Up, Down, Zero] (uint[4]
).
- Total payouts received for predictions and individual outcomes [Total, Up, Down, Zero] (uint[4]
).
- If bettor
have never interacted with the provided erc20
token for predictions deposits and payouts returns zeros.
- If bettor
have never interacted with the cotract it returns zeros.
Name | Type | Description |
---|---|---|
bettor | address | The address of the bettor to query. |
erc20 | address | The address of the ERC20 token used for the bettor’s predictions. |
Name | Type | Description |
---|---|---|
bettorid | address | The address of the bettor (or zero address if no predictions are found). |
predictions | uint256[4] | Array of four uint values: [0]: Total number of predictions made. [1]: Number of predictions for Up. [2]: Number of predictions for Down. [3]: Number of predictions for Zero. |
deposits | uint256[4] | Array of four uint values: [0]: Total amount deposited using the ERC20 token. [1]: Amount deposited for Up predictions. [2]: Amount deposited for Down predictions. [3]: Amount deposited for Zero predictions. |
payouts | uint256[4] | Array of four uint values: [0]: Total payout amount received for the ERC20 token. [1]: Payout amount received for Up predictions. [2]: Payout amount received for Down predictions. [3]: Payout amount received for Zero predictions. |
function _updatePrediction(struct Game game, bytes32 roundid, uint8 position, uint256 amount, address bettor) internal
Updates the bettor’s prediction or creates a new one if it doesn’t exist for the current game round.
This function handles both creating new predictions and updating existing ones.
It adjusts the bettor’s token deposit for their prediction and ensures that internal mappings remain consistent.
It also emits an event when a prediction is created or updated.
Requirements:
- The bettor’s address must not be zero.
- amount
must be greater than zero.
Emits:
- PredictionCreated
event if a new prediction is created.
- IncreasePredictionDeposit
event if the bettor’s prediction is updated.
Name | Type | Description |
---|---|---|
game | struct Game | The game structure associated with the prediction. |
roundid | bytes32 | The unique identifier of the round within the game. |
position | uint8 | The predicted outcome for the round (1 for Down, 2 for Up, 3 for Zero). |
amount | uint256 | The amount of tokens being deposited for the prediction. |
bettor | address | The address of the bettor making the prediction. |
function _updateRound(struct Game game, bytes32 roundid, uint8 position, uint256 amount) internal
Updates a round’s state by creating a new round if necessary and updating its prize pool.
This function checks if the round already exists; if not, it initializes a new round.
Then, based on the provided position and amount, it increments the respective prize pool.
The position represents the bettor’s predicted price movement direction (1 for Down, 2 for Up, 3 for Zero) within the round.
The prize pool is updated accordingly based on the amount wagered for the specified position.
Emits:
- RoundCreated
event upon successful creation of the round.
- RoundPrizepoolAdd
event to signal that the prize pool has been updated.
Name | Type | Description |
---|---|---|
game | struct Game | The struct representing the game associated with the round. |
roundid | bytes32 | The unique identifier for the round to be updated. |
position | uint8 | The prediction position chosen by the bettor (1 for Down, 2 for Up, 3 for Zero). |
amount | uint256 | The amount of tokens being wagered on the position. |
function _isResolved(bytes32 roundid) internal view returns (bool resolved)
Checks whether a specific prediction round has been resolved.
This function checks the status of a round using its unique ID.
It is marked as internal
, so it can only be accessed within this contract or derived contracts.
The status of resolution implies that the round’s outcome have been settled.
Name | Type | Description |
---|---|---|
roundid | bytes32 | The unique identifier (ID) of the round to check. |
Name | Type | Description |
---|---|---|
resolved | bool | Returns true if the round is resolved, meaning outcome have been settled, otherwise returns false . |
function _resolve(bytes32 roundid, uint80 exitPriceid) internal
Resolves an round by determining the final outcome based on the provided exit price.
This function calculates the outcome of a prediction round using the given exitPriceid
, which must be fetched from an external oracle.
Possible outcomes:
- Down: The outcome is resolved as “Down” if the Exit Price
is lower than the Entry Price
. This indicates a price decrease during the round.
- Up: The outcome is resolved as “Up” if the Exit Price
is higher than the Entry Price
, indicating a price increase during the round.
- Zero: The outcome is resolved as “Zero” if the Exit Price
is equal to the Entry Price
- No Contest: All participants predicted the same outcome (either all Up, all Down, or all Zero), making it impossible to determine winners.
- No Contest: None of the participants correctly predicted the outcome.
- No Contest: The round was not resolved within the allowed time limit.
This function permanently finalizes the state of the round and should only be called when the round is in settlement phase and unresolved.
Requirements:
- The round must be unresolved state.
- The exitPriceid
must be valid and Exit Price
from the oracle.
Emits:
- RoundResolvedNoContest
: If the round concludes with a “No Contest” outcome.
- RoundResolved
: If the round ends with a valid outcome: Down, Up, or Zero.
Name | Type | Description |
---|---|---|
roundid | bytes32 | The unique identifier of the round being resolved. |
exitPriceid | uint80 | The ID representing the price used to determine the final outcome of the round. |
function _computeRoundid(uint16 phaseId, uint64 aggregatorRoundId) internal pure returns (uint80 roundId)
Computes a unique round ID by combining a phase ID with an aggregator round ID. This ensures that the round ID is unique across different phases of the price feed aggregator.
The round ID is computed by shifting the 16-bit phaseId
left by 64 bits and then adding the 64-bit aggregatorRoundId
.
This results in a single 80-bit value representing the unique round ID.
The left shift ensures that the phaseId
occupies the higher bits and does not overlap with the aggregatorRoundId
.
Name | Type | Description |
---|---|---|
phaseId | uint16 | The 16-bit ID representing the phase of the price feed aggregator. Each phase consists of multiple rounds. |
aggregatorRoundId | uint64 | The 64-bit round ID provided by the underlying price feed aggregator for a specific phase. |
Name | Type | Description |
---|---|---|
roundId | uint80 | A unique 80-bit round ID that is a combination of the phase and aggregator round IDs. |
function _claimPrediction(bytes32 roundid, bytes32 predictionid, address erc20) internal returns (uint256 payout, uint256 commission)
Claims the payout for a bettor’s prediction in a specific round with a given ERC20 token.
This function ensures that all necessary checks are performed before allowing a claim:
- Verifies that claimd ERC20 matches round ERC20 address.
- Ensures the provided prediction ID related the round ID.
- Checks that the prediction is associated with the round.
- Confirms the caller is the original bettor who made the prediction.
- Ensures the prediction hasn’t already been claimed.
- Validates that the round has been resolved.
- Confirms that the prediction’s position matches the final resolution of the round or handles a “No Contest” scenario.
If all validations pass, the function calculates the payout and the commission, updates the prediction’s status to claimed, and returns both the payout and commission values.
Emits:
- PredictionClaimed
event emitted when a bettor claims the payout for prediction.
- RoundPrizepoolReleased
event on a successful prize pool release.
- RoundArchived
event once the round is archived.
Name | Type | Description |
---|---|---|
roundid | bytes32 | The unique identifier of the round to which the prediction belongs. |
predictionid | bytes32 | The unique identifier of the prediction for which the payout is claimed. |
erc20 | address | The address of the ERC20 token in which the payout is requested. |
Name | Type | Description |
---|---|---|
payout | uint256 | The amount awarded to the bettor based on the prediction. |
commission | uint256 | The commission deducted from the payout for stakers and mentors. |
event RoundResolvedNoContest(bytes32 roundid, address resolvedBy, uint256 resolvedAt, uint8 resolution)
Emitted when a round is resolved as a “No Contest”, allowing participants to reclaim their funds.
This event is triggered when the outcome of a round cannot be determined due to conditions that prevent a clear resolution.
Name | Type | Description |
---|---|---|
roundid | bytes32 | The unique identifier of the round that has been resolved as “No Contest”. |
resolvedBy | address | The address of the EOA that initiated the resolution of the round. |
resolvedAt | uint256 | The Unix timestamp at which the round was resolved. |
resolution | uint8 | The constant value representing the “No Contest” outcome, a predefined value (4 for No Contest). |
event RoundResolved(bytes32 roundid, struct Price exitPrice, address resolvedBy, uint256 resolvedAt, uint8 resolution)
Emitted when a prediction round is resolved and its outcome is determined.
This event logs important information about the resolution of a round, including the round ID, the exit price, the bettor who triggered the resolution, and the final outcome of the round.
Name | Type | Description |
---|---|---|
roundid | bytes32 | The unique identifier of the resolved prediction round. |
exitPrice | struct Price | The price used to calculate the result of the round, fetched from Chainlink’s price feed. |
resolvedBy | address | The address of the bettor that triggered the resolution of the round. |
resolvedAt | uint256 | The timestamp (in seconds) when the round was resolved. |
resolution | uint8 | The outcome of the round: (1 for Down, 2 for Up, 3 for Zero) |
event RoundArchived(bytes32 roundid, uint256 archivedAt)
This event logs the archival of the round, marking the end of the round’s lifecycle.
Emitted when a round is archived.
Name | Type | Description |
---|---|---|
roundid | bytes32 | The unique identifier of the archived round. |
archivedAt | uint256 | The timestamp when the round was archived. |
event RoundCreated(bytes32 roundid, bytes32 gameid, address openedBy, address erc20, address pricefeed, struct Price entryPrice, uint256 startDate, uint256 lockDate, uint256 endDate, uint256 expirationDate, uint256 openedAt)
Emitted when a new prediction round is created.
This event indicates the creation of a new prediction round within the ongoing game. It includes essential details such as the round ID, associated game, the ERC20 token for predictions, the price feed contract for asset price, and the timestamps defining round phases.
Name | Type | Description |
---|---|---|
roundid | bytes32 | The unique identifier of the created round. |
gameid | bytes32 | The unique identifier of the game to which the round is linked. |
openedBy | address | The address of the entity EOA that initiated the round creation. |
erc20 | address | The address of the ERC20 token contract used for placing predictions in the round. |
pricefeed | address | The address of the price feed contract used to retrieve the asset price for predictions. |
entryPrice | struct Price | The initial price of the asset at the start of the round, retrieved from the price feed. |
startDate | uint256 | The timestamp (in seconds since Unix epoch) when the round starts. |
lockDate | uint256 | The timestamp when the prediction phase ends and no more entries can be placed. |
endDate | uint256 | The timestamp when the round ends and the outcome of the price movement can be determined. |
expirationDate | uint256 | The deadline timestamp by which the round must be settled, or else it defaults to ‘No Contest’. |
openedAt | uint256 | The timestamp when the round was created (when first prediction entered the round). |
event RoundPrizepoolAdd(bytes32 roundid, address erc20, uint8 position, uint256 amount)
Emitted when funds are added to a specific position’s prize pool for a given round. This event tracks the addition of tokens to a prize pool, which is associated with a particular round and a specific position (Down, Up, Zero).
The position can have three possible values: (1 for Down, 2 for Up, 3 for Zero)
Name | Type | Description |
---|---|---|
roundid | bytes32 | The ID of the round to which the prize pool is associated. |
erc20 | address | The address of the ERC20 token that is being added to the prize pool. |
position | uint8 | The position (Down, Up, or Zero) in the prize pool where the tokens are added. |
amount | uint256 | The amount of tokens being added to the prize pool for the given position. |
event RoundPrizepoolReleased(bytes32 roundid, uint256 payout, uint256 commission)
Emitted when funds are released to a bettor for a given round. This event tracks the release of tokens from the prize pool for a particular round, including the bettor’s payout and any commission.
The payout
includes the bettor’s share of the prize pool, which is calculated proportional to their contribution.
The commission
is a amount deducted from the prize, which is allocated to stakers and mentors.
The event helps to audit the flow of funds for transparency and tracking of prize distribution.
Name | Type | Description |
---|---|---|
roundid | bytes32 | The ID of the round from which the funds are being released. |
payout | uint256 | The total payout being released to the bettor, after deducting the commission. |
commission | uint256 | The commission amount deducted from the prize, allocated to stakers and mentors. |
event PredictionCreated(bytes32 predictionid, bytes32 roundid, address bettor, uint8 position, uint256 createdAt, address erc20, bytes32 gameid)
Emitted when a new prediction is created in the game.
This event is triggered whenever a bettor makes a new prediction. It logs the details such as the round, bettor’s address, and the prediction outcome.
Name | Type | Description |
---|---|---|
predictionid | bytes32 | The unique identifier of the created prediction. |
roundid | bytes32 | The ID of the round the prediction belongs to. |
bettor | address | The address of the bettor who created the prediction. |
position | uint8 | The predicted outcome. (1 for Down, 2 for Up, 3 for Zero) |
createdAt | uint256 | The timestamp (in seconds since the Unix epoch) when the prediction was created. |
erc20 | address | The address of the ERC20 token used as deposit for the prediction. |
gameid | bytes32 | The ID of the game instance that the prediction is associated with. |
event IncreasePredictionDeposit(bytes32 predictionid, uint256 deposit)
Emitted when a bettor deposits tokens within the round.
This event is emitted every time a bettor deposits tokens, either by creating a new prediction or increasing an existing one.
Name | Type | Description |
---|---|---|
predictionid | bytes32 | The unique identifier (ID) of the prediction being created or increased. |
deposit | uint256 | The amount of tokens deposited. |
event PredictionClaimed(bytes32 predictionid, address bettor, address erc20, uint256 payout, uint256 commission)
Emitted when a bettor claims the payout for prediction.
This event is triggered when a prediction is successfully claimed, detailing the bettor, payout, and commission.
Name | Type | Description |
---|---|---|
predictionid | bytes32 | The unique identifier of the claimed prediction. |
bettor | address | The address of the bettor who is claiming the prediction payout. |
erc20 | address | The ERC20 token used for both the payout and the commission. |
payout | uint256 | The amount of tokens paid out to the bettor as a reward for the prediction. |
commission | uint256 | The amount of tokens deducted from the payout as commission. |
Serves as the main control point for creating and managing games within the Oracly Protocol.
Provides the Oracly Team with the ability to block abused or manipulated games. Game Registry: Maintains a list of active games along with their parameters (schedule, price feed address). Game Creation: Allows authorized users (the Oracly Team) to create and configure new games. Game Blocking: Enables the Oracly Team to block specific games in case of suspected manipulation or technical issues. IMPORTANT: If a Game is blocked, any Rounds with Unverified Outcomes will automatically be treated as No Contest.
uint256 SHORTEST_ROUND
Defines the minimum duration a round can last.
This constant represents the shortest possible round duration in the game, set to 1 minute.
uint256 SHORTEST_POSITIONING
Defines the minimum time required for the positioning phase within a round.
This constant ensures the positioning phase lasts for at least 30 seconds.
uint256 SHORTEST_EXPIRATION
Defines the minimum time before a round can expire after it ends.
This constant enforces a minimum round expiration time of 1 hour.
uint256 LONGEST_EXPIRATION
Defines the maximum time before a round can expire after it ends.
This constant enforces a maximum expiration time of 7 days for any round.
constructor() public
The deployer of this contract will automatically be assigned as the contract owner (Oracly Team), who has the privilege to manage game creation, blocking and unblocking the game.
Initializes the contract by setting the deployer as the initial owner (Oracly Team).
function addGame(address pricefeed, address erc20, uint16 version, uint256 schedule, uint256 positioning, uint256 expiration, uint256 minDeposit) external
Adds a new game to the Oracly Protocol, linking it to a Chainlink price feed and an ERC20 token for deposits and payouts. Can only be called by the contract owner (Oracly Team).
This function registers a new game configuration with specified parameters, including the price feed, token, game logic version, and timing rules for rounds.
Requirements:
- Caller must be the contract owner (Oracly Team) (enforced via onlyOwner
modifier).
Emits a GameAdded
event when a new game is successfully added.
Name | Type | Description |
---|---|---|
pricefeed | address | The address of the Chainlink price feed used to provide pricing data feed for the game. |
erc20 | address | The address of the ERC20 token used for both deposits and payouts in the game. |
version | uint16 | The version of the Oracly game logic, useful for compatibility and updates. |
schedule | uint256 | The interval in seconds between rounds of the game (e.g., 300 for 5 minutes). |
positioning | uint256 | The duration in seconds for the positioning phase, where bettors place predictions. |
expiration | uint256 | The duration in seconds after which the round expires, and only withdraw deposit actions are allowed. |
minDeposit | uint256 | The minimum deposit required to participate in the round, denoted in the ERC20 token. |
function getActiveGames(address erc20, uint256 offset) external view returns (struct Game[] games, uint256 size)
Retrieves a list of active games that use a specific ERC20 token.
This function returns a paginated list of active Game
structs that utilize the specified ERC20 token.
The results can be fetched using the provided offset
for pagination.
Name | Type | Description |
---|---|---|
erc20 | address | The address of the ERC20 token being used by the games. |
offset | uint256 | The starting index for pagination of active games. |
Name | Type | Description |
---|---|---|
games | struct Game[] | An array of Game structs representing the active games using the given ERC20 token. |
size | uint256 | The total number of active games using the specified ERC20 token. |
function getGame(bytes32 gameid) external view returns (struct Game game)
Retrieves the details of a specific game based on its unique identifier.
This function fetches the game details from internal storage using the provided game ID. The game details include all the relevant information about a specific prediction game.
Name | Type | Description |
---|---|---|
gameid | bytes32 | The unique identifier for the game, represented as a bytes32 value. |
Name | Type | Description |
---|---|---|
game | struct Game | A Game struct containing the metadata of the requested game. |
function unblockGame(bytes32 gameid) external
Unblocks a previously blocked game, allowing it to resume normal operation.
Unblocking a game restores its availability for bettors and enables gameplay to continue.
Can only be called by the contract owner (Oracly Team).
Emits a GameUnblocked
event upon successful execution.
Requirements:
- The game must be in a blocked state.
- Can only be called by the contract owner.
Name | Type | Description |
---|---|---|
gameid | bytes32 | The unique identifier of the game to be unblocked. |
function blockGame(bytes32 gameid) external
Blocks a game, preventing new prediction rounds from being initiated and marking unresolved rounds as impacted.
Blocks the specified game, ensuring no new rounds are created and impacting any currently unresolved rounds.
Emits a GameBlocked
upon successful blocking.
Requirements:
- This function can only be called by the contract owner (Oracly Team).
- The game must exist and not already be blocked.
Name | Type | Description |
---|---|---|
gameid | bytes32 | The unique identifier of the game to block. |
event GameAdded(bytes32 gameid, address pricefeed, address erc20, uint16 version, uint256 schedule, uint256 positioning, uint256 expiration, uint256 minDeposit)
This event is emitted when a new game is added to the Oracly Protocol.
Captures important parameters such as the Chainlink price feed, ERC20 token used, game version, and round timing details.
Name | Type | Description |
---|---|---|
gameid | bytes32 | The unique identifier of the newly added game, used for tracking purposes. |
pricefeed | address | The address of the Chainlink price feed used to provide external data for the game. |
erc20 | address | The address of the ERC20 token used for both deposits and payouts in the game. |
version | uint16 | The version of the Oracly game logic, useful for compatibility and updates. |
schedule | uint256 | The interval in seconds between rounds of the game (e.g., 300 for 5 minutes). |
positioning | uint256 | The duration in seconds for the positioning phase, where bettors place predictions. |
expiration | uint256 | The duration in seconds after which the round expires, and only withdraw deposit actions are allowed. |
minDeposit | uint256 | The minimum deposit required to participate in the round, denoted in the ERC20 token. |
event GameBlocked(bytes32 gameid)
This event is emitted when a game is blocked by the Oracly team. It can signal to external systems or users that a game is no longer available for participation or prediction.
Emitted when a game is blocked by the Oracly Team due to unforeseen issues, violations, or any other reasons defined within the protocol.
Name | Type | Description |
---|---|---|
gameid | bytes32 | The unique identifier of the blocked game. |
event GameUnblocked(bytes32 gameid)
This event is emitted when a previously blocked game is unblocked by the Oracly Team.
Emitted when a previously blocked game is unblocked.
Name | Type | Description |
---|---|---|
gameid | bytes32 | The unique identifier of the game that has been unblocked. |
Represents a series of prediction rounds where bettors predict cryptocurrency price movements for a chance to win rewards.
The struct defines key parameters for a game instance, including the price feed, token used for rewards, and schedule details.
- gameid
This is a hashed value of main properites representing the game ID.
- pricefeed
The price feed provides cryptocurrency price data for bettors to make predictions.
- erc20
Participants deposit this token to join the game, and rewards are distributed in the same token.
- version
Tracks the version of the game to differentiate between various game variants.
- scheduled
Specifies the start time of the game, which is set during initialization.
- positioning
Defines the time period before the game locks in which bettors can position their predictions.
- expiration
The time at which the round expires after it ends, and only withdraw deposit actions are allowed.
- minDeposit
Specifies the smallest amount of ERC20 tokens that a bettor must deposit to enter the game.
- blocked
If set to true, the game is blocked and no new actions (such as placing predictions) can be taken.
struct Game {
bytes32 gameid;
address pricefeed;
address erc20;
uint16 version;
uint256 schedule;
uint256 positioning;
uint256 expiration;
uint256 minDeposit;
bool blocked;
}
Represents a self-contained prediction contest where bettors predict whether the price of a selected asset will go Down, Up, or remain the same (Zero) within a short timeframe.
Rounds progress through several distinct phases:
- Entry (Positioning): Bettors can place predictions starting at startDate
and ending at lockDate
.
- Round: Begins at lockDate
and ends at endDate
.
- Settlement: Starts at endDate
and ends either when the outcome is settled or at expirationDate
. If not resolved by expirationDate
, the round defaults to “No Contest”.
- Payout: Begins at resolvedAt
and ends either when the last prediction is claimed at archivedAt
.
- Archive: Starts at archivedAt
and is considered the final phase; no further actions can be taken on the round.
Bettors with matching predictions share the prize pool proportionally to their deposit.
- roundid
This is a hashed value representing the round ID.
- gameid
Links the round to a specific game instance.
- resolution
This value reflects the round’s outcome. (0 for Undefined, 1 for Down, 2 for Up, 3 for Zero, 4 for No Contest)
- entryPrice
The price of the selected asset at the round’s opening, used for determining the outcome.
- exitPrice
The price of the selected asset by the round’s end time to determine the actual price movement.
- startDate
Bettors can place predictions once the round has started.
- lockDate
Bettors must submit predictions before this time. After this, no new entries are allowed.
- endDate
The round ends at this time, and price movement can be evaluated.
- expirationDate
After this date, unresolved rounds default to “No Contest”.
- resolved
This is true if the round outcome has been settled.
- resolvedAt
This indicates when the round’s outcome was settled.
- openedAt
Indicates when first bettor entered the round.
- erc20
Bettors use this token for betting and receiving payouts.
- pricefeed
The price feed provides the entry and exit prices used to determine the outcome.
- archived
Once a round is archived, no further actions can be performed on the round.
- archivedAt
This timestamp is recorded when the archived
status is set to true, marking the end of the round’s lifecycle.
struct Round {
bytes32 roundid;
bytes32 gameid;
uint8 resolution;
struct Price entryPrice;
struct Price exitPrice;
uint256 startDate;
uint256 lockDate;
uint256 endDate;
uint256 expirationDate;
bool resolved;
uint256 resolvedAt;
uint256 openedAt;
address erc20;
address pricefeed;
bool archived;
uint256 archivedAt;
}
Represents a bettor’s choice of outcome (Down, Up, Zero) in a prediction game round.
If the bettor’s prediction aligns with the actual price change, they win a share of the prize pool.
- predictionid
This is a hashed value representing the prediction ID.
- roundid
Refers to the specific round within the game.
- gameid
Links the prediction to a specific game instance.
- bettor
Represents the bettor’s wallet address.
- position
This is an unit8
where (1 for Down, 2 for Up, 3 for Zero).
- deposit
This variable stores the value of the deposit for the prediction in the current round.
- claimed
This is true if the bettor has successfully claimed their payout after winning.
- createdAt
Records when the bettor made their prediction.
- payout
This is the amount the bettor receives from the prize pool upon winning.
- commission
The commission represents the amount deducted and allocated to stakers and mentors on a winning prediction.
- erc20
Bettors use this token for betting and receiving rewards in the game.
struct Prediction {
bytes32 predictionid;
bytes32 roundid;
bytes32 gameid;
address bettor;
uint8 position;
uint256 deposit;
bool claimed;
uint256 createdAt;
uint256 payout;
uint256 commission;
address erc20;
}
Represents a price point from the Chainlink price feed, including the value, timestamp, and round ID.
Each price point consists of the value, the timestamp when the price was updated, and the Chainlink round ID.
- value
This represents the price data from the Chainlink price feed.
- timestamp
Represents the time when the price was updated on the Chainlink feed.
- roundid
The round ID provides context on which round the price data was fetched from.
struct Price {
int256 value;
uint256 timestamp;
uint80 roundid;
}
Enum representing the possible outcomes of a prediction round in the game.
Bettors predict whether the price of a selected asset will go Down, Up, or remain the same (Zero).
Undefined
: Value is the initial state when the outcome is unknown.
No Contest
:
- All participants predicted the same outcome (either all Up, all Down, or all Zero), making it impossible to determine winners.
- None of the participants correctly predicted the outcome.
- The round was not resolved within the allowed time limit.
enum EOutcome {
Undefined,
Down,
Up,
Zero,
NoContest
}
This contract manages multiple aspects of staking, including: - Epoch Management: Handles the creation and lifecycle of staking epochs, ensuring structured reward distribution cycles. - Deposit Tracking: Manages both pending and active staking deposits, providing transparency about stakers’ locked amounts and statuses. - Reward Mechanics: Calculates staking rewards per epoch based on deposited ORCY token amounts automatically. - Buy4Stake: Allows stakers to acquire ORCY tokens directly for staking through the Buy4Stake process.
This contract implements staking functionality for the Oracly Protocol, allowing ORCY token holders to lock tokens in return for staking rewards.
Stakers can claim rewards for each epoch through which their deposit was Staked
or in Pending Unstake
status.
The contract uses the Ownable pattern to restrict administrative functions and the ReentrancyGuard to protect against reentrancy attacks.
It also implements the ICommissionCollector interface to manage reward distribution mechanisms.
Stakers can stake ORCY tokens, claim rewards, and withdraw their stake.
uint32 SCHEDULE
The duration of one staking epoch in days.
A staking epoch is fixed at 7 days. This constant used to calculate staking period durations.
bool __FATAL_INSUFFICIENT_STAKEFUNDS_ERROR__
Signals a fatal error caused by insufficient stake funds in the staking pool.
This flag is set to true when the staking pool lacks sufficient funds to continue normal operations. Once active, it blocks new staking actions, although existing stakes will continue to accrue rewards. This is a critical safeguard to prevent the system from allowing additional stakes into a compromised stake pool.
mapping(address => bool) __FATAL_INSUFFICIENT_REWARDFUNDS_ERROR__
Tracks whether a fatal error has occurred for specific ERC20 tokens due to insufficient reward funds.
This mapping records a boolean flag for each ERC20 token address, indicating if the reward pool has encountered a critical shortage of funds.
The flag is set to true
when the system detects that there are insufficient ERC20 tokens available to fulfill reward obligations.
Once set, the system prevents the token from being used for reward accumulation by the contract to avoid further depletion and losses.
The flag signals the necessity for manual intervention by an external authorized entity (EOA) to handle reward distribution.
Existing rewards will still be distributed, but no new rewards can be accumulated for this token.
address STAKING_ERC20_CONTRACT
The address of the ERC20 contract used as staking tokens. (ORCY)
This is an immutable address, meaning it is set once at contract deployment and cannot be changed.
address AUTHORIZED_COMMISSION_GATHERER
The address of the authorized funds gatherer for the contract.
This is the address responsible for gathering staking rewards from the bettor’s prize on withdrawal and passing them to the contract for further distribution to stakers.
address BUY_4_STAKE_ERC20_CONTRACT
The address of the ERC20 contract used in the Buy4Stake process, enabling participants to acquire ORCY tokens at a 1:1 exchange rate.
The Buy4Stake mechanism uses this ERC20 token as a base for participants to purchase and stake ORCY tokens.
uint256 ACTUAL_EPOCH_ID
Tracks the current epoch ID used in the staking contract.
This value increments with the beginning of each new staking epoch. It starts at a phantom epoch ‘0’, meaning no staking epochs have been initiated yet. The epoch ID is used in various staking operations to identify the current staking epoch.
uint256 BUY_4_STAKEPOOL
Tracks the total amount of ORCY tokens available for the Buy4Stake pool.
The Buy4Stake pool allows users to purchase ORCY tokens at a 1:1 rate and automatically stake them in a single transaction. This variable represents the total funds currently allocated in the Buy4Stake pool.
constructor(address erc20, address b4s_erc20) public
The provided addresses for the staking token (erc20
) and Buy4Stake token (b4s_erc20
) must be valid contract addresses and have non-zero total supplies.
The contract deployer is assigned as the owner of this contract.
Initializes the StakingOraclyV1 contract with the given ERC20 token addresses for staking and Buy4Stake mechanisms. This constructor ensures that both token addresses are valid and sets the deployer (Oracly Team) as the owner.
Name | Type | Description |
---|---|---|
erc20 | address | The address of the ERC20 token to be used for staking. It must be a valid ERC20 token contract and have a non-zero total supply. |
b4s_erc20 | address | The address of the Buy4Stake ERC20 token. It must be a valid ERC20 token contract and have a non-zero total supply. |
function getStakeOf(address staker) external view returns (uint256 stakeof)
Retrieves the current active stake amount for a given staker.
This function calculates the active stake of a staker by subtracting the total unstaked amount from the total staked amount.
Name | Type | Description |
---|---|---|
staker | address | The address of the staker whose active stake is being queried. |
Name | Type | Description |
---|---|---|
stakeof | uint256 | The amount of active stake held by the staker. |
function getStakerDeposits(address staker, uint256 offset) external view returns (struct Deposit[] deposits, uint256 size)
Retrieves a paginated list of deposits made by a specific staker. This function helps avoid gas limitations when querying large data sets by allowing the retrieval of deposits in smaller batches (up to 20 deposits per call).
Implements pagination to efficiently retrieve a manageable number of deposits in each query.
It returns a maximum of 20 deposits per call, starting from the specified offset
.
Name | Type | Description |
---|---|---|
staker | address | The address of the staker whose deposits are being queried. |
offset | uint256 | The starting index for pagination, allowing retrieval of deposits starting from that point. |
Name | Type | Description |
---|---|---|
deposits | struct Deposit[] | An array of Deposit structs representing the staker’s deposits within the specified range. |
size | uint256 | The total number of deposits made by the staker, regardless of pagination. |
function getStakerPaidout(address staker, address erc20) external view returns (uint256 paidout)
Returns the total amount that has been paid out to a specific staker for a given ERC20 token across all staking rewards.
This function provides a read-only view of the total accumulated payouts for a staker across all deposits in the specified ERC20 token.
Name | Type | Description |
---|---|---|
staker | address | The address of the staker whose accumulated payouts are being queried. |
erc20 | address | The address of the ERC20 token contract for which the payout is being queried. |
Name | Type | Description |
---|---|---|
paidout | uint256 | The total amount paid out to the staker in the specified ERC20 token. |
function getDepositPaidout(bytes32 depositid, address erc20) external view returns (uint256 paidout)
Retrieves the total amount paid out for a specific deposit and ERC20 token.
This function provides a view into the accumulated payouts for a specific deposit across all staking epochs for a given ERC20 token.
Name | Type | Description |
---|---|---|
depositid | bytes32 | The unique identifier of the deposit for which the payout is being queried. |
erc20 | address | The address of the ERC20 token corresponding to the payout. |
Name | Type | Description |
---|---|---|
paidout | uint256 | The total amount that has been paid out for the specified deposit in the given ERC20 token. |
function getDepositEpochPaidout(bytes32 depositid, address erc20, uint256 epochid) external view returns (uint256 paidout)
Retrieves the total amount already paid out for a given deposit, ERC20 token, and epoch.
This function provides a view into the accumulated payouts for a specific deposit in a particular epoch and for a specific ERC20 token.
Name | Type | Description |
---|---|---|
depositid | bytes32 | The unique identifier of the deposit for which the payout is being queried. |
erc20 | address | The address of the ERC20 token for which the payout is being queried. |
epochid | uint256 | The identifier of the epoch for which the payout is being checked. |
Name | Type | Description |
---|---|---|
paidout | uint256 | The total amount paid out for the specified deposit, ERC20 token, and epoch. |
function getDeposit(bytes32 depositid) external view returns (struct Deposit deposit)
Retrieves the details of a specific deposit identified by depositid
.
Fetches a Deposit
struct containing details about the deposit, such as the staker’s address, the amount deposited, entry epoch.
Name | Type | Description |
---|---|---|
depositid | bytes32 | The unique identifier of the deposit. |
Name | Type | Description |
---|---|---|
deposit | struct Deposit | The Deposit struct containing the relevant information associated with the given depositid . |
function getEpoch(uint256 epochid, address erc20) external view returns (struct Epoch epoch, uint256[3] stakes, uint256[3] stakepool, uint256[2] rewards)
Retrieves full information about a specific staking epoch.
This function provides a view into the current state of a specific staking epoch, including details about stakes, stakepool, and rewards for a given ERC20 token.
Name | Type | Description |
---|---|---|
epochid | uint256 | The unique identifier of the staking epoch. |
erc20 | address | The address of the ERC20 token associated with the epoch (optional for rewards stats). |
Name | Type | Description |
---|---|---|
epoch | struct Epoch | The Epoch struct containing details such as epochid, start and end dates, and timestamps. |
stakes | uint256[3] | An array containing the total staked amount, pending incoming stakes, and pending outgoing stakes for the epoch. |
stakepool | uint256[3] | An array containing the total stakepool amount, pending incoming stakepool, and pending outgoing stakepool for the epoch. |
rewards | uint256[2] | An array containing the collected and released reward amounts for the epoch with respect to the provided ERC20 token. |
function buy4stake(address erc20, uint256 epochid, uint256 amount) external
Allows stakers to purchase ORCY tokens using a specific ERC20 token and automatically stake them in the current epoch.
Validates the ERC20 contract, the staker’s balance, allowance, and ensures the epoch is correct.
Releases the ORCY tokens from the BUY_4_STAKEPOOL
,
Distributes the collected tokens among current stakers and stakes the ORCY tokens on staker’s behalf for the current epoch.
Requirements
- The erc20
must be the BUY_4_STAKE_ERC20_CONTRACT
.
- The staker must have sufficient balance and allowance for the ERC20 token.
- The epochid
must match the current epoch (ACTUAL_EPOCH_ID
).
- The BUY_4_STAKEPOOL
must have enough ORCY tokens to cover the purchase.
- The staking contract must hold enough ORCY tokens.
- Only externally-owned accounts (EOAs) can call this function via the onlyOffChainCallable
modifier.
Emits:
- FATAL_EVENT_INSUFFICIENT_STAKEFUNDS
if the staking contract has insufficient ORCY tokens.
- Buy4StakepoolReleased
event for off-chain tracking.
- NewEpochStarted
event to indicate the start of a new epoch.
- RewardCollected
event when the reward is successfully collected and transferred to the contract.
- DepositCreated
event upon successful creation of a new deposit.
- IncreaseDepositAmount
event upon successful staking of tokens.
Name | Type | Description |
---|---|---|
erc20 | address | The address of the ERC20 token used for the purchase (must match the designated BUY_4_STAKE_ERC20_CONTRACT ). |
epochid | uint256 | The ID of the epoch in which the purchased tokens will be staked (must match the current epoch ACTUAL_EPOCH_ID ). |
amount | uint256 | The amount of ERC20 tokens the staker wishes to spend on purchasing ORCY tokens. |
function donateBuy4stake(uint256 amount) external
Allows stakers to donate ORCY tokens to the buy4stake pool.
Transfers ORCY tokens from the donator’s wallet to the contract, increasing the buy4stake pool.
The transfer will revert if the staker’s balance is insufficient or the allowance granted to this contract is not enough.
This function can only be called by off-chain EOA, and it uses a non-reentrant modifier to prevent re-entrancy attacks.
Requirements:
- The caller must have approved the contract to spend at least amount
tokens.
- Only externally-owned accounts (EOAs) can call this function via the onlyOffChainCallable
modifier.
- The function is protected against re-entrancy through the nonReentrant
modifier.
Emits the Buy4StakepoolIncreased
event after successfully increasing the pool.
Name | Type | Description |
---|---|---|
amount | uint256 | The amount of ORCY tokens the staker wishes to donate. |
function setBuy4stakeERC20(address erc20) external
Sets the accepted ERC20 token contract address for the Buy4Stake functionality. The specified ERC20 token will be used to purchase staking tokens (ORCY) in the Buy4Stake process.
This function ensures that the token contract has a non-zero total supply, confirming it is a valid ERC20 token.
It also enforces that only the contract owner (Oracly Team) can invoke this function.
The function updates the state variable BUY_4_STAKE_ERC20_CONTRACT
with the provided ERC20 contract address.
Emits the Buy4StakeAcceptedERC20Set
event upon successful execution.
Name | Type | Description |
---|---|---|
erc20 | address | The address of the ERC20 token contract that will be accepted for Buy4Stake staking operations. |
function setGatherer(address gatherer) external
Updates the authorized gatherer address responsible for collecting staking rewards from bettors’ prizes.
This function can only be called by the contract owner (Oracly Team).
It checks that the new gatherer is valid contract address.
This function is protected by onlyOwner
to ensure that only the contract owner can change the gatherer.
Emits AuthorizedGathererSet
event upon successful update of the gatherer address.
Name | Type | Description |
---|---|---|
gatherer | address | The address to be set as the authorized reward gatherer. |
function stake(uint256 epochid, uint256 amount) external
Allows a staker to stake a specified amount of ORCY tokens for a given epoch.
The staker must have a sufficient ORCY token balance and must approve the contract to transfer the specified amount
of tokens on their behalf.
The function uses the nonReentrant
modifier to prevent re-entrancy attacks.
Only externally-owned accounts (EOAs) can call this function via the onlyOffChainCallable
modifier.
Emits:
- DepositCreated
event upon successful creation of a new deposit.
- IncreaseDepositAmount
event upon successful staking of tokens.
Name | Type | Description |
---|---|---|
epochid | uint256 | The ID of the staking epoch for which the tokens are being staked. |
amount | uint256 | The number of ORCY tokens the staker wishes to stake. |
function unstake(uint256 epochid, bytes32 depositid) external
Initiates the unstaking process for a specific deposit during the current staking epoch. The unstaking process will unlock the staked ORCY tokens in the following epoch. During the current epoch, the stake will continue generating rewards until the next epoch starts.
Implements the unstaking mechanism, ensuring:
- The staked deposit exists and is owned by the caller.
- The caller is unstaking within the correct epoch.
- Prevents reentrancy attacks using the nonReentrant
modifier.
- Only externally-owned accounts (EOAs) can call this function via the onlyOffChainCallable
modifier.
Emits a DepositUnstaked
event upon successful unstaking, indicating the deposit ID and the staker who unstaked it.
Name | Type | Description |
---|---|---|
epochid | uint256 | The ID of the epoch in which the unstaking is initiated. |
depositid | bytes32 | The unique identifier of the deposit to be unstaked. |
function withdraw(bytes32 depositid) external
Allows a staker to withdraw a previously unstaked deposit.
The function reverts under the following conditions:
- The deposit does not exist.
- The caller is not the owner of the deposit.
- The deposit is still actively staked.
- The deposit has already been withdrawn.
- The withdrawal is attempted before the deposit’s associated out epoch has ended.
Requirements:
- Only externally-owned accounts (EOAs) can invoke this function, enforced by the onlyOffChainCallable
modifier.
- The nonReentrant
modifier ensures that the function cannot be called again until the first execution is complete.
Emits:
- DepositWithdrawn
on successful withdrawal of the deposit.
- FATAL_EVENT_INSUFFICIENT_STAKEFUNDS
if the contract lacks sufficient funds to cover the withdrawal.
Name | Type | Description |
---|---|---|
depositid | bytes32 | The unique identifier of the deposit to be withdrawn. |
function claimReward(uint256 epochid, bytes32 depositid, address erc20) external
Claims the staking reward for a specific deposit within a given epoch.
This function ensures that the reward claim process is secure and valid by performing several checks:
- Validates that the provided ERC20 token address corresponds to an allowed reward token.
- Ensures that the deposit exists and is owned by the caller.
- Verifies that the provided epoch ID is within the valid range and associated with the deposit.
- Checks that the reward for this deposit and epoch has not been fully claimed previously.
- Confirms that the epoch exists and has been initialized correctly.
- Ensures that the contract has sufficient funds to distribute the reward; otherwise, it emits a fatal error event.
If all checks pass, the reward is calculated, the deposit is marked as rewarded, and the ERC20 tokens are transferred to the caller.
Requirements:
- The caller must own the deposit.
- The epoch ID must be valid and associated with the deposit.
- The epoch must be initialized before claiming rewards.
- Can only be called by off-chain EOA (using onlyOffChainCallable
).
Emits:
- RewardClaimed
Event emitted when the reward is successfully claimed.
- FATAL_EVENT_INSUFFICIENT_REWARDFUNDS
Event emitted when the contract lacks sufficient funds to pay the reward.
Name | Type | Description |
---|---|---|
epochid | uint256 | The ID of the staking epoch for which the reward is being claimed. |
depositid | bytes32 | The unique identifier of the deposit associated with the staker. |
erc20 | address | The address of the ERC20 token that represents the reward. |
function collectCommission(address bettor, address erc20, uint256 commission) external
Allows a designated gatherer to collect staking rewards from a bettor’s prize. This function facilitates the transfer of ERC20 tokens from the gatherer’s balance to the contract and processes the reward distribution.
This function performs several important checks to ensure secure commission collection:
- Ensures that the gatherer has a sufficient balance of ERC20 tokens to cover the request for commission collection.
- Verifies that the gatherer has approved the contract to transfer at least commission
of ERC20 tokens.
Requirements:
- The caller must be an authorized gatherer (onlyGathererCallable
).
- The gatherer must have a sufficient balance and allowance for the ERC20 token.
- The function is protected against reentrancy attacks using the nonReentrant
modifier.
Emits:
- NewEpochStarted
event to indicate the start of a new epoch.
- RewardCollected
event when the commission is successfully collected and transferred to the contract.
Name | Type | Description |
---|---|---|
bettor | address | The address of the bettor who paid the commission. |
erc20 | address | The address of the ERC20 token contract from which tokens will be collected. |
commission | uint256 | The amount of ERC20 tokens to collect for reward distribution. |
modifier onlyOffChainCallable()
Restricts function execution to external accounts (EOA) only.
This modifier ensures that only EOAs (Externally Owned Accounts) can call functions protected by this modifier, preventing contracts from executing such functions.
The check is performed by verifying that the caller has no code associated with it (not a contract) and by comparing tx.origin
with _msgSender()
.
modifier onlyGathereCallable()
Restricts function execution to the authorized funds gatherer.
This modifier ensures that only the authorized entity, defined by the AUTHORIZED_COMMISSION_GATHERER
address, can call functions protected by this modifier.
If an unauthorized entity tries to invoke the function, the transaction is reverted.
event FATAL_EVENT_INSUFFICIENT_REWARDFUNDS(address staker, bytes32 depositid, address erc20, uint256 epochid, uint256 payout)
Emitted when there are insufficient reward funds available to fulfill a staker’s reward claim.
Acts as an important signal for stakers, indicating that the contract cannot collect the specific ERC20 token and that a manual EOA (Externally Owned Account) distribution is required.
Name | Type | Description |
---|---|---|
staker | address | The address of the staker attempting to claim the reward. |
depositid | bytes32 | The unique identifier of the staker’s deposit. |
erc20 | address | The address of the ERC20 token associated with the reward being claimed. |
epochid | uint256 | The ID of the staking epoch in which the reward being claimed. |
payout | uint256 | The amount of the reward that could not be fulfilled due to insufficient funds. |
event FATAL_EVENT_INSUFFICIENT_STAKEFUNDS(address staker, address erc20, uint256 balance, uint256 amount)
Emitted when a staker attempts to withdraw an unstaked deposit, but the contract does not have sufficient balance of the staking token (ORCY) to complete the withdrawal.
This serves as a crucial signal for stakers to know that the contract is blocked, and a manual EOA distribution is required.
Name | Type | Description |
---|---|---|
staker | address | The address of the staker attempting to withdraw funds. |
erc20 | address | The address of the ERC20 token in which the staked funds are held. |
balance | uint256 | The current ERC20 token balance held by the contract. |
amount | uint256 | The amount of ERC20 tokens the staker attempted to withdraw, which the contract could not fulfill. |
event DepositUnstaked(bytes32 depositid, address staker, uint256 epochid)
Emitted when a staker unstakes a deposit.
This event is triggered when a staker initiates the process of unstaking their deposit from a specific epoch.
Name | Type | Description |
---|---|---|
depositid | bytes32 | The unique identifier of the unstaked deposit. |
staker | address | The address of the staker who unstaked the deposit. |
epochid | uint256 | The identifier of the epoch during which the deposit was unstaked. |
event DepositWithdrawn(bytes32 depositid, address staker)
Emitted when a staker successfully withdraws their stake deposit.
This event indicates the complete removal of deposited funds by a staker from the contract.
Name | Type | Description |
---|---|---|
depositid | bytes32 | The unique identifier of the withdrawn deposit. |
staker | address | The address of the staker who initiated the withdrawal. |
event RewardClaimed(bytes32 depositid, address staker, address erc20, uint256 epochid, uint256 payout)
Emitted when a staker claims their staking reward for a specific deposit during a particular epoch.
This event is triggered after a successful reward claim by a staker. The event parameters provide detailed information about the deposit, staker, reward token, epoch, and payout amount.
Name | Type | Description |
---|---|---|
depositid | bytes32 | The unique identifier of the deposit for which the reward is claimed. |
staker | address | The address of the staker who claimed the reward. |
erc20 | address | The address of the ERC20 token representing the reward. |
epochid | uint256 | The ID of the epoch in which the reward was earned. |
payout | uint256 | The amount of reward claimed by the staker. |
event CommissionCollected(uint256 epochid, address erc20, address bettor, uint256 commission)
Emitted when staking rewards are collected from a bettor’s paid commission.
This event logs the commission collection for a specific epoch and bettor.
Name | Type | Description |
---|---|---|
epochid | uint256 | The identifier of the staking epoch during which the commission is collected. |
erc20 | address | The address of the ERC20 token contract from which tokens are collected. |
bettor | address | The address of the bettor who paid the commission. |
commission | uint256 | The amount of ERC20 tokens collected as commission for reward distribution. |
event NewEpochStarted(uint256 epochid, uint256 prevepochid, address erc20, uint256 startedAt, uint256 startDate, uint256 endDate, uint256 stakes, uint256 stakepool)
Emitted when a new staking epoch is initiated, signaling the transition between epochs.
This event provides details about the newly started staking epoch, including its unique identifiers, the ERC20 token being staked, the staking period timestamps, and information about the stakes and stakepool.
Name | Type | Description |
---|---|---|
epochid | uint256 | The unique identifier of the newly started staking epoch. |
prevepochid | uint256 | The unique identifier of the epoch that directly preceded the new one. |
erc20 | address | The address of the staking token (ORCY) used for stakepool of the epoch. |
startedAt | uint256 | The timestamp when the new epoch was started. |
startDate | uint256 | The timestamp representing the start of the new epoch’s staking period. |
endDate | uint256 | The timestamp representing the end of the new epoch’s staking period. |
stakes | uint256 | The total amount of deposits staked in new epoch. |
stakepool | uint256 | The total amount of tokens staked in the new epoch. |
event IncreaseDepositAmount(bytes32 depositid, address staker, uint256 amount)
Emitted when a staker deposits ORCY tokens into the contract, either by creating a new deposit or increasing an existing one.
This event is emitted every time a staker deposits ORCY tokens into the contract, whether it is a new deposit or an increase to an existing one.
Name | Type | Description |
---|---|---|
depositid | bytes32 | The unique identifier of the deposit being created or increased. |
staker | address | The address of the staker making the deposit. |
amount | uint256 | The amount of ORCY tokens deposited. |
event DepositCreated(bytes32 depositid, uint256 epochid, address staker, uint256 createdAt, address erc20)
Emitted when a new stake deposit is created in the contract.
This event is triggered whenever a staker successfully creates a new deposit. It provides details about the deposit including the unique deposit ID, epoch ID, staker’s address, timestamp of creation, and the ERC20 token being staked.
Name | Type | Description |
---|---|---|
depositid | bytes32 | Unique identifier for the deposit. |
epochid | uint256 | The ID of the staking epoch in which the deposit is created. |
staker | address | The address of the staker who made the deposit. |
createdAt | uint256 | The timestamp when the deposit is created. |
erc20 | address | The address of the staking token (ORCY) being staked in the deposit. |
event AuthorizedGathererSet(address gatherer)
Emitted when a new gatherer is authorized for the contract.
This event is triggered whenever the contract owner (Oracly Team) assigns a new gatherer.
Name | Type | Description |
---|---|---|
gatherer | address | The address of the authorized gatherer. |
event Buy4StakeAcceptedERC20Set(address erc20)
This event is emitted when the ERC20 token accepted for the Buy4Stake functionality is changed. It indicates that a new ERC20 token will now be used for acquiring ORCY tokens via staking.
This event is critical for tracking updates to the ERC20 token used in Buy4Stake operations.
Name | Type | Description |
---|---|---|
erc20 | address | The address of the new ERC20 token that is now accepted for Buy4Stake. |
event Buy4StakepoolIncreased(address erc20, uint256 stakepool, uint256 amount)
Emitted when the Buy4Stake pool balance is increased.
This event signals that more funds have been added to the Buy4Stake pool. The new total balance of the Buy4Stake pool and the amount that was added.
Name | Type | Description |
---|---|---|
erc20 | address | The address of the staking token (ORCY) being added to the Buy4Stake pool. |
stakepool | uint256 | The new balance of the Buy4Stake pool after the increase. |
amount | uint256 | The amount added to the Buy4Stake pool. |
event Buy4StakepoolReleased(address erc20, uint256 stakepool, uint256 amount)
Emitted when funds are released from the Buy4Stake pool.
This event logs the details of funds being released from the Buy4Stake pool, including the updated stake pool balance and the amount released.
Name | Type | Description |
---|---|---|
erc20 | address | The address of the staking token (ORCY) associated with the release. |
stakepool | uint256 | The updated balance of the stake pool after the funds are released. |
amount | uint256 | The amount of ERC20 tokens that were released from the pool. |
Represents a staking deposit of ORCY tokens in the Oracly Staking Contract.
A staker’s deposit is locked for a Staking Epoch, earns rewards, and grants voting power in governance processes.
- depositid
This is a hashed value representing the deposit ID.
- staker
This is the wallet address of the staker depositing ORCY tokens.
- inEpochid
Represents the epoch during which the deposit was created.
- createdAt
Records the time when the staker deposited ORCY tokens.
- amount
Specifies the quantity of ORCY tokens deposited into the staking contract.
- outEpochid
Defines the epoch during which the unstake process was initiated.
- unstaked
If true, the staker has requested to unlock their staked ORCY tokens.
- unstakedAt
Records the time when the staker unstake their ORCY tokens from the contract.
- withdrawn
If true, the staker has successfully withdrawn their tokens after unstaking.
- withdrawnAt
Records the time when the staker withdrew their ORCY tokens from the contract.
struct Deposit {
bytes32 depositid;
address staker;
uint256 inEpochid;
uint256 createdAt;
uint256 amount;
uint256 outEpochid;
bool unstaked;
uint256 unstakedAt;
bool withdrawn;
uint256 withdrawnAt;
}
Represents a recurring staking period (approximately 7 days) during which the staking pool remains unchanged.
Staking rewards are distributed to stakers proportionally based on Oracly Commissions collected during the epoch.
If no stakers register, the start of the epoch is delayed until participation occurs.
- epochid
This ID is used to track individual epochs.
- startDate
Indicates when the epoch is set to begin; however, the actual start may be delayed if no stakers participate.
- endDate
Defines when the staking epoch is expected to conclude, 7 days after the start date.
- startedAt
This records when the epoch started, which may differ from the scheduled start date due to a delayed start.
- endedAt
This captures the moment the epoch concluded, and no new staking reward commission is collected into the epoch.
struct Epoch {
uint256 epochid;
uint256 startDate;
uint256 endDate;
uint256 startedAt;
uint256 endedAt;
}
This contract establishes the mentorship structure, including mentor registration, reward distribution based on Proteges’ success, and relationship tracking within the Oracly Protocol.
Implements a mentorship system within the Oracly Protocol, allowing experienced bettors (Mentors) to guide less experienced bettors (Proteges) through prediction games. The contract manages mentor registrations, tracks mentor-protege relationships, and handles the distribution of Mentoring Rewards. Mentoring Rewards are calculated as a fixed percentage (0.25%) of the Proteges’ winnings from prediction games, encouraging knowledge sharing within the ecosystem.
uint8 MENTOR_COMMISSION_PERCENTAGE
Percentage of the total Prediction Reward allocated to Mentoring Rewards, expressed in basis points.
The value is set in basis points, where 1% equals 100 basis points.
Constant is set to 25
(0.25%) of the commission is allocated to mentoring rewards.
mapping(address => bool) __FATAL_INSUFFICIENT_REWARDFUNDS_ERROR__
Tracks whether the contract is experiencing insufficient reward funds for distribution.
This flag is set to prevent further operations when reward funds are insufficient.
address AUTHORIZED_COMMISSION_GATHERER
The address of the authorized funds gatherer for the contract.
This is the address responsible for gathering mentoring rewards from the bettor’s prize on withdrawal and passing them to the contract for further distribution to mentors.
constructor() public
The deployer will automatically be granted the required permissions to gather funds into the contract.
Constructor that initializes the contract, setting the deployer as the owner (Oracly Team) and granting them the role of AUTHORIZED_COMMISSION_GATHERER
.
The contract deployer is automatically assigned as the owner (Oracly Team) of the contract through the Ownable
constructor.
Additionally, the deployer is designated as the AUTHORIZED_COMMISSION_GATHERER
, a role required for gathering funds.
function getMentor(address mentor, address erc20) external view returns (address mentorid, uint256 circle, uint256 rewards, uint256 payouts, uint256 createdAt, uint256 updatedAt)
Retrieves information about a mentor including proteges, rewards, and payout history for a given ERC20 token.
Returns detailed mentor information for the specified ERC20 token, including associated proteges and financial data.
Name | Type | Description |
---|---|---|
mentor | address | The address of the mentor. |
erc20 | address | The address of the ERC20 token. |
Name | Type | Description |
---|---|---|
mentorid | address | the address of the mentor. |
circle | uint256 | The number of proteges associated with the mentor. |
rewards | uint256 | The total rewards earned by the mentor in the specified ERC20 token. |
payouts | uint256 | The total payouts made to the mentor in the specified ERC20 token. |
createdAt | uint256 | The timestamp when the mentor was created. |
updatedAt | uint256 | The timestamp when the mentor’s information was last updated. |
function getProtege(address protege, address erc20) external view returns (address protegeid, address mentor, uint256 earned, uint256 earnedTotal, uint256 createdAt, uint256 updatedAt)
Retrieves detailed information about a specific Protege, including their mentor, earned rewards for a given ERC20 token, and timestamps for creation and updates.
This function is a view function that returns the following information about the Protege: - Protege’s address - Mentor’s address - Earned rewards for the ERC20 token with the mentor - Total earned rewards for the ERC20 token across all mentors - Timestamps for creation and last update
Name | Type | Description |
---|---|---|
protege | address | The address of the Protege whose information is being retrieved. |
erc20 | address | The address of the ERC20 token for which reward details are queried. |
Name | Type | Description |
---|---|---|
protegeid | address | The Protege’s address, if found. |
mentor | address | The address of the Protege’s mentor. |
earned | uint256 | The rewards earned by the Protege for the specified ERC20 token with their mentor. |
earnedTotal | uint256 | The total rewards earned by the Protege for the specified ERC20 token. |
createdAt | uint256 | The timestamp when the Protege was first created. |
updatedAt | uint256 | The timestamp when the Protege’s information was last updated. |
function getMentorProteges(address mentor, uint256 offset) external view returns (address[] proteges, uint256 size)
Retrieves a paginated list of Proteges associated with a specific Mentor.
This function returns a list of Protege addresses along with the total number of Proteges linked to the given Mentor. The results can be paginated by specifying an offset.
Name | Type | Description |
---|---|---|
mentor | address | The address of the Mentor whose Proteges are being queried. |
offset | uint256 | The starting index for the pagination of the Protege list. |
Name | Type | Description |
---|---|---|
proteges | address[] | An array of addresses representing the Proteges. |
size | uint256 | The total number of Proteges associated with the Mentor. |
function getProtegeMentorEarned(address protege, address erc20, address mentor) external view returns (uint256 earned)
Returns the amount of ERC20 tokens earned by a mentor from a specified protege.
This function retrieves the accumulated earnings a mentor has gained from their protege in the specified ERC20 token.
Name | Type | Description |
---|---|---|
protege | address | The address of the protege whose earnings are being queried. |
erc20 | address | The address of the ERC20 token for which the earnings are being checked. |
mentor | address | The address of the mentor who has earned the tokens. |
Name | Type | Description |
---|---|---|
earned | uint256 | The total amount of ERC20 tokens earned by the mentor from the protege. |
function setGatherer(address gatherer) external
Sets the authorized funds gatherer address. Only callable by the contract owner (Oracly Team).
Updates the address authorized to gather funds. This function can only be executed by the contract owner (Oracly Team).
It ensures that the new gatherer is valid contract address.
Emits AuthorizedGathererSet
event upon successful update of the gatherer address.
This function is protected by onlyOwner
to ensure that only the contract owner can change the gatherer.
Name | Type | Description |
---|---|---|
gatherer | address | The new address to be set as the gatherer. |
function joinMentor(address mentor) external
Allows a proteges to join a mentor-protege relationship.
This function is external and non-reentrant, ensuring it can only be called from outside the contract and preventing re-entrancy attacks.
The onlyOffChainCallable
modifier restricts access to off-chain EOA to prevent internal or contract-based invocation.
Emits an JoinedMentor
event upon successful join.
Name | Type | Description |
---|---|---|
mentor | address | The address of the mentor that the protege wants to join. |
function expelProtege(address protege) external
Removes a Protege from the Mentor’s circle. This function can only be called by the Mentor who currently mentors the Protege.
Requirements:
- The caller of the function (the mentor
) must be the current mentor of the protege
.
- protege
must be currently associated with the calling mentor
.
Emits an ProtegeExpelled
event upon successful removal.
Name | Type | Description |
---|---|---|
protege | address | The address of the Protege to be expelled from the Mentor’s circle. |
function transferProtege(address protege, address mentor) external
Transfers a protege from one mentor to another. The caller must be the current mentor of the protege.
This function ensures that a protege’s mentorship is updated by transferring them from one mentor to another.
The transaction is protected against reentrancy attacks and can only be called from an off-chain context.
Emits an ProtegeExpelled
event upon successful removal from an old mentor.
Emits an JoinedMentor
event upon successful join to a new mentor.
Name | Type | Description |
---|---|---|
protege | address | The address of the protege being transferred. |
mentor | address | The address of the new mentor to which the protege is assigned. |
function calculateReward(address protege, uint256 amount) external view returns (uint256 reward)
Calculates the Mentoring Reward for a specific protege based on a provided amount.
This function is an external view override, meaning it can be called externally to view the calculated reward for a protege without any gas fees for state changes.
Name | Type | Description |
---|---|---|
protege | address | The address of the protege whose reward is being calculated. |
amount | uint256 | The amount used as the base for the reward calculation. |
Name | Type | Description |
---|---|---|
reward | uint256 | The calculated Mentoring Reward for the given protege and amount. |
function collectCommission(address protege, address erc20, uint256 commission) external
Collects a reward from commission of a protege’s prize and distributes it to the corresponding Mentoring Reward pool. The function facilitates the transfer of rewards from the protege to the mentor’s reward pool using the specified ERC20 token.
Collects a reward from commission of a protege’s prize and distributes it to the associated mentor.
Requirements:
- protege
and sender
must be valid.
- commission
must be greater than zero.
- The specified ERC20 token must not be blocked for reward collection.
- The caller must have sufficient ERC20 token balance and allowance.
- The function ensures reentrancy protection and restricts access using the onlyGathereCallable
modifier.
Emits a MentorfundsAdded
event upon successful reward distribution to the mentor.
Name | Type | Description |
---|---|---|
protege | address | The address of the protege, who is receiving mentorship. |
erc20 | address | The address of the ERC20 token used for the reward distribution. |
commission | uint256 | The amount of the ERC20 token to collect and distribute as the reward. |
function claimReward(address erc20) external
Allows the Mentor (caller) to claim their accumulated Mentoring Reward for a specified ERC20 token.
This function transfers the accumulated Mentoring Reward for the specified ERC20 token to the caller.
Requirements:
- erc20
must be a valid ERC20 token address.
- The caller must have accumulated Mentoring Rewards for the specified ERC20 token.
- The contract must hold enough balance of the specified ERC20 token to cover the reward payout.
Emits:
- MentorRewardPayout
event upon a successful claim.
- FATAL_EVENT_INSUFFICIENT_REWARDFUNDS
event if the contract lacks sufficient funds.
Name | Type | Description |
---|---|---|
erc20 | address | The address of the ERC20 token for which the reward is being claimed. |
modifier onlyOffChainCallable()
Restricts function execution to external accounts (EOA) only.
This modifier ensures that only EOAs (Externally Owned Accounts) can call functions protected by this modifier, preventing contracts from executing such functions.
The check is performed by verifying that the caller has no code associated with it (not a contract) and by comparing tx.origin
with _msgSender()
.
modifier onlyGathereCallable()
Restricts function execution to the authorized funds gatherer.
This modifier ensures that only the authorized entity, defined by the AUTHORIZED_COMMISSION_GATHERER
address, can call functions protected by this modifier.
If an unauthorized entity tries to invoke the function, the transaction is reverted.
event FATAL_EVENT_INSUFFICIENT_REWARDFUNDS(address mentor, address erc20, uint256 balance, uint256 payout)
Emitted when the reward pool does not have sufficient funds to cover a mentor’s earnings payout. This signals a critical issue as the reward pool is depleted, preventing a successful distribution of rewards.
This event provides transparency on the failure to payout a mentor due to insufficient reward funds. It includes information on the affected mentor, the ERC20 token involved, the current reward fund balance, and the attempted payout amount. It acts as an important signal for mentors to know that the contract is blocked from collecting specific ERC20 tokens and that a manual EOA distribution is required.
Name | Type | Description |
---|---|---|
mentor | address | The address of the mentor who should have received the payout. |
erc20 | address | The address of the ERC20 token representing the reward currency. |
balance | uint256 | The current balance of the reward pool for the given ERC20 token. |
payout | uint256 | The intended amount to be paid to the mentor. |
event JoinedMentor(address protege, address mentor)
Emitted when a protege successfully joins a mentor.
This event is triggered when a protege is associated with a mentor in the Oracly Protocol.
Name | Type | Description |
---|---|---|
protege | address | The address of the protege who joins the mentor. |
mentor | address | The address of the mentor that the protege is joining. |
event ProtegeExpelled(address protege, address mentor)
Emitted when a mentor expels a protege.
This event is triggered when a mentor decides to disassociate a protege from their mentorship.
Name | Type | Description |
---|---|---|
protege | address | The address of the protege being expelled. |
mentor | address | The address of the mentor performing the expulsion. |
event MentorfundsAdded(address protege, address mentor, address erc20, uint256 reward)
Emitted when a Protege withdraws their prize and 0.25% is assigned to the Mentor’s reward.
This event is triggered whenever a Protege contributes funds to their Mentor.
Name | Type | Description |
---|---|---|
protege | address | The address of the Protege who earned the funds. |
mentor | address | The address of the Mentor receiving the reward. |
erc20 | address | The ERC20 token contract address used for the reward transaction. |
reward | uint256 | The amount of Mentor’s reward in ERC20 tokens. |
event MentorRewardPayout(address mentor, address erc20, uint256 payout)
Emitted when a Mentor claims and receives a payout of their accumulated Mentoring Rewards.
This event provides details about the Mentor, the ERC20 token used for the payout, and the payout amount.
Name | Type | Description |
---|---|---|
mentor | address | The address of the Mentor who is receiving the payout. |
erc20 | address | The address of the ERC20 token contract used for the payout. |
payout | uint256 | The amount of ERC20 tokens paid to the Mentor. |
event AuthorizedGathererSet(address gatherer)
Emitted when a new gatherer is authorized for the contract.
This event is triggered whenever the contract owner (Oracly Team) assigns a new gatherer.
Name | Type | Description |
---|---|---|
gatherer | address | The address of the authorized gatherer. |
The ORCY token is the native token of the Oracly Protocol, enabling staking, governance, and facilitating reward distribution.
This contract implements the standard ERC-20 functionality for the ORCY token, allowing users to transfer ORCY, check balances, and participate in staking and governance. It controls the minting process according to the OraclyV1 Economy, distributing tokens for growth, team, seed, and buy4stake addresses.
uint256 TOTAL_SUPPLY
Fixed total supply of ORCY tokens, permanently set to 10 million tokens.
The supply is scaled to 18 decimal places (10 million * 1e18).
string TOKEN_NAME
Official name of the ORCY token, represented as ‘Oracly Glyph’.
This is the full name used in the ERC-20 standard.
string TOKEN_SYMBOL
The symbol of the ORCY token, denoted as ‘ORCY’.
This symbol will be displayed on exchanges and wallets.
uint8 GROWTH_PERCENTAGE
Percentage of the total token supply allocated for the growth fund.
Set at 10%, this portion is reserved for initiatives that promote ecosystem growth.
uint8 TEAM_PERCENTAGE
Percentage of the total token supply allocated for the team.
Set at 10%, this portion is reserved for team members as compensation.
uint8 SEED_PERCENTAGE
Percentage of the total token supply allocated for seed investors.
Set at 5%, this portion is reserved for early-stage investors who funded the project.
uint8 BUY4STAKE_PERCENTAGE
Percentage of the total token supply allocated for the buy4stake program.
Set at 50%, this portion is reserved for the buy4stake mechanism to incentivize staking.
uint8 GROWTH_VESTING_PERCENTAGE
Percentage of the total token supply allocated for growth-related vesting.
Set at 10%, this portion will be unlocked over time to sustain long-term growth initiatives.
uint8 TEAM_VESTING_PERCENTAGE
Percentage of the total token supply allocated for team vesting.
Set at 10%, this portion will be unlocked gradually for team members as part of their vesting schedule.
uint8 SEED_VESTING_PERCENTAGE
Percentage of the total token supply allocated for seed investors’ vesting.
Set at 5%, this portion will be released over time to early investors in accordance with the vesting schedule.
constructor(address growth_address, address team_address, address seed_address, address buy4stake_address, address growth_vesting_address, address team_vesting_address, address seed_vesting_address) public
Initializes the ORCY token contract by minting the total supply and distributing it according to the ORCY economy’s token allocation plan.
The total supply of ORCY tokens is minted and allocated across various addresses based on predefined percentages for growth, team, seed investors, and buy4stake mechanisms.
Name | Type | Description |
---|---|---|
growth_address | address | Address that receives the portion allocated for growth initiatives (10%). |
team_address | address | Address that receives the portion allocated for the team (10%). |
seed_address | address | Address that receives the portion allocated for seed investors (5%). |
buy4stake_address | address | Address that receives the portion allocated for the buy4stake program (50%). |
growth_vesting_address | address | Address that receives the vesting portion for long-term growth initiatives (10%). |
team_vesting_address | address | Address that receives the vesting portion for team members (10%). |
seed_vesting_address | address | Address that receives the vesting portion for seed investors (5%). |
Provides a free allocation of DEMO tokens for demonstrating OraclyV1 gameplay.
This contract acts as a faucet, dispensing a controlled amount of DEMO tokens to bettors. Token Allocation: Each eligible request grants 1,000 DEMO tokens. Wallet Limits: No wallet address can request more than 10,000 DEMO tokens in total. ERC-20: Implements basic ERC-20 token functionality for DEMO, allowing transfers and balance checks.
uint256 INIT_SUPPLY
Initial supply of DEMO tokens distributed upon contract deployment.
This constant defines the total initial supply of the DEMO tokens (1,000 tokens)
uint256 DEMO_SUPPLY
Amount of DEMO tokens dispensed per mint request
Defines the fixed number of DEMO tokens (1,000 tokens) that can be minted for each minting request.
uint256 MAX_ADDRESS_MINT
Maximum amount of DEMO tokens that a single wallet can mint.
This constant caps the amount of tokens a single wallet can mint (10,000 tokens), ensuring no wallet can exceed this limit.
string TOKEN_NAME
Official name of the DEMO token, represented as “Oracly Demo”.
This is the full name used in the ERC-20 standard.
string TOKEN_SYMBOL
The symbol of the DEMO token, denoted as “DEMO”.
This symbol will be displayed on exchanges and wallets.
mapping(address => uint256) minted
Tracks the number of DEMO tokens minted by each bettor.
Maps a bettor’s wallet address to the total number of DEMO tokens they have minted. This mapping is used to enforce minting limits.
constructor() public
Initializes the contract by minting the initial supply of DEMO tokens to the deployer’s address.
Mints 1,000 DEMO tokens to the deployer’s address upon contract deployment.
The ERC20
constructor is called with TOKEN_NAME
and TOKEN_SYMBOL
as parameters.
function mint() external
Mints 1,000 DEMO tokens to the caller, ensuring the wallet does not exceed the 10,000 DEMO cap.
This function allows the caller to mint 1,000 DEMO tokens at a time, provided they have not reached the maximum cap of 10,000 DEMO tokens per wallet.
If minting the tokens would cause the caller’s minted token amount to exceed the cap, the transaction is reverted with MintLimitExceeded
.
Requirements:
- The caller must be an EOA (Externally Owned Account), enforced by the onlyOffChainCallable
modifier.
- The contract tracks the balance and limits the total mintable tokens to a maximum of 10,000 DEMO per address.
modifier onlyOffChainCallable()
Restricts function execution to external accounts (EOA) only.
This modifier ensures that only EOAs (Externally Owned Accounts) can call functions protected by this modifier, preventing contracts from executing such functions.
The check is performed by verifying that the caller has no code associated with it (not a contract) and by comparing tx.origin
with _msgSender()
.
This contract is designed to handle the vesting of ORCY tokens, aligning token release with long-term project goals and incentivizing continued participation.
A vesting contract for ORCY tokens within the Oracly Protocol ecosystem. This contract ensures a gradual and controlled release of ORCY tokens to a designated beneficiary over a 26-month period with a 6-month cliff.
The contract overrides the release
and receive
functions to prevent direct token release or receipt of native tokens.
uint64 DURATION
The duration of the vesting period after the cliff, spanning 20 months.
This constant defines the length of time over which the tokens are gradually released after the cliff period.
uint64 CLIFF
The cliff period for the vesting, which lasts 6 months.
No tokens are released during the cliff period. Tokens start releasing only after this period ends.
constructor(address beneficiary) public
Constructor for VestingOraclyV1 contract.
Initializes the vesting wallet with a predefined cliff period and total duration. Tokens begin vesting after the cliff, and are released gradually over the 20-month duration.
Name | Type | Description |
---|---|---|
beneficiary | address | The address of the beneficiary who will receive the vested ORCY tokens. |
function release() public virtual
Prevents the direct release of native tokens.
Overrides the release
function to disable native token release. Only ORCY tokens are managed by this contract.
receive() external payable virtual
Prevents the contract from receiving native tokens.
Overrides the receive
function to reject incoming native token transfers.
Oracly Protocol is a decentralized prediction market maker on the Polygon (PoS) ↗ network. It gamifies the essential skill of trading - forecasting crypto prices - making markets accessible, exciting, and rewarding for everyone.
Players compete in short, dynamic rounds to predict whether the price of an asset will go UP, DOWN, or remain the same (ZERO), directly placing deposits and withdrawing payouts from prize pools. Oracly Protocol utilizes reliable Chainlink ↗ price feeds to create a secure, permissionless, and non-custodial environment.
Traditional crypto trading, with its complexities and demanding long-term strategies, can be intimidating for many potential users. Oracly Protocol breaks down these barriers by transforming crypto trading into an engaging and accessible prediction game. Its simplified format, centered around three core choices, opens the world of crypto to a much wider audience.
Complexity vs Gamification: Instead of complex and long-term trading routines and strategies, Oracly Protocol offers short rounds where you predict if an asset’s price will go UP, DOWN, or stay the same (ZERO). Players directly contribute to prize pools, and winners withdraw their rewards at the end of each round.
Volatility vs Prediction: Oracly Protocol turns market volatility into the focus of the game. Payouts are determined by the direction of price change, not the size of the movement.
Security plus Transparency: Powered by the Polygon (PoS) ↗ blockchain, all game rules, predictions, and payouts are transparent and unchangeable. Chainlink Price Feeds ↗ ensure reliable real-time data, guaranteeing fair outcomes for everyone.
Oracly Protocol offers a unique prediction game with continuous rounds. Players predict asset price movements and win a share of the Prize Pool if their predictions are correct.
A self-contained prediction contest where players predict whether the price of a selected asset will go UP, DOWN, or remain the same (ZERO) within a short timeframe. Rounds progress through Entry, Round, Settlement, Payout, and Archive phases. At the end of the short round Player with Prediction matching actual price movement share the Prize Pool proportionally to their deposit.
Players place their Predictions (UP, DOWN, ZERO) with deposits for the selected asset’s price movement. This phase determines the Entry Price that all predictions are based on, and the minimum deposit size depends on the Game Level.
Game Level | Minimum Deposit |
---|---|
Bronze | 1 USDC |
Silver | 10 USDC |
Gold | 100 USDC |
During the Round Phase, funds is locked and players wait for the Outcome. Predictions can’t be changed. The Prize Pool is finalized, and Players await the Feed to publish the final price point of the phase, which will determine the round’s Outcome.
The Feed publishes final price point of the Round Phase and the Outcome becomes publicly known. However, Outcome requires protocol’s verification to become permanent. The first player to withdraw their Prediction Reward or Refund performs this verification.
Players with winning predictions withdraw their share of the Prize Pool, with payouts based on their deposit size. Protocol collects 1% of Oracly Commission. If the round was NO CONTEST, players withdraw Refunds.
Once a round enters the Archive Phase, it’s permanently closed, signifying the end of its lifecycle. All outcomes, predictions, and payouts are finalized and recorded on the blockchain for transparency and historical reference.
OraclyV1 ↗: 0xf41c3bec833bf3b05834b8459ee70816d167cf37
MetaOraclyV1 ↗: 0x9acff323637f765fa770c3d1cdbc76bfbfdb4fa8
StakingOraclyV1 ↗: 0x55135638b6301a700070bf08c9b0ef67caf875e4
MentoringOraclyV1 ↗: 0xda4a5d10fd2525b83558f66a24c0c012d67d45a5
ORCY ↗: 0x8def651cbf7deaa35835ed6d4a4d4daabb8b898b
DEMO ↗: 0xde41431172704248b723a36d00044f8132fa444e
Vesting Growth ↗: 0x39ee332b91dc58d6ca668bf874df539cae158016
Vesting Team ↗: 0xd8708ea8214da5a170edac19d9a50c0fffd1b5dc
Vesting Seed ↗: 0xdd084b37837eb0da72abd817375045d22bf73e93
This contract is the core of the Oracly Protocol’s decentralized prediction game.
Serves as the control point for creating new games in the Oracly Protocol. Provides the Oracly Team with the ability to block abused games.
IMPORTANT
Facilitates the core staking functionality of the Oracly Protocol, enabling ORCY token holders to lock their tokens for Staking Reward.
Establishes a mentorship system within the Oracly Protocol, connecting experienced players (Mentors) with those seeking guidance (Proteges). Incentivizes skilled players to share their knowledge by offering Mentoring Rewards based on their Proteges’ winnings.
The DEMO contract acts as a faucet, dispensing a free allotment of DEMO tokens for demonstration of gameplay. It implements a limit to prevent abuse.
The ORCY token is native token of the Oracly Protocol, enabling staking, governance, and facilitating reward distribution. Enables users to lock their ORCY tokens, earning a share of the protocol’s collected Oracly Commissions. Empowers ORCY holders to vote on proposals that shape the future direction of the protocol. Implements the standard ERC-20 ↗ functionality, allowing for seamless transfers and management of ORCY tokens.
This contract implements a vesting mechanism for the ORCY token within the Oracly Protocol ecosystem. It ensures a gradual and controlled release of ORCY tokens to a designated beneficiary over a predefined vesting period. It ensures that key contributors or stakeholders receive their allocated ORCY tokens in a manner that aligns with the long-term goals of the project. This approach helps to foster commitment, incentivize continued participation, and maintain the stability of the ORCY token’s value.
The Oracly Team is a dedicated group of engineers and visionaries behind the creation of the Oracly Protocol. Their expertise and passion drive the development and growth of our innovative prediction platform.
Mykhailo Nakonechnyi (Core Contributor): Leads the strategic direction of the Oracly Protocol, ensuring its vision aligns with market needs and technological advancements.
Romain Potochevscky (Core Contributor): Shapes the visual identity and user experience of Oracly, creating an engaging and intuitive platform.
Dmitry Kondratenko (Core Contributor): Translates Oracly’s concepts into robust code, ensuring the platform’s functionality, security, and scalability.
ORCY is the staking and governance token of the Oracly Protocol, empowering community participation and profit distribution within the platform.
Oracly Protocol offers a rewarding staking mechanism for ORCY token holders. By locking their ORCY tokens in the Staking Contract, Stakers earn a share of collected Oracly Commissions and gain voting power to shape the protocol’s future:
IMPORTATNT: Oracly Risks Mitigation - Staker can withdraw their pending ORCY deposit at any time. - Staker cannot stake a new deposit in the same Staking Epoch in which a pending deposit was unstaked.
Stakers gain voting power to participate in decisions that shape the Oracly Protocol’ future. Stakers with at least 1% of the ORCY total supply staked are able to join the Presidium and gain the right to submit proposals.
Voting: All Stakers have a 48-hour window to vote on proposals submitted by Councilors.
Proposals: Only Stakers holding 1% or more of the total ORCY supply may join the Presidium as Councilors, gaining the right to submit proposals.
Execution: A proposal with more Support than Oppose votes after 48 hours and exceeding the quorum requirement is considered Approved by Stakers and ready for execution by Presidium.
The Oracly Protocol offers a streamlined process to purchase ORCY and immediately begin staking through the Buy4Stake feature on the Oracly Staking Platform
This fund is strategically allocated to fuel initiatives that drive the Oracly Protocol long-term growth, stability, and market reach.
This allocation recognizes the Oracly Team for their exceptional work in conceptualizing and successfully launching the Oracly Protocol V1. Their dedication and passion over the past two years were instrumental in bringing this project to fruition.
This allocation is reserved for strategic partners who played a pivotal role in the Oracly Protocol’s early development. Their support extends beyond financial investments.
A significant 5,000,000 ORCY (50% of the total supply) is dedicated to the Buy4Stake feature, offering a streamlined path to acquiring ORCY and becoming part of the Oracly Protocol ecosystem.
Buy4Stake Process:
Oracly Protocol prioritizes security and fairness, so implemented a multi-faceted approach to mitigation. The protocol implements cirtain measures to address potential risks, ensuring the platform’s integrity.
A malicious player could attempt to manipulate a round’s Outcome by submitting a false price point. This undermines the fairness of the Oracly Protocol.
External price feeds could become inaccurate or manipulated. False or corrupted price point data could be received as a valid price point from the Feed.
Chainlink Aggregators can occasionally undergo swaps due to maintenance, updates, or unforeseen circumstances. This could lead to inconsistencies if the Oracly Protocol switches to a new aggregator mid-round.
Temporary outages on the Polygon PoS L2 Sequencer could interrupt the flow of updated price data from Chainlink Price Feeds. This stale data creates a risk of unreliable outcomes in Oracly Protocol rounds.
IMPORTANT: In the event of a NO CONTEST, all player deposits within that round become eligible for Refunds.
Fatal errors represent a severe mismatch between Oracly Protocol’ expected state and the actual funds within its contracts. These errors jeopardize the security and reliability of the platform.
FATAL_EVENT_INSUFFICIENT_PRIZEFUNDS
- Not enough funds to cover player payout or refund.FATAL_EVENT_INSUFFICIENT_PRIZEFUNDS
- Not enough funds to cover mentor rewards.FATAL_EVENT_INSUFFICIENT_REWARDFUNDS
- Not enough funds to distribute staking rewards.
FATAL_EVENT_INSUFFICIENT_STAKEFUNDS
- Not enough funds to process a staked token withdrawal.Immediate Blocking: Affected contracts automatically block further user deposits, preventing the situation from worsening.
Transparent Communication: The protocol emits clear FATAL_EVENT_*
signals, enabling users and developers to understand the specific error and its potential impact.
NO CONTEST: In the event of a Fatal Error affecting a game round, the affected rounds are automatically declared NO CONTEST. This ensures that no player’s predictions are unfairly impacted due to the error.
If no stakers register for a newly scheduled Staking Epoch, Oracly Protocol delays the epoch’s start indefinitely until Stakers participate.
The mentoring system could potentially allow for circular relationships, where a mentor becomes the protege of their own protege (directly or indirectly), creating a loop. This could potentially lead to abuse.
These formulas help to calculate exact amount of Prediction Reward before reward withdrawl. By calculating the Reward (R(d)) and Profit Percentage (PP(d)), Player knows the exact amount of his Prediction Reward payout.
PR(50) = 1000 * 50 / 200 * (1 - 0.01) = 247.5 USDC
PPP(50) = 247.5 / 50 - 1 = 3.95 = 395%
Deposit: 50 USDC Reward: 247.5 USDC +395%
These formulas help to estimate potential Prediction Reward per deposit amount before entering the round. By calculating the Potential Reward (PR(d)) and Potential Profit Percentage (PPP(d)), Player can make more informed decisions about deposit amount and prediction choices.
Example:
PR(50) = (1000 + 50) * 50 / (200 + 50) * (1 - 0.01) = 207.9 USDC
PPP(50) = 207.9 / 50 - 1 = 3.158 = 315.8%
Deposit: 50 USDC Potential Reward: 207.9 USDC +315.8%
This example illustrates a complete Oracly Protocol Round with four players, demonstrating how predictions, deposits, and rewards work. It also highlights the flow of information in simplified terms, focusing on player actions and blockchain confirmations.
We’ll refer to the confirmed state of the blockchain as “Public Information.”
Round:
Players:
The following timeline will show how the round progresses, with each player’s prediction, deposit amount, and the resulting impact on potential rewards for each Outcome (UP, DOWN, ZERO).
UpBob cannot estimate Potential Reward, the Prize Pool is empty. UpBob places minimum deposit 10 USDC predicting UP. UpBob’s prediction will confirm Entry Price of the Round.
Public Information
Prize Pool: 0 USDC (total)
- UP: 0 USDC
- DOWN: 0 USDC
- ZERO: 0 USDC
UpBob’s prediction becomes public, altering the round’s dynamic. Other players must now factor in his prediction and the Entry Price when making their own choices.
Public Information
Predictions:
- UpBob: 10 USDC (UP)
Prize Pool: 10 USDC (total)
- UP: 10 USDC
- DOWN: 0 USDC
- ZERO: 0 USDC
Entry Price: $99,999.99999999
Potential Reward per minuimum deposit (10 USDC)
Outcome | Deposit | Potential Reward | Potential Profit Percentage |
---|---|---|---|
UP | 10 | 10 (*) | 0% |
DOWN | 10 | 19.8 | +98% |
ZERO | 10 | 19.8 | +98% |
DownOw decided to deposit 50 USDC predicting DOWN.
Public Information
Predictions:
- UpBob: 10 USDC (UP)
Prize Pool: 10 USDC (total)
- UP: 10 USDC
- Down: 0 USDC
- Zero: 0 USDC
Entry Price: $99,999.99999999
Potential Reward per DownOw’ deposit (50 USDC)
Outcome | Deposit | Potential Reward | Potential Profit Percentage |
---|---|---|---|
UP | 50 | 50 (*) | 0% |
DOWN | 50 | 59.4 | +18.7% |
ZERO | 50 | 59.4 | +18.7% |
DownOw’s prediction becomes public, altering the round’s rewards again.
Public Information
Predictions:
- DownOw: 50 USDC (DOWN)
- UpBob: 10 USDC (UP)
Prize Pool: 60 USDC (total)
- UP: 10 USDC
- Down: 50 USDC
- Zero: 0 USDC
Entry Price: $99,999.99999999
Potential Reward per minimum (10 USDC) deposit baised on Public Information
Outcome | Deposit | Potential Reward | Potential Profit Percentage |
---|---|---|---|
UP | 10 | 34.65 | +246.5% |
DOWN | 10 | 11.55 | +15.5% |
ZERO | 10 | 69.3 | +593% |
UpInna decided to deposit 15 USDC predicting UP.
Public Information
Predictions:
- DownOw: 50 USDC (DOWN)
- UpBob: 10 USDC (UP)
Prize Pool: 60 USDC (total)
- UP: 10 USDC
- DOWN: 50 USDC
- ZERO: 0 USDC
Entry Price: $99,999.99999999
Potential Reward per UpInna’ (15 USDC) deposit:
Outcome | Deposit | Potential Reward | Potential Profit Percentage |
---|---|---|---|
UP | 15 | 44.55 | +197% |
DOWN | 15 | 17.134 | +14.2% |
ZERO | 15 | 74.25 | +395% |
UpInna’s prediction becomes public altering the round’s rewards.
Public Information
Predictions:
- UpInna: 15 USDC (UP)
- DownOw: 50 USDC (DOWN)
- UpBob: 10 USDC (UP)
Prize Pool: 75 USDC (total)
- UP: 25 USDC
- DOWN: 50 USDC
- ZERO: 0 USDC
Entry Price: $99,999.99999999
Potential Reward per minimum (10 USDC) deposit:
Outcome | Deposit | Potential Reward | Potential Profit Percentage |
---|---|---|---|
UP | 10 | 24.042 | +140.4% |
DOWN | 10 | 14.025 | +40.2% |
ZERO | 10 | 84.15 | +741.5% |
ZeroIda decided to deposit 10 USDC predicting ZERO.
Public Information
Predictions:
- UpInna: 15 USDC (UP)
- DownOw: 50 USDC (DOWN)
- UpBob: 10 USDC (UP)
Prize Pool: 75 USDC (total)
- UP: 25 USDC
- DOWN: 50 USDC
- ZERO: 0 USDC
Entry Price: $99,999.99999999
Potential Reward per ZeroIda’s (10 USDC) deposit:
Outcome | Deposit | Potential Reward | Potential Profit Percentage |
---|---|---|---|
UP | 10 | 24.042 | +140.4% |
DOWN | 10 | 14.025 | +40.2% |
ZERO | 10 | 84.15 | +741.5% |
ZeroIda’s prediction becomes public altering the round’s rewards.
Public Information
Predictions:
- ZeroIda: 10 USDC (ZERO)
- UpInna: 15 USDC (UP)
- DownOw: 50 USDC (DOWN)
- UpBob: 10 USDC (UP)
Prize Pool: 85 USDC (total)
- UP: 25 USDC
- DOWN: 50 USDC
- ZERO: 10 USDC
Entry Price: $99,999.99999999
Potential Reward per minimum (10 USDC) deposit:
Outcome | Deposit | Potential Reward | Potential Profit Percentage |
---|---|---|---|
UP | 10 | 26.871 | +168.7% |
DOWN | 10 | 15.675 | +56.7% |
ZERO | 10 | 47.025 | +370.2% |
Funds is locked and UpBob, UpInna, DownOw, ZeroIda wait for the Outcome. Predictions can’t be changed. The Prize Pool is finalized, and Players await the Feed to publish the final price point within the phase, which will determine the round’s Outcome.
Public Information
Predictions:
- ZeroIda: 10 USDC (ZERO)
- UpInna: 15 USDC (UP)
- DownOw: 50 USDC (DOWN)
- UpBob: 10 USDC (UP)
Prize Pool: 85 USDC (total)
- UP: 25 USDC
- DOWN: 50 USDC
- ZERO: 10 USDC
Entry Price: $99,999.99999999
Prediction Rewards in case of currect prediction.
Player | Outcome | Deposit | Reward | Profit Percentage |
---|---|---|---|---|
ZeroIda | Zero | 10 | 84.15 | +741.5% |
UpInna | Up | 15 | 50.49 | +236.6% |
DownOw | Down | 50 | 84.15 | +68.3% |
UpBob | Up | 10 | 33.66 | +236.6% |
The Feed publishes the final price point of the Round, publicly revealing the round’s Outcome. While the final price of $100,000.00 per 1 BTC becomes the potential Exit Price, it remains Unverified by the protocol and therefore not yet permanent.
Public Information
Predictions:
- ZeroIda: 10 USDC (ZERO)
- UpInna: 15 USDC (UP)
- DownOw: 50 USDC (DOWN)
- UpBob: 10 USDC (UP)
Prize Pool: 85 USDC (total)
- UP: 25 USDC
- DOWN: 50 USDC
- ZERO: 10 USDC
Entry Price: $99,999.99999999
Exit Price: $100,000.00000000 (Unverified)
Outcome: UP (Unverified)
UpBob withdraw his Prediction Reward providing the final price point ($100,000.00 per 1 BTC) of the Feed within the Round Phase for verification. The potential Exit Price remains Unverified until confirmed by the protocol.
Public Information
Predictions:
- ZeroIda: 10 USDC (ZERO)
- UpInna: 15 USDC (UP)
- DownOw: 50 USDC (DOWN)
- UpBob: 10 USDC (UP)
Prize Pool: 85 USDC (total)
- UP: 25 USDC
- DOWN: 50 USDC
- ZERO: 10 USDC
Entry Price: $99,999.99999999
Exit Price: $100,000.00000000 (Unverified)
Outcome: UP (Unverified)
Prediction Rewards (Unverified)
Player | Prediction | Deposit | Payout | Profit Percentage |
---|---|---|---|---|
UpInna | UP | 15 USDC | 50.49 USDC | +236.6% |
UpBob | UP | 10 USDC | 33.66 USDC | +236.6% |
UpBob’s verification is confirmed, finalizing the Outcome. The final price point is verified as the Exit Price. This signifies the Outcome as permanent on the blockchain.
Public Information
Payouts:
- UpBob: 33.66 USDC (commission: 0.33 USDC)
Predictions:
- ZeroIda: 10 USDC (ZERO)
- UpInna: 15 USDC (UP)
- DownOw: 50 USDC (DOWN)
- UpBob: 10 USDC (UP)
Prize Pool: 85 USDC (total)
- UP: 25 USDC
- DOWN: 50 USDC
- ZERO: 10 USDC
Entry Price: $99,999.99999999
Exit Price: $100,000.00000000
Outcome: UP
Rewards
Player | Prediction | Deposit | Payout | Profit Percentage |
---|---|---|---|---|
UpInna | UP | 15 USDC | 50.49 USDC | +236.6% |
UpBob | UP | 10 USDC | 33.66 USDC | +236.6% |
UpInna’s decited to withdraw her reward after 10 days delay.
UpBob’s verification of the Outcome within the first 24 hours permanently confirmed it on the blockchain. This crucial step enabled UpInna to execute her delayed claim of the Prediction Reward.
UpInna’s withdrawal, published on the blockchain, marks the completion of the Round and the start of the Archive Phase. With all rewards claimed, the Round becomes immutable, forever recorded on the blockchain.
Public Information (Archived)
Payouts:
- UpInna: 50.49 USDC (commission: 0.51 USDC)
- UpBob: 33.66 USDC (commission: 0.33 USDC)
Predictions:
- ZeroIda: 10 USDC (ZERO)
- UpInna: 15 USDC (UP)
- DownOw: 50 USDC (DOWN)
- UpBob: 10 USDC (UP)
Prize Pool: 85 USDC (total)
- UP: 25 USDC
- DOWN: 50 USDC
- ZERO: 10 USDC
Entry Price: $99,999.99999999 per BTC
Exit Price: $100,000.00000000 per BTC
Outcome: UP
Player | Prediction | Deposit | Payout | Profit Percentage |
---|---|---|---|---|
UpInna | UP | 15 USDC | 50.49 USDC | +236.6% |
UpBob | UP | 10 USDC | 33.66 USDC | +236.6% |
A nonstop series of prediction rounds where players predict cryptocurrency price movements for a chance to win rewards.
A self-contained prediction contest where players predict whether the price of a selected asset will go UP, DOWN, or remain the same (ZERO) within a short timeframe. Rounds progress through Entry, Round, Settlement, Payout, and Archive phases. At the end of the short round Player with Prediction matching actual price movement share the Prize Pool proportionally to their deposit.
Players place their Predictions (UP, DOWN, ZERO) with deposits for the selected asset’s price movement. This phase determines the Entry Price that all predictions are based on, and the minimum deposit size depends on the Game Level.
Game Level | Minimum Deposit |
---|---|
Bronze | 1 USDC |
Silver | 10 USDC |
Gold | 100 USDC |
During the Round Phase, funds is locked and players wait for the Outcome. Predictions can’t be changed. The Prize Pool is finalized, and Players await the Feed to publish the final price point of the phase, which will determine the round’s Outcome.
The Feed publishes final price point of the Round Phase and the Outcome becomes publicly known. However, Outcome requires protocol’s verification to become permanent. The first player to withdraw their Prediction Reward or Refund performs this verification.
Players with winning predictions withdraw their share of the Prize Pool, with payouts based on their deposit size. Protocol collects 1% of Oracly Commission. If the round was NO CONTEST, players withdraw Refunds.
Once a round enters the Archive Phase, it’s permanently closed, signifying the end of its lifecycle. All outcomes, predictions, and payouts are finalized and recorded on the blockchain for transparency and historical reference.
The sum of all player deposits that will be distributed to winners at the end of a Round.
Funds that was collected from the Oracly Protocol and distributed as rewards for Stakers and Mentors:
Oracly Protocol utilizes two types of commissions:
The payout a player earns if they correctly predict whether an asset’s price will go UP, DOWN, or stay the same (ZERO) within a game round. The larger the deposit, and the smaller the amount of funds deposited by who picked the same outcome, the bigger potential reward.
Prediction Reward can be calcualted using Reward (R(d)).
Oracly Protocol takes 1% commission on withdrwas of reward for prediction.
Example: In a round with a 1000 USDC Prize Pool, Where 200 USDC was deposited on the winning UP outcome, The deposit of 50 USDC, could earn 247.5 USDC reward.
A Refund is the full return of a player’s deposit when a round is declared NO CONTEST.
Refund mechanism ensures that players do not lose their deposited funds due to unforeseen circumstances or technical issues affecting the Outcome. Oracly Protocol does not collect any commission in a NO CONTEST scenario.
Refund Occurs:
A NO CONTEST round, and subsequent Refunds, can be triggered by various events, such as:
The actual change in the selected asset’s price between Entry Price and Exit Price of the Round, as published by the Chainlink Price Feed. Outcome can be UP, DOWN, ZERO, or NO CONTEST.
IMPORTANT Precision of the price points in the Feed is 8 decimals. Scenarios of NO CONTEST resolution:
The Chainlink network operates as a decentralized network of oracles, which are crucial in fetching and delivering external data to blockchain smart contracts. This decentralized arrangement enhances the reliability and security of the data, as it minimizes the risks associated with data manipulation by ensuring no single point of failure. This structure is particularly important because it helps maintain the integrity and accuracy of the data fed into smart contracts, which are foundational for Oracly Protocol.
Chainlink’s network consists of numerous independent nodes, known as oracles, that collectively work to fetch data from various external sources. These nodes are incentivized to perform accurately and reliably to maintain their reputation and effectiveness within the network. By aggregating data from multiple sources, Chainlink ensures that the final data provided to the smart contracts is well-rounded and robust against potential data-specific risks or inaccuracies.
An aggregator is the contract that receives periodic data updates from the Chainlink oracle network. Aggregators store aggregated data onchain so that consumers can retrieve it and act upon it within the same transaction.
The 3 Levels of Data Aggregation in Chainlink Price Feeds ↗
Price Feeds ↗ provide data that is aggregated from many data sources by a decentralized set of independent node operators. The Decentralized Data Model ↗ describes this in detail. Oracly Protocol uses Low Market Risk ↗ feeds to ensure consistent, accurate, and manipulation-resistant price data for fair outcomes.
Feed price points genesis mechanism Offchain Reporting (OCR) Tech Deep Dive: OCR Protocol Paper
A round of the game where the Outcome is publicly known (the asset’s price movement) but not yet verified and confirmed by Oracly Procotol contracts and therefore not yet permanent. While the Outcome is typically confirmed, there’s a possibility it could change if the protocol detects discrepancies in the Price Data.
Player who mentor Proteges. Mentor rewarded with 0.25% of each win payout to their Protege in currency of the payout.
A reward earned by Mentors within the Oracly Protocol ecosystem.
Example
A player who receives guidance and support from a more experienced player Mentors. Proteges benefit from their mentor’s knowledge, gaining valuable insights into crypto realm and the Oracly Protocol’ prediction game.
Polygon is a “layer two” or “sidechain” scaling solution that runs alongside the Ethereum blockchain — allowing for speedy transactions and low fees. MATIC is the network’s native cryptocurrency, which is used for gas fees on the platform.
MATIC is the native cryptocurrency of the Polygon (PoS) network. It’s primarily used to pay for transaction fees (gas fees) on the platform.
A player’s choice of Outcome (UP, DOWN, ZERO) within a round. If the prediction aligns with the actual price change, the player wins a share of the Prize Pool.
Determines the minimum amount player can deposit on a prediction within a single round. Oracly Protocol offers different Game Levels to cater to various player preferences and risk appetites.
Game Level | Minimum Deposit |
---|---|
Bronze | 1 USDC |
Silver | 10 USDC |
Gold | 100 USDC |
A special-purpose token used exclusively within the Oracly Protocol’s demonstration environment. It allows players to experience the gameplay and mechanics of the platform without risking real assets.
The native token of the Oracly Protocol.
The Oracly Staking Platform is a gateway to earning share of system income and becoming an integral part of the Oracly Protocol ecosystem. By staking ORCY tokens, Staker not only receive a share of the Oracly Commissions, but also gain the power to vote on proposals that shape the protocol’s future.
A unique feature within the Oracly Protocol that streamlines the process of acquiring ORCY tokens and immediately participating in staking. A significant 5,000,000 ORCY (50% of the total supply) is dedicated to the Buy4Stake feature, allocated at the time of ORCY token generation.
Buy4Stake Process
A pool of ORCY tokens within the Oracly Protocol where holders can securely lock their tokens for an arbitrary period.
Rewards earned by ORCY token holders who lock their tokens in the Oracly Staking Contract. Stakers claims a share of the Oracly Commissions based on the size of a Staking Deposit relative to the overall Staking Pool.
A recurring period (approximately 7 days) during which the staking pool remains unchanged. Staking Rewards are distributed as Oracly Commissions collected throughout the epoch are distributed proportionally to Stakers. Epochs ensure predictable staking cycles for Stakers.
IMPORTANT
An ORCY holder who locks their tokens in the Oracly Staking Contract to earn Staking Rewards and participate in Oracly Protocol’ governance.
The governing council within the Oracly Protocol. Presidium members is Stakers who hold at least 1% of the total ORCY supply staked and expricitly join Presidium community of Councilors, gaining the right to submit proposals. Presidium responsible for creating and executing proposals.
A Councilor is a member of the Presidium who holds at least 1% of the total ORCY supply staked. Councilors have the exclusive right to submit proposals for consideration by the Stakers, playing a crucial role in shaping the future direction of the platform through decentralized governance.
The initial staking period (approx. 7 days) during which a staker’s ORCY deposit is pending. Stakers cannot earn rewards in the Entry Epoch, but they can increase or withdraw their deposit. Staking Rewards begin in the epoch immediately following the Entry Epoch.
The specific quantity of ORCY tokens that a user commits to the Oracly Staking Contract. This deposit is locked for a Stakign Epoch and earns rewards based on its size relative to the total amount staked in the system. Staking Deposits also grant the user voting power in the protocol’s governance processes.
A state in a round where the Outcome (UP, DOWN, ZERO) is publicly known based on the Chainlink Price Feeds data, but not yet verified as Exit Price by the Oracly Protocol contracts. This is a temporary state that ensures the Outcome is accurate and hasn’t been tampered with before payouts are made.
May 10, 2024 (@metaferryman)