這篇文章是三篇系列文章的第一篇,討論DeFi 借貸協議的工作原理——它們的關鍵組成部分、公式和用例。在這一過程中,我們將強調,儘管協議使用不同和創意的命名方式,但它們傾向於重複、迭代和分享核心概念。其中一篇本博客文章中詳細介紹如何使用ERC 20 Token 來代表用戶在藉貸池中的份額。我們將從分析這些協議的獨特元素開始,並提供技術概念來區分它們的工作方式。
借貸池
在傳統金融(或TradFi)中,借貸由第三方金融機構進行調整。這些金融機構被委託執行兩項關鍵任務:強制借方向貸方支付利息,並評估並防止被認為是不可信的當事方參與這些活動。
相比之下,在去中心化金融(或DeFi)中,第三方借款人和貸款人是不值得信任的。這種信任的缺失激發了一個創新的設計,用於在鏈上促進借貸過程。
借貸池是一個智能合約。DeFi 協議用戶可以存入資產(通常是ERC 20 Token),目的是使用該合約來借出他們存入的資產。其他用戶可以與借貸池進行交互,享受即時貸款,即抵押在池中的資產進行借款。
與傳統金融方法相比,借貸池在藉貸方面具有一些重大的優點,例如:
· 在DeFi 中,貸款不受貸款資金與借款金額1: 1 可用性的限制。相反,來自協議所有用戶的資金都被存入池中,從而創建了足夠大的 Token 庫存,以立即滿足貸款需求。
· DeFi 不需要還款計劃。貸款是根據以前存入的抵押品執行的,用戶可以隨時選擇還款。
此時,你可能會想,「如果我不得不提供同等價值(甚至高估)的資產作為抵押品,為什麼要在藉貸協議上借入資產?難道我不應該出售抵押品併購買所借資產嗎?」
實際上,這種DeFi 借貸協議似乎只允許完全抵押(或超額抵押)的貸款,為一個有趣的「交易」方法打開了大門:槓桿。
假設你對WBTC 非常看好,非常確定它的價值會飆升!你可以在你最喜歡的借貸協議上存入一些WBTC(價值1000 美元),然後使用它來借入一些穩定幣(例如USDC),然後用這些穩定幣在某個交易所上購買更多的WBTC(對於我們的場景,假設你的初始存款的一半,即500 美元)。在這種情況下,你暴露於WBTC 的價值為1500 美元,而你的初始存款只有1000 美元。
但是,如果你把你的500 美元的WBTC 抵押品存入協議來借入更多的USDC 呢?這個過程被稱為超額槓桿,你可以一直這樣做,直到你超出了你的借款能力,而協議的政策會阻止你這樣做。
在類似的情況下,假設你對WBTC 持悲觀態度(畢竟現在是Crypto 冬天)。你可以採取我們之前場景的相反操作,將USDC 作為抵押品存入協議來借入WBTC,然後立即以更多的穩定幣換掉它。如果你的預測成為現實,WBTC 的價格下降了,你可以在交易所上以更便宜的價格購買相同數量的WBTC,償還貸款並獲得多餘的USDC,從而打開(並關閉)WBTC 的空頭頭寸。
份額 Token
與傳統金融一樣,將資產存入借貸池的用戶會受到長期保留資金的激勵,並獲得存款利息。利息隨時間累計,按用戶在協議中的存款的百分比計算,並由其相應的存款用戶聲明。用戶在藉貸池中保留資產的時間越長,他們獲得的利息就越多。
協議如何記錄每個用戶在池中的份額?當一個用戶向池中存入資產時,他們的「份額」會稀釋所有用戶的份額,協議會相應地反映這一點。然而,協議不會直接跟踪和更新每個用戶的池份額,而是僅處理存款人份額的變化,而無需每次提取或存入時主動更新其他用戶的份額。
你可能會認為這個協議讓你既能擁有蛋糕,又能吃掉蛋糕。但實際上不是這樣的:
協議通過鑄造和銷毀ERC 20 Token 來處理利息發放,我們稱之為「份額 Token」,它代表了貸款池中一個貸方的份額(或存款資產的比例)。這種「份額 Token」設計自動調整其他「股東」的股份稀釋,以反映「份額」的鑄造和銷毀,與他們的基礎資產的存款或提取成比例。
下面,我們將提供不同協議如何使用「份額 Token」的實際示例,並討論它們的相似之處。
aToken:AAVE 的「份額 Token」
aToken 是AAVE 的收益生成 Token,由貸款池在存入和提取資產時鑄造和銷毀。
aToken 是集成到AAVE 協議中的類似於ERC 20 的 Token,因此用戶可以進入的每個不同市場(存入抵押品)都有一個對應的aToken。
如果我們查看AAVE 借貸池合約,我們可以看到當用戶向池中存入資產時發生的基本操作:

我們可以看到與用戶存入的市場相對應的aToken 將被稱為「鑄造」函數。

我們可以看到,實際要鑄造的數量是:

如上圖所示,在這個例子中,用戶加入了一個已經在之前的存款中賺取了一些利息的市場。上面的方程式幫助我們理解這一點,因為它顯示瞭如何使用全局指數來考慮所有用戶的利息累計,這個指數會在各種操作(存款、提款等)時更新。
當用戶提取他們的基礎資產時,liquidityIndex 將用作乘數來計算交易中所欠的 Token 數量。
以下是來自借貸池合約的相關代碼片段:

在這裡,aToken 合約的balanceOf 函數有點奇怪。畢竟,我們剛剛確定鑄造的aToken 數量與存入的基礎資產數量不同。調用IAToken(aToken).balanceOf(address(user)) 如何產生用戶即將提取的基礎資產數量(如在函數底部所示)?原因如下:
· 當用戶提取他們的資產時,他們的aToken 將被銷毀。這些已銷毀的aToken 保持其他用戶所擁有的aToken 的總量與他們的份額成比例,這些份額是在用戶資產提取之後的。
· 用戶提取資金的市場利率會隨著每次提取而更新。

正如我們先前所述,aToken 是類似於ERC 20 的 Token。我們強調它們是「類似」ERC 20 Token,因為它們的balanceOf 函數具有獨特的屬性。在常規的ERC 20 Token 中,balanceOf 函數返回一個地址擁有的 Token 數量。
由於aToken 代表池的份額,而不是直接的價值,因此aToken 的balanceOf 函數返回協議欠用戶的基礎 Token 的數量,以對其存款進行補償。

在此,該balanceOf 函數覆蓋了繼承的aToken 合約中的balanceOf 函數。結果,該示例邏輯中的balanceOf 邏輯被執行,而不是用戶 Token 數量的常規(繼承)映射查找。
上述提到的 Token 數量然後乘以getReserveNormalizedIncome 的結果,該函數執行以下邏輯:

我們可以識別此處的分支:
· 如果在該塊中已經更新了保留數據:返回該市場的liquidityIndex 值,因為它已經更新。
· 否則:我們需要看看calculateLinearInterest 中發生了什麼才能找出下一個流程。

當前市場的ReserveData 對像中的currentLiquidityRate 和lastUpdateTimestamp 被傳遞到此函數中,函數的結果為:

讓我們分解此方程式的組件,以更好地理解linearInterest 值的要點:
· currentLiquidityRate:可以將其視為我們所在市場的年利率(APY)
· block_{timestamp} – lastUpdatedTimestamp:自上次更新以來經過的時間
注意:由於我們在getNormalizedIncome 中選擇了第二個分支,因此在此時保證該值為正值。
因此,我們可以將此利息應計機制視為一個簡單的利息複合機制,它在每個區塊中進行複合。現在,我們已經確定了要為用戶累計的利息金額,我們只需要將該值乘以流動性指數,然後在balanceOf 函數中進行用戶的規範化收入乘法:

現在我們了解了aToken 背後的邏輯,但我們仍然需要解決liquidityIndex 的工作原理之謎。
在下面的示例中,liquidityIndex 可以定義為一定時間內儲備積累的利息:

回顧之前提到的liquidityRate 變量- 現在我們將討論它在計算liquidityIndex 中的使用。只有當liquidityRate 大於0 時,才會積累利息- 換句話說,只有該市場中有任何APY 時才會積累利息。這是有意義的。
讓我們快速回顧一下calculateLinearInterest 的實際操作:

上述邏輯可以轉化為以下方程式:

正如我們可以在DefaultReserveInterestRateStrategy.sol 合約中看到的那樣,liquidityRate 是通過以下方式定義的:

因此,可以寫為:

整體借款利率(overallBorrowRate)在此定義為:

我們可以將其寫成:


利用率(utilizationRate)可以定義為:

在定義利用率時,我們更容易考慮儲備中流動性(當前借出的流動性)與市場中總流動性之間的比率,這可以簡化為:

現在我們可以使用這兩個定義來編寫流動性指數的方程式:

由於totalBorrows 在分子和分母中都存在,因此我們可以寫成:

關於流動性指數的方程式,現在已經說得夠多了,我們以後會再來討論這個定義。
cToken:Compound 的「份額 Token」
讓我們繼續我們下一個借貸協議示例,Compound。
Compound 使用稱為cToken 的「份額 Token」來處理借款和放貸。這個 Token 為Compound 協議中所有可用於用戶借貸的資產進行記賬。
與我們在AAVE V2 中討論的類似,Compound 的「份額 Token」被鑄造並用於贖回基礎資產。
Compound 使用的匯率類似於AAVE V2 的流動性指數,以確定應鑄造多少cToken。這個匯率是一個這樣的函數:

讓我來解釋這裡的關鍵術語:
·totalCash:cToken 賬戶擁有的ERC 20 基礎 Token 的數量。
· totalBorrows:借款者藉出市場上的ERC 20 基礎 Token 的數量。
· totalReserves:保留的一定數量的ERC 20 基礎 Token,可通過治理方式進行提取或轉移。
· totalSupply:返回cToken 的總供應量的ERC 20 函數。
有了這個背景,我們可以寫出Compound 的匯率方程式:

當用戶存入ERC 20 Token 時,匯率決定了將鑄造多少cToken 作為回報:

要鑄造的cToken 數量由以下方程式定義:

eToken:Euler 的「份額 Token」
為了進一步鞏固這些協議之間的相似性,讓我們再分析另一個借貸協議Euler,看看它如何處理借貸。
在下面的示例中,deposit 函數允許用戶存入ERC 20 Token 以換取eToken。

正如我們所見,internalAmount 是為此轉移鑄造的eToken 數量。

與Compound 的名字和函數exchangeRate 又一次直接重疊。
讓我來解釋一下用於計算匯率的關鍵參數:
· poolSize:使用基礎資產的ERC 20 合約中,以池合約地址調用balanceOf(address)函數的結果。
· totalBorrows:借出的ERC 20 基礎 Token 的總量,目前不在池中。
· totalBalances:所有eToken 持有者的總餘額。
因此,方程式將是:
總結
我們已經涵蓋了3 個借貸協議:
· AVE V2
· 化合物
·歐拉
我們已經檢查了「份額 Token」的鑄造方式,以及它們如何通過借貸池交換存款資產。
我們提出的三個方程式可以歸納為一個簡單的方程式:

請記住,匯率可以按照協議定義的任何方式進行定義。這些任意的匯率可以增加鑄造的 Token 數量(如果小於1 ),如果大於1 則會減少數量。
在AAVE V2 和Compound 中,我們已經看到了someRate 變量的一些相似之處。在Compound 中,someRate 是:

而對於AAVE V2,someRate 的定義如下:

流動性指數的定義為:

雖然我們不能將每個協議的匯率歸納為一個式子,但對於AAVE 2 和Compound,我們知道匯率是市場中總流動性的函數。回到我們的方程式,給定totalLiquidity 是市場中ERC 20 基礎 Token 的總量,那麼在exchangeRate 表達式的分子中和liquidityRate 的分母中的分子是功能上相同的。
簡而言之:這些協議在本質上是相似的。雖然它們有時可能使用不同的術語,但當將它們分解為方程式時,每個組件在實現中都具有類似的目的。我們邀請讀者隨機選擇一個借貸協議,並檢查我們在此處討論的歸納是否也適用於該協議。如果適用的話,請隨時告訴我們。