Core Contracts

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

Loss of precision in interest rate calculation leads to incorrect borrowing rates

Summary

The calculateCompoundedInterest() function performs division before multiplication when calculating interest rates, leading to precision loss that compounds over time and results in incorrect borrowing rates.

Vulnerability Details

In ReserveLibrary::calculateCompoundedInterest(), the rate per second is calculated by dividing the annual rate by seconds per year before multiplying by the time delta:

function calculateCompoundedInterest(uint256 rate,uint256 timeDelta) internal pure returns (uint256) {
if (timeDelta < 1) {
return WadRayMath.RAY;
}
uint256 ratePerSecond = rate.rayDiv(SECONDS_PER_YEAR); // Division before multiplication
uint256 exponent = ratePerSecond.rayMul(timeDelta);
return WadRayMath.rayExp(exponent);
}

This approach loses precision because Solidity truncates decimal places during division. The loss is amplified because:

  1. The result is used as an exponent in interest calculations

  2. The error compounds over time as interest accrues

  3. The precision loss affects all subsequent calculations that depend on the interest rate

Proof of Concept

  1. Assume an annual rate of 5% (5e27 in RAY)

  2. Current calculation:

    ratePerSecond = 5e27 / 31536000158,548,959,918,823 (truncated)
    exponent = 158,548,959,918,823 * timeDelta
  3. Correct calculation:

    exponent = (5e27 * timeDelta) / 31536000
  4. The difference grows exponentially due to the exponent calculation

Impact

  • Borrowers receive incorrect interest rates that deviate from intended rates

  • Protocol calculations are inaccurate

  • Protocol will receive less than it should

Recommendation

Reorder operations to multiply before dividing:

function calculateCompoundedInterest(uint256 rate,uint256 timeDelta) internal pure returns (uint256) {
if (timeDelta < 1) {
return WadRayMath.RAY;
}
- uint256 ratePerSecond = rate.rayDiv(SECONDS_PER_YEAR);
- uint256 exponent = ratePerSecond.rayMul(timeDelta);
+ uint256 exponent = rate.rayMul(timeDelta).rayDiv(SECONDS_PER_YEAR);
return WadRayMath.rayExp(exponent);
}
Updates

Lead Judging Commences

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

Support

FAQs

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