Chainlink 价格馈送的每个代理合约都可以有多个底层聚合器合约,其中一个在任何给定实例中都设置为“活动”。也就是说,每当 Chainlink Labs 团队部署新版本的聚合器时,他们都会更新代理合约以将当前的聚合器版本设置为新版本,并且所有新的价格数据都开始写入新的聚合器。
基于此,如果您想要最近几周左右的代理合约/价格对的历史价格数据,您需要转到代理合约的当前聚合器,然后获取当前轮次信息 (包括时间戳),然后在循环中返回聚合器轮次,直到到达小于搜索参数时间戳的轮次。
要查找代理合约的当前聚合器合约地址,可以调用代理合约中的aggregator getter 函数。
阶段 ID 可以被认为是一个递增的 ID 号,代理合约在将每个聚合器添加到代理时使用它来识别它,所以第一个是 1,第二个是 2 等等。找出当前的阶段 ID 是当前聚合器的,您可以使用代理合约中的 phaseId getter 函数。
聚合器轮次 ID 从 1 开始,每次增加 1。例如,您可以使用聚合器 latestRound getter 函数来查找它存储的最后一轮,然后从该数字作为输入参数开始到 getRoundData,然后将数字减一并循环直到达到您的目的及时。
与聚合器轮次 ID 不同,代理轮次 ID 是像 36893488147419113293 这样非常长的数字,实际上只是基于聚合器阶段 ID 和聚合器轮次 ID 的派生值。这样做是为了确保代理轮次 ID 的值始终在增加,并且不同聚合器之间的相同轮次之间永远不会有任何重叠,例如,来自具有阶段 ID 1 的聚合器的第 5000 轮应该具有比第 5000 轮更低的代理轮次 ID来自阶段 ID 为 2 的聚合器
在 Solidity 中,您可以使用以下公式轻松复制代理轮 ID 派生值,传入聚合器的阶段 ID 和聚合器轮 ID
return uint80(uint256(_phaseId) << 64 | _aggregatorRoundId);
您甚至可以获取该派生值并将其传递给代理合约 getRoundData 函数,并获得与在给定聚合器轮 ID 的聚合器合约中调用 getRoundData 相同的数据结果。
我发现解决这些问题的一个好方法是直接在 etherescan 上与函数进行交互,并查看返回的数据。即这里是 Kovan ETH/USD proxy 和它的 latest aggregator
关于第二个问题的答案,最好的方法是从“现在”开始,即获取最新的聚合器,获取聚合器中的最新一轮,然后通过将聚合器轮次 ID 减 1 来及时返回,以及继续获取定价信息,直到回合时间戳为
最后,在 Solidity 中循环并不是很省油。您可以采取的另一种方法是将外部计算卸载到预言机,预言机可以为您提供正确的轮 ID,然后您可以使用它并在链上验证结果。 Here's an example 采用外部适配器形式的该设计模式,该适配器根据时间戳检索历史价格数据。 Kovan 上也有这个运行的实时版本,查看自述文件了解更多信息