Core Contracts

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

`boostState.minBoost` is set to `1e18` in BaseGauge constructor instead of `10 000`.

Summary

boostState.minBoost is set to 1e18 in BaseGauge constructor but this incorrect.

Indeed, maxBoost is 25000 (x2.5) and minBoost should be 10000 (x1).

This is problematic as it leads to systematic revert for stake, withdraw, claimrewards, and notifyrewards functions.

constructor(
address _rewardToken,
address _stakingToken,
address _controller,
uint256 _maxEmission,
uint256 _periodDuration
) {
rewardToken = IERC20(_rewardToken);
stakingToken = IERC20(_stakingToken);
controller = _controller;
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
_grantRole(CONTROLLER_ROLE, _controller);
boostState.maxBoost = 25000; // 2.5x
// @audit MEDIUM minBoost should be 10000
boostState.minBoost = 1e18;
boostState.boostWindow = 7 days;
uint256 currentTime = block.timestamp;
uint256 nextPeriod = ((currentTime / _periodDuration) * _periodDuration) + _periodDuration;
// Initialize period state
periodState.periodStartTime = nextPeriod;
periodState.emission = _maxEmission;
TimeWeightedAverage.createPeriod(
periodState.votingPeriod,
nextPeriod,
_periodDuration,
0,
10000 // VOTE_PRECISION
);
}

Indeed, these 4 functions apply the updateRewards modifier, which will ultimately call earned function, which calls getUserWeight and finally _applyBoost. This function will call calculateBoost defined as follows:

function calculateBoost(uint256 veBalance, uint256 totalVeSupply, BoostParameters memory params)
internal
pure
returns (uint256)
{
// Return base boost (1x = 10000 basis points) if no voting power
if (totalVeSupply == 0) {
return params.minBoost;
}
// Calculate voting power ratio with higher precision
uint256 votingPowerRatio = (veBalance * 1e18) / totalVeSupply;
// Calculate boost within min-max range
uint256 boostRange = params.maxBoost - params.minBoost;
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;
}

This function will systematically revert at line:

uint256 boostRange = params.maxBoost - params.minBoost;

Because minBoostis way bigger than maxBoost

Impact

The impact of this issue can be considered as medium as it will lead to issues when computing boosts, with systematic reverts for all main functions. This issue is not high given that there is a setBoostParameters function allowing the controller to modify this error:

function setBoostParameters(uint256 _maxBoost, uint256 _minBoost, uint256 _boostWindow) external onlyController {
boostState.maxBoost = _maxBoost;
boostState.minBoost = _minBoost;
boostState.boostWindow = _boostWindow;
}

Tools Used

Manual review.

Recommendations

Make sure to set minBoost to 10000 instead of 1e18:

constructor(
address _rewardToken,
address _stakingToken,
address _controller,
uint256 _maxEmission,
uint256 _periodDuration
) {
rewardToken = IERC20(_rewardToken);
stakingToken = IERC20(_stakingToken);
controller = _controller;
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
_grantRole(CONTROLLER_ROLE, _controller);
boostState.maxBoost = 25000; // 2.5x
boostState.minBoost = 10000;
boostState.boostWindow = 7 days;
uint256 currentTime = block.timestamp;
uint256 nextPeriod = ((currentTime / _periodDuration) * _periodDuration) + _periodDuration;
// Initialize period state
periodState.periodStartTime = nextPeriod;
periodState.emission = _maxEmission;
TimeWeightedAverage.createPeriod(
periodState.votingPeriod,
nextPeriod,
_periodDuration,
0,
10000 // VOTE_PRECISION
);
}
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!