This happens due to the strange way the liquidity index is upgraded
By taking a look at the ReserveLib::deposit function, we see the following setup:
First thing done in the function is to call the updateReserveInterests function, which will update the liquidity index as can be seen here:
Then at the end of the ReserveLib::deposit function, the ReserveLib::updateInterestRatesAndLiquidity is called and as can be seen in the following block of code, the updateInterestRatesAndLiquidity function aims to call the updateReserveInterests function again:
This time nothing will be updated because of the following check in the updateReserveInterests function:
This means that after someone deposit, the liquidity index won't actually be updated until the next deposit or withdraw, since this same thing happens with the withdraw function. This won't affect the minting or burning of tokens since they only happen right after the state is updated, but when tokens are transferred it would be a big problem. Example of this can be the StabilityPool contract, where rTokens are always transferred. This is important because of the overriden transfer and transferFrom (This happens in the transferFrom because of the overriden _update function) functions in the rToken contract and the fact that if the liquidity index is not properly fetched, the transferred amount will be inaccurate:
The getNormalizedIncome function returns inaccurate liquidity index practically every time when used during minting/burning of RTokens, which will affect the following functions: RToken::totalSupply, RToken::transfer, RToken::balanceOf,RToken::trasferFrom and will result in inaccurate amounts of RToken being transferred from StabilityPool to users and from users to StabilityPool
Manual Review
Instead of just returning the reserve.liquidityIndex in the getNormalizedIncome function, just return the ReserveLib::getNormalizedIncome function instead. It will calculate the proper liquidity index and wont impact the already working functionality
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.