When a user borrows crvUSD, they are minted DebtTokens to represent their debt to the protocol. These debt balances increase over time due to interest accrual. However, due to the logic of burn()function in DebtToken.sol, it results in no interest accrued on the user's debt. Borrowers can borrow at 1:1 ratio with zero added interests paid.
Assume Alice borrowed 10,000 crvUSD. After 1 month, she now wants to repay her debt by calling repay()function in LendingPool.sol.
repay()will internally call _repay()function. The amount of crvUSD to be repaid is passed as 10000e18
Reserve states are updated before repayment, via ReserveLibrary.updateReserveState()
UserDebt, UserScaledDebt, actualRepayAmountand scaledAmountare calculated. We will not dive into these calculations as it is OOS of this vulnerability.
Now, DebtToken.burn()function is called, passing amount which is 10000e18
In DebtToken.burn()function, particularly these lines:
As seen above, amountis passed in _burn(). 10000 DebtTokens have been burned. Assuming index = 2, amountScaled= 5000e18. Function will return (10000e18, totalSupply(), 5000e18, balanceIncrease)
Now back to _repay()function:
As seen above, crvUSD being repayed by msg.sender is in amountScaled, which is 10000e18. amountBurnedis stored as 5000e18.
[_repay function](https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/pools/LendingPool/LendingPool.sol#L418-L422)
[burn function](https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/tokens/DebtToken.sol#L206-L214)
As seen in the scenario above, Alice repays 10,000 crvUSD, and 10,000 DebtTokens are also burned - no accrued interest has been accounted for when repaying her debt.
Borrowers hence can repay less than they actually owe, underpaying their debt. The protocol will lose expected interest income, and can lead to large financial risk and protocol instability.
Manual
Ensure that the accrued interest for DebtTokens have been accounted for when burning DebtTokens.
Interest IS applied through the balanceOf() mechanism. The separate balanceIncrease calculation is redundant/wrong. Users pay full debt including interest via userBalance capping.
Interest IS applied through the balanceOf() mechanism. The separate balanceIncrease calculation is redundant/wrong. Users pay full debt including interest via userBalance capping.
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.