本文详细探讨了在Aave协议更新过程中遇到的平衡不稳定问题,强调了在去中心化金融(DeFi)系统中维护不变性的重要性。通过数学模型和对事务的全面分析,定位了两个主要问题:闪电贷款计算错误和储备因子的调整失误,进而提出了改进措施。文章的结论强调了持续监控和全面问题解决的重要性。
BGD Labs团队在Aave从v3升级到v3.1的过程中遇到了问题,并找到了我们。本文详细解释了问题,描述了我们如何寻找问题的源头,以及研究的结果。TLDR: 资金是安全的 :)
任何稳定的DeFi池的一个关键方面是确保存款人在任何时候都可以访问自己的资金,无论市场状况如何。这是通过保持不变性来实现的——一种数学条件,保证始终有足够的流动性可用。如果这个条件失败,池子可能没有足够的余额返还给存款人,从而削弱协议的可靠性。
在Aave市场中,存在借贷和债务机制,意味着池子本质上无法立即满足所有提款请求。然而,假设债务可以被激励进行偿还或清算,可以建立一个关键的不变性:所有存入代币的总和,连同它们产生的利息,减去借出的代币及其累积的债务,必须不超过市场中的实际基础代币余额。这个条件确保了债务和流动性利息保持和谐,防止还款债务不足以覆盖存款人应得的代币。
从数学上讲,这个不变性通过虚拟余额公式表示,代表市场正常运作所需的基础代币的最小数量:
$$ B_v = ( S_a + T ) • I_a – ( S_v • I_v + S_s • I_s) $$
其中:
( $S_a$ ) 是 aToken 股份的总供应量。
( T ) 是国库的股份,已累计但不包括在 ( $S_a$ ) 中。
( $I_a$ ) 是流动性利息指数。
( $S_v$ ) 和 ( $S_s$ ) 分别是可变和稳定债务代币的总供应量。
( $I_v$ ) 和 ( $I_s$ ) 分别是可变和稳定债务的累计利息指数。
这个公式确保虚拟余额 ( $B_v$ ) 不超过实际代币余额 ( $B_u$ ):
$$ B_u ≥ B_v $$
在健康的市场中,通过确保线性增长的流动性利息保持在指数增长的债务利息的边界内,维护了这个不变性。
在从版本3.0升级到3.1的过程中,BGD Labs团队发现了一个令人关注的问题:即使在不变性中预计会有某种小偏差,在一些特定情况下,这种偏差稍微高于预期。在某些情况下,虚拟余额显著偏离,导致预期和实际余额之间存在显著差异:
B Δ = B v – B u
尽管偏差并不大,且对用户没有任何影响,但其幅度显然并不是由于灰尘积累造成的。确定导致这种偏差的原因是至关重要的,以确保整体系统的稳定性。为了确定根本原因,进行了对历史交易的全面分析。
BGD Labs团队分享了他们认为可能导致不变性偏差的根本原因的看法。对过去可能出错的情况进行了不同的假设。例如,市场存在非常高的历史利率、实施更新,甚至是更新的 accruedToTreasury 逻辑。他们指出,有一个市场存在不变性偏差,而这个市场的资产没有被借出。我们决定从这个特定市场开始,以简化调查。这个简化减少了虚拟余额公式中的变量,缩小了可能的原因。一个显著的案例是 aArbAave 市场。初步分析显示,一个看似例行的闪电贷 交易 导致了 delta 激增 5*10^7。
对闪电贷逻辑的初步审查并未显示出任何明显的错误。尽管轻微的舍入误差可能导致 delta 略有增加,但无法解释观察到的显著激增。为了孤立有问题的交易,采用了二分搜索的方法,揭示上一次显著 delta 增加发生在一年前,暗示在较旧的实施中存在问题。对最后一次交易后相关更新的审查揭示了问题的起源。
通过对受影响版本之间的 FlashLoanLogic.sol 代码差异进行审查,发现闪电贷操作期间 reserve.liquidityIndex 的计算未考虑 accruedToTreasury 变量。这个变量代表国库的应计利息份额,该份额未包含在 aTokens 的总供应量中,但仍会随着时间的推移积累利息。
具体来说,负责根据从闪电贷中收取的溢价调整 liquidityIndex 的 cumulativeToLiquidityIndex 函数,使用了 aTokens 的总供应量而未加上 accruedToTreasury。因此,溢价实际上被分配在了一个比应该更少的代币上,导致 liquidityIndex 增加超过适当水平。
这种错误计算导致虚拟余额 B v 的高估,使其超过实际余额 B u。
在实施更新后,后续交易中未再观察到显著的 delta 增加(超出几个wei),证实这一错误确实是该市场的根本原因。
尽管与闪电贷相关的问题得到解决,但仍在启用了借贷的市场中发现了类似问题。这些市场的 delta 变化显著,但代码库没有最近的更新,暗示存在不同的潜在原因。
这些市场的 delta 随时间变化并没有 consistently 增加或减少,使分析更加复杂。为了识别有问题的交易,使用了一种调整后的搜索方法,专注于 delta 随时间的可视化。
分析表明,在每个受影响的市场中,一笔特定交易导致了 delta 的突然和显著增加。这些交易各不相同:包括借贷、供应和提款操作,但都发生在市场实施没有任何最近变化的情况下。
进一步调查显示,在每一个此类交易之前,reserveFactor 参数已被修改。reserveFactor 确定借款人支付的利息中分配给协议国库而不是存款人的部分。
当 reserveFactor 增加时,国库的利息份额增大,但如果立即不重新计算利率和指数,系统就不会正确考虑这一变化。具体而言,影响 liquidityIndex 增长的 liquidityRate 应该调整以反映新的 reserveFactor。如果这种重新计算未发生,liquidityIndex 将继续按以前的速度增长,而国库开始获得更大份额的利息。这种不匹配导致虚拟余额 ( B_v ) 的高估,又一次违反了不变性。
这个问题的示例可以如下所示:
在检测到问题之前,针对这一问题的更新也已在 PoolConfigurator 实施中做出。该更新确保每当修改 reserveFactor 时,利率和指数立即重新计算,以使利息分配与新的设定一致。
在确认 delta 膨胀是由这两个问题造成的:闪电贷计算错误和 reserveFactor 调整的疏忽,并且两者都已得到解决后,调查得以完成。
对Aave市场余额完整性问题的调查突显了在去中心化金融系统中维持稳定性的重要考虑:
综合问题解决:解决实时系统中的问题不仅需要实施代码修复,还需要缓解可能已经发生的任何潜在问题。在这个案例中,在问题被完全识别之前,代码已更新以纠正错误计算。然而,虚拟余额中现存的不平衡仍未解决。如果在实施修复后立即采取措施调整 delta,可能会将需要进行广泛历史数据分析的需要降至最低。这突显了不仅要修正代码,还要积极解决任何残留效应,以确保系统恢复到稳定状态的重要性。
关键不变性的持续监控:定期监控重要不变性对及早发现问题至关重要。在这个场景中,delta 的显著偏差在很长一段时间内未被察觉,使不平衡继续存在。实施稳健的监控工具来跟踪关键不变性可以帮助在出现不一致时识别出问题,从而在及时干预中防止潜在的正常操作干扰。
历史背景意识:当一个未知问题被识别时,理解其根源至关重要。调查问题何时开始并收集全面的数据,包括审查过去的实施更新和参数改变,提供了对根本原因的宝贵洞察。这种方法确保解决方案的准确性和有效性,解决的不仅是症状,还有导致该问题的根本因素。
对Aave市场中不变性违反的分析突显了在保持稳定的DeFi协议中涉及的复杂性。通过识别和理解导致不平衡的因素,实施了措施来增强系统的稳定性。展望未来,主动监控和彻底的问题解决对于确保去中心化金融平台的持续可靠性和稳健性将是至关重要的。
MixBytes 是一支专业的区块链审计和安全研究人员团队,专门为EVM兼容和Substrate基础项目提供全面的智能合约审计和技术咨询服务。请在 X 上关注我们,以获取最新的行业动态和见解。
- 原文链接: mixbytes.io/blog/investi...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!