admin管理员组

文章数量:1332881

I am developing a contract that needs to use historical Chainlink prices.

I use the following approach: The caller passes the roundId to contract, according to which we get the price data. Contract get the next roundId to make sure that the roundId is in the right time range.

Current understanding: proxyRoundId = phaseId >> x64 | aggregatorRoundId proxyRoundId - increases monotonously(+1) each new round within same phase. Increases nonmonotonically if phase change. phaseId - depends on Argregator version/implementation. When change aggregator increases phaseId(+1). aggregatorRoundId - starts from 1 and increases monotonously(+1) with each new round.

I checked the value of RoundData for oracles during the transition between phases and did not fully understand the logic of publishing RoundData.

The contract -

roundId   uint80 :  18446744073709551727 => phaseId 1, aggregatorRoundId 111
answer   int256 :  99939094
startedAt   uint256 :  1725911063
updatedAt   uint256 :  1725911063
answeredInRound   uint80 :  18446744073709551727
roundId   uint80 :  36893488147419103233 => phaseId 2, aggregatorRoundId 1
answer   int256 :  99894945
startedAt   uint256 :  1720771216
updatedAt   uint256 :  1720771295
answeredInRound   uint80 :  36893488147419103233

Questions:

  1. Why RoundData(36893488147419103233).updatedAt < RoundData(18446744073709551727).updatedAt? Based on the current understanding, the new phase should have the newest values compared to the previous one.
  2. I think that for this task I can try to use a binary search by roundId and check RoundData.updatedAt, but the implementation in the contract consumes a lot of gas. Do you know more effective ways to get roundId by timestamp?
  3. Up to what time are the rounds in the old phase updated (when is the switch to the new phase)?
  4. How is it optimal to search for prices based on historical data if the timestamp may overlap in different phases?

I am developing a contract that needs to use historical Chainlink prices.

I use the following approach: The caller passes the roundId to contract, according to which we get the price data. Contract get the next roundId to make sure that the roundId is in the right time range.

Current understanding: proxyRoundId = phaseId >> x64 | aggregatorRoundId proxyRoundId - increases monotonously(+1) each new round within same phase. Increases nonmonotonically if phase change. phaseId - depends on Argregator version/implementation. When change aggregator increases phaseId(+1). aggregatorRoundId - starts from 1 and increases monotonously(+1) with each new round.

I checked the value of RoundData for oracles during the transition between phases and did not fully understand the logic of publishing RoundData.

The contract - https://etherscan.io/address/0xa569d910839Ae8865Da8F8e70FfFb0cBA869F961

roundId   uint80 :  18446744073709551727 => phaseId 1, aggregatorRoundId 111
answer   int256 :  99939094
startedAt   uint256 :  1725911063
updatedAt   uint256 :  1725911063
answeredInRound   uint80 :  18446744073709551727
roundId   uint80 :  36893488147419103233 => phaseId 2, aggregatorRoundId 1
answer   int256 :  99894945
startedAt   uint256 :  1720771216
updatedAt   uint256 :  1720771295
answeredInRound   uint80 :  36893488147419103233

Questions:

  1. Why RoundData(36893488147419103233).updatedAt < RoundData(18446744073709551727).updatedAt? Based on the current understanding, the new phase should have the newest values compared to the previous one.
  2. I think that for this task I can try to use a binary search by roundId and check RoundData.updatedAt, but the implementation in the contract consumes a lot of gas. Do you know more effective ways to get roundId by timestamp?
  3. Up to what time are the rounds in the old phase updated (when is the switch to the new phase)?
  4. How is it optimal to search for prices based on historical data if the timestamp may overlap in different phases?
Share asked Nov 22, 2024 at 5:11 Егор ПереверзевЕгор Переверзев 1
Add a comment  | 

1 Answer 1

Reset to default 0

Here is a Pseudocode for Binary Search

function findRoundId(uint256 targetTimestamp) public view returns (uint80 roundId) {
    AggregatorV3Interface aggregator = AggregatorV3Interface(AGGREGATOR_ADDRESS);
    uint80 low = aggregator.firstRound(); 
    uint80 high = aggregator.latestRound(); 

    while (low < high) {
        uint80 mid = low + (high - low) / 2;
        (, , , uint256 midTimestamp, ) = aggregator.getRoundData(mid);

        if (midTimestamp < targetTimestamp) {
            low = mid + 1;
        } else {
            high = mid;
        }
    }
    return low; // Closest round ID
}

本文标签: Issues with chainlink historical data feedsStack Overflow