The RToken is not interest bearing. During the withdrawal process, the amount owed to the user is not properly scaled to include interest. Specifically, the calculation of liquidity index upon burning during the withdrawal process from LendingPool is broken. No interest is calculated or added and provided to the user.
Uninvoked updateLiquidityIndex(): The function updateLiquidityIndex(uint256 newLiquidityIndex), which is responsible for updating the internal _liquidityIndex, is not invoked anywhere in the protocol. As a result, the _liquidityIndex variable in RToken.sol remains fixed at its initial value (1e27). Despite being callable by the Reserve Pool (as enforced by the onlyReservePool modifier), no contract (including the LendingPool) ever calls this function.
Stale Liquidity Index: Because _liquidityIndex is initialized to WadRayMath.RAY (1e27) and never updated, the scaling mechanism used in balanceOf(), transferFrom(), and other functions does not apply any interest accrual. The intended dynamic adjustment of user balances based on accrued interest is effectively bypassed.
Parallel Liquidity Index Mechanism also not scaled to Deposit: There is a parallel liquidity index update mechanism used in updateReserveInterests()::ReserveLibrary.sol and calculateLiquidityIndex()::ReserveLibrary.sol. These are, however, incorrectly implemented in burn() of RToken.sol. Although the burn() function calculates an "amountScaled" using amount.rayMul(index), it never actually uses that scaled value in the burn operation. Instead, it directly burns amount.toUint128() and returns the unscaled amount, which means that the intended multiplication by the liquidity index does not take effect.
Root Cause:
Run the test below in LendingPool.test.js with the following command:
No Interest Accrual for Depositors: Depositors receive RToken without any interest growth, undermining the promise of an interest-bearing asset and reducing the token to a static ERC20 asset.
Misleading Token Economics: Functions that rely on a dynamic liquidity index (such as balanceOf() and transferFrom()) perform calculations using the fixed initial value, leading to inaccurate representations of users' actual balances.
Protocol Economic Imbalance: The entire economic model of the protocol assumes that deposited assets accrue interest over time. With the liquidity index stagnant, risk assessments, yield calculations, and borrowing limits may be significantly misaligned with the protocol’s design.
Manual Review, Hardhat
Ensure that the amountScaled variable in burn() is passed to the _burn().
Remove the redundant use of userState mapping. Remove the redundant updateLiquidityIndex() which serves no practical purpose.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.