Core Contracts

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

Locked Update Functions in RToken and DebtToken Prevent Liquidity and Usage Index Updates

Summary

The RToken and DebtToken contracts include functions (updateLiquidityIndex and updateUsageIndex) that are responsible for updating key indices used in calculating accrued interest. Both functions are guarded by an onlyReservePool modifier, ensuring that only the designated reserve pool can call them. However, in practice, these functions are intended to be invoked by the LendingPool or ReserveLibrary. Due to the strict access control, if neither the LendingPool nor ReserveLibrary is set as the Reserve Pool, these functions become locked and effectively unusable, which may prevent the proper updating of liquidity and debt accrual data.

Vulnerability Details

How It Begins

  1. Function Implementations:

    The updateLiquidityIndex function in the RToken contract:

    /**
    * @notice Updates the liquidity index
    * @param newLiquidityIndex The new liquidity index
    */
    // @info: locked function
    function updateLiquidityIndex(uint256 newLiquidityIndex) external override onlyReservePool {
    if (newLiquidityIndex < _liquidityIndex) revert InvalidAmount();
    _liquidityIndex = newLiquidityIndex;
    emit LiquidityIndexUpdated(newLiquidityIndex);
    }

    The updateUsageIndex function in the DebtToken contract:

    /**
    * @notice Updates the usage index
    * @param newUsageIndex The new usage index
    */
    // @info: locked function
    function updateUsageIndex(uint256 newUsageIndex) external override onlyReservePool {
    if (newUsageIndex < _usageIndex) revert InvalidAmount();
    _usageIndex = newUsageIndex;
    emit UsageIndexUpdated(newUsageIndex);
    }
  2. Access Control:

    Both functions are protected by the onlyReservePool modifier:

    /**
    * @dev Ensures that only the Reserve Pool can call the function
    */
    modifier onlyReservePool() {
    if (msg.sender != _reservePool) revert OnlyReservePool();
    _;
    }
  3. The Issue:

    In the current system configuration, the LendingPool or ReserveLibrary is expected to call these functions to update the reserve’s liquidity and usage indices. However, because these contracts are not assigned as the Reserve Pool (i.e., they do not match the _reservePool address), any call from them will revert. Consequently, the critical functions for updating interest and debt accrual remain inaccessible, which can lead to stale index values and erroneous calculations across the protocol.

Proof of Concept

Scenario Example

  1. Intended Operation:

    • The LendingPool or ReserveLibrary should call updateLiquidityIndex and updateUsageIndex during operations such as deposits, withdrawals, or borrowings to adjust the interest-bearing token values and debt calculations.

  2. Misconfiguration Impact:

    • If the _reservePool variable is not set to the address of the LendingPool or ReserveLibrary, any attempt to update the indices will trigger the onlyReservePool check:

      if (msg.sender != _reservePool) revert OnlyReservePool();
    • This prevents the function from executing and leaves the indices unmodified, resulting in inaccurate interest calculations and potential imbalances in the protocol’s accounting.

  3. Demonstration:

    • A test scenario where LendingPool (or ReserveLibrary) attempts to update the liquidity or usage index will fail with an OnlyReservePool() error, highlighting that the functions are effectively locked due to the misconfiguration of the _reservePool address.

Impact

  • Stale Reserve Data:
    Without the ability to update liquidity and usage indices, the protocol cannot accurately track accrued interest or debt, which can lead to mispriced borrow rates and incorrect deposit yields.

  • Systematic Accounting Errors:
    Over time, the failure to update these indices can compound, leading to significant discrepancies in user balances and overall reserve health.

  • Operational Risk:
    The inability to adjust these critical parameters may affect risk management and the stability of the protocol, potentially undermining user trust and leading to financial losses.

Tools Used

  • Manual Code Review

  • Foundry (Forge) for testing access control scenarios

Recommendations

  • Reconfigure Access Control:
    Ensure that the _reservePool variable is correctly set to the address of the LendingPool or ReserveLibrary (whichever is intended to invoke these functions). This may involve:

    • Updating the constructor or initialization logic in the RToken and DebtToken contracts.

    • Adding administrative functions to update the _reservePool address securely if necessary.

  • Alternative Approach:
    If the design requires that multiple contracts call these update functions, consider using a more flexible access control mechanism (e.g., AccessControl from OpenZeppelin) that permits a defined set of authorized callers instead of a single fixed address.

Updates

Lead Judging Commences

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

[INVALID] Unused _usageIndex Variable and updateUsageIndex() Function in DebtToken Contract

RToken::updateLiquidityIndex() has onlyReservePool modifier but LendingPool never calls it, causing transferFrom() to use stale liquidity index values

Support

FAQs

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

Give us feedback!