The getNormalizedDebt function in ReserveLibrary returns inconsistent values depending on the time delta. When timeDelta < 1, it returns the actual borrowed amount (reserve.totalUsage), but for any other case, it returns only the usage index without scaling it with the total borrowed amount, leading to incorrect debt calculations throughout the protocol.
The issue lies in how the normalized debt is calculated;
Even the comment The normalized debt (in underlying asset units). suggests that the amount returned should be in underlying asset units which is crvUSD and not RAY.
For timeDelta < 1, it correctly returns reserve.totalUsage (actual borrowed amount in crvUSD)
For timeDelta >= 1, it returns calculateCompoundedInterest(rateData.currentUsageRate, timeDelta).rayMul(reserve.usageIndex)
The second case only calculates an updated usage index but doesn't multiply it by the total borrowed amount. This is incorrect because:
The usage index (in RAY = 1e27) represents the cumulative interest factor
To get the actual debt, you need to multiply the usage index by the total borrowed amount
This affects debt calculations throughout the protocol since LendingPool and DebtToken rely on this function
This is significant issue since the getNormalizedDebt function is used in other functions such as updateInterestRatesAndLiquidity, getBorrowRate and getLiquidityRate which are used or may be used (therefore it brings incorrect accounting).
Incorrect debt accounting throughout the protocol
Affects liquidation calculations since health factors depend on debt amounts
Interest accrual calculations become inaccurate
Could lead to under/over collection of debt payments
Manual review
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.