Summary
Boost values is expected to be in BPS value. MaxBoost is set to 25000 but MinBoost is set to 1e18. This leads to a scenario in which the boost amount is way bigger and as a result users always get the MaxBoost value.
Vulnerability Details
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;
boostState.minBoost = 1e18;
boostState.boostWindow = 7 days;
uint256 currentTime = block.timestamp;
uint256 nextPeriod = ((currentTime / _periodDuration) * _periodDuration) + _periodDuration;
periodState.periodStartTime = nextPeriod;
periodState.emission = _maxEmission;
TimeWeightedAverage.createPeriod(
periodState.votingPeriod,
nextPeriod,
_periodDuration,
0,
10000
);
}
In this calculateBoost function we can see that increased boost value will lead to a scenario where boost is always bigger than params.maxBoost. As a result users will alawys receive params.maxBoost as a boost multiplier.
function calculateBoost(
uint256 veBalance,
uint256 totalVeSupply,
BoostParameters memory params
) internal pure returns (uint256) {
if (totalVeSupply == 0) {
return params.minBoost;
}
uint256 votingPowerRatio = (veBalance * 1e18) / totalVeSupply;
uint256 boostRange = params.maxBoost - params.minBoost;
uint256 boost = params.minBoost + ((votingPowerRatio * boostRange) / 1e18);
if (boost < params.minBoost) {
return params.minBoost;
}
if (boost > params.maxBoost) {
return params.maxBoost;
}
return boost;
}
Impact
Users will always get maxBoost as multiplier due to incorrect initialization.
Tools Used
Manual Review, Hardhat
Recommendations
Change minBoost initial value to 10000.