In RToken.sol
-> the liquidityIndex
is used throughout the contract for the purpose of scaling the amount of RTokens
that either the protocol or user has in their balance.
The correct and most accurate and up-to-date liquidityIndex
is used everywhere accept for in the function transferFrom
.
For all functions and actions that use the liquidityIndex
for scaling purposes, the most up-to-date and accurate value is used as the scaling factor, accept for transferFrom
.
It is important to note that liquidityIndex
is a value that is updated and stored within LendingPool
(which is represented as _reservePool
in the RToken
contract.
The contract uses the most up-to-date index by these 2 methods:
Accepts the most up-to-date and accurate liquidityIndex
value as an argument within a function. The argument is populated from the LendingPool
, when calling these functions in RToken
: as such:
Calls the LendingPool
directly and gets the return value of getNormalizedIncome
-> which returns the accurate liquidityIndex
BUT the transferFrom
function uses _liquidityIndex
for the scaling factor. This variable is defined and stored within the RToken
contract itself.
It is originally set during the constructor
of RToken:
There is a function, updateLiquidityIndex
-> that is supposed to update the local liquidityIndex-> and is only callable by the LendingPool/reservePool
. The reservePool is the LendingPool contract.
The problem is that this function is never called within the LendingPool
. There is no point in the LendingPool
or the contracts inherited by the LendingPool
that call this function. Therefore, the local _liquidityIndex
is never updated and is continuously the value it was set as in the cosntructor
.
When transferFrom
is called, it will use a different liquidityIndex
than the rest of the contract uses.
To compare the discrepancy lets look at the difference between transfer
and transferFrom
-> which both attempt to scale the value by the liquidityIndex
:
The wrong amount will be transferred when transferFrom
is called.
I have this as a LOW becasue the protocol does not lose any funds, but the discrepency in the value can cause a user to lose funds and have the wrong amount transferred out. Also, it can have the reverse effect.
Manual Review
Follow the methods of using the liquidityIndex
as the rest of the contract does. In this scenario, since it is a public variable and not accepting input paramater of liquidityIndex
-> Use the logic in transfer
get the liquidityIndex
by calling the lending pool directly - amount.rayDiv(ILendingPool(_reservePool).getNormalizedIncome());
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.