This repository has been archived by the owner on Mar 3, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTellorOracle.sol
124 lines (109 loc) · 5.36 KB
/
TellorOracle.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// SPDX-License-Identifier: UNLICENSED
// Copyright (c) 2023 Tokemak Foundation. All rights reserved.
pragma solidity 0.8.17;
import { BaseOracleDenominations, ISystemRegistry } from "src/oracles/providers/base/BaseOracleDenominations.sol";
import { IEthValueOracle } from "src/interfaces/pricing/IEthValueOracle.sol";
import { Errors } from "src/utils/Errors.sol";
import { UsingTellor } from "usingtellor/UsingTellor.sol";
/**
* @title Gets the spot price of tokens that Tellor provides a feed for.
* @dev Will convert all tokens to Eth pricing regardless of original denomination.
* @dev Returns 18 decimals of precision.
*/
contract TellorOracle is BaseOracleDenominations, UsingTellor {
/**
* @notice Used to store information about Tellor price queries.
* @dev No decimals, all returned in e18 precision.
* @param queryId bytes32 queryId for pricing query. See here: https://tellor.io/queryidstation/.
* @param pricingTimeout Custom timeout for asset. If 0, contract will use default defined in
* `BaseOracleDenominations.sol`.
* @param denomination Enum representing denomination of price returned.
*/
struct TellorInfo {
bytes32 queryId;
uint32 pricingTimeout;
Denomination denomination;
}
/// @dev Token address to TellorInfo structs.
mapping(address => TellorInfo) private tellorQueryInfo;
/// @notice Emitted when information about a Tellor query is registered.
event TellorRegistrationAdded(address token, Denomination denomination, bytes32 _queryId);
/// @notice Emitted when information about a Tellor query is removed.
event TellorRegistrationRemoved(address token, bytes32 queryId);
constructor(
ISystemRegistry _systemRegistry,
address _tellorOracleAddress
)
// Tellor requires payable address
UsingTellor(payable(_tellorOracleAddress))
BaseOracleDenominations(_systemRegistry)
{
Errors.verifyNotZero(_tellorOracleAddress, "tellor");
}
/**
* @notice Allows permissioned address to set _queryId, denomination for token address.
* @param token Address of token to set queryId for.
* @param _queryId Bytes32 queryId.
* @param denomination Denomination of token.
* @param pricingTimeout Custom timeout for queryId if needed. Can be set to zero
* to use default defined in `BaseOracleDenominations.sol`.
*/
function addTellorRegistration(
address token,
bytes32 _queryId,
Denomination denomination,
uint32 pricingTimeout
) external onlyOwner {
Errors.verifyNotZero(token, "tokenForQueryId");
Errors.verifyNotZero(_queryId, "queryId");
if (tellorQueryInfo[token].queryId != bytes32(0)) revert Errors.MustBeZero();
tellorQueryInfo[token] =
TellorInfo({ queryId: _queryId, denomination: denomination, pricingTimeout: pricingTimeout });
emit TellorRegistrationAdded(token, denomination, _queryId);
}
/**
* @notice Allows permissioned removal registration for token address.
* @param token Token to remove TellorInfo struct for.
*/
function removeTellorRegistration(address token) external onlyOwner {
Errors.verifyNotZero(token, "tokenToRemoveRegistration");
bytes32 queryIdBeforeDeletion = tellorQueryInfo[token].queryId;
Errors.verifyNotZero(queryIdBeforeDeletion, "queryIdBeforeDeletion");
delete tellorQueryInfo[token];
emit TellorRegistrationRemoved(token, queryIdBeforeDeletion);
}
/**
* @notice External function to view TellorInfo struct for token address.
* @dev Will return empty struct for unregistered token address.
* @param token Address of token to view TellorInfo struct for.
*/
function getQueryInfo(address token) external view returns (TellorInfo memory) {
return tellorQueryInfo[token];
}
/**
* @dev Tellor always returns prices with 18 decimals of precision for spot pricing, so we do not need
* to worry about increasing or decreasing precision here. See here:
* https://github.com/tellor-io/dataSpecs/blob/main/types/SpotPrice.md
*/
// slither-disable-start timestamp
function getPriceInEth(address tokenToPrice) external returns (uint256) {
TellorInfo memory tellorInfo = _getQueryInfo(tokenToPrice);
uint256 timestamp = block.timestamp;
// Giving time for Tellor network to dispute price
(bytes memory value, uint256 timestampRetrieved) = getDataBefore(tellorInfo.queryId, timestamp - 30 minutes);
uint256 tellorStoredTimeout = uint256(tellorInfo.pricingTimeout);
uint256 tokenPricingTimeout = tellorStoredTimeout == 0 ? DEFAULT_PRICING_TIMEOUT : tellorStoredTimeout;
// Check that something was returned and freshness of price.
if (timestampRetrieved == 0 || timestamp - timestampRetrieved > tokenPricingTimeout) {
revert InvalidDataReturned();
}
uint256 price = abi.decode(value, (uint256));
return _denominationPricing(tellorInfo.denomination, price, tokenToPrice);
}
// slither-disable-end timestamp
/// @dev Used to enforce non-existent queryId checks
function _getQueryInfo(address token) private view returns (TellorInfo memory tellorInfo) {
tellorInfo = tellorQueryInfo[token];
Errors.verifyNotZero(tellorInfo.queryId, "queryId");
}
}