本文只涉及到利率計算的數學原理,不作源碼解析:
存款
首先我們假設小明在aave里面存了10000usdt,存的時候年化收益率是5%,那么半年后其存款的利息是多少呢?常規的計算方式如下:
利息=10000*5%*(存款的時長/一年的時長)
這么做有什么問題呢?假設現在的存款利率有變化,存的時候是5%,過了兩個月變成了6%,那么現在到了第6個月用戶提款的時候其利息就會變為:
利息=10000*0.05*(2/12)+10000*0.06*(4/12)
如果利率多變動幾次,分步計算的數量會更多,并且需要把用戶存款的時間點,以及每次利率變化的時間點和當時對應的利率記錄下來,這樣才能完整的計算利息。
aave的利率本身是動態的,每次有人存款,取款,借貸,還款都會觸發利率的變化,如果把這些都記錄下來的話對于智能合約來說是個很大的負擔,不僅耗費存儲量空間,在最終結息時候的計算量也是巨大的,隨著合約的運行,其gas費用會越來越高!
liquidityIndex
aave使用了引入流動性指數這個參數來解決這個問題,aave中存儲的每一種資產都有一個liquidityIndex的變量記錄儲備資產的累積流動性增長率。
一個用戶最終的結息金額和三個條件相關:本金,儲蓄時間,利率。實際上我們的期望是不管我存了多長時間,結息的時候乘以存款的最終利率是就好,打個比方在利率不變的情況下,年化利率5%,5%/12就是每個月的利率,存半年的最終利率就是5%/12*6=2.5%,那如果每個月利率都在變的情況下最終利率怎么算呢,按照上面的舉例前面兩個月是5%,后面4個月是6%,半年后取款的最終利率是多少(aave對利率計算的時間精確到秒,這里方便說明使用月代替),計算方式如下:
?
把時間作為權重,乘以相應的利率在累加就是最后的利率。結息的時候用本金乘以最終的利率就可以得到最后的利息金額。
這意味著每一種資產只需要記錄3個值,當前的利率(currentLiquidityRate);上一次更新利率的時間戳(lastUpdateTimestamp);從存款開始到上一次更新利率所累計的總利率(liquidityIndex)
liquidityIndex的初始值為1,代表尚未產生任何利潤,lastUpdateTimestamp就是存款發生的時間,隨著時間的推移,liquidityIndex的值會逐漸變大,因為每時每刻都在累積利息,但其并不會被更新,直到發生了利率變化,比如當前資產發生了存取,借貸,資金池的金額發生變化就會促使利率發生變化。這個時候就會發生liquidityIndex的累加,還是用上面的例子,前面兩個月利率是5%:
后面4個月利率是6%則:
如果此時取款,直接用本金乘以liquidityIndex就可以得到本息的金額。
scaledBalance
細心的同學此時可能會有個疑問,上面的例子闡述了一種資產一個用戶進行儲蓄時的利息計算,如果有多個用戶在不同的時間點存入金額,只用一個公共的liquidityIndex,如何精準計算每個人的利息呢?這就涉及到scaledBalance參數的應用,前面說到影響最終利息的三大要素本金,儲蓄時間,利率,scaledBalance這個參數就是本金的變種,每個用戶都會存儲一份。接著上面的示例,假設現在的liquidityIndex已經從最初的1變成了1.01,那么是不是我存入10000立馬就能取出10100出來呢,顯然是太美好的想象,實際上每個用戶存入資金的時候都會根據當前的liquidityIndex對本金進行換算,得到scaledBalance。比如此時的liquidityIndex為1.01,存入10000元,換算出的scaledBalance為10000/1.01=9900.99,真正計算本息的時候是用scaledBalance*liquidityIndex,所以存入立刻取出是不可能有任何利潤的。
最后我們用示例總結下上面的內容:
場景:三個用戶在不同時間存款
時間線
T0:?liquidityIndex?=?1.0,?Alice?存入?10,000?USDC
T6:?liquidityIndex?=?1.025,?Bob?存入?5,000?USDC??
T12:?liquidityIndex?=?1.051,?Charlie?存入?8,000?USDC
T18:?liquidityIndex?=?1.078,?查詢所有用戶余額
計算過程
Alice:
-?scaledBalance?=?10,000?÷?1.0?=?10,000
-?最終余額?=?10,000?×?1.078?=?10,780?USDC
-?利息收入?=?780?USDCBob:
-?scaledBalance?=?5,000?÷?1.025?=?4,878.05
-?最終余額?=?4,878.05?×?1.078?=?5,258.54?USDC
-?利息收入?=?258.54?USDCCharlie:
-?scaledBalance?=?8,000?÷?1.051?=?7,611.80
-?最終余額?=?7,611.80?×?1.078?=?8,205.52?USDC
-?利息收入?=?205.52?USD
借款
有了存款利率的原理做基礎,理解借款利率的原理就很容易了,相應的借款最終利息的三要素借款金額,利率,時間,借款也有自己的變量存儲隨時間不斷變大的累計利率variableBorrowIndex和經過轉換后的借款金額scaledDebt,計算方式和存款的利率如出一轍。
總還款金額=variableBorrowIndex*scaledDebt