The StabilityPool contract incorrectly tracks user deposits of rToken by using the unscaled amount, while the underlying RToken's transfer logic scales the actual transferred value based on accrued interest. This discrepancy leads to incorrect accounting of user deposits and potential fund insolvency.
The RToken's _update function scales transferred amounts by the normalized income (interest accrued). When a user deposits rTokens into the StabilityPool, the actual underlying transferred is scaled down if interest has accrued. However, the StabilityPool records the deposit using the unscaled amount parameter. This mismatch causes the pool to overstate user deposits, leading to inflated withdrawal entitlements and potential insolvency when users withdraw more than the pool holds.
Initial State:
Assume RToken's normalized income is 1.1e27 (10% interest accrued).
User deposits 1000 rTokens into StabilityPool.
Deposit Execution:
rToken.safeTransferFrom transfers 1000 rTokens. RToken's _update scales this to: 1000 / 1.1e27 * 1e27 ≈ 909.09.
StabilityPool records userDeposits[user] += 1000.
Withdrawal Attempt:
User requests to withdraw 1000 rTokens worth. StabilityPool calculates rcrvUSDAmount = calculateRcrvUSDAmount(deCRVUSDAmount) using unscaled 1000, allowing withdrawal of 909.09 rToken * 1.1 ≈ 1000 rToken.
However, the pool only holds 909.09 rToken. Subsequent withdrawals will fail due to insufficient funds.
RToken Transfer Scaling:
StabilityPool Deposit Recording:
Users can withdraw more tokens than the pool holds, leading to insolvency.
Early withdrawers gain excess rTokens, diluting later users' funds.
Manual Review
Modify the StabilityPool to track scaled rToken amounts:
Update calculateDeCRVUSDAmount and calculateRcrvUSDAmount to use scaled values for accurate accounting.
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.