The RToken contract has an updateLiquidityIndex function that is never called, while maintaining its own _liquidityIndex state variable. This creates a discrepancy with the liquidityIndex tracked in ReserveLibrary, leading to incorrect amount calculation in RToken's transferFrom function.
The issue stems from two parallel but disconnected liquidity index tracking mechanisms:
In ReserveLibrary:
In RToken:
The function updateLiquidityIndex is never called from the pool, which means the _liquidityIndex will forever remain stale.
But on the other hand, the ReserveLibrary correctly updates its own liquidityIndex through updateReserveInterests(), which is called before any operation, So we have inconsistency of the two separately tracked liquidity indices.
So the problem is that, RToken's _liquidityIndex remains static at WadRayMath.RAY (1e27) because updateLiquidityIndex() is never called, yet the _liquidityIndex is used in the transferFrom function, see below;
Looking at the transferFrom it uses this stale _liquidityIndex.
The critical discrepancy appears in RToken's transferFrom function where the stale _liquidityIndex is used for scaling amounts, while other functions like transferFrom and balanceOf correctly use the updated index from LendingPool:
Alice deposits 1000 USDC into LendingPool, receives 1000 RTokens
Time passes, interest accrues, ReserveData.liquidityIndex increases to 1.1e27
Alice approves her 100 RTokens to Bob
Bob calls the transferFrom function which uses stale _liquidityIndex (1e27), calculating incorrect scaled amount
The actual value transferred will be incorrect because the scaling doesn't account for accrued interest
Incorrect transfer amounts when users approve their RTokens to be spent transfered from them.
Manual code review
Remove the unused _liquidityIndex from RToken and modify transfer functions to use LendingPool's index:
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.