简体   繁体   中英

What is the best way to access historical price data from Chainlink on a token in a decentralised manner?

I need to get the Chainlink prices of a token from a specific time to the most recent round. This time varies based on user input but will be relatively short windows (1 day to 2 weeks max) based on the heartbeat of the token. This is used to calculate the price of a payout both in the smart contract and on the application homepage.

To get historical price data Chainlink needs a 'roundId' which is a non-incremental value.

What is the best way to either get all roundIds for the given time window from Chainlink or record them in a way that is open, decentralised and can be accessed in a solidity smart contract?

Each proxy contract for a Chainlink Price Feed can have multiple underlying aggregator contracts, with one of them being set as the 'active' one at any given instance. Ie whenever the Chainlink Labs team deploys new versions of the aggregator, they update the proxy contract to set the current aggregator version to be the new one, and all new price data starts getting written to the new aggregator.

Based on this, if you want historical price data for a proxy contract/price pair from the last couple weeks or so, you'd need to go to the current aggregator for the proxy contract, then get the current round info (including timestamp), then go back in aggregator rounds in a loop until you get to a round that is less than your search parameter timestamp.

To find the current aggregator contract address for a proxy contract, you can call the aggregator getter function in the proxy contract.

The phase ID can be thought of as an incrementing ID number that the proxy contract uses to identify each aggregator as it gets added to the proxy, so the first one is 1, second is 2 etc. To find out what the current phase ID is of the current aggregator, you can use the phaseId getter function in the proxy contract.

Aggregator round IDs start from 1 and increase by 1 each time. Eg you can use the aggregator latestRound getter function to find the last round that it stored, and then start from that number as an input parameter to getRoundData , and then reduce the number by one and loop through until you reach your point in time.

Unlike Aggregator round IDs, proxy round IDs are those big really long numbers like 36893488147419113293 , and are actually just a derived value based on the aggregator phase ID and the aggregator round ID. This is done to ensure the proxy round IDs are always increasing in value, and that there will never be any overlap between the same rounds across different aggregators, eg round 5000 from aggregator with phase ID 1 should have a lower proxy round ID that round 5000 from aggregator with phase ID 2

In Solidity you can easily replicate the proxy round ID derived value with the following formula, passing in the phase ID of the aggregator and the aggregator round ID

return uint80(uint256(_phaseId) << PHASE_OFFSET | _aggregatorRoundId);

You can even then take that derived value and pass it into the proxy contract getRoundData function, and get the same data result as calling getRoundData in the aggregator contract for the given aggregator round ID.

I find A good way to play around with these is to interact with the functions directly on etherescan, and see the data returned. Ie here's the Kovan ETH/USD proxy and its latest aggregator

Regarding the answer your second question, the best way is to start from 'now', ie get the latest aggregator, grab the latest round in the aggregator and then go back in time by reducing the aggregator round ID by 1, and continue to get pricing info until the round timestamp is < your search timestamp.

Finally, looping in Solidity is not very gas efficient. Another approach you can take is to off-load the external computation to an oracle, and the oracle can give you the correct round ID, and you can then take that and verify the results on-chain. Here's an example of that design pattern in the form of an external adapter that retrieves historical price data based on a timestamp. There is a live version of this running on Kovan too, check out the readme for more info

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM