价格预言机已经成为了 DeFi 中不可获取的基础设施,很多 DeFi 应用都需要从价格预言机来获取稳定可信的价格数据,包括借贷协议 Compound、AAVE、Liquity,也包括衍生品交易所 dYdX、PERP 等等。
The price forecaster has become an unattainable infrastructure in DeFi, and many of its applications require reliable price data from price forecasters, including loan agreements
目前最主流的价格预言机主要有 Chainlink、UniswapV2、UniswapV3,这几种价格预言机的接入方式和适用场景都不太一样,可以单独使用,也可以结合使用。鉴于不少同学还不知道这些预言机具体有哪些接入方式,也不了解背后的机制,更不清楚如何才能做到保证安全性的同时又能以最小的成本接入。下面,我将分享下我的经验总结,以供参考。
The current most mainstream price forecasters are
先从 Chainlink 的价格预言机开始聊起,这应该是使用最广泛的价格预言机了。
Starting with the Chainlink price foreword machine, this should be the most widely used.
其实,Chainlink 提供的产品不只是价格预言机,还有其他产品,包括 Verifiable Random Numbers (VRF)、Call External APIs、Chainlink Keepers。当然,使用最广泛的还是价格预言机,叫 Data Feeds。
In fact, Chainlink provides more than a price forecaster, but also other products, including
Chainlink Data Feeds 目前已经支持了多条链,主要还是 EVM 链,包括 Ethereum、BSC、Heco、Avalanche 等,也包括 Arbitrum、Optimism、Polygon 等 L2 的链。另外,也支持了非 EVM 链,目前支持了 Solana 和 Terra。不过,我对非 EVM 链并不熟悉,所以只讲 EVM 链的使用。
DeFi 应用接入使用 Chainlink Data Feeds 其实很简单,而且还有不同的使用方式,下面就来看看最常用的使用方式。
DeFi applies access to Chainlink Data Feeds, which is very simple and has different uses.
第一种使用方式,官方给的示例代码是这样的:
The first type of use, the official example code, is as follows:
首先,每个交易对都有一个单独的 Price Feed,也叫 Aggregator,其实就是一个个 AggregatorProxy,像下面这样:
First, each transaction has a separate
可以看到,每个 Pair 都有一个对应的 Proxy,读取价格其实就是从 Proxy 提供的方法读取的。Proxy 的具体实现稍微有点复杂,但 DeFi 应用要接入的话,只要知道 Interface 就够了,这个 Interface 则很简单,就是示例代码中所引入的 AggregatorV3Interface,其代码如下:
As can be seen, each Pair has a corresponding Proxy, which is actually read from the method Proxy provides. The practical realization of Proxy is a little complicated, but the DeFi application, if you want access, is enough to know that Interface, which is simple, is the AggregatorV3Interface, which has been introduced in the example code with the following code:
就 5 个查询方法而已,简单介绍下这几个方法:
It's just five search methods, so let's briefly describe them:
- decimals():返回的价格数据的精度位数,一般为 8 或 18
- description():一般为交易对名称,比如 ETH / USD
- version():主要用来标识 Proxy 所指向的 Aggregator 类型
- getRoundData(_roundId):根据 round ID 获取当时的价格数据
- latestRoundData():获取最新的价格数据
大部分应用场景可能只需要读取最新价格,即调用最后一个方法,其返回参数中,answer 就是最新价格。
Most applications may simply need to read the latest price, i.e. call the last method, and return to the parameter that answer is the latest price.
另外,大部分应用读取 token 的价格都是统一以 USD 为计价单位的,若如此,你会发现,以 USD 为计价单位的 Pair,精度位数都是统一为 8 位的,所以一般情况下也无需根据不同 token 处理不同精度的问题。
In addition, most of the token prices are read in USD, and if so, you will find that Pair, which is denominated in USD, has a single 8, so that there is no need to deal with different accuracy issues according to the different token.
当然,在实际应用中,肯定不会只读取一个固定 Token 的价格,更多场景是根据 Token 读取该 Token 的 USD 价格,因此可以将前面的示例合约升级为如下:
Of course, in practical application, only one fixed Token price will certainly not be read. More scenarios are based on Token's USD price for the Token, so the previous example contract can be upgraded to the following:
原先的示例只能读取 ETH/USD 一个 Pair 的价格,而现在则可以设置和读取多个不同 token 的价格。比如,现在想要读取 UNI 的 USD 价格,就可以先查出 UNI/USD 的 priceFeed,查出其 Proxy 为 0x553303d460EE0afB37EdFf9bE42922D8FF63220e ,而 UNI token 地址为 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984,那就可以调用:
The original example can only read
如此,UNI 所使用的 priceFeed 就设置好了,想读取 UNI 的最新价格时,调用 getLatestPrice() 就可读取到结果了,如下:
Thus, the priceFeed used by UNI is set to read the results when you want to read the latest prices of UNI by calling getLatestPrice(), as follows:
另外,mapping 所使用的 key 也可以不用 token address,改用 token symbol 或其它具有唯一标识性的属性也是可以的。
In addition, the key used by mappening can be replaced with token address, or with token symbol or other unique identifiers.
虽然该示例比较简单,很多实际应用中,可能比这复杂,但基本核心功能是差不多的了。
While the example is relatively simple and may be more complex in many practical applications, the basic core functions are similar.
第一种接入方式虽然已经很简单,但每个 token 都需要 owner 执行 setPriceFeed,治理成本其实有点高,对某些场景来说就不太灵活。这时候,就可以考虑使用第二种方式来接入 Chainlink Data Feeds 了,通过使用 Feed Registry 的方式来接入。
The first type of access is already simple, but each token needs to own the implementation of setPriceFeed. The cost of governance is actually a little high, and it is inflexible for some scenarios. At this point, the second way to access Chainlink Data Feeds can be considered, with access using fedRegistry.
Feed Registry 可以简单理解为 PriceFeeds 的聚合器,已经聚合了多个 priceFeed,有了它,使用者就无需自己去设置 priceFeed 了,可直接通过 Feed Registry 读取价格数据,如下图:
Feed Registry, a polymer that can be understood simply as
官方给的使用示例代码则如下:
The official sample code is as follows:
可看到,开头引入了两个 sol 文件,FeedRegistryInterface 和 Denominations。 是一个很简单的 library,主要定义了各种货币的地址,如下:
As can be seen, two sol files, FeedRegistry Interface and Developments, were introduced at the beginning. A simple library, which mainly defines the addresses of various currencies, as follows:
则定义了不少函数,包括和 AggregatorV3Interface 一样的几个函数,只是每个函数相比 AggregatorV3Interface 多了两个参数:base 和 quote,如下:
Defines a number of functions, including those similar to AggregatorV3Interface, except that each function has two more parameters than AggregatorV3Interface: base and quate, as follows:
假设交易对为 UNI/USD,那 base 为 UNI 的 token 地址,quote 则为 USD 的地址,即为 Denominations.USD;假设交易对为 ETH/BTC,那 base 则为 Denominations.ETH,quote 为 Denominations.BTC。
Assuming the transaction is UNI/USD, the base is the Token address of UNI, and the Quote is the address of the USD, i.e. Demominations.USD; assuming the transaction is ETH/BTC, the base is Denominations.ETH, Quote is Denominations.BT.
另外,也可以通过 getFeed(address base, address quote) 直接读取到 priceFeed。
In addition, it can be read directly to PriceFeed by
可以发现,使用 Feed Registry 的方式,主要都是用 base/quote 的方式进行查询。
It can be found that the use of Feed Registry is mostly a base/quate search.
FeedRegistry 里的每个 priceFeed 则是通过先后调用 proposeFeed() 和 confirmFeed() 两个函数设置的,不过这两个函数只有 FeedRegistry 的 owner 才可以调用。
至此,我们已经知道如何接入 Chainlink Data Feeds 来获取价格信息了,但还不够,我们还要了解背后的喂价机制,也要了解价格数据多久更新一次的,如此才能更好地判定 Chainlink 的价格预言机是否能满足具体的场景需求。
So far, we know how to access Chainlink Data Feeds to obtain price information, but it is not enough. We also need to know the feeding mechanisms behind it, and how often price data are updated, so that we can better determine whether Chainlink's price prophecies meet specific scenario needs.
首先,Price Feed 的价格是通过多个层级的数据聚合得到的。实际上有三个数据聚合层:数据源聚合、节点运营商聚合、预言机网络聚合。
First, Price Feed's price is obtained through multiple layers of data aggregation. In fact, there are three data polymer layers: data source aggregation, node operator aggregation, predictor network convergence .
最原始的价格数据主要来源于币安、火币、Coinbase 等中心化交易平台,以及 Uniswap、Sushi 等去中心化交易平台。存在一些专门做数据聚合的服务商(比如 amberdata、CoinGecko),会从这些交易平台收集原始的价格数据,并对这些数据源进行加工整合,比如根据交易量、流动性和时差等进行加权计算。
The most original price data are derived from such central trading platforms as coins, turkeys, Coinbase, and from decentralised trading platforms as Uniswap, Sushi. There are a number of service providers specializing in data aggregation (e.g. strong>amberdata, CoinGecko) that collect raw price data from these trading platforms and process and integrate these data sources, such as weighting based on volume, liquidity and time difference.
这就是第一个层面的聚合,对数据源的聚合。拥有可靠的价格数据源的关键是要有全面的市场覆盖,才能保证一个价格点能代表所有交易环境的精确聚合,而不是单个交易所或少数交易所的价格,以防止数据被人为操纵和出现价格偏差。也因此,为了确保数据具有高度的防篡改和可靠性,Chainlink Data Feeds 只会从优质的数据聚合服务商获取数据,这意味着每个数据源都代表一个从所有中心化和去中心化交易所聚合的经过交易量调整的精细价格点,也因此可以有效抵抗闪电贷或价格异常偏差等攻击。
This is the first level of aggregation, for the data source. The key to having reliable price data sources is full market coverage to ensure that a price point represents the precise aggregation of all trading environments, rather than the price of a single exchange or a few exchanges, in order to prevent data from being manipulated and price deviations. Thus, in order to ensure a high degree of security and reliability of data, Chainlink Data Feeds will only obtain data from a high-quality data aggregation service provider, which means that each data source represents a fine, adjusted price point from all centralized and decentralized exchanges, and thus effectively resists attacks such as flash loans or abnormal price deviations.
第二层则是 Chainlink Node Operators 所做的聚合。每个 Chainlink Node Operator 主要负责运行用于在区块链上获取和广播外部市场数据的 Chainlink 核心软件。Node Operators 会从多个独立的数据聚合服务商获取价格数据,并获取它们之间的中值,剔除掉异常值和 API 停机时间。比如,从 A 数据聚合服务商获取到价格点为 7.0,从 B 服务商获取到价格点为 7.2,那取中值后的价格点为 7.1。这意味着不仅每个单独的数据源反映了来自所有交易环境的聚合价格点,而且每个单独的节点的响应代表了来自多个数据源的聚合,进一步防止任何单一来源成为故障点,即避免了单点故障。
The second floor is the aggregation made by
最后一层则是整个预言机网络的聚合,其聚合的方式有多种,但最常见的聚合方式是当响应节点数量达到预设值时对数据取中值。比如总共有 31 个节点,预设值为 21,即收到了 21 个节点的响应后,就取这些节点的价格数据的中值作为最终的价格。不过,并非每一轮的价格结果都会更新到链上,只有满足两个触发参数之一的时候才会更新:偏差阈值(Deviation Threshold)和心跳阈值(Heartbeat Threshold)。而且,不同 PriceFeed 的这两个参数的值可能会不一样。
The last layer is the condensation of the entire foreword network, which is condensed in a variety of ways, but the most common form of aggregation is the median of data when the number of response nodes reaches the preset value. For example, there are 31 nodes with a preset value of 21, i.e. when the 21 nodes respond, the median of the price data for these nodes is taken as the final price. However, not every round of price results are updated to the chain, and only if one of the two trigger parameters is met: the deviation threshold of
比如,ETH/USD 的偏差阈值为 0.5%,即表示新一轮的价格点跟上一次更新的价格偏差超过 0.5% 的时候才会更新链上价格;而心跳阈值为 3600 秒,即表示上一次价格更新后过了 1 小时后才会更新链上价格。另外,因为每一轮的数据聚合都不是实时的,也需要时间,再加上偏差阈值的限制,所以,有时候,要隔几十分钟才会有价格更新,这点比较关键,需要清楚。有些 Price Feed 的偏差阈值比较大,会高达十几个小时才会有价格更新,比如下面这个:
For example, the deviation threshold for ETH/USD is 0.5%, which means that the price point of the new round will not be updated until the updated price deviation exceeds 0.5%; and the heart rate is 3600 seconds, which means that the price will not be updated until one hour after the last price update. Also, because each round of data aggregates is not real-time, it will take time, plus the limitation of the deviation threshold, sometimes it will take a few minutes to update prices, which is more critical and clear. Some Price Feed deviation thresholds are larger than 10 hours before price updates, for example:
可看到,其偏差阈值高达 5%,且已经长达 11 个小时没有价格更新了,而它的心跳阈值其实也比较高,长达 24 小时。
As can be seen, the deviation threshold is as high as 5 per cent and has not been updated for 11 hours, while the heart rate is also relatively high, at 24 hours.
高达 5% 的偏差阈值,且这么长时间都没有更新价格,这如果是应用到一些高杠杆的交易产品,可能就不太合适了。
A deviation threshold of up to 5 per cent, with no price updates for such a long period of time, may not be appropriate if some highly leveraged trade products are applied.
总而言之,Chainlink 价格预言机接入方便,且安全性还是比较高的,但因为其价格更新机制存在偏差阈值,导致价格更新比较慢,短则几分钟或几十分钟更新一次,长则可能达 24 小时才更新一次,因此,一般只适用于对价格更新不太敏感的应用。这也是 Chainlink 价格预言机的局限性,并无法适用所有场景的应用。
In summary, Chainlink price forecasts are easily accessible and safe, but their price update mechanism has a deviation threshold that causes price updates to be slow, with minutes or minutes to be updated and possibly 24 hours to be updated, so that they are generally applied only to applications that are less sensitive to price updates. This is also the limitation of the Chainlink price forecasts and does not apply to all scenarios.
注册有任何问题请添加 微信:MVIP619 拉你进入群
打开微信扫一扫
添加客服
进入交流群
发表评论