Chainlink 对 Luna 报价失误分析

0x01 Luna 价格崩了,借贷应用躺枪了

近期 Luna 是圈内最热门的话题了,其价格从最高的 100 多美金,直接跌倒不到 0.000001 美金,后面又涨了 100 多倍到 0.000X 美金。

当大家都在分析 Luna 本身时,币安链上最大的借贷应用 Venus 却出事了,有人存入大量的 Luna,借走了大量资产,导致平台坏账。Venus 使用业界头部预言机 Chainlink 作为价格源,当时 Luna 的价格在 0.01 美金左右,但从 Chainlink 拿到的报价却停留在了 0.107 美金。


image.png

Chainlink 的报价居然停止工作了

0x02 Chainlink 的回应

按照 Chainlink 官方回应,停止报价的原因是因为 Luna 的价格波动超出了正常范围,触发了内置的熔断机制,这是协议抗风险的一种措施。

image.png

只是这个抗风险的措施却带来了实实在在的损失,也是滑稽。

官方的第二个回应,是让 Luna 价格源 404(https://data.chain.link/bsc/mainnet/crypto-usd/luna-usd)了。

0x03 熔断代码分析

Chainlink 的价格都是最终由一个叫聚合器(Aggregator)的合约生成的,比如 ADA/BNB 的聚合器就是这个:https://bscscan.com/address/0x50204d36c231cd4f0de67545cd1e36c01336e46b#code
当报价节点报价时会调用这个合约的 transmit 函数,这个函数有下面的逻辑。

image.png

其实最核心的就是下面这句:

      require(minAnswer <= median && median <= maxAnswer, "median is out of min-max range");

当生成的价格超过预设的一个价格范围后,报价会失败。 达到的效果就是价格会停留在上次成功报价不变。

这个价格范围是价格聚合器合约被创建时就通过构造函数设置好的。

  // Lowest answer the system is allowed to report in response to transmissions
  int192 immutable public minAnswer;
  // Highest answer the system is allowed to report in response to transmissions
  int192 immutable public maxAnswer;

这两个变量被设置成了 immutable, 意味着只能被设置一次,之后不可更改。Chainlink 要紧急手动修复这个价格范围也就不可能了。

如果价格只是短期异常波动,这个设置并没什么问题,但是当价格像 Luna 这样正常单边超大幅波动时,问题就出现了,价格再也报不上来了。这个聚合器合约我看了一下又是不可升级的,意味着必须要替换合约才能修正价格范围了。

0x04 启示

  1. 这个问题的根本原因是当价格剧烈波动时,预言机熔断了,应用端缺没熔断,导致悲剧发生。
  2. 这是 Chainlink 预言机设计的严重漏洞,显然是当初没考虑到 Luna 这种情况的。
  3. 对价格预言机来说,将某个币种价格波动永久限制在某个范围,感觉也是非常不合理的。这个价格范围应该根据某个算法定期修正。
  4. 对预言机来说,当出现极端情况时,有两个选择,一个是暂停报价,一个是返回报价为 0,选用哪个策略应该由应用端决定。并返回标记告诉应用端目前是报价异常状态,方便应用端做熔断处理。
  5. 对应用来说,当某个资产价格剧烈波动时,需要及时进行监控并在需要的时候进行熔断处理,对借贷应用来说,可能要暂停存款,及时清算,调整抵押率。

你可能感兴趣的:(Chainlink 对 Luna 报价失误分析)