Core Contracts

Regnum Aurum Acquisition Corp
HardhatReal World AssetsNFT
77,280 USDC
View results
Submission Details
Severity: medium
Valid

Missing Debt Token Supply Sync Leads to Incorrect Interest Rate Calculations

Relevant Context

The LendingPool contract implements a lending protocol where users can deposit assets and borrow against them. The protocol tracks debt using a debt token, whose totalSupply() represents the total debt scaled by the current usage index.

The calculation flow for interest rates is:

  1. LendingPool.deposit()

  2. ReserveLibrary.deposit()

  3. ReserveLibrary.updateInterestRatesAndLiquidity()

  4. ReserveLibrary.calculateUtilizationRate()

The utilization rate, calculated in the final step, is crucial for determining both borrow and lending rates.

Finding Description

When a user calls deposit() in the LendingPool, the following sequence occurs:

  1. updateReserveState() is called to update indices

  2. The function then calls ReserveLibrary.deposit(), which in turn calls updateInterestRatesAndLiquidity()

  3. Inside updateInterestRatesAndLiquidity(), calculateUtilizationRate() is called with the formula:

utilizationRate = totalDebt / (totalLiquidity + totalDebt)

However, reserve.totalUsage (used as totalDebt) is not synchronized with the debt token's total supply after updateReserveState(). When the usageIndex increases over time due to interest accrual, the debt token's totalSupply() correctly reflects this increase as it's scaled by the usage index, but reserve.totalUsage remains outdated.

Impact Explanation

High. The miscalculation of utilization rates leads to:

  1. Incorrect borrow rates being set

  2. Incorrect lending rates for depositors

  3. Protocol-wide economic imbalances

  4. Potential loss of protocol revenue

Likelihood Explanation

High. This issue affects every operation that involves rate calculations and occurs whenever there is a time gap between operations where interest has accrued.

Proof of Concept

Consider this scenario:

  1. Initial state: reserve.totalUsage = 100, usageIndex = 1.0 RAY

  2. Time passes, usageIndex increases to 1.2 RAY

  3. User calls LendingPool.deposit():

    • updateReserveState() updates usageIndex to 1.2 RAY

    • Debt token's totalSupply() correctly returns 120 (scaled by new index)

    • But reserve.totalUsage remains at 100

    • Flow continues to ReserveLibrary.deposit()updateInterestRatesAndLiquidity()calculateUtilizationRate()

    • calculateUtilizationRate() uses 100/(totalLiquidity + 100) instead of 120/(totalLiquidity + 120)

  4. Result: Incorrect utilization rate leads to wrong interest rate calculations

Recommendation

Update the totalUsage after calling updateReserveState() in each of the core functions (deposit(), withdraw()):

function deposit(uint256 amount) external nonReentrant whenNotPaused onlyValidAmount(amount) {
// Update the reserve state
ReserveLibrary.updateReserveState(reserve, rateData);
// Update total usage to match debt token supply
reserve.totalUsage = IERC20(reserve.reserveDebtTokenAddress).totalSupply();
// Perform the deposit through ReserveLibrary
uint256 mintedAmount = ReserveLibrary.deposit(reserve, rateData, amount, msg.sender);
// ... rest of the function ...
}

Apply the same pattern to withdraw() function to ensure the total usage is always up to date with the actual debt token supply before any rate calculations are performed.

Updates

Lead Judging Commences

inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Validated
Assigned finding tags:

LendingPool's utilization calculations use stale totalUsage when deposits occur, failing to account for accrued interest since last borrow/repay action, resulting in artificially lower rates

inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Validated
Assigned finding tags:

LendingPool's utilization calculations use stale totalUsage when deposits occur, failing to account for accrued interest since last borrow/repay action, resulting in artificially lower rates

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!