This documentation outlines the functionality of the Tellor adapter for DIVA Protocol v1.
-
System overview
3.1 Contract addresses and subgraphs
3.2 Ownership and privileges
3.3 Upgradeability
3.4 Audit -
Tellor contract
4.1 What is Tellor Protocol
4.2 How Tellor Protocol works
4.3 How to report values to Tellor Protocol -
Tellor adapter contract
5.1 How to use the Tellor adapter
5.2 Supported data feeds
5.3 Reporting software
5.4 Reporting rewards
5.5 Reporting costs
5.6 Function overview
5.7 Core functions
5.8 Getter functions
5.9 Reentrancy protection
5.10 Events
5.11 Errors
5.12 Risks and mitigants
DIVA Protocol is a smart contract that allows its users to create derivative contracts on virtually any metric with pre-defined expiration times. To calculate the payouts for the long and short positions of the contract, an oracle input is required following the derivative contract's expiration.
The Tellor adapter offers DIVA Protocol users a decentralized oracle solution for outcome reporting. Using the Tellor adapter for outcome reporting is as simple as assigning its contract address as the data provider when creating a pool.
The key benefits of using the Tellor adapter for outcome reporting include:
- No single point of failure as outcome reporting is decentralized and permissionless.
- No interruption in the reporting process following disputes, eliminating the need for additional requests.
- Option to add tips for additional reporting incentives.
These advantages provide users with a high level of confidence in correct settlement.
This documentation provides an overview of the Tellor Protocol, how the Tellor adapter works, and how it can be used in conjunction with DIVA Protocol. It is assumed that the reader has a basic understanding of DIVA Protocol.
Important: Users should familiarize themselves with the potential risks and the corresponding mitigation measures outlined in the "Risks and Mitigants" section prior to utilizing the Tellor adapter.
In this documentation, the following terms will be used interchangeably to refer to the same concepts:
- Derivative contract, contingent pool, and pool
- Protocol, smart contract, and contract
- Contract owner, DIVA owner, and owner; DIVA owner because the Tellor adapter inherits the owner from the same contract as DIVA Protocol
The DIVA Tellor integration is an interplay between three smart contracts:
- Tellor contract: The contract where reporters submit their values.
- DIVA contract: The contract that expects outcome reporting for expired pools.
- Tellor adapter contract: The connector contract that passes valid values from Tellor contract to the DIVA contract for settlement.
The interplay is visualized below. For the sake of simplicity, the reward claim process has been omitted from the illustration.
Relevant contract addresses and subgraphs are summarized below, grouped by network:
Name | |
---|---|
Tellor contract | Address of the contract where values are reported and TRB is staked. |
Tellor adapter contract | Address of the contract that connects the Tellor contract with the DIVA contract and to be used as data provider when creating a pool on DIVA Protocol. |
Tellor adapter playground contract | Playground version of Tellor adapter contract without the need to stake for reporting and a 10 seconds dispute period. Only available on testnets. |
DIVA contract | Address of the DIVA Protocol smart contract. |
TRB token | Address of the TRB token that needs to be staked in order to report values to the Tellor contract. |
Tellor governance contract | Address of the contract that handles Tellor disputes. |
DIVA subgraph explorer | Subgraph url to query DIVA pool related information in the browser. |
DIVA subgraph query API | Subgraph url to query DIVA pool related information in scripts. |
Name | |
---|---|
Tellor contract | 0xD9157453E2668B2fc45b7A803D3FEF3642430cC0 |
Tellor adapter contract | 0x7950db13cc37774614b0aa406e42a4c4f0bf26a6 |
DIVA contract | 0x2C9c47E7d254e493f02acfB410864b9a86c28e1D |
TRB token | 0x88dF592F8eb5D7Bd38bFeF7dEb0fBc02cf3778a0 |
Tellor governance contract | 0x46038969D7DC0b17BC72137D07b4eDe43859DA45 |
DIVA subgraph explorer | n/a |
DIVA subgraph query API | n/a |
Name | |
---|---|
Tellor contract | 0xD9157453E2668B2fc45b7A803D3FEF3642430cC0 |
Tellor adapter contract | 0x7950db13cc37774614b0aa406e42a4c4f0bf26a6 |
DIVA contract | 0x2C9c47E7d254e493f02acfB410864b9a86c28e1D |
TRB token | 0xe3322702bedaaed36cddab233360b939775ae5f1 |
Tellor governance contract | 0x46038969D7DC0b17BC72137D07b4eDe43859DA45 |
DIVA subgraph explorer | https://thegraph.com/explorer/subgraph/divaprotocol/diva-protocol-v1-polygon |
DIVA subgraph query API | https://api.thegraph.com/subgraphs/name/divaprotocol/diva-protocol-v1-polygon |
Name | |
---|---|
Tellor contract | 0xD9157453E2668B2fc45b7A803D3FEF3642430cC0 |
Tellor adapter contract | 0x7950db13cc37774614b0aa406e42a4c4f0bf26a6 |
DIVA contract | 0x2C9c47E7d254e493f02acfB410864b9a86c28e1D |
TRB token | 0xaad66432d27737ecf6ed183160adc5ef36ab99f2 |
Tellor governance contract | 0x46038969D7DC0b17BC72137D07b4eDe43859DA45 |
DIVA subgraph explorer | https://thegraph.com/hosted-service/subgraph/divaprotocol/diva-protocol-v1-gnosis |
DIVA subgraph query API | https://api.thegraph.com/subgraphs/name/divaprotocol/diva-protocol-v1-gnosis |
Name | |
---|---|
Tellor contract | 0xD9157453E2668B2fc45b7A803D3FEF3642430cC0 |
Tellor adapter contract | 0x7950db13cc37774614b0aa406e42a4c4f0bf26a6 |
DIVA contract | 0x2C9c47E7d254e493f02acfB410864b9a86c28e1D |
TRB token | 0xd58D345Fd9c82262E087d2D0607624B410D88242 |
Tellor governance contract | 0x46038969D7DC0b17BC72137D07b4eDe43859DA45 |
DIVA subgraph explorer | n/a |
DIVA subgraph query API | n/a |
Name | |
---|---|
Tellor contract | 0xD9157453E2668B2fc45b7A803D3FEF3642430cC0 |
Tellor adapter contract | 0x7950db13cc37774614b0aa406e42a4c4f0bf26a6 |
Tellor adapter playground contract | 0x0625855A4D292216ADEFA8043cDc69a6c99724C9 |
DIVA contract | 0x2C9c47E7d254e493f02acfB410864b9a86c28e1D |
TRB token | 0x51c59c6cAd28ce3693977F2feB4CfAebec30d8a2 |
Tellor governance contract | 0x46038969D7DC0b17BC72137D07b4eDe43859DA45 |
DIVA subgraph explorer | n/a |
DIVA subgraph query API | n/a |
Name | |
---|---|
Tellor contract | 0x199839a4907ABeC8240D119B606C98c405Bb0B33 |
Tellor adapter contract (linked to Tellor contract) | 0x7950db13cc37774614b0aa406e42a4c4f0bf26a6 |
Tellor playground contract | 0x3251838bd813fdf6a97D32781e011cce8D225d59 |
Tellor adapter playground contract (linked to Tellor playground contract) | 0x0625855A4D292216ADEFA8043cDc69a6c99724C9 |
DIVA contract | 0x2C9c47E7d254e493f02acfB410864b9a86c28e1D |
TRB token | 0x80fc34a2f9FfE86F41580F47368289C402DEc660 |
Tellor governance contract | 0x8C9057FA16D3Debb703ADBac0A097d2E5577AA6b |
DIVA subgraph explorer | n/a |
DIVA subgraph query API | n/a |
The Tellor adapter contract implements an owner which is inherited from the DIVA Ownership contract, which is the same contract that DIVA Protocol inherits their owner from. The owner is authorized to update the maximum amount of DIVA rewards that a reporter can receive, denominated in USD, as well as the recipient of any excess DIVA reward.
The update process is the same as in DIVA Protocol. The owner initiates an update of the relevant value, which only becomes effective after a pre-defined delay. In the Tellor adapter contract, this delay is fixed at 3 days and cannot be modified. During this period, the contract owner has the ability to revoke the update if needed.
The Tellor adapter contract is not upgradeable.
The Tellor adapter contract was audited as part of the DIVA Protocol audit by six independent teams. The report is available in the DIVA Protocol GitHub repository.
The Tellor contract is where reporters submit their values to be used as the final reference value in DIVA Protocol. In this section, we will provide an overview of the Tellor Protocol and explain how users can report values to it.
Tellor is a decentralized oracle protocol that allows smart contracts on EVM chains to securely and reliably access data from off-chain sources, including data from other chains. It uses a decentralized network of stakers to provide this data, and incentivizes them with the Tellor token (TRB) to maintain the integrity of the network.
To participate in the Tellor Protocol as a reporter, users must stake TRB tokens. The amount of TRB required for one stake is equal to the minimum of $1'500 or 100 TRB. This allows a reporter to submit one value every 12 hours. If a user wishes to submit more values during the same period, they must stake additional TRB tokens in proportion to the number of values they wish to submit. For example, if a user wants to submit two values every 12 hours, they must stake twice the amount of TRB required for one stake.
Assuming that the value of TRB is at least $15 (corresponding to 100 TRB required for one stake), the reporting process is as follows:
- Reporters submit values to a specific key, also known as queryId. Only one value can be reported per queryId and block.
- If a reported value is deemed incorrect, anyone can dispute it for a maximum of 12 hours from the time of reporting. Disputers pay a dispute fee starting at 10 TRB, which doubles up to a maximum of 100 TRB with each round of dispute for a given queryId.
- Once a dispute is submitted, the potentially malicious reporter who submitted the value is placed in a locked state for the duration of the vote. For the next two days, TRB holders vote on the validity of the reported value. All TRB holders have an incentive to maintain an honest oracle and can vote on the dispute. The disputed value is removed from the key-value store and the reporting process continues uninterrupted, allowing other reporters to submit valid values. For more information on Tellor's dispute process, refer to the official Tellor docs.
To ensure the reliability of reported data, Tellor recommends that only data reports that have remained undisputed for a specified duration (up to 12 hours) should be considered valid. The Tellor adapter implements the maximum duration of 12 hours and utilizes the earliest value that satisfies this criterion as the settlement value, ignoring any subsequent values that also meet the condition.
For technical details on how to submit DIVA related values to the Tellor contract, refer to the corresponding Tellor documentation. The easiest and safest way to obtain the right queryData
and queryId
for submitting values to the Tellor contract is by using the getQueryDataAndId
function inside the Tellor adapter contract. Refer to the Tellor adapter test script for code examples and explore existing reporting software for further assistance.
The Tellor adapter contract serves as a bridge that retrieves values reported to the Tellor contract and forwards them to the DIVA contract for settlement. In this section, we will provide an overview how the Tellor adapter can be used for outcome reporting in DIVA Protocol.
Using the Tellor adapter for outcome reporting in DIVA Protocol is as simple as assigning its contract address as the data provider when creating a pool. The process of reporting outcomes for pools that use the Tellor adapter as the data provider consists of the following four elements:
-
Monitoring: To identify expired pools that require reporting, Tellor reporters monitor the DIVA subgraph or use DIVA Protocol's
getPoolParameters
function. -
Reporting to Tellor contract: When a pool expires, reporters submit their values to the Tellor contract during the applicable submission period, which lasts between 3 and 15 days. It's important to note that the effective submission period is shorter by the 12-hour dispute period. This means that any submissions made within the last 12 hours of the submission period will not be accepted due to the dispute delay that has to be respected.
-
Disputes: Tellor reporters monitor the submissions to the Tellor contract and dispute any incorrect submissions.
-
Reporting to DIVA contract: The first value that is submitted to the Tellor Protocol and remains undisputed for over 12h will be considered the final value. By calling the
setFinalReferenceValue
function on the Tellor adapter contract, this value is then passed on to DIVA Protocol which is used to determine the payouts for the pool. With that, the value is confirmed and no further submissions to DIVA Protocol are possible thereafter. Note that submissions to the Tellor contract made before pool expiration or for already confirmed pools will be ignored.
Refer to the reporting software section to learn more about software that automates the described reporting process.
The Tellor Protocol has the capability to handle any type of data. This universality extends to the Tellor adapter, which can be utilized with any data feed. To ensure high coverage by reporters, it's suggested to check with the Tellor community which data feeds are well-established and which may need extra support and communication.
There are two available versions of Tellor reporter software that facilitate the process of monitoring and reporting pools using the Tellor adapter as the data provider:
- DIVA focused Tellor reporter: Developed by the DIVA team, this software is designed to report outcomes for DIVA pools specifically.
- Generic Tellor reporter: Developed by the Tellor team, this software can be used to report values for anything, not necessarily focused on DIVA.
If you plan to build your own reporter software, please refer to the README for guidance.
Reporters receive rewards from two different sources:
- DIVA rewards from DIVA Protocol
- Tips from Tellor adapter
DIVA rewards are derived from two different sources:
- Settlement fee: DIVA Protocol pays a settlement fee of 0.05% (updateable by DIVA owner) of the gross collateral deposited into the pool over time to the data provider in the pool's collateral token. For example, reporting for a pool that has had USDC 100k in liquidity added over its lifetime would yield a settlement fee of USDC 50.
- Tips: In addition to the settlement fee, users can add a tip using DIVA Protocol's
addTip
function to incentivize reporting. This can be particularly useful when the gross collateral of the pool is relatively small and the settlement fee alone would not justify the gas cost for reporting. Note that in DIVA Protocol, the tip can only be given in the collateral token of the respective pool. Use the tipping functionality inside the Tellor adapter for more flexibility in that regard.
Important: The DIVA reward is capped at USD 10 per pool, with any excess fee going to the recipient specified by the contract owner. This measure was recommended by the Tellor team to prevent "dispute wars" where disputing valid submissions becomes a profitable strategy to receive an outsized reward.
The Tellor adapter contract also implements tipping via the addTip
function, which allows tipping in any ERC20 token. Unlike DIVA rewards, tips added to the Tellor adapter contract are not subject to the USD 10 cap. Reporters can select which tips they eventually want to claim.
To report data, two function calls are required, which together cost approximately 410k gas. The first function call, submitValue
in the Tellor contract, uses around 160k gas, while the second call, setFinalReferenceValue
in the Tellor adapter contract, uses around 250k gas. At a price of 100 Gwei/gas, the total gas fee for reporting is 41m Gwei or 0.041 ETH on Ethereum, 0.041 MATIC on Polygon, etc.
The following table shows the functions implemented in the Tellor adapter contract:
Function | Description | |
---|---|---|
Core functions | ||
setFinalReferenceValue |
Function to pass a value from the Tellor contract to the DIVA contract for settlement for a given poolId. The caller has the option to claim tips and/or DIVA rewards in the same call. | |
addTip |
Function to tip a pool in any ERC20 token. | |
claimReward |
Function to claim tips and/or DIVA rewards. | |
Governance functions (execution is reserved for DIVA owner only) | ||
updateExcessDIVARewardRecipient |
Function to update the excess DIVA reward recipient address. | |
updateMaxDIVARewardUSD |
Function to update the maximum USD DIVA reward that goes to the reporter. | |
revokePendingExcessDIVARewardRecipientUpdate |
Function to revoke a pending excess DIVA reward recipient address update and restore the previous one. | |
revokePendingMaxDIVARewardUSDUpdate |
Function to revoke a pending maximum USD DIVA reward update and restore the previous one. | |
Getter functions | ||
getChallengeable |
Function to return whether the Tellor adapter's data feed is challengeable inside DIVA Protocol. In this implementation, the function always returns false , which means that the first value submitted to DIVA Protocol will determine the payouts, and users can start claiming their payouts thereafter. |
|
getExcessDIVARewardRecipientInfo |
Function to return the excess DIVA reward recipient info, including the last update, its activation time and the previous value. | |
getMaxDIVARewardUSDInfo |
Function to return the max USD DIVA reward info, including the last update, its activation time and the previous value. | |
getMinPeriodUndisputed |
Function to return the minimum period (in seconds) a reported value has to remain undisputed in order to be considered valid. Hard-coded to 12 hours (= 43'200 seconds) in this implementation. | |
getTippingTokensLengthForPoolIds |
Function to return the number of tipping tokens for a given set of poolIds. | |
getTippingTokens |
Function to return the array of tipping tokens for a given set of poolIds. | |
getTipAmounts |
Function to return the tipping amounts for a given set of poolIds and tipping tokens. | |
getReporters |
Function to return the list of reporter addresses that are entitled to receive rewards for a given list of poolIds. | |
getPoolIdsLengthForReporters |
Function to return the number of poolIds that a given list of reporter addresses are eligible to claim rewards for. Useful before calling getPoolIdsForReporters . |
|
getPoolIdsForReporters |
Function to return a list of poolIds that a given list of reporters is eligible to claim rewards for. | |
getDIVAAddress |
Function to return the DIVA address that the oracle is linked to. | |
getOwnershipContract |
Function to return the DIVA ownership contract contract address that stores the contract owner. The owner can be obtained by calling the getOwner function at the returned contract address. |
|
getActivationDelay |
Function to return the activation delay (in seconds) for governance related updates. Hard-coded to 3 days (= 259'200 seconds). | |
getQueryDataAndId |
Function to return the query data and Id for a given poolId which are required for reporting values via Tellor's submitValue function. |
|
Batch functions | ||
batchSetFinalReferenceValue |
Batch version of setFinalReferenceValue function. |
|
batchClaimReward |
Batch version of claimReward function. |
|
batchAddTip |
Batch version of addTip function. |
Function to set the final reference value for a given _poolId
. It retrieves the first value that was submitted to the Tellor contract after the pool expiration and remained undisputed for at least 12 hours, and passes it on to the DIVA smart contract for settlement. The address of the reporter who submitted the final reference value to the Tellor smart contract will be stored within the _poolIdToReporter
mapping and will be eligible to claim the reward.
The caller, which can be anyone, can trigger the claim of the rewards in the same call by specifying which tips to claim from the Tellor adapter contract using the _tippingTokens
array and/or by indicating whether to claim the DIVA reward by setting the _claimDIVAReward
parameter to true
. The tipping tokens associated with a pool can be obtained via the getTippingTokens
function. Any reward that is not claimed during this function call can be claimed later using the claimReward
function.
If no tipping tokens are provided and _claimDIVAReward
is set to false
, the function will not claim any rewards and users can claim them separately via the claimReward
function.
Note that the DIVA reward, which includes the settlement fee and any tip added via DIVA's addTip
function (not to be confused with the addTip
function inside the Tellor adapter), is capped at USD 10. The remaining reward goes to the excess DIVA reward recipient address set by the DIVA owner. This measure was put in place to prevent "dispute wars" where disputing valid submissions becomes a profitable strategy to receive an outsized reward. Note that tips added via the addTip
function to the Tellor adapter contract are not affected by this cap.
Important: The function
setFinalReferenceValue
should be called within submission window of the pool. This window is restricted by the DIVA smart contract to a range of 3 to 15 days and can be retrieved via DIVA'sgetSettlementPeriods
function by passing theindexSettlementPeriods
obtained viagetPoolParameters
.
The function executes the following steps in the following order:
- Load the pool parameters from the DIVA smart contract.
- Get the queryId for the specified
poolId
to look up the reported value inside the Tellor contract. - Retrieve the submitted values, which include the final reference value and the USD value of the collateral token. Latter is used to calculate the equivalent of the USD 10 reward cap in collateral token.
- Confirm that the value pair has been submitted after pool expiration and remained undisputed for at least 12 hours. Note that disputed values will be removed from the key-value store and not returned during the
getDataAfter
call. - Decode the submitted values.
- Retrieve the reporter address and store it as the eligible address to claim the reward inside the
_poolIdToReporter
mapping. - Add an entry to
_reporterToPoolIds
array to allow reporters to retrieve the pools that they are eligible for viagetPoolIdsForReporters
. - Pass on the final reference value to the DIVA smart contract to determine the payouts. Note that DIVA's challenge feature is disabled and the first value successfully submitted will be confirmed, allowing position token holders to start claiming their payouts.
- Calculate the USD equivalent of the collateral token, and then credit the eligible reporter with their respective amount, up to a maximum of USD 10. Any excess reward beyond USD 10 will be credited to the excess DIVA reward recipient. Please note that DIVA rewards are not claimed in this step, but rather re-allocated from the contract to the eligible reporter, as the contract acts as the data provider in the pool. DIVA rewards are claimed in the same function call if the
_claimDIVAReward
parameter is set totrue
or laster using theclaimReward
function. - Emit a
FinalReferenceValueSet
event on success. - If
_tippingTokens
are provided and/or the_claimDIVAReward
parameter is set totrue
, proceed with the same steps as outlined inclaimReward
.
The function reverts under the following conditions:
- No value has been reported after pool expiration. In this case
getDataAfter
returnstimestampRetrieved = 0
. Reverts with aNoOracleSubmissionAfterExpiryTime
error. - A value has been submitted but the minimum dispute period of 12 hours hasn't passed yet. Reverts with a
MinPeriodUndisputedNotPassed
error. - Triggered outside of the submission window for the pool.
function setFinalReferenceValue(
bytes32 _poolId, // The Id of the pool
address[] calldata _tippingTokens, // Array of tipping tokens to claim
bool _claimDIVAReward // Flag indicating whether to claim the DIVA reward
)
external;
Batch version of setFinalReferenceValue
.
function batchSetFinalReferenceValue(
ArgsBatchSetFinalReferenceValue[] calldata _argsBatchSetFinalReferenceValue
)
external;
where ArgsBatchSetFinalReferenceValue
is given by
struct ArgsBatchSetFinalReferenceValue {
bytes32 poolId; // The Id of the pool
address[] tippingTokens; // Array of tipping tokens to claim
bool claimDIVAReward; // Flag indicating whether to claim the DIVA reward
}
Function to tip a pool. Tips can be added in a wide range of ERC20 tokens until the final value has been submitted and confirmed in DIVA Protocol by successfully calling the setFinalReferenceValue
function. Tips can be claimed via the claimReward
function after final value confirmation. Refer to batchAddTip
for the batch version of the function.
❗Important: Rebasable and fee-on-transfer tokens are not supported! While deposits of tokens that charge fees on transfers will be rejected by the contract, deposits of rebasable tokens won't. When tokens with a flexible supply are considered, only tokens with a constant balance mechanism such as Compound's cToken or the wrapped version of Lido's staked ETH (wstETH) should be used.
The function executes the following steps in the following order:
- Confirm that the final value hasn't been submitted to DIVA Protocol yet, in which case
_poolIdToReporter
would resolve to the zero address. - Add a new entry in the
_poolIdToTippingTokens
array if the specified_tippingToken
does not yet exist for the specified pool. - Update balance before doing a potentially unsafe
safeTransferFrom
call. Requires prior user approval to succeed. - Transfer tipping token from
msg.sender
to this contract if the token didn't charge fees on the transfer. - Emit a
TipAdded
event on success.
The function reverts under the following conditions:
- The final value has already been submitted and confirmed in DIVA Protocol.
- The
msg.sender
has insufficient balance or allowance for the_tippingToken
. - The tipping token charges a fee on transfers. It's important to reiterate that the function will not revert if rebasable tokens are used!
function addTip(
bytes32 _poolId, // The Id of the pool
uint256 _amount, // The amount to tip expressed as an integer with tipping token decimals
address _tippingToken // Tipping token address
)
external;
Note: DIVA Protocol also has an
addTip
function, but it only allows tipping with the collateral token of the pool. When a tip is added through DIVA'saddTip
function, it is credited to the Tellor reporter along with the settlement fees (combined referred to as DIVA reward) once the final value is confirmed.
Batch version of addTip
.
function batchAddTip(
ArgsBatchAddTip[] calldata _argsBatchAddTip
)
external;
where ArgsBatchAddTip
is given by
struct ArgsBatchAddTip {
bytes32 poolId; // The Id of the pool
uint256 amount; // The amount to tip expressed as an integer with tipping token decimals
address tippingToken; // Tipping token address
}
Function to claim tips and/or DIVA rewards. Users can specify which tips to claim from the Tellor adapter contract using the _tippingTokens
array, and can indicate whether they want to claim the DIVA reward by setting the _claimDIVAReward
parameter to true
. Users can obtain the tipping tokens associated with a pool by calling the getTippingTokens
function.
It's important to note that rewards can only be claimed after the final value has been submitted and confirmed in the DIVA Protocol by successfully calling the setFinalReferenceValue
function. This function can be triggered by anyone to transfer the rewards to the eligible reporter.
The function executes the following steps in the following order:
- Check that pool has already been confirmed.
- Check whether the caller has provided any tipping tokens in the
_tippingTokens
array. If tipping tokens are provided, the function will proceed with the following steps. If not, the function will skip these steps.- Retrieve the tip amount for the pool in the specified tipping token.
- Set the tip amount to zero to prevent multiple payouts in case the same tipping token is provided multiple times.
- Transfer the tip from the Tellor adapter contract to the eligible reporter stored in the
_poolIdToReporter
mapping (set during successful execution of thesetFinalReferenceValue
function). - Emit a
TipClaimed
event for each tipping token claimed.
- If the
_claimDIVAReward
parameter is set totrue
, the function will trigger the claim of the DIVA reward from the DIVA smart contract:- Retrieve the collateral token of the pool from the pool parameters stored within the DIVA smart contract.
- Transfer the reward to the eligible reporter via the
claimFee
function. - Emit a
FeeClaimed
event on successful completion of theclaimFee
function.
**Note: ** If no tipping tokens are provided and
_claimDIVAReward
is set tofalse
, the function will not execute anything, but will not revert. Further note, that the DIVA reward can also be claimed directly from the DIVA smart contract by calling theclaimFee
function.
function claimReward(
bytes32 _poolId, // The Id of the pool
address[] memory _tippingTokens, // Array of tipping tokens to claim
bool _claimDIVAReward // Flag indicating whether to claim the DIVA reward
)
external;
Batch version of claimReward
.
function batchClaimReward(
ArgsBatchClaimReward[] calldata _argsBatchClaimReward
)
external;
where ArgsBatchClaimReward
is given by
struct ArgsBatchClaimReward {
bytes32 poolId; // The Id of the pool
address[] tippingTokens; // Array of tipping tokens to claim
bool claimDIVAReward; // Flag indicating whether to claim the DIVA reward
}
The execution of the following functions is reserved to the contract owner only.
Function to update the excess DIVA reward recipient address. Activation is restricted to the contract owner and subject to a 3-day delay. On success, emits a ExcessDIVARewardRecipientUpdated
event including the new excess DIVA reward recipient address as well as its activation time. A pending update can be revoked by the contract owner using the revokePendingExcessDIVARewardRecipientUpdate
. The previous excess DIVA reward recipient address as well as the current one can be obtained via the getExcessDIVARewardRecipientInfo
function.
Reverts if:
msg.sender
is not contract owner.- provided address equals zero address.
- there is already a pending excess DIVA reward recipient address update.
function updateExcessDIVARewardRecipient(
address _newExcessDIVARewardRecipient // New excess DIVA reward recipient address
)
external;
Function to update the maximum amount of DIVA reward that a reporter can receive, denominated in USD. Activation is restricted to the contract owner and subject to a 3-day delay. On success, emits a MaxDIVARewardUSDUpdated
event including the new excess DIVA reward recipient address as well as its activation time. A pending update can be revoked by the contract owner using the revokePendingMaxDIVARewardUSDUpdate
. The previous amount as well as the current one can be obtained via the getMaxDIVARewardUSDInfo
function.
Reverts if:
msg.sender
is not contract owner.- there is already a pending amount update.
function updateMaxDIVARewardUSD(
uint256 _newMaxDIVARewardUSD // New amount expressed as an integer with 18 decimals
)
external;
Function to revoke a pending excess DIVA reward recipient update and restore the previous one. On success, emits a PendingExcessDIVARewardRecipientUpdateRevoked
event including the revoked and restored excess DIVA reward recipient address.
Reverts if:
msg.sender
is not contract owner.- New excess DIVA reward recipient is already active (i.e.
block.timestamp >= startTime
).
function revokePendingExcessDIVARewardRecipientUpdate()
external;
Function to revoke a pending max USD DIVA reward update and restore the previous one. On success, emits a PendingMaxDIVARewardUSDUpdateRevoked
event including the revoked and restored amount.
Reverts if:
msg.sender
is not contract owner.- New amount is already active (i.e.
block.timestamp >= startTime
).
function revokePendingMaxDIVARewardUSDUpdate()
external;
The Tellor adapter implements the following getter functions.
Function to return whether the Tellor adapter's data feed is challengeable inside DIVA Protocol. In this implementation, the function always returns false
, which means that the first value submitted to DIVA Protocol will determine the payouts, and users can start claiming their payouts thereafter.
function getChallengeable()
external
view
returns (bool);
Function to return the excess DIVA reward recipient info, including the last update, its activation time and the previous value. The initial excess DIVA reward recipient is set when the contract is deployed. The previous excess DIVA reward recipient is set to the zero address initially.
function getExcessDIVARewardRecipientInfo()
external
view
returns (
address previousExcessDIVARewardRecipient, // Previous excess DIVA reward recipient address.
address excessDIVARewardRecipient, // Latest update of the excess DIVA reward recipient address.
uint256 startTimeExcessDIVARewardRecipient // Timestamp in seconds since epoch at which `excessDIVARewardRecipient` is activated.
);
Function to return the max USD DIVA reward info, including the last update, its activation time and the previous value. The initial value is set when the contract is deployed. The previous value is set to zero initially.
function getMaxDIVARewardUSDInfo()
external
view
returns (
uint256 previousMaxDIVARewardUSD, // Previous value
uint256 maxDIVARewardUSD, // Latest update of the value
uint256 startTimeMaxDIVARewardUSD // Timestamp in seconds since epoch at which `maxDIVARewardUSD` is activated
);
Function to return the minimum period (in seconds) a reported value has to remain undisputed in order to be considered valid. Hard-coded to 12 hours (= 43'200 seconds) in this implementation.
function getMinPeriodUndisputed()
external
view
returns (uint32);
Function to return the number of tipping tokens for a given set of poolIds. Useful before calling getTippingTokens
.
function getTippingTokensLengthForPoolIds(
bytes32[] calldata _poolIds // Array of poolIds
)
external
view
returns (uint256[] memory);
Function to return an array of tipping tokens for a given list of poolIds, along with start and end indices to manage the return size of the array. Useful before calling claimReward
or setFinalReferenceValue
.
function getTippingTokens(
ArgsGetTippingTokens[] calldata _argsGetTippingTokens // List containing poolId, start index and end index
)
external
view
returns (address[][] memory);
where ArgsGetTippingTokens
struct is defined as
struct ArgsGetTippingTokens {
bytes32 poolId; // The Id of the pool
uint256 startIndex; // Start index within the `_poolIdToTippingTokens` mapping array
uint256 endIndex; // End index within the `_poolIdToTippingTokens` mapping array
}
Function to return the tipping amounts for a given set of poolIds and tipping tokens.
function getTipAmounts(
ArgsGetTipAmounts[] calldata _argsGetTipAmounts
)
external
view
returns (uint256[][] memory);
where ArgsGetTipAmounts
struct is defined as
struct ArgsGetTipAmounts {
bytes32 poolId; // The Id of the pool
address[] tippingTokens; // List of tipping token addresses
}
Function to return the list of reporter addresses that are entitled to receive rewards for a given list of poolIds. If a value has been reported to the Tellor contract but hasn't been pulled into the DIVA contract via the setFinalReferenceValue
function yet, the function returns the zero address.
function getReporters(
bytes32[] calldata _poolIds // List of poolIds
)
external
view
returns (address[] memory);
Function to return the number of poolIds that a given list of reporter addresses are eligible to claim rewards for. Useful before calling getPoolIdsForReporters
.
function getPoolIdsLengthForReporters(
address[] calldata _reporters // List of reporter address
)
external
view
returns (uint256[] memory);
Function to return a list of poolIds that a given list of reporters are eligible to claim rewards for. It takes a list of reporter addresses, as well as the start and end indices as input to manage the return size of the array. Useful before calling claimReward
or its batch version.
function getPoolIdsForReporters(
ArgsGetPoolIdsForReporters[] calldata _argsGetPoolIdsForReportersindex
)
external
view
returns (bytes32[][] memory);
where ArgsGetPoolIdsForReporters
struct is defined as
struct ArgsGetPoolIdsForReporters {
address reporter; // Reporter address
uint256 startIndex; // Start index within the `_reporterToPoolIds` mapping array
uint256 endIndex; // End index within the `_reporterToPoolIds` mapping array
}
Function to return the DIVA contract address that the Tellor adapter is linked to. The address is set in the constructor at contract deployment and cannot be modified.
function getDIVAAddress()
external
view
returns (address);
Function to return the DIVA ownership contract address that stores the contract owner. The owner can be obtained by calling the getOwner
function at the returned contract address.
function getOwnershipContract()
external
view
returns (address);
Function to return the activation delay (in seconds) for governance related updates. Hard-coded to 3 days (= 259'200 seconds).
function getActivationDelay()
external
pure
returns (uint256);
Function to return the query data and Id for a given poolId which are required for reporting values via Tellor's submitValue
function. Read more about it in the Tellor docs.
function getQueryDataAndId(
bytes32 _poolId // The Id of the pool
)
external
view
returns (
bytes memory, // queryData
bytes32 // queryId
);
All state-modifying functions, including their batch versions, implement openzeppelin's nonReentrant
modifier to protect against reentrancy attacks, with the exception of governance related functions.
Emitted when the final reference value is set via the setFinalReferenceValue
function.
event FinalReferenceValueSet(
bytes32 indexed poolId, // The Id of the pool
uint256 finalValue, // Tellor value expressed as an integer with 18 decimals
uint256 expiryTime, // Pool expiry time as a unix timestamp in seconds
uint256 timestamp // Tellor value timestamp
);
Emitted when a tip is added via the addTip
function.
event TipAdded(
bytes32 poolId, // The Id of the tipped pool
address tippingToken, // Tipping token address
uint256 amount, // Tipping token amount expressed as an integer with tipping token decimals
address tipper // Tipper address
);
Emitted when the reward is claimed via the claimReward
function.
event TipClaimed(
bytes32 poolId, // The Id of the pool
address recipient, // Address of the tip recipient
address tippingToken, // Tipping token address
uint256 amount // Claimed amount expressed as an integer with tipping token decimals
);
Emitted when the excess DIVA reward recipient is updated via the updateExcessDIVARewardRecipient
function.
event ExcessDIVARewardRecipientUpdated(
address indexed from, // Address that initiated the change (contract owner)
address indexed excessDIVARewardRecipient, // New excess DIVA reward recipient address
uint256 startTimeExcessDIVARewardRecipient // Timestamp in seconds since epoch at which the new excess DIVA reward recipient will be activated
);
Emitted when the max USD DIVA reward is updated via the updateMaxDIVARewardUSD
function.
event MaxDIVARewardUSDUpdated(
address indexed from, // Address that initiated the change (contract owner)
uint256 maxDIVARewardUSD, // New max USD DIVA reward expressed as an integer with 18 decimals
uint256 startTimeMaxDIVARewardUSD // Timestamp in seconds since epoch at which the new max USD DIVA reward will be activated
);
Emitted when a pending excess DIVA reward recipient update is revoked via the revokePendingExcessDIVARewardRecipientUpdate
function.
event PendingExcessDIVARewardRecipientUpdateRevoked(
address indexed revokedBy, // Address that initiated the revocation
address indexed revokedExcessDIVARewardRecipient, // Pending excess DIVA reward recipient that was revoked
address indexed restoredExcessDIVARewardRecipient // Previous excess DIVA reward recipient that was restored
);
Emitted when a pending max USD DIVA reward update is revoked via the revokePendingMaxDIVARewardUSDUpdate
function.
event PendingMaxDIVARewardUSDUpdateRevoked(
address indexed revokedBy, // Address that initiated the revocation
uint256 revokedMaxDIVARewardUSD, // Pending max USD DIVA reward that was revoked
uint256 restoredMaxDIVARewardUSD // Previous max USD DIVA reward that was restored
);
The following errors may be emitted during execution of the functions, including their batch versions.
Error name | Function | Description |
---|---|---|
NotConfirmedPool() |
claimReward / setFinalReferenceValue |
Thrown if rewards are claimed before a pool was confirmed. |
AlreadyConfirmedPool() |
addTip |
Thrown if user tries to add a tip for an already confirmed pool |
FeeTokensNotSupported() |
addTip |
Thrown if the tipping token implements a fee |
ZeroExcessDIVARewardRecipient() |
updateExcessDIVARewardRecipient / constructor |
Thrown if the zero address is passed as excess DIVA reward recipient address. |
NoOracleSubmissionAfterExpiryTime() |
setFinalReferenceValue |
Thrown if there is no data reported after the expiry time for the underlying pool. |
MinPeriodUndisputedNotPassed() |
setFinalReferenceValue |
Thrown if user tries to call setFinalReferenceValue before the minimum period undisputed period has passed. |
ZeroOwnershipContractAddress() |
constructor | Thrown in constructor if zero address is provided as ownershipContract. |
ZeroDIVAAddress() |
constructor | Thrown in constructor if zero address is provided for DIVA Protocol contract. |
NotContractOwner(address _user, address _contractOwner) |
updateExcessDIVARewardRecipient / updateMaxDIVARewardUSD / revokePendingExcessDIVARewardRecipientUpdate / revokePendingMaxDIVARewardUSDUpdate |
Thrown in constructor if zero address is provided as ownershipContract. |
PendingExcessDIVARewardRecipientUpdate(uint256 _timestampBlock, uint256 _startTimeExcessDIVARewardRecipient) |
updateExcessDIVARewardRecipient |
Thrown if there is already a pending excess DIVA reward recipient address update. |
PendingMaxDIVARewardUSDUpdate(uint256 _timestampBlock, uint256 _startTimeMaxDIVARewardUSD) |
updateMaxDIVARewardUSD |
Thrown if there is already a pending max USD DIVA reward update. |
ExcessDIVARewardRecipientAlreadyActive(uint256 _timestampBlock, uint256 _startTimeExcessDIVARewardRecipient) |
revokePendingExcessDIVARewardRecipientUpdate |
Thrown if the excess DIVA reward recipient update to be revoked is already active. |
MaxDIVARewardUSDAlreadyActive(uint256 _timestampBlock, uint256 _startTimeMaxDIVARewardUSD) |
revokePendingMaxDIVARewardUSDUpdate |
Thrown if the max USD DIVA reward update to be revoked is already active. |
Using the Tellor adapter as data provider for DIVA pools comes with the following risks:
Risks | Mitigants |
---|---|
No value is reported because the reward from reporting does not justify the associated cost (e.g., due to high gas price or small pool size). | Add tips or report yourself. |
No value is reported because the data point is not available. | Use publicly available and verifiable metrics as your reference asset. Additionally, when choosing pools, prioritize those with expiration dates that are not too far in the future to minimize the risk of data unavailability. |
An inaccurate value submitted to the Tellor contract remains undisputed for more than 12h and is pushed into DIVA Protocol resulting in inaccurate payouts. | Use metrics that are closely monitored and accurately reported by many reporters. |
Bug in Tellor adapter contract. | All three contracts involved in the DIVA Tellor integration, including the Tellor adapter contract, have been audited to reduce the likelihood of bugs. |