Chainlink历史数据Feed技术咨询:跨阶段数据与查询优化
背景与当前方案
我正在开发一款需使用Chainlink历史价格数据的智能合约,当前方案为:调用方向合约传入roundId,合约据此获取价格数据,并通过获取下一个roundId验证其是否处于正确时间范围。
对Chainlink机制的理解
proxyRoundId = phaseId >> 64 | aggregatorRoundId;同一阶段内proxyRoundId单调递增(每次+1),阶段切换时非单调递增phaseId取决于Aggregator版本/实现,切换Aggregator时phaseId递增(+1)aggregatorRoundId从1开始,随每轮新数据单调递增(+1)
阶段过渡期间的RoundData示例
我查看了预言机阶段过渡期间的RoundData值,但未完全理解其发布逻辑。以下是相关数据:
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
技术问题解答
为何新阶段RoundData的updatedAt反而更小?
这是因为Chainlink切换Aggregator阶段时,新Aggregator的初始轮次(aggregatorRoundId=1)可能在旧Aggregator仍持续更新数据的情况下就已创建。也就是说,新Aggregator的第一轮数据发布时间早于旧Aggregator后续轮次的更新时间,两者存在并行运行的时间窗口,并非新阶段启动后旧阶段立刻停止工作。如何高效实现按时间戳获取roundId?
合约内二分查询Gas成本极高,推荐两种优化方案:
- 链下预处理+链上验证:通过Chainlink历史数据接口在链下查询对应时间戳的
roundId,再将其传入合约,合约仅需验证该roundId的updatedAt是否在目标时间范围内即可,大幅降低链上消耗。 - 借助Chainlink Functions:利用Chainlink Functions在链下执行时间戳到
roundId的查询逻辑,再将结果返回链上,避免链上复杂计算。
旧阶段轮次会更新到何时?
旧Aggregator的停止时间由Chainlink节点运营商决定,通常在新阶段启动后,旧Aggregator会继续运行数小时到数天以确保过渡平滑,之后才会停止更新,没有固定的统一时间标准。不同阶段时间戳重叠时,如何优化历史价格查询?
核心是明确各阶段的时间覆盖范围,优化思路如下:
- 链下阶段过滤:先查询每个阶段首尾轮次的
updatedAt确定时间区间,定位目标时间戳所属阶段后再查询对应roundId,避免跨阶段无效查询。 - 链上阶段有效性校验:合约查询价格时,除验证
roundId的updatedAt,还可校验该roundId对应的phaseId是否为目标时间点的有效阶段(对比阶段起止时间)。 - 优先选择新阶段数据:若同一时间戳在新旧阶段均有数据,优先选用新阶段数据,因为新阶段通常对应更优的Aggregator版本。
内容的提问来源于stack exchange,提问作者Егор Переверзев

