The burn() function of the RToken contract fails to perform a validation to ensure that amountScaled is greater than zero before proceeding with the burn operation. This allows for withdrawal where users end up with underlying tokens but no Rtokens are burnt in exchange.
The reserve.liquidityIndex represents the cumulative interest earned by liquidity providers in the lending protocol.
Now, the protocol overides the normal _update() function as follows in RToken contract:
This function is designed to first scale the amount into scaledAmount via the rayDiv function based on the current liquidityIndex.
However, notice that _update() is an internal function invoked in functions such as _mint() and _burn() which here are used to mint and burn RTokens to/from users respectively.
Now during deposit, a user specifies the amount of reserve tokens they wish to supply. This amount effectively propagates to RToken.mint() as amountToMint which is handled as follows:
As seen above, the amountToMint is first scaled via the rayDiv(index) as done by the _update(). The function further ensures that this amountScaled is not 0 to ensure that a user does not end up with zero minted RTokens when they have supplied real amount of underlying tokens.
During withdrawal however, the amountScaled is calculated incorrectly much less validated.
When withdrawing, a user specifies the amount of reserve tokens they want to withdraw and this amount is propagated downstream to RToken.burn():
Now, the amount is scaled via the rayMul(index) when in reality, during burning, the amount will be scaled in _update() via the rayDiv(index). Furthermore, this function fails to ensure that the amountScaled is greater than 0 but simply proceeds to transfer underlying tokens to the user.
Since the amountScaled is not validated, the amount burned can be 0 yet the user gets real underlying tokens in exchange. This results in incorrect withdrawals as users end up with real funds from the protocol without incurring the necessary token burns.
Manual Review
Perfrom a zero validation in burn():
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.