Core Contracts

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

Incorrect Max Rate Calculation in calculateNewEmissionRate: Inaccurate Emission Adjustments

Summary

The calculateNewEmissionRate function in the RAACMinter contract is responsible for dynamically adjusting the RAAC token emission rate based on system utilization. When the utilization rate exceeds the target, the function increases the emission rate by adding an adjustment. However, the function incorrectly determines the "maxRate" by selecting the higher value between the increased rate and the benchmark rate. According to the provided @info comment ("wrong maxRate pickup"), this logic is reversed—likely, the intended behavior is to pick the lower value to prevent an excessive emission rate increase. This error can lead to inaccurate emissions, which in turn may cause erratic token minting, potential economic imbalances, and inefficiencies in the protocol's dynamic emissions schedule.

Vulnerability Details

Function Analysis

The relevant portion of the function is as follows:

function calculateNewEmissionRate() internal view returns (uint256) {
uint256 utilizationRate = getUtilizationRate();
uint256 adjustment = (emissionRate * adjustmentFactor) / 100;
if (utilizationRate > utilizationTarget) {
uint256 increasedRate = emissionRate + adjustment;
// @info: wrong maxRate pickup
uint256 maxRate = increasedRate > benchmarkRate ? increasedRate : benchmarkRate;
return maxRate < maxEmissionRate ? maxRate : maxEmissionRate;
} else if (utilizationRate < utilizationTarget) {
uint256 decreasedRate = emissionRate > adjustment ? emissionRate - adjustment : 0;
uint256 minRate = decreasedRate < benchmarkRate ? decreasedRate : benchmarkRate;
return minRate > minEmissionRate ? minRate : minEmissionRate;
}
return emissionRate;
}

Issue Identified:

  • When utilization is above target, the function calculates an increasedRate by adding an adjustment. It then uses a ternary operator to set maxRate as:

    uint256 maxRate = increasedRate > benchmarkRate ? increasedRate : benchmarkRate;

    This expression picks the higher of increasedRate and benchmarkRate. However, based on the @info comment ("wrong maxRate pickup"), the intended behavior is likely to select the lower value between the two. This would help to moderate the emission rate increase and prevent overshooting the target, maintaining a more controlled emission schedule.

  • The function then caps the value at maxEmissionRate, but the error in selecting maxRate can result in an emission rate that is too high or inconsistent with the intended benchmark.

How It Affects Consistency

Incorrectly choosing the higher rate when utilization is high may:

  • Over-inflate the Emission Rate:
    Leading to token oversupply if the increased rate far exceeds the benchmark.

  • Destabilize the Emission Schedule:
    Result in erratic changes to the emission rate, undermining the protocol's dynamic adjustments.

  • Create Economic Imbalances:

Impact

  • Overly Aggressive Emission Increases:
    Selecting the higher value between increasedRate and benchmarkRate can lead to an emission rate that overshoots the intended target, potentially resulting in an excessive token supply.

  • Unpredictable Emission Behavior:
    Erratic adjustments in the emission rate may destabilize the protocol, affecting lending, borrowing, and overall economic incentives.

  • Economic Instability:
    Incorrect emissions may distort token valuation, undermining user confidence and potentially leading to market manipulation.

Tools Used

  • Manual Review

  • Foundry

Recommendations

To address this issue, update the max rate selection logic in the calculateNewEmissionRate function. The function should choose the lower value between the increased rate and the benchmark rate when utilization exceeds the target.

Proposed Diff for calculateNewEmissionRate

function calculateNewEmissionRate() internal view returns (uint256) {
uint256 utilizationRate = getUtilizationRate();
uint256 adjustment = (emissionRate * adjustmentFactor) / 100;
if (utilizationRate > utilizationTarget) {
uint256 increasedRate = emissionRate + adjustment;
- // @info: wrong maxRate pickup
- uint256 maxRate = increasedRate > benchmarkRate ? increasedRate : benchmarkRate;
+ // Correct the maxRate selection by picking the lower value between increasedRate and benchmarkRate
+ uint256 maxRate = increasedRate < benchmarkRate ? increasedRate : benchmarkRate;
return maxRate < maxEmissionRate ? maxRate : maxEmissionRate;
} else if (utilizationRate < utilizationTarget) {
uint256 decreasedRate = emissionRate > adjustment ? emissionRate - adjustment : 0;
uint256 minRate = decreasedRate < benchmarkRate ? decreasedRate : benchmarkRate;
return minRate > minEmissionRate ? minRate : minEmissionRate;
}
return emissionRate;
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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

Give us feedback!