Aave V2 逻辑整理

  • A+
所属分类:技术

chatGPT账号

Aave V2 逻辑整理

Aave 就相当于去中心化交易所中的一个银行,在其中用户可以进行一系列的资金操作,下面基于行为的角度对其两个功能进行阐述:借贷、存款。

借贷

在 Aave 中借贷有两种方式:借款(有抵押物的)、闪电贷(无抵押物的)。

闪电贷

Aave V2 的闪电贷感觉没有什么特别的地方,就是在一个区块交易内完成借出和还入两个操作。

  function flashLoan(
    address receiverAddress, // 借款受益人地址
    address[] calldata assets, // 借款代币地址(数组)
    uint256[] calldata amounts, // 借款数量(数组)
    uint256[] calldata modes, // 借款模式(数组)
    address onBehalfOf, // 还款人地址
    bytes calldata params, // 入参编码
    uint16 referralCode // 推荐码
  ) external override whenNotPaused {

查看 Aave V2 的代码(参考上述的函数头),我们可以知道,Aave V2 允许一次性借出多种贷款(assets是个数组),并且允许选择模式(由modes决定,不同资产可以选择不同模式),有:闪电贷模式(0,正常闪电贷)、借款模式(1,普通的借款,采用稳定利率;2,普通的借款,采用浮动利率)。

对于每一笔贷款(无论哪种模式) Aave V2 都会先转出借款费用、计算手续费,然后再根据模式进行判断:

  • 闪电贷:从贷款者处(receiverAddress)转账还款(借款+手续费
  • 借款模式:执行借款的函数逻辑

总的来说,Aave V2 在闪电贷种添加了一个转入正常借贷的机会,可以将闪电贷、正常借贷合并在一笔交易中。

借款

关于借款,就开始麻烦起来了,借款可以分为三个部分:借款(借钱这件事)、还款(还钱这件事)、清算(清算合约中不良借款这件事)

清算

我们首先来看看清算这件事。由于区块链中没办法轻易的溯源到账户拥有者本人,所以对于合约中每一笔借款都不能有坏账(借出款的价值大于抵押物的价值)这件事发生合约就会不被信任了。

我们知道合约对于借款策略采用的是超额抵押借贷(如抵押 100价值的抵押物,借贷的钱不能到达100价值的抵押物,借贷的钱不能到达100 那么多,可能只有 50$),所以可以设定一个阈值(抵押物价值/所欠金额),到达一定比值后资产就会被清算(合约自动卖出抵押物,借款人就不用还款了)。

那么这个清算阈值是怎么确定的呢?Aave V2 定义了一个健康系数(HealthFactor),当其小于 1 时,该笔交易就可以清算。那么这个HealthFactor如何定量呢?

ℎ=∗ℎℎHealthFactor=TotalDebtInETHTotalCollateralInETHLiquidationThreshold

首先分母TotalDebtInETH表示:总共的债务量(借款 + 利息,但在实际中只会计算债务量,因为 Aave V2 采用的是利滚利模型)。分子TotalCollateralInETH表示:借款人抵押物的总价值(以ETH为单位)。分子LiquidationThreshold表示:该种资产设定的阈值(一个百分比,例如75%)。

分子两者相乘,得到当前抵押物能借出金额上限,分母表示当前借出的债务。分子受市场波动影响,抵押物价值下降,HealthFactor就有可能逼近 1 了,而TotalDebtInETH由于债务利率的存在,会不断的上涨,也会让HealthFactor逐渐的逼近 1 。

清算具体会发生什么呢?当用户抵押了价值 200 $的抵押物,借出了 100 USDT,此时清算阈值是 75%,那么抵押物的价值如果下跌,最多跌倒133.3(用 100 / 0.75 得到,并且忽略利息对健康系数分母的影响),一旦跌倒这个价格之下,那么清算开始发生。

此时有一个清算人负责清算该资产,它可以清算该笔资产的一部分(用户自己决定,但有上限,由 Aave V2 决定,其不允许一次性清算完全部抵押资产),Aave V2 将对抵押物折价卖出,清算人付出借出债务的代币(0%~Aave V2 规定的上限 50%),以当前折扣价买入被清算的抵押物((市场价/代还款)*(1+奖励比例),其中奖励比例就是清算人比起在正常市场中购买代币,在 Aave V2 清算中能额外获得的利润)。此时借款人的健康系数受到影响,变得健康:以上清算行为相当于 Aave V2 自动帮借款人卖出一部分抵押物,来偿还借款(略低于市场价,但高于阈值 * 市场价,因此可以提高健康系数)。

如何发起清算呢?合约由于不能说根据触发条件自动执行函数,所以需要外部的套利者不断的巡视整个市场,发现这些可以清算的交易,对于到达清算线的交易,所有人都可以对其进行清算。清算过后:套利者获得一定利润(通过奖励比例),合约避免了坏账的诞生,维护了市场的稳定。

借款

Aave V2 对于借款人的债务进行了token化,即债务就是一个个的代币。首先有一个问题:债务是token那么转移token是不是就不用还钱了。理论是这样的,但是 Aave V2 将transfer函数重载了,调用后就会revert,所以是没办法转移债务的。

然后就是如何借款了。在 Aave V2 中借款有两种:稳定利率债务、可变利率债务。前者利率固定,借钱时利率是多少,后面利滚利时利息就一直是多少(也有可能调整,如借钱时固定利率和当前利率差距过大);后者利率不固定,随着市场波动,借钱的人多(资金池使用率高),利率就高,人少,利率就低。

当我们想统计t时刻债务总量即:=(稳定利率债务)+(浮动利率债务)Dtasset=SDt(稳定利率债务)+VDt(浮动利率债务),而借款关系到存款利率问题(借款为合约赚取收入,收入分配给存款用户,实现银行的基本功能)。

浮动利率债务

浮动利率虽然浮动(会因为资金池利用率而改变,利用率高,浮动利率就该,反之变低),但是其计算实现反而更加简单。Aave V2 对于每一笔可变债务都首先放缩到0时刻(创世时间)然后利用一个变量存储累计可变债务指数,从而统计出用户当前总可变债务(仅浮动利率债务部分)。

首先理解这个放缩(scaled),它将当前借出的债务换算到创世时间时(即假设你这笔债务在创世时间时借出),假设现在是 1t1 时刻,从 0t0 时刻(创世时间)到当前的累计可变债务 VNtasset 为 200%(假设创世初借款100,现在 1t1 就需要还200了),那么用户借出 1000 相当于创世初时借了500相当于创世初时借了500。上述这个 1000 到 500 的过程就是放缩。

然后就是这个累计可变债务指数 VNtasset 又是如何确定的呢?白皮书中的定义是:

=(1+)∆∗−1VNt=(1+TyearVRt)TVIt1

下面介绍公式中的每个变量的定义,首先是 VRt 表示的是:当前浮动利率(这种当前利率放到最后阐述,先默认已知),即当前所有浮动债务所需要每秒支付利息的利率,这个利率是年华利率。Tyear 表示:一年的秒数(固定值),配合其分子进行除法运算,即可得到每秒的利率。ΔΔT 表示:前后两次操作发生之间的间隔时间,这个操作包含借出、存入、取出、偿还、交换、清算。−1VIt1 表达的含义应该与 VNtasset 一样(我认为的),因为两者白皮书上定义公式一致:

=(1+)∆∗−1VIt=(1+TyearVRt)TVIt1

而其初始值应该为 1 ,然后随着用户不断的操作使得这个变量单调递增。每当我们借出一笔价值为 m 的债务,然后合约进行放缩得到债务值VNtm ,然后加上过去放缩到创世时间的债务(这种方式方便合约计算债务,只需要改变这个累计值,不然浮动利率不断变动,每次操作都要遍历所有债务计算新的债务,又或者记录每次利率变化,gas消耗太大):

()=−1()+ScVBt(x)=ScVBt1(x)+VNtm

当我们想知道当前债务到底是多少时,也很容易计算(其中 x 指某个用户,VNt 在白皮书中为 Dt,查了下资料说可能是白皮书排版错误,Dt 表示放缩后总债务,包含了浮动和固定的):

()=()∗VD(x)=ScVB(x)VNt

对于开头的 SDt (浮动利率债务)的计算就是所有用户的 ()VD(x) 的总和了。

稳定利率债务

对于稳定利率,其计算方法就不一样了。首先需要明确,稳定利率债务不是说借贷利率恒定不变(非硬编码在合约中),而是在计算复利(利滚利)时,利率固定下来,不会因为资金利用率(合约中资金使用程度)而改变,当然当前稳定利率还是会不断改变的。

那么借出一笔稳定利率的债务是怎么进行的呢?在 Aave V2 中记录的是用户的平均稳定借款利率和稳定借款债务,通过两者即可计算当前债务量。

为什么要计算平均稳定借款利率呢?如果使用平均稳定借款利率,那么统计债务的时候就需要遍历每一笔稳定利率借款,而且每一笔债务都需要单独的存储,这都会需要大量的gas,而采用平均稳定利率,那么对于每个用户想要得到当前时刻的债务 ()SDt(x),需要存储的就变为,用户所有债务的平均稳定利率 SRt 和稳定利率债务总量 ()SB(x)

()=()∗(1+‾)ΔSDt(x)=SB(x)(1+TyearSRt)ΔT

上述公式另外几个变量的含义都比较清楚,与浮动利率中的一致。那么上面的平均稳定利率这些变量是怎么确定的呢?首先是平均稳定利率 SRt ,作为平均的利率,肯定是稳定利率平均而来,其公式为:

‾=∗−1‾+∗+SRt=SDt+SBnewSDtSRt1+SBnewSRt

上述公式表示,当用户借出一笔新的资金 SBnew ,在此时,资金池的稳定利率为 SRt ,而用户此前的稳定利率债务为 SDt (不包含 SBnew,并且个人觉得使用 −1SDt1更加符合含义)此前的平均稳定利率为 −1‾SRt1。在初始和还清债务时,用户的 SDt 和 −1‾SRt1 均为 0 。如此,如果用户不断借钱,那么这个平均稳定利率就会不断靠近当前稳定利率。

在上面的几个公式中 SDt 和 ()SB(x) 不断交替出现,其含义十分相似,都表示用户的稳定利率的债务,但还是有一些区别。对于 ()SB(x) 其表示的存储于合约上的债务,即用户当前拥有的债务 token,而()SDt(x) 更多的表示实际需要还给合约的欠款,从()SB(x) 到 ()SDt(x) 需要经过开头的那个公式。

还款

浮动利率还款

在前面我们知道,统计用户的浮动利率债务的时候用的是放缩后的债务 token,而还款也是一样,扣除的是放缩后的债务 token,以此保持浮动利率债务的统计。那么还款后应该扣除多少放缩后的债务 token 呢?这个逻辑和借款的逻辑相反,用户还款 m 根据从创世到现在的累计可变债务 VNtasset 即可得到新的债务:()=−1()−ScVBt(x)=ScVBt1(x)VNtm

稳定利率还款

稳定利率和浮动利率不同,没有这个放缩的过程,所以是计算当前实际欠款 ()SDt(x)(利用借款中其定义公式),然后减去还款数额,并且重新计算平均稳定利率(分母不能为 0 所以分条件):

‾={0, −()=0,∗−1‾−()∗()−, −>0SRt={0SDtSBxSDtSRt1SB(x)SR(x),if SDtSB(x)=0,,if SDtSBx>0

存款

Aave V2中对于用户的存款也是采用放缩和 token 的方法存储用户的存款额度。首先是用户查看当前存款额度()aBt(x)(能取出多少钱):

()=()∗aBt(x)=ScBt(x)NIt

其中 ()ScBt(x) 正是用户放缩后的存款额度(同样是放缩到创世时间),而后面的 NIt 正是累计流动性指数,和借款里的累计类似,这是一个全局的变量(所有的存款共用):

=(∗Δ+1)∗−10=1∗1027=1 LIt=(LRtΔTyear+1)LIt1LI0=11027=1 ray

上面阐述了这个累计指数的初始值和后续的变化方法,而其中的 LRt 是指当前的流动性(一个随着每次资金池操作而改变的值)。在上面我们看到了这个累计流动性指数也是和可变债务指数一样,在不断的单调递增,利用放缩到创世初的存储金额两者结合计算当前存款。

当用户新存入一笔存款 m 也是放缩到创世初,然后两个相加,取款类似(具体是按照取款额度还是放缩后的代币额度需要后续看源码):

()=−1()+ScBt(x)=ScBt1(x)+NItm

利率变化

在上述的各种操作,我们可以知道 Aave V2 其实挺像一个银行了,利用用户的存款进行出借,赚取借贷的利息,然后将利息作为存款的利息发放给存款用户,实现存款获得利息,借款付出利息(虽然是超额抵押借贷)。

但还有一个问题,上述的三个实时利率(当前稳定利率、当前浮动利率、当前流动性率)都是如何确定的呢?首先明确影响这些利率的因素:资金池使用率(使用率越高,借贷的利率理所当然的会更高,反之降低)。

基本上说所有的操作都会影响这个,然后影响其他:借款拉高、还款降低、存款拉低、取回拉高。同时借贷的利息越多,用户存款所得到的利息才会高(存款利息的来源就是借贷的利息)。

首先明确借款的当前利率如何确定:

#={#+∗#1, <#+#1+−1−∗#2, ≥#Rtasset=#Rbaseasset+UoptimalassetUtasset#Rslope1asset,if Utasset<Uoptimalasset#Rbaseasset+#Rslope1asset+1UoptimalUtassetUoptimal#Rslope2asset,if UtassetUoptimal

我们知道借款分为浮动和稳定,而上述公式同时适用于两种,将其中的 ## 替换成为VS即表示浮动和稳定两种。上面的式子表达的意思是:利率从 ##Rbaseasset (由管理员设置)开始起步计算(相当于起步价),根据当前的资金使用率 Utasset (总债务/总储蓄)判断,如果小于最佳借款使用率 Uoptimalasset(由管理员设置),基础利率加上对应比例slope1(由管理员设置)的利率(∗#1UoptimalassetUtasset#Rslope1asset)。超过最佳借款使用率 Uoptimalasset 就在基础利率和slope1利率的和上,根据超过对应比例的slope2(由管理员设置)的利率(−1−∗#21UoptimalUtassetUoptimal#Rslope2asset)递增。

而存款利率(即流动性利率),理所当然的根据债务所产生的利息决定:

=‾∗LRt=RtUt

其中 Ut 是资金池的使用率,Rt 是总体借款利率,总体借款利率通过计算浮动债务和稳定债务的得到:

‾={0, =0∗+∗‾, >0Rt=0,if Dt=0DtVDtVRt+SDtSRt,if Dt>0

参考文章

AAVE v2 - white paper

AAVE V2 学习笔记

Dapp-Learning: AAVE

免责声明

免责声明:

本文不代表知点网立场,且不构成投资建议,请谨慎对待。用户由此造成的损失由用户自行承担,与知点网没有任何关系;

知点网不对网站所发布内容的准确性,真实性等任何方面做任何形式的承诺和保障;

网站内所有涉及到的区块链(衍生)项目,知点网对项目的真实性,准确性等任何方面均不做任何形式的承诺和保障;

网站内所有涉及到的区块链(衍生)项目,知点网不对其构成任何投资建议,用户由此造成的损失由用户自行承担,与知点网没有任何关系;

知点区块链研究院声明:知点区块链研究院内容由知点网发布,部分来源于互联网和行业分析师投稿收录,内容为知点区块链研究院加盟专职分析师独立观点,不代表知点网立场。

本文是全系列中第229 / 238篇:行业技术

  • 我的微信
  • 这是我的微信扫一扫
  • weinxin
  • 我的电报
  • 这是我的电报扫一扫
  • weinxin
chatGPT账号
知点

发表评论

您必须登录才能发表评论!