The protocol uses a usageIndex to track the accrual of interest on outstanding debt. This index is updated over time using compounded interest with the formula:
Since compounded interest (via a Taylor series expansion) produces a factor greater than one for positive rates and time deltas, the usageIndex increases over time as intended to reflect accumulating interest. However, the subsequent use of this increasing usageIndex in the normalized debt calculation leads to an unintended effect: it causes the normalized debt to be lower than expected. When the DebtToken functions scale debt amounts using this normalized debt, borrowers end up with lower effective debt values, effectively receiving a discount instead of being charged the appropriate interest. This miscalculation undermines the protocol’s revenue model and shifts economic risk away from borrowers.
How the Usage Index Is Updated
The update function recalculates the usageIndex as follows:
Intended Behavior:
The compounded interest factor (computed via calculateCompoundedInterest) is greater than 1, so multiplying the last index by this factor increases the usageIndex over time to capture accrued interest on the debt.
Misuse in Normalized Debt Calculation
Normalized debt is derived using the updated usageIndex:
Issue:
Although the usageIndex is correctly increased to represent accrued interest, its use in this calculation inadvertently lowers the normalized debt value. DebtToken functions subsequently rely on this normalized debt to scale user balances. For instance, when updating debt balances, the protocol computes:
Because the normalized debt is lower than it should be, the scaling operation results in a smaller debt being recorded. Consequently, borrowers effectively pay less interest—or even receive a discount—on their debt.
Balance Calculations:
The balanceOf function multiplies a scaled balance by the normalized debt. With a lower-than-expected normalized debt, users’ effective debt balances are underrepresented.
Burning Debt Tokens:
In the burn function, the difference between the updated usageIndex and the user’s stored index is used to calculate accrued interest. However, because the normalized debt is understated, the additional debt due to interest accrual is not fully captured, allowing users to burn tokens without paying the full accrued interest.
Total Supply Calculation:
The total supply of debt tokens is scaled by the normalized debt. An understated normalized debt means the overall debt in the system is lower than intended, potentially compromising the protocol's financial stability.
Economic Exploitation:
Borrowers benefit from an effective discount on their debt, paying less interest than the protocol intends. This mispricing can lead to significant revenue losses for the platform.
Interest Accrual Failure:
The miscalculation prevents proper interest accrual on borrowed assets, undermining the fundamental lending mechanics and potentially destabilizing the reserve.
Accounting Inconsistencies:
Downstream functions that rely on normalized debt (e.g., balance updates, burns, and total supply calculations) yield inaccurate results. This inconsistency affects risk assessments and may lead to unexpected liquidations or solvency issues.
Scenario Setup
Assume the following initial conditions:
Initial usageIndex: 1e27 (this is the RAY constant representing “1” in 27-decimal precision).
Total Debt (totalUsage): 1,000 underlying units.
Usage Rate: 10% per year (expressed in RAY as 0.1 × 1e27, i.e. 1e26).
Time Delta: 31,536,000 seconds (approximately one year).
Compounded Interest Calculation:
For a 10% rate over one year, the compounded interest factor computed by calculateCompoundedInterest is approximately 1.10517e27 (i.e. a 10.517% increase).
Current (Flawed) Calculation
Usage Index Update:
The current code updates the usageIndex as follows:
With our numbers:
lastIndex = 1e27
interestFactor = 1.10517e27
→ New usageIndex becomes ~1.10517e27.
Normalized Debt Calculation:
Later, the protocol calculates normalized debt by (simplified):
Substituting the values:
Compounded interest factor = 1.10517e27
Updated usageIndex = 1.10517e27
→ Normalized Debt ≈ 1.10517e27 × 1.10517e27 / 1e27 ≈ 1.2214e27.
Debt Token Repayment Impact:
Suppose a borrower originally incurred a debt of 1,000 underlying units (scaled as 1,000 tokens, since initially usageIndex = RAY).
After one year, the expected debt with proper interest would be roughly 1,000 × 1.10517 = 1,105.17 underlying units.
However, when the borrower repays 1,105.17 units, the protocol scales this repayment using:
Plugging in our numbers:
scaledAmount = 1,105.17e18 (if we assume underlying units in 1e18 precision) divided by 1.2214e27
≈ 903.4 tokens.
Interpretation:
The borrower ends up burning only ~903 tokens to repay 1,105.17 underlying units. Instead of fully accruing interest on the debt, the flawed calculation results in a “discount” on the debt repayment. Over time, this discrepancy could allow borrowers to repay less than they should, undermining the protocol’s revenue and risk model.
Manual Review
The root cause is that the usageIndex is updated by multiplying by the compounded interest factor. If the intended design is to have the normalized debt increase with accrued interest (so borrowers pay more), the usageIndex should decrease over time. One approach is to update the usageIndex using division instead of multiplication.
Revised calculateUsageIndex Function
Below is a sample fix. In this example, we change the update so that:
Instead of multiplying the previous index by the interest factor, we divide by the interest factor.
This adjustment causes the normalized debt (which is computed from the usageIndex) to be higher, properly reflecting the accrued interest.
Updated Interest Update Function
With the revised usage index update, the updateReserveInterests function will now compute:
Expected Outcome with the Fix
Using the same numbers:
Initial usageIndex: 1e27
Interest Factor: 1.10517e27
New usageIndex (fixed): 1e27.rayDiv(1.10517e27) ≈ 0.9048e27
Then, when normalized debt is computed (assuming it uses the usageIndex without an extra compounded factor), the debt scaling will properly increase the effective debt. For example, if the borrower’s scaled debt remains 1,000 tokens:
New normalized debt ≈ 0.9048e27 (or used in scaling such that the effective underlying debt becomes closer to 1,105.17 units).
The borrower will need to repay more debt tokens (or the conversion factor will be adjusted so that the accrued interest is correctly reflected), thereby eliminating the unintended discount.
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.