Core Contracts

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

Incorrect Boost Configuration in BaseGauge Causes Underflow Issue and Potential Denial of Service

Summary:

The BaseGauge.getUserWeight() function, reverts when applying boost calculation to an user, due to an incorrect configuration of minimum and maximum boost values. This leads to an underflow during boost range calculation within the BoostCalculator library, ultimately causing denial of service to reward distribution. Specifically, the minBoost value (1e18) is greater than the maxBoost value (25000), which results in a panic revert.

Vulnerability Details:

  1. Incorrect Boost Configuration: In the BaseGauge constructor, the boostState is initialized with maxBoost = 25000 and minBoost = 1e18. This configuration is incorrect because minBoost is significantly larger than maxBoost.

  2. Underflow in Boost Calculation: The BoostCalculator.calculateBoost function (called by _applyBoost in BaseGauge) calculates a boostRange using the formula params.maxBoost - params.minBoost. When minBoost is greater than maxBoost, this calculation results in an underflow, causing a revert.

  3. DoS of Reward Distribution: The getUserWeight function in BaseGauge uses the result of _applyBoost (which is affected by the underflow) to determine a user's weight. As this weight is then used in the earned function to calculate the user's reward. But due to the underflow, the reward distribution logic is disrupted, potentially leading to a denial of service.

List of functions affected:

Relevant Code Snippets:

function calculateBoost(
uint256 veBalance,
uint256 totalVeSupply,
BoostParameters memory params
) internal pure returns (uint256) {
// ... other calculations
uint256 boostRange = params.maxBoost - params.minBoost; // <-- Potential underflow here
uint256 boost = params.minBoost + ((votingPowerRatio * boostRange) / 1e18);
// Ensure boost is within bounds
if (boost < params.minBoost) {
return params.minBoost;
}
if (boost > params.maxBoost) {
return params.maxBoost;
}
return boost;
}

Impact:

As the getUserWeight function reverts due to the underflow in boost calculation, this weight is used in updateReward modifier to calculate the user's reward. This leads to a denial of service in the reward distribution mechanism, affecting the staking and reward claiming process. Thus eventually causing a total denial of service to the reward distribution mechanism.

Proof of Concept (PoC):

  1. Alice stakes 100 staking tokens in the RAACGauage contract.

  2. The updateRewad modifier is invoked, which calls the getUserWeight function to calculate the user's weight for calculating rewards.

  3. The getUserWeight function calls the _applyBoost function, which in turn calls the BoostCalculator.calculateBoost function.

  4. Due to the incorrect configuration of minBoost and maxBoost, the boostRange calculation underflows, causing a revert in the calculateBoost function.

  5. As a result, the getUserWeight function reverts, the whole stake tx fails, causing a denial of service.

Proof Of Code:

  1. Use this guide to intergrate foundry into your project: foundry

  2. Create a new file FortisAudits.t.sol in the test directory.

  3. Add the following gist code to the file: Gist Code

  4. Run the test using forge test --mt test_FortisAudit_UnderflowInRewardCalculation -vvvv.

function test_FortisAudit_UnderflowInRewardCalculation() public {
vm.startPrank(initialOwner);
raacToken.setMinter(initialOwner);
raacToken.mint(address(raacGauge), 125_000e18);
raacToken.mint(anon, 1000e18);
gaugeController.addGauge(address(raacGauge), IGaugeController.GaugeType.RAAC, 1000e18);
vm.stopPrank();
stakingToken.mint(anon, 100e18);
vm.warp(1739686038); // (Feb 16 2025)
vm.startPrank(anon);
raacToken.approve(address(veraacToken), 1000e18);
veraacToken.lock(400e18, 365 days); // 100e18 veRAACToken is minted for 400e18 RAACToken
gaugeController.distributeRewards(address(raacGauge));
skip(1 days);
stakingToken.approve(address(raacGauge), 100e18);
vm.expectRevert();
raacGauge.stake(100e18);
vm.stopPrank();
}

Tools Used:

  • Manual code review

Recommended Mitigation:

To prevent the underflow in boost calculation, ensure that the minBoost value is less than the maxBoost value. This will prevent the underflow in the calculateBoost function and allow the reward distribution mechanism to function correctly.

constructor(
...
) {
// other initializations
// Initialize boost parameters
- boostState.maxBoost = 25000; // 2.5x
+ boostState.maxBoost = 25e17; // 2.5x
boostState.minBoost = 1e18;
boostState.boostWindow = 7 days;
// other initializations
}
Updates

Lead Judging Commences

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

boostState.minBoost is set to 1e18

Support

FAQs

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

Give us feedback!