Core Contracts

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

Missing BASE_EMISSION_UPDATE_INTERVAL Validation in setEmissionUpdateInterval: Potential for Erratic Emission Updates

Summary

The RAACMinter contract manages the dynamic emission of RAAC tokens, and its behavior is influenced by an emission update interval. The function setEmissionUpdateInterval is intended to allow administrators (with the UPDATER_ROLE) to adjust how frequently emission rates are updated. However, the function only checks that the new interval is non-zero and does not exceed the maximum allowed interval; it omits a crucial validation to ensure that the new interval is not lower than the BASE_EMISSION_UPDATE_INTERVAL. Without this check, an administrator could set an interval that is shorter than the base threshold, potentially leading to excessively frequent updates and erratic emission behavior, which can cause operational instability and inefficient gas usage.

Vulnerability Details

How It Begins

The function setEmissionUpdateInterval is implemented as follows:

function setEmissionUpdateInterval(uint256 _emissionUpdateInterval) external onlyRole(UPDATER_ROLE) {
// @info: missing _emissionUpdateInterval to BASE_EMISSION_UPDATE_INTERVAL validation check
if (_emissionUpdateInterval == 0 || _emissionUpdateInterval > MAX_EMISSION_UPDATE_INTERVAL) {
revert InvalidEmissionUpdateInterval();
}
uint256 oldInterval = emissionUpdateInterval;
emissionUpdateInterval = _emissionUpdateInterval;
emit EmissionUpdateIntervalUpdated(oldInterval, _emissionUpdateInterval);
}

Issue:
The function lacks a check that enforces:

  • Minimum Interval Validation: The new update interval must not be less than BASE_EMISSION_UPDATE_INTERVAL.
    This oversight means that an administrator with the UPDATER_ROLE could set the emission update interval to a value lower than the base (which is intended to be the minimum acceptable interval), leading to overly frequent emission rate updates.

Potential Consequences

  • Excessive Emission Updates:
    Setting an interval below the base threshold could result in the system recalculating and updating emission rates too frequently. This may lead to unpredictable token emission behavior, potentially destabilizing the protocol's economic model.

  • Increased Gas Costs:
    Overly frequent updates can significantly increase gas consumption, affecting both the protocol’s efficiency and user experience.

  • Operational Instability:
    Erratic emission updates can create a misalignment between the intended emissions schedule and the actual minting behavior, potentially leading to unexpected token inflation or deflation.

Proof of Concept

Scenario Walkthrough

  1. Initial State:
    The contract defines a constant BASE_EMISSION_UPDATE_INTERVAL (e.g., 1 day) that represents the minimum allowable interval for updating emission rates.

  2. Faulty Parameter Update:
    An administrator calls setEmissionUpdateInterval with a value lower than BASE_EMISSION_UPDATE_INTERVAL (e.g., 12 hours). Because the function only checks for zero and a maximum limit, it accepts the value.

  3. Resulting Behavior:
    The emission update interval is set to an undesirably low value, resulting in frequent recalculations of the emission rate, which could lead to operational inefficiencies and unpredictable token minting behavior.

Test Suite Example

Below is a simplified Foundry test case that demonstrates the vulnerability:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import {Test, console} from "forge-std/Test.sol";
import {RAACMinter} from "../src/core/minters/RAACMinter/RAACMinter.sol";
import {RAACToken} from "../src/core/tokens/RAACToken.sol";
contract RAACMinterEmissionTest is Test {
RAACToken raacToken;
RAACMinter raacMinter;
address RAAC_OWNER = makeAddr("RAAC_OWNER");
address RAAC_MINTER_OWNER = makeAddr("RAAC_MINTER_OWNER");
uint256 initialRaacSwapTaxRateInBps = 200;
uint256 initialRaacBurnTaxRateInBps = 150;
address stabilityPool = makeAddr("STABILITY_POOL");
address lendingPool = makeAddr("LENDING_POOL");
// Assume BASE_EMISSION_UPDATE_INTERVAL is 1 days and MAX_EMISSION_UPDATE_INTERVAL is defined.
function setUp() public {
raacToken = new RAACToken(RAAC_OWNER, initialRaacSwapTaxRateInBps, initialRaacBurnTaxRateInBps);
vm.warp(block.timestamp + 1 days);
raacMinter = new RAACMinter(address(raacToken), stabilityPool, lendingPool, RAAC_MINTER_OWNER);
}
function testSetEmissionUpdateIntervalBelowBaseFails() public {
// Attempt to set the emission update interval to a value below BASE_EMISSION_UPDATE_INTERVAL (e.g., 12 hours)
uint256 invalidInterval = 12 hours;
vm.startPrank(RAAC_MINTER_OWNER);
raacMinter.setEmissionUpdateInterval(invalidInterval);
vm.stopPrank();
}
}

How to Run the Test

  1. Initialize a Foundry Project:

    forge init my-foundry-project
  2. Place Contract Files:
    Ensure that RAACMinter.sol and RAACToken.sol are in the src directory.

  3. Create a Test Directory:
    Create a test directory adjacent to src and add the test file (e.g., RAACMinterEmissionTest.t.sol).

  4. Run the Test:

    forge test --mt testSetEmissionUpdateIntervalBelowBaseFails -vv
  5. Expected Outcome:
    The test should not revert, confirming that the function should accepts intervals below the base threshold. (In the current implementation, this check is missing.)

Impact

  • Erratic Emission Behavior:
    Without enforcing a minimum update interval, the protocol may experience too frequent emission updates, leading to inconsistent token minting and potential market instability.

  • Increased Operational Costs:
    Overly frequent updates can increase gas usage and computational overhead, impacting the protocol’s efficiency.

  • Unpredictable Economic Outcomes:
    The dynamic emissions strategy relies on a stable update interval. Allowing an interval below the base threshold may result in misaligned token supply and unexpected inflation/deflation effects.

Tools Used

  • Manual Review

  • Foundry

Recommendations

To resolve this vulnerability, update the setEmissionUpdateInterval function to enforce that the new interval is not below the BASE_EMISSION_UPDATE_INTERVAL.

Proposed Diff for setEmissionUpdateInterval

function setEmissionUpdateInterval(uint256 _emissionUpdateInterval) external onlyRole(UPDATER_ROLE) {
- if (_emissionUpdateInterval == 0 || _emissionUpdateInterval > MAX_EMISSION_UPDATE_INTERVAL) {
- revert InvalidEmissionUpdateInterval();
- }
+ // Enforce that the new interval is at least the base update interval
+ if (_emissionUpdateInterval < BASE_EMISSION_UPDATE_INTERVAL || _emissionUpdateInterval > MAX_EMISSION_UPDATE_INTERVAL) {
+ revert InvalidEmissionUpdateInterval();
+ }
uint256 oldInterval = emissionUpdateInterval;
emissionUpdateInterval = _emissionUpdateInterval;
emit EmissionUpdateIntervalUpdated(oldInterval, _emissionUpdateInterval);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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

Give us feedback!