Core Contracts

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

Incorrect Utilization Rate Calculation

Summary:

The RAACMinter contract's getUtilizationRate() function incorrectly uses the lending pool's normalized debt (interest index) instead of the actual borrowed amount, resulting in high utilization rates that break the emission rate mechanism.

Vulnerability Details:

In the RAACMinter contract:

function getUtilizationRate() internal view returns (uint256) {
// ❌ WRONG: Using normalized debt (interest index) instead of actual borrowed amount
uint256 totalBorrowed = lendingPool.getNormalizedDebt();
uint256 totalDeposits = stabilityPool.getTotalDeposits();
if (totalDeposits == 0) return 0;
return (totalBorrowed * 100) / totalDeposits;
}

Example 1: Small Loan
Given:

  • Actual borrowed = 100 RAAC

  • Interest index (RAY) = 1e27

  • Total deposits = 1000 RAAC

Current calculation:

  • utilizationRate = (1e27 100) / 1000e18

  • = 1e29 / 1e21

  • = 100,000,000% (incorrect!)

Expected calculation:

  • utilizationRate = (100 100) / 1000

  • = 10% (correct)

Example 2: Medium Loan
Given:

  • ctual borrowed = 5000 RAAC

  • Interest index (RAY) = 1.1e27

  • Total deposits = 10000 RAAC

Current calculation:

  • utilizationRate = (1.1e27 100) / 10000e18

  • = 1.1e29 / 1e22

  • = 110,000,000% (incorrect!)

Expected calculation:

  • utilizationRate = (5000 100) / 10000

  • = 50% (correct)

Impact:

  • Emission rate mechanism breaks due to extreme utilization rates

  • Maximum emission rates triggered unnecessarily

  • Incorrect token distribution

  • Protocol economics severely impacted

  • Potential for excessive token inflation

Tools Used:

Manual code review

Recommendations:

  • Use actual borrowed amount:

function getUtilizationRate() internal view returns (uint256) {
uint256 totalBorrowed = lendingPool.getTotalBorrowed(); // New function to get actual borrowed
uint256 totalDeposits = stabilityPool.getTotalDeposits();
if (totalDeposits == 0) return 0;
return (totalBorrowed 100) / totalDeposits;
}
  • Add validation checks:

function getUtilizationRate() internal view returns (uint256) {
uint256 totalBorrowed = lendingPool.getTotalBorrowed();
uint256 totalDeposits = stabilityPool.getTotalDeposits();
require(totalBorrowed <= totalDeposits, "Invalid pool state");
if (totalDeposits == 0) return 0;
uint256 utilization = (totalBorrowed 100) / totalDeposits;
require(utilization <= 100, "Utilization exceeds 100%");
return utilization;
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Validated
Assigned finding tags:

RAACMinter::getUtilizationRate incorrectly mixes stability pool deposits with lending pool debt index instead of using proper lending pool metrics

inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Validated
Assigned finding tags:

RAACMinter::getUtilizationRate incorrectly mixes stability pool deposits with lending pool debt index instead of using proper lending pool metrics

Support

FAQs

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