The _update function in the RToken contract incorrectly scales token amounts during minting, burning, and transferring operations. This issue arises because the liquidityIndex is always increasing, causing users to receive fewer tokens than expected when minting and withdrawing. Additionally, the scaling logic is duplicated in the transfer and transferFrom functions, leading to double scaling and further loss of value for users.
In the _update function, where token amounts are scaled by the liquidityIndex:
The liquidityIndex is always increasing, which means that the scaling factor (rayDiv) reduces the amount of tokens users receive during minting and increases the amount of tokens they burn during withdrawals. This results in users receiving fewer tokens than they should when minting and withdrawing.
Additionally, the transfer and transferFrom functions already scale the amounts before calling _update, leading to double scaling:
This double scaling further exacerbates the loss of value for users, as the amounts are scaled twice, leading to even fewer tokens being transferred.
Consider the following scenario:
The liquidityIndex is 1.1e27 (10% interest accrued).
A user deposits 110e18 units of the underlying asset.
The mint function calculates the scaled amount as:
The user receives 100e18 RTokens instead of 110e18.
When the user withdraws, the burn function calculates the scaled amount as:
The user receives 110e18 units of the underlying asset, but due to the double scaling in transfer and transferFrom, the actual amount received is less.
If the user transfers tokens, the amount is scaled twice:
This results in the user transferring fewer tokens than intended.
Loss of Value for Users: Users receive fewer tokens than expected when minting and withdrawing, leading to a loss of value.
Double Scaling: The transfer and transferFrom functions scale amounts twice, further reducing the number of tokens transferred.
Manual review
The _update function should not scale the amounts, as the scaling is already handled in the mint, burn, transfer, and transferFrom functions. The corrected _update function should look like this:
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.