深入解析AAVE智能合约:存款
Wong Shouhao

概述

我们在上一篇文章AAVE交互指南中主要介绍了aave前端、利率计算等内容,本篇文章
将在交互指南基础上介绍aave-v3的合约源代码的相关情况。

与之前所写的深入解析Safe多签钱包智能合约系列文章不同,本文主要以我们在AAVE交互指南中进行的合约操作为主线进行分析介绍,较为实战化。

相比于其他项目,AAVE提供了一个较为完整的文档。在文档内基本涵盖了所有函数的签名及其作用,读者也可作为阅读源代码的重要参考。

AAVE的总体架构如下:

AAVE Frame

本文使用存款描述用户向流动性池内注入资产的行为,或称supplydeposit,当然在 V3 版本中,deposit已被遗弃。当然,有很多人认为此名词应翻译为质押,由于作者的写作习惯,后文统称为存款

代码准备

我们在此处仍使用Foundry作为开发和测试框架,使用以下命令初始化仓库:

1
forge init aave-v3 

前往AAVE Releases页面下载最新的源代码,并解压。将解压后的contracts中的文件转移到上文初始化的aave-v3仓库中的src文件夹下,最终形成如下目录结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.
├── foundry.toml
├── lib
│ └── forge-std
├── script
│ └── Counter.s.sol
├── src
│ ├── Counter.sol
│ ├── dependencies
│ ├── deployments
│ ├── flashloan
│ ├── interfaces
│ ├── misc
│ ├── mocks
│ └── protocol
└── test
└── Counter.t.sol

整体逻辑

在介绍具体的合约代码前,我们首先应当明确存款行为的具体逻辑。作为金融系统,其逻辑具有相当的数学性,我们会结合具体的数学公式介绍存款的具体逻辑。与上一篇文章相比,本节给出的逻辑会更加详细且主要服务于后文代码解释,建议以本节为纲要以避免迷失在具体实现中。

本文主要参考了AAVE V2 Whitepaper,此文档给出了具体的逻辑阐述。

AAVE V3 的白皮书是建立在 V2 白皮书基础上的,所以 V3 白皮书仅介绍了与 V2 不同的部分,不足够详细。

我们引入以下参数:

  • 当前的存款利率(currentLiquidityRate),计算方法为
    (此公式在上一篇文章内有详细解释,读者可作为参考)

    参数含义如下:

    • 为浮动存款和固定存款利率的加权平均数
    • 为利用率
  • 贴现因子(liquidityIndex),计算方法为

    如果有读者阅读过原文,可能发现此遍历英文名为cumulated liquidity index,但本质是贴现因子。我们会在后文讨论此参数,当然读者也可以通过各种方式了解此概念。

有读者可能发现 是以线性利率的形式进行的计算,与我们上一篇文章所说明的存款利率复利计算是不符的,但为什么上一篇文章内使用复利计算的结果与和约相同? 原因在于此处的单利计算会在用户每一次进行操作时更新,高频率的单利计算与复利计算会渐趋一致

在AAVE的设计中,贴现因子的使用具有普遍性,如存款、贷款等情况下均使用了贴现因子概念,由于此文主要分析存款,所以若无特殊说明,后文的贴现因子均指存款的贴现因子

假设用户在 时刻存入资产Token的数量为 ,我们在智能合约中记录的用户存入数值为

时刻,用户取出资产,获得的资产数量为

此部分使用了金融学内简单的贴现概念,我们将所有存入资产均贴现到 时期,在用户提款时将其折算回 。此处使用的 事实上就是 贴现因子。如果读者无法理解此部分,可简单选择任一金融学课本阅读此部分内容。

假设用户的存款数量用 表示,则用户存入 单位质押品后,存款数量为:

$${ScB}_t(x) = {ScB}_{t-1}(x) + \frac{m}