Core Contracts

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

Missing Interest Rates and Liquidity Update in transferAccruedDust Causes Stale Reserve Data

Summary

The transferAccruedDust function is designed to transfer accumulated "dust" from the interest-bearing RToken to a specified recipient. However, it fails to call the ReserveLibrary.updateInterestRatesAndLiquidity function after performing the dust transfer. As a result, the reserve’s interest rates and liquidity values may remain outdated or inconsistent, potentially leading to incorrect calculations for borrowers and depositors.

Vulnerability Details

How It Begins

  • Function Implementation:

    The transferAccruedDust function is implemented as follows:

    function transferAccruedDust(address recipient, uint256 amount) external onlyOwner {
    ReserveLibrary.updateReserveState(reserve, rateData);
    require(recipient != address(0), "LendingPool: Recipient cannot be zero address");
    IRToken(reserve.reserveRTokenAddress).transferAccruedDust(recipient, amount);
    // @info: forgot to call ReserveLibrary.updateInterestRatesAndLiquidity
    }
  • Issue:

    After transferring the accrued dust, which affects the interest-bearing RToken, the function does not update the reserve’s interest rates or liquidity data. The lack of this update means that the internal state of the reserve (i.e., total liquidity, total usage, and derived interest rates) may not accurately reflect the latest changes. Over time, this can lead to inaccurate interest accrual, mispriced borrowing rates, and potential discrepancies between the expected and actual balances in the system.

  • Related Function:

    The ReserveLibrary.updateInterestRatesAndLiquidity function is responsible for adjusting the reserve’s liquidity and interest rates based on recent operations. Without calling this function, any change made by transferring accrued dust remains “stale,” undermining the dynamic adjustments critical to the protocol’s health.

Proof of Concept

Scenario Example

  1. Initial State:

    • The reserve maintains up-to-date interest rates and liquidity based on recent deposits, borrows, and repayments.

  2. Dust Transfer Operation:

    • An administrator calls transferAccruedDust to transfer a specified amount of accrued dust to a recipient.

    • The function updates the reserve state (via ReserveLibrary.updateReserveState) but does not update the interest rates and liquidity using ReserveLibrary.updateInterestRatesAndLiquidity.

  3. Impact:

    • Because the RToken’s accrued dust has been transferred without updating the interest rate model, the reserve’s liquidity and interest calculations remain based on outdated data.

    • This discrepancy could lead to an underestimation or overestimation of current interest rates, affecting both borrowers’ costs and depositors’ returns.

Impact

  • Inaccurate Interest Calculations:
    Without updating the interest rates and liquidity, the protocol may calculate borrowing costs and deposit yields based on outdated data.

  • Mispricing of Borrowing Rates:
    Borrowers might be charged rates that do not reflect the true state of the reserve, potentially leading to imbalances or exploitation.

  • Reduced System Integrity:
    Over time, stale reserve data can compound, leading to systemic risk and undermining user confidence in the protocol’s stability.

Tools Used

  • Manual Review

  • Foundry (Forge)

Recommendations

To remediate this vulnerability, modify the transferAccruedDust function to call ReserveLibrary.updateInterestRatesAndLiquidity after transferring accrued dust. For example:

Recommended Diff

@@ In LendingPool.sol, function transferAccruedDust:
- IRToken(reserve.reserveRTokenAddress).transferAccruedDust(recipient, amount);
-
- // @info: forgot to call ReserveLibrary.updateInterestRatesAndLiquidity
+ IRToken(reserve.reserveRTokenAddress).transferAccruedDust(recipient, amount);
+ // Update interest rates and liquidity after transferring accrued dust
+ ReserveLibrary.updateInterestRatesAndLiquidity(reserve, rateData, 0, 0);

By applying this change, the reserve’s liquidity and interest rates will be recalculated immediately after the dust transfer, ensuring that all state variables remain consistent with the latest operations.

After implementing the recommended modifications, rerun the test suite to confirm that the reserve data is updated correctly and that the accrued dust transfer no longer leads to stale interest calculations.

Updates

Lead Judging Commences

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

LendingPool::transferAccruedDust doesn't update reserve.totalLiquidity when dust is transferred, causing discrepancy between tracked and actual liquidity

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

LendingPool::transferAccruedDust doesn't update reserve.totalLiquidity when dust is transferred, causing discrepancy between tracked and actual liquidity

Support

FAQs

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

Give us feedback!