Core Contracts

Regnum Aurum Acquisition Corp
HardhatReal World AssetsNFT
77,280 USDC
View results
Submission Details
Severity: medium
Invalid

DebtToken's usage index can break the protocol's interest rate mechanics

Summary

The DebtToken's usage index, which governs interest rate calculations across the lending protocol, can be manipulated to decrease between updates. This breaks the fundamental assumption that interest rates only compound forward in time, similar to how a bank can't retroactively reduce already accrued interest.

In the DebtToken's updateUsageIndex() function, where the protocol tracks lending pool utilization to calculate interest rates. The current implementation allows the ReservePool to update the usage index with potentially lower values, creating a dangerous gap in the protocol's interest rate mechanics.

When the usage index decreases, it disrupts the entire chain of debt calculations:

  • Interest accrual becomes inconsistent

  • Debt positions are incorrectly valued

  • The lending pool's accounting system loses accuracy

Consider a scenario where:

  1. Initial usage index: 1.5 (150% utilization)

  2. New update sets index to 1.2 (120% utilization)

  3. Result: 20% reduction in accrued interest

This is equivalent to suddenly declaring that last month's 5% APR was actually 4%, and retroactively reducing all borrower obligations. In the RAAC protocol's context, this directly impacts the stability of real estate-backed lending positions.

Vulnerability Details

The DebtToken contract, a cornerstone of RAAC's real estate lending system, has a flaw in its interest rate mechanics. At its core, the protocol tracks lending pool utilization through a usage index that should only increase over time, similar to how mortgage interest compounds. However, the current implementation allows this index to decrease, undermining the entire lending system's stability.

Picture a real estate loan where the interest rate suddenly drops retroactively, this is exactly what can happen in the protocol. When the ReservePool calls updateUsageIndex(), it can potentially set a lower index value than previously recorded. For example, if a real estate position starts with a usage index of 1.5 (representing 150% utilization), the index could be maliciously updated to 1.2, effectively erasing 20% of the accrued interest across all positions.

function updateUsageIndex(uint256 newUsageIndex) external override onlyReservePool {
// ๐Ÿ”‘ Access Control: Only ReservePool can call
// ๐Ÿšจ Vulnerability: Check uses < instead of <=
if (newUsageIndex < _usageIndex) revert InvalidAmount();
// ๐Ÿ’พ State Update: Index can remain unchanged
_usageIndex = newUsageIndex;
// ๐Ÿ“ข Event: Broadcasts potentially problematic update
emit UsageIndexUpdated(newUsageIndex);
}

The impact ripples through RAAC's entire lending ecosystem. Since DebtToken works alongside RAACToken and veRAACToken for governance, compromised interest calculations affect not just individual loans but the protocol's entire economic model. The stability mechanism, designed to maintain reliable real estate backing, becomes unreliable when debt positions can be artificially deflated.

Impact

Interest rate calculations are non-negotiable, the usage index vulnerability strikes at the heart of this, imagine a mortgage where the interest rate could retroactively decrease!

// Current Implementation
function updateUsageIndex(uint256 newUsageIndex) external {
if (newUsageIndex < _usageIndex) revert InvalidAmount();
_usageIndex = newUsageIndex;
}
โ€‹
// The assumption
// "The ReservePool will always provide increasing indices"
โ€‹
// What Can Actually Happen ๐Ÿ’ฅ
1. Initial _usageIndex = 1.5
2. ReservePool calls with newUsageIndex = 1.2
3. Check passes (1.2 >= 1.5 is false, but no strict inequality)
4. Interest rates decrease unexpectedly

Recommendations


By enforcing strict monotonic increases in the usage index, we protect the protocol's core interest rate mechanics and ensure reliable debt accounting for all real estate-backed positions.
change < to <= in the validation check, ensuring the index strictly increases with each update.

function updateUsageIndex(uint256 newUsageIndex) external override onlyReservePool {
// ๐Ÿ”‘ Access Control: Only ReservePool can call
// โœ… Check: Prevents equal values
if (newUsageIndex <= _usageIndex) revert InvalidAmount("Index must strictly increase");
// ๐Ÿ’พ State Update: Now guaranteed to increase
_usageIndex = newUsageIndex;
// ๐Ÿ“ข Event Emission: Always signals true increase
emit UsageIndexUpdated(newUsageIndex);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 5 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
inallhonesty Lead Judge 5 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.