本手冊將深入探討 AAVE V2 協議的核心設計、關鍵功能及相關審計要點。

作者: flush

編輯: Liz

引言

隨著去中心化金融 (DeFi) 生態系統的迅速發展,AAVE V2 作為領先的去中心化借貸協議之一,在提供創新借貸與流動性管理解決方案方面始終處於行業前沿。其獨特的無信任機制和高效的資本利用率吸引了大量用戶和機構的參與。然而,隨著其應用的普及及所涉及的資金規模逐步擴大,安全審計和風控措施的重要性日益凸顯。本手冊將深入探討 AAVE V2 協議的核心設計、關鍵功能及相關審計要點。

專案背景概述

AAVE V2 是一個基於以太坊區塊鏈構建的開放式借貸平台,允許用戶存入各種 ERC-20 代幣並從中賺取利息,同時也允許以支付利息的形式借用市場中的代幣。透過引入「利率市場」的概念,AAVE V2 實現了去中心化的資金池管理和自動化的利率調整機制。此外,AAVE V2 還提供了閃電貸、抵押貸款和代幣交換等高級功能,以滿足用戶的多樣化需求,進一步鞏固了其在 DeFi 領域的領先地位。

專案架構分析

AAVE V2 的整體架構設計圍繞著用戶、資金流動管理、抵押機制、清算流程以及利率策略等關鍵功能展開,旨在提供高效且安全的去中心化借貸服務。以下是綜合分析:

使用者操作流程

  • 用戶:用戶可以進行存款、借款、償還、提取、借貸利率模式交換、閃電貸以及委託信用等多種操作。當使用者與協議互動時,會根據其操作自動鑄造或銷毀相應的 aTokens,代表其在協議中的存款權益,並根據利率策略獲得收益。
  • 委託信用:用戶可以將自己的信用額度委託給其他用戶,擴展了協議的靈活性和使用場景。

核心組件

  • LendingPool:作為核心模組負責處理所有使用者的營運請求,包括存款、借款、償還、借貸利率模式交換、閃電貸和清算,並更新利率和狀態。
  • Collat​​eral Manager:管理抵押資產,確保用戶借款行為安全可控。當抵押資產不足時,會觸發清算流程來保護系統的整體流動性。
  • Libraries:封裝儲蓄金邏輯,驗證邏輯,通用功能邏輯,如清算和借貸操作的計算,為 LendingPool 提供支援。
    • GenericLogic 計算並驗證使用者狀態,包括資產評估、抵押品價值計算、健康係數等操作。
    • ReserveLogic 用於管理儲備金池,追蹤並更新每種資產的存款量、借款量以及當前利率狀況。
    • ValidationLogic 負責驗證使用者的操作是否符合協議規則,在使用者進行存款、借款、還款、清算、閃電貸、切換債務模式等操作時,對抵押品和負債進行嚴格檢查。

債務與代幣化

  • Debt Tokens:用來追蹤用戶的借款負債,與貸出資金金額 1:1。債務代幣分別有固定利率和可變利率選項(如 DebtDAI Stable、DebtDAI Variable 等),且債務代幣不可轉移。
  • aTokens:用戶存入資產時會產生 1:1 的 aTokens 錨定底層資產,這些 aTokens 會不斷增值以反映存款所賺取的利息。其中由此引入與本金餘額一起儲存為一個比率,稱為縮放餘額 scaled balance (ScB)。

    公式如下:

價格和利率

  • Oracles Proxy:依賴外部預言機 (Chainlink) 提供資產市場價格數據,用於評估使用者抵押資產的價值,確保借貸行為的定價準確性和系統的穩定性。
  • Lending Rate Oracle:根據系統的狀態和市場狀況,提供動態的借貸利率,優化資本利用率和流動性。

配置與管理

  • Configurator:用於配置系統參數,如不同資產的風險參數和借貸限額,管理儲備金的各種操作,包括啟動、借款、抵押、凍結、更新參數及在緊急情況下啟用或停用功能。確保協議可以根據市場變化進行動態調整。

其他關鍵功能

  • Liquidation Manager:當使用者抵押品價值下降至清算門檻以下時,管理清算作業,保護系統的資金安全。清算人可以透過清算操作獲得獎勵。
  • Reserves Balances:儲存系統的儲備資金數據,用於計算和調整利率策略。

利率策略

  • Interest Rate Strategy:根據市場和用戶需求,動態調整利率以實現最佳資本配置,同時考慮流動性風險,確保系統在不同市場條件下的靈活性和穩定性。儘管存在兩種利率模型(穩定型和浮動型),但其模型計算都類似於一個拐點型模型。在拐點最優利用率下的 slope1 和超過最佳利用率的 slope2 分段計算,且在這個條件下也分為固定利率模型與變動利率模型。

公式如下:

流程梳理

存款

使用者透過呼叫 LendingPool 合約的 deposit 函數進行存款,該函數接受四個參數:資產地址、存款金額、接收方地址及推薦碼。首先驗證合約未處於啟用狀態,然後透過 ValidationLogic.validateDeposit 驗證存款金額必須大於 0,同時確認儲備處於啟動狀態且未被凍結。接著系統會更新儲備狀態,呼叫 reserve.updateState() 更新流動性累積指數和可變借款指數,併計算時間段內產生的利息,其中一部分利息會被鑄造並轉入協議國庫。

公式如下:

接著透過 reserve.updateInterestRates 根據最新的供需關係動態調整流動性利率、穩定借款利率和可變借款利率(都由 DefaultReserveInterestRateStrategy.calculateInterestRates 函數計算更新)。資產轉移環節,系統將使用者的基礎資產轉入 aToken 合約,同時鑄造等額 aToken 給使用者所提交的 onBehalfOf 地址。其中,aToken 採用縮放機制 (scaled balance) 處理利息累積。如果是使用者首次存款,系統會自動將該資產標記為使用者的抵押品。

與 Compound 相比,AAVE V2 的存款過程有以下主要特點:

  • 支援指定接收方位址 (onBehalfOf)。
  • 透過 ValidationLogic 合約進行存款驗證。
  • 更新流動性累積指數和可變借款指數計算並分配協議國庫利息。
  • 同時調整流動性、穩定借款及可變借款三種利率。
  • 使用 aToken 的縮放機制 (scaled balance) 處理利息。
  • 首次存款自動標記為抵押品。

提現

使用者透過呼叫 withdraw 函數進行提現操作。首先取指定資產的儲備數據,包括對應的 aToken 位址,檢查此使用者在 aToken 中的餘額。接下來,呼叫 ValidationLogic.validateWithdraw 函數來驗證提現請求,包括檢查提現金額是否有效、使用者餘額是否足夠、儲備是否處於活動狀態等。其中透過 GenericLogic.balanceDecreaseAllowed 對使用者的健康係數以及提現是否影響抵押品進行檢查,類似於 compound 中 getHypotheticalAccountLiquidityInternal 函數的作用。在 balanceDecreaseAllowed 函數中,calculateUserAccountData 和 calculateHealthFactorFromBalances 函數計算取出資金後的清算閥值並檢查使用者總抵押,總借貸金額以及使用者目前的健康係數,以此來判斷是否使用者健康係數處於流動性閥值的安全狀態。

HF 計算公式如下:

隨後更新儲備的狀態,並更新利率,將提現金額傳遞給函數。若使用者要求的提現金額等於其目前餘額,則更新使用者配置,將該儲備標記為不再作為抵押使用。最後銷毀用戶的 aToken,並將提現的資產轉帳到指定的地址。

與 Compound 相比,AAVE V2 的提現過程有以下主要特點:

  • 使用 aToken 代表用戶在協議中的存款,提現實際上是銷毀 aToken。
  • 允許使用者提現到指定位址(透過 to 參數),增加了靈活性。
  • 提供了部分提現和全額提現的選項。
  • 在提現驗證中,AAVE 使用了更複雜的 balanceDecreaseAllowed 函數來檢查提現對使用者整體抵押品狀況的影響。
  • AAVE 的提現過程直接更新了利率,而不是像 Compound 那樣透過 accrueInterest 函數來更新。

借貸

使用者透過 borrow 函數進行借貸,執行借款會先從價格預言機取得資產的當前價格,將借款金額轉換為 ETH 等價。隨後透過 ValidationLogic.validateBorrow 檢查以及 GenericLogic.calculateUserAccountData 用戶借款是否合法,計算包括 onBehalfOf 地址的總抵押資產、總債務、當前貸款價值比率 (LTV)、清算閾值和健康因子以及市場的穩定性等(類似於 Comppotheound 的 getHymInterpothetical),是否有足夠的抵押貸款資產。 reserve.updateState 更新儲備狀態,如利率和借款指數(這一步驟類似於 Compound 中的 accrueInterest),用於計算和更新利息。

隨後根據用戶選擇進行的 interestRateMode(穩定利率或浮動利率)產生債務,選擇不同的利率模型的代幣合約來鑄造代幣。同時,鑄造代幣時也會進行檢查,如果 onBehalfOf 地址不是調用者,則會在代幣合約中減去其對調用用戶的借貸授權。如果是用戶的首次借款,會將其配置為活躍借款者。 DebtToken 鑄造給用戶後,協議會透過 updateInterestRates 更新借款利率,反映借款後的新利率和儲備池的變化。如果用戶要求釋放借款的底層資產,協議會將資產直接轉移給用戶。

與 Compound 相比,AAVE V2 的借貸過程有以下主要特點:

  • 支援穩定和可變兩種利率模式。
  • 使用單獨的驗證邏輯合約進行借貸驗證。
  • 使用債務代幣 (DebtToken) 來表示用戶的借款。
  • 支援信用委託,允許使用者代表其他地址進行借款。

還款

使用者透過 repay 函數進行還款,首先取得使用者目前的債務(包括穩定債務 stableDebt 和浮動債務 variableDebt)。根據使用者選擇的利率模式(穩定或浮動),由 ValidationLogic.validateRepay 驗證使用者的還款操作合法性,包括使用者的債務餘額是否足夠進行還款。根據使用者選擇的利率模式來決定還款的特定債務類型(穩定利率或浮動利率)。如果用戶要還的金額小於當前債務餘額,系統會使用用戶提供的還款金額進行部分還款;否則,將償還所有債務。更新儲備的狀態 updateState,用於計算並更新協議中的利息、借貸量以及借貸指數。隨後燃燒相應的穩定債務代幣,並透過 updateInterestRates 更新借款利率。此時,如果用戶的所有債務(包括穩定和浮動債務)在還款後為零,則會將該用戶的借款狀態標記為 false,表示用戶不再藉款。最後用戶將還款金額從其帳戶轉移到協議的 aToken 合約地址。

與 Compound 相比,AAVE V2 的還款過程有以下主要特點:

  • 支援穩定和浮動兩種利率模式的還款。
  • 使用 DebtToken 來表示和管理債務,還款時會燃燒對應債務代幣。
  • 支持部分還款和全額還款,並分別處理穩定債務和浮動債務。
  • 支援用戶透過信用委託為其他地址還款。

清算

使用者透過 lendingpool 的 liquidationCall 函數進行清算,函數透過代理模式呼叫 LendingPoolCollat​​eralManager 的 liquidationCall 函數,確保函數的成功執行。首先 GenericLogic.calculateUserAccountData 取得抵押品資產及債務資產的儲備資料和使用者的配置訊息,計算使用者的健康因子,並透過 getUserCurrentDebt 取得使用者目前的穩定和可變負債。

ValidationLogic.validateLiquidationCall 函數驗證清算呼叫的合法性,包括檢查使用者的健康因子、債務狀態和抵押品配置。若健康因子小於閥值,已作為抵押品,且兩種債務都不為 0 則驗證通過。接著計算用戶的最大可清算債務,並確定實際需要清算的債務數量。如果清算的債務超過用戶的可用抵押物,將調整清算金額。

如果清算人選擇接收被清算人抵押的底層資產,則需要確保抵押物儲備中有足夠的流動性。更新債務儲備的狀態,並根據清算人是否接收 aToken 情況,燃燒相應數量的可變和穩定債務代幣。更新債務的利率,反映清盤後的市場狀況。清算人獎勵如果選擇接收 aToken,清算人將獲得相應數量的 aToken。如果不接受 aToken,則更新其抵押狀態和抵押物的利率,從用戶帳戶中燃燒掉對應數量的 aToken ,將底層資產轉移給清算人。最後,將清算所需的債務資產從清算人轉移到相應的儲備 aToken 中,完成清算過程。

與 Compound 相比,AAVE V2 的清算過程有以下主要特點:

  • 支持多種抵押品和債務資產的組合清算。
  • 允許清算人選擇接收 aToken 或底層資產。
  • 清算過程更加模組化,將驗證邏輯、計算邏輯等分離到不同的函數中。
  • 支持穩定利率和可變利率兩種債務類型的清算。

閃電貸

使用者透過 lendingpool 的 flashLoan 函數進行閃電貸。作為借貸協議的閃電貸,可以允許當前閃電貸立刻還款或是作為債務來後續還款,其中以傳入的 modes 參數不同而決定。 0 為立刻還款,1 為作為穩定型債務,2 為浮動型債務。

函數首先透過 ValidationLogic.validateFlashloan 檢查輸入參數匹配,計算閃電貸方所需的溢價成本,並直接將所需的 aToken 轉給接收者地址。呼叫接受者的 executeOperation 操作實現預設的閃電貸。 AAVE 實現的閃電貸作業已包括了兌換,兌換清算,以及兌換償還作業。在 executeOperation 完成以上操作後,記錄需償還的閃電貸金額和對應的費用。如果用戶選擇以非債務模式歸還資金:系統更新儲備狀態,累積儲備流動性以及更新流動性指數。最後再從請求者轉移資金和費用至儲備池。若使用者選擇以債務模式處理,則呼叫_executeBorrow,開啟對應的債務部位。

轉換債務模式

在 AAVE V2 中,使用者可以透過 swapBorrowRateMode 函數在穩定利率模式和浮動利率模式之間切換。首先透過 getUserCurrentDebt 函數取得使用者在目標資產上的當前穩定利率債務和浮動利率債務,確定使用者的債務狀況。接著呼叫 ValidationLogic.validateSwapRateMode 函數驗證切換操作是否合法。其中檢查使用者是否有足夠的穩定或浮動債務以支援模式切換,確保切換目標模式符合資產的配置和使用者的債務狀況。呼叫 reserve.updateState 更新資產儲備的狀態,確保儲備資料最新。接著就是對於兩種債務代幣的相互轉換,燃燒穩定債務代幣鑄造浮動債務代幣或是燃燒浮動債務代幣鑄造穩定債務代幣。轉換完成後,reserve.updateInterestRates 更新目標資產利率,確保反映當前市場狀態和使用者債務的變化。

安全漏洞 Checklist

空市場導致的捨入漏洞

在 AAVE 和 Compound 中,都存在空市場中精確度損失所造成的漏洞問題。如果在一個空市場的情況(即沒有用戶在市場中進行借貸),由於 cumulateToLiquidityIndex 函數中 liquidityIndex 的值依賴於合約對應的底層資產代幣的數量,所以攻擊者可以通過閃電貸向合約存入大量的底層資產代幣來操縱 aToken 的價格。

與先前 Compound fork 專案 Hundred Finance 第一次被駭相似,在 HopeLend 事件中,攻擊者先操縱 liquidityIndex 將 hETHWBTC 兌 WBTC 的價值控制為 1:1,透過兌換底層資產以及借貸的方式又提高 liquidityIndex 的值。隨後透過循環的閃電貸不斷呼叫_handleFlashLoanRepayment 函數。

在 cumulateToLiquidityIndex 函數中,rayDiv 的精確度損失會再次放大 reserve.liquidityIndex 的數值,最終放大了能兌換出的 WBTC。(攻擊交易:https://etherscan.io/tx/0x1a7ee0a7efc70ed7429edef069a1dd001fbff378748d91f17ab1876dc6d10392)

審計重點:在審計時,需要關注兌換率的計算方式是否容易被操控以及舍入的方式是否恰當,同時可以建議專案團隊在新的市場創建後立刻鑄造 aToken,以防止市場為空進而被操控。

ERC677 / ERC777 代幣導致的重入漏洞

與先前 Compound fork 專案 Hundred Finance 第二次被駭相同,在 Agave 攻擊事件中,攻擊者在沒有任何負債的情況下呼叫了 liquidateCall 函數來清算自己。而清算的代幣是 Gnosis Chain 鏈上使用的 ERC-677 標準代幣, 該類代幣轉賬時會外部調用接收地址的函數, 所以使得清算合約調用了攻擊合約,攻擊合約在此過程中存入了 2728 個通過閃電貸獲取的 WETH,鑄造出 2728 aWETH,並以此為抵押,藉出了所有資產。外部呼叫結束後,liquidationCall 函數直接清算了攻擊者先前存入的 2728 aWETH,並將其轉給清算者。

function transfer(address _to, uint256 _value) public returns (bool) {
require(superTransfer(_to, _value));
callAfterTransfer(msg.sender, _to, _value);
return true;
}
function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
require(super.transferFrom(_from, _to, _value));
callAfterTransfer(_from, _to, _value);
return true;
}
function callAfterTransfer(address _from, address _to, uint256 _value) internal {
if (AddressUtils.isContract(_to) && !contractFallback(_from, _to, _value, new bytes(0))) {
require(!isBridge(_to));
emit ContractFallbackCallFailed(_from, _to, _value);
}
}
function contractFallback(address _from, address _to, uint256 _value, bytes _data) private returns (bool) {
return _to.call(abi.encodeWithSelector(ON_TOKEN_TRANSFER, _from, _value, _data));
}

(參考來源:https://x.com/danielvf/status/1503756428212936710; 攻擊交易:https://gnosis.blockscout.com/tx/0xa262141abcf7c127b88b4042aee8bf6014f32d

稽核重點:在稽核中,需要注意借貸功能的相關程式碼是否符合 CEI (Checks-Effects-Interactions) 規範或是否有防重入鎖,並且需要考慮具有回呼功能的代幣造成的影響。

不恰當的預言機機制所導致的價格操控風險

在 Blizz Finance 計畫被駭事件中,由於當時 LUNA 的價格持續暴跌,協議使用的 Chainlink 價格資訊變得不準確,導致可以用價格高昂的 LUNA 抵押品借入資金。同時專案沒有現有的故障安全機制,儘管看起來已經提前發出警報,但並沒有及時建立預防措施來防止損失。當價格跌破該水平時,使得任何人都可以以市場價格購買(遠低於 0.10 美元的價格)大量 LUNA,並將其作為抵押品(價值 0.10 美元)從平台借出資金。

function _executeBorrow(ExecuteBorrowParams memory vars) internal {
...
uint256 amountInETH =
IPriceOracleGetter(oracle).getAssetPrice(vars.asset).mul(vars.amount).div(
10**reserve.configuration.getDecimals()
);
ValidationLogic.validateBorrow(
vars.asset,
reserve,
vars.onBehalfOf,
vars.amount,
amountInETH,
vars.interestRateMode,
_maxStableRateBorrowSizePercent,
_reserves,
userConfig,
_reservesList,
_reservesCount,
oracle
);
...
}
function validateBorrow(
...
) external view {
...
(
vars.userCollateralBalanceETH,
vars.userBorrowBalanceETH,
vars.currentLtv,
vars.currentLiquidationThreshold,
vars.healthFactor
) = GenericLogic.calculateUserAccountData(
userAddress,
reservesData,
userConfig,
reserves,
reservesCount,
oracle
);
require(vars.userCollateralBalanceETH > 0, Errors.VL_COLLATERAL_BALANCE_IS_0);
require(
vars.healthFactor > GenericLogic.HEALTH_FACTOR_LIQUIDATION_THRESHOLD,
Errors.VL_HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD
);
vars.amountOfCollateralNeededETH = vars.userBorrowBalanceETH.add(amountInETH).percentDiv(
vars.currentLtv
); //LTV is calculated in percentage
require(
vars.amountOfCollateralNeededETH <= vars.userCollateralBalanceETH,
Errors.VL_COLLATERAL_CANNOT_COVER_NEW_BORROW
);
...
}

(參考來源:https://x.com/BlizzFinance/status/1524911400992243761)

審計重點:在審計時,需要關注計算抵押品價值時採用的預言機餵價機制是否容易被外部操控,可以建議項目方採用多種價格來源進行綜合評估,以規避單一價格來源造成的風險。同時也需要注意項目是否有合理的暫停機制,以預防此類突發情況。

外圍合約外部調用引入的非預期問題

在 AAVE 協定與 Para Swap 協定的交互中,Aave Collat​​eral Repay Adapter V3 合約的_buyOnParaSwap 函式有多個安全隱患。此函數透過呼叫 safeApprove 方法,在 tokenTransferProxy 上設定 assetToSwapFrom 的限額為 maxAmountToSwap,但未考慮未進行兌換或部分兌換的情況,導致在未完全使用限額的情況下,剩餘額度仍保持不變。此外,函數依賴外部合約呼叫 (augustus.call(buyCalldata)) 執行兌換,並且未對 paraswapData 傳參進行充分驗證與限制,從而允許攻擊者透過惡意建構的 paraswapData 操控解碼後的 buyCalldata 和 augustus 合約位址,繞過預期的兌換邏輯或完全避免兌換。由於該函數在兌換後未減少或檢查 assetToSwapFrom 的代幣限額,即使兌換失敗或被繞過,攻擊者仍可利用未變化的高額限額提取合約中的代幣,從而實現未經授權的資金轉移。出現因缺乏輸入資料和交換結果的驗證,以及未能有效管理代幣限額的情況,導致合約被攻擊者利用。

(攻擊交易:https://etherscan.io/tx/0xc27c3ec61c61309c9af35af062a834e0d6914f9352113617400577c0f2b0e9de)

審計重點:在審計時,需特別注意與外部第三方協議的交互代碼。重點評估外部合約的輸入和輸出是否經過嚴格限制,交互邏輯是否對協議核心模型或資金安全產生潛在影響,輸入資料是否經過清理和驗證,防止惡意資料引發安全問題。透過嚴格審查外部互動的程式碼邏輯以及資料驗證機制,可有效降低此類漏洞風險。

代幣與利率策略兼容問題

在 Polygon 鏈上,AAVE 部署過程中,由於 InterestRateStrategy 設定不相容的問題導致功能異常,錯誤地為 WETH 設定了不相容的利率策略。

錯誤設定的 InterestRateStrategy 合約中的 interface 如下:

function calculateInterestRates(
address reserve,
uint256 utilizationRate,
uint256 totalStableDebt,
uint256 totalVariableDebt,
uint256 averageStableBorrowRate,
uint256 reserveFactor
)external view returns (…);

而 AAVE V2 的 LendingPool 實作的程式碼如下:

function calculateInterestRates(
address reserve,
address aToken,
uint256 liquidityAdded,
uint256 liquidityTaken,
uint256 totalStableDebt,
uint256 totalVariableDebt,
uint256 averageStableBorrowRate,
uint256 reserveFactor
)external view returns (…);

(參考來源:https://x.com/mookim_eth/status/1659589328727859205)

由於介面不相容,新 InterestRateStrategy 無法正常被 LendingPool 調用,直接導致 AAVE V2 的 WETH 池功能中斷,使用者無法存入或提取 ETH。

稽核重點:在稽核時,需確保程式碼(或 fork)中關鍵元件的介面完全相容。同時,儘管以上問題並非由多鏈特性導致的原因,但是審計時仍需要注意不同鏈的特性下是否會造成非預期的結果。

Dust 代幣問題

AAVE 的存款和提款會透過 setUsingAsCollat​​eral 函數設定 usingAsCollat​​eral 來實現,從而靈活地管理抵押策略。當外部協議或合約透過 AAVE 借貸函數第一次借入資金時,借貸函數會將 usingAsCollat​​eral 設為 true。當外部協議或合約從 AAVE 完全提取資金時,AAVE 中協議處理程序的 usingAsCollat​​eral 狀態將被設定為 false。但實際上,AAVE 在計算取款需要燒掉的 aToken 數量時,此時如果由於算術精度誤差,協議處理程序中可能還有極少的 aToken 剩餘。因此,當協議處理程序下次向 AAVE 存款時,usingAsCollat​​eral 將不會變動,依然設為 true,由於協議處理程序合約中沒有調用 setUserUseReserveAsCollat​​eral 函數的接口,這可能導致協議處理程序無法再執行借款操作。

function deposit(
address asset,
uint256 amount,
address onBehalfOf,
uint16 referralCode
) external override whenNotPaused {
...
if (isFirstDeposit) {
_usersConfig[onBehalfOf].setUsingAsCollateral(reserve.id, true);
emit ReserveUsedAsCollateralEnabled(asset, onBehalfOf);
}
...
}
function withdraw(
address asset,
uint256 amount,
address to
) external override whenNotPaused returns (uint256) {
...
if (amountToWithdraw == userBalance) {
_usersConfig[msg.sender].setUsingAsCollateral(reserve.id, false);
emit ReserveUsedAsCollateralDisabled(asset, msg.sender);
}
...
}
function setUserUseReserveAsCollateral(address asset, bool useAsCollateral)
external
override
whenNotPaused
{
...
_usersConfig[msg.sender].setUsingAsCollateral(reserve.id, useAsCollateral);
...
}

審計重點:在審計時,需要對所調用的協議有充分的熟悉度,充分了解其特性的情況下,判斷是否對於其與外部協議交互存在一定的兼容性問題,如代幣兼容性、調用實現邏輯兼容性等。

寫在最後

本手冊深入探討了 AAVE V2 協議的核心設計、關鍵功能及相關審計要點,我們希望手冊可以更好地幫助開發人員和安全研究人員識別潛在風險並確保協議的安全運作。由於篇幅限制,本文省略了部分程式碼和圖片,讀者可點擊文末的閱讀原文跳轉至 GitHub 閱讀完整版 (https://github.com/slowmist/AAVE-V2-Security-Audit-Checklist)。

參考資料

[1] https://github.com/aave/protocol-v2

[2] https://github.com/YAcademy-Residents/defi-fork-bugs[3] https://solodit.cyfrin.io/

[4] https://blog.solidityscan.com/aave-repay-adapter-hack-analysis-aafd234e15b9

[5] https://gist.github.com/mookim-eth/72f185019e8c4df3a1edba637067f734

免責聲明:作為區塊鏈資訊平台,本站所發布文章僅代表作者及來賓個人觀點,與 Web3Caff 立場無關。文章內的資訊僅供參考,均不構成任何投資建議及要約,並請您遵守所在國家或地區的相關法律法規。