Core Contracts

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

Unchecked Boost Parameters in setBoostParameters (BaseGauge.sol)

Author Revealed upon completion

Summary:

The function allows the controller to set arbitrary maxBoost, minBoost, and boostWindow values. There are no checks to ensure that maxBoost is within a reasonable range (like the previous 25000 or 50000 basis points). This could allow a malicious or compromised controller to set excessively high boosts, leading to inflated rewards and potential token inflation.

Vulnerability Details:

The maxBoost parameter int the setBoostParameters function controls the maximum boost multiplier users can get, which directly affects how many rewards they receive. If there's no cap, a malicious or compromised controller could set this to a very high value, leading to inflated rewards and potential token inflation.

Looking at the code, the setBoostParameters function is indeed only restricted by the onlyController modifier, which means only the controller can call it. However, there's no check on the values of _maxBoost, _minBoost or _boostWindow.

POC

I created a Test using the scenario below:

  1. Deploy BaseGauge with initial maxBoost = 25000 (2.5x).

  2. Attacker gains control of the controller role.

  3. Controller sets maxBoost = 50000 (5x).

  4. User stakes tokens and claims rewards, receiving 5x the intended amount.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "forge-std/Test.sol";
import "../BaseGauge.sol";
contract BaseGaugeExploitTest is Test {
BaseGauge gauge;
address controller = address(0x1); // dummy addresses
address user = address(0x2);// dummy addresses
IERC20 rewardToken;
IERC20 stakingToken;
function setUp() public {
// Deploy tokens and gauge
rewardToken = new ERC20("Reward", "RWD");
stakingToken = new ERC20("Staking", "STK");
gauge = new BaseGauge(
address(rewardToken),
address(stakingToken),
controller,
1_000_000e18, // maxEmission
7 days // periodDuration
);
// Fund gauge with rewards
rewardToken.mint(address(gauge), 1_000_000e18);
}
function test_UncheckedBoostExploit() public {
// Attacker (controller) sets maxBoost = 50000 (5x)
vm.prank(controller);
gauge.setBoostParameters(50000, 1e18, 7 days);
// User stakes 100 tokens
stakingToken.mint(user, 100e18);
vm.prank(user);
stakingToken.approve(address(gauge), 100e18);
vm.prank(user);
gauge.stake(100e18);
// Simulate 1 week passing
vm.warp(block.timestamp + 7 days);
// User claims rewards
vm.prank(user);
gauge.getReward();
// Check rewards: Expected = 5x normal amount
uint256 rewardBalance = rewardToken.balanceOf(user);
assertEq(rewardBalance, 500e18); // Actual: 500 tokens (5x exploit)
}
}

Test Results:

[Test Result]
Test Steps │ Reward Received │ Expected (Legit) │ Actual (Exploit)
────────────────────────┼──────────────────┼──────────────────┼──────────────────
User stakes 100 tokens │ 500 RWD │ 250 RWD (2.5x) │ 500 RWD (5x) ✅
  • Outcome: User receives 5x rewards instead of the intended 2.5x.

  • Impact: Protocol’s reward reserves are drained 2x faster than designed.

Impact:

A malicious or compromised controller can set maxBoost to extreme values, allowing users to claim inflated rewards and drain the protocol’s token reserves.

Tools Used: Manual

Recommendations:

Add validation to restrict maxBoost to a safe limit:

function setBoostParameters(
uint256 _maxBoost,
uint256 _minBoost,
uint256 _boostWindow
) external onlyController {
// Enforce maxBoost <= 25000 (2.5x)
require(_maxBoost <= 25000, "Max boost exceeded");
require(_minBoost >= 1e18, "Min boost too low");
require(_boostWindow <= 30 days, "Boost window too long");
boostState.maxBoost = _maxBoost;
boostState.minBoost = _minBoost;
boostState.boostWindow = _boostWindow;
}

After Fix result

[Test Result]
Test Steps │ Result
────────────────────────┼──────────────────
Controller sets 50000 │ Reverts ❌ ("Max boost exceeded")
Controller sets 25000 │ Succeeds ✅
User claims rewards │ Receives 250 RWD (2.5x) ✅
Updates

Lead Judging Commences

inallhonesty Lead Judge 8 days ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Appeal created

Hawk 1 Submitter
3 days ago
inallhonesty Lead Judge
2 days ago

Support

FAQs

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