本文作者:Ashton[1]
0x01 Luna 价格崩了,借贷应用躺枪了
近期 Luna 是圈内最热门的话题了,其价格从最高的 100 多美金,直接跌倒不到 0.000001 美金,后面又涨了 100 多倍到 0.000X 美金。
当大家都在分析 Luna 本身时,币安链上最大的借贷应用 Venus 却出事了,有人存入大量的 Luna,借走了大量资产,导致平台坏账。Venus 使用业界头部预言机 Chainlink[2] 作为价格源,当时 Luna 的价格在 0.01 美金左右,但从 Chainlink 拿到的报价却停留在了 0.107 美金。
Chainlink 的报价居然停止工作了
0x02 Chainlink 的回应
按照 Chainlink 官方回应,停止报价的原因是因为 Luna 的价格波动超出了正常范围,触发了内置的熔断机制,这是协议抗风险的一种措施。
只是这个抗风险的措施却带来了实实在在的损失,也是滑稽。
官方的第二个回应,是让 Luna 价格源 404(https://data.chain.link/bsc/mainnet/crypto-usd/luna-usd)了。
0x03 熔断代码分析
Chainlink 的价格都是最终由一个叫聚合器(Aggregator)的合约生成的,比如 ADA/BNB 的聚合器就是这个:https://bscscan.com/address/0x50204d36c231cd4f0de67545cd1e36c01336e46b#code 当报价节点报价时会调用这个合约的 transmit 函数,这个函数有下面的逻辑。
其实最核心的就是下面这句:
代码语言:javascript复制require(minAnswer <= median && median <= maxAnswer, "median is out of min-max range");
当生成的价格超过预设的一个价格范围后,报价会失败。 达到的效果就是价格会停留在上次成功报价不变。
这个价格范围是价格聚合器合约被创建时就通过构造函数设置好的。
代码语言:javascript复制// 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 启示
- 这个问题的根本原因是当价格剧烈波动时,预言机熔断了,应用端缺没熔断,导致悲剧发生。
- 这是 Chainlink 预言机设计的严重漏洞,显然是当初没考虑到 Luna 这种情况的。
- 对价格预言机来说,将某个币种价格波动永久限制在某个范围,感觉也是非常不合理的。这个价格范围应该根据某个算法定期修正。
- 对预言机来说,当出现极端情况时,有两个选择,一个是暂停报价,一个是返回报价为 0,选用哪个策略应该由应用端决定。并返回标记告诉应用端目前是报价异常状态,方便应用端做熔断处理。
- 对应用来说,当某个资产价格剧烈波动时,需要及时进行监控并在需要的时候进行熔断处理,对借贷应用来说,可能要暂停存款,及时清算,调整抵押率。
参考资料
[1]
Ashton: https://learnblockchain.cn/people/29
[2]
预言机 Chainlink: https://learnblockchain.cn/article/587