Core Contracts

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

Uncapped Boost Calculation in BoostController::calculateBoost and \_calculateBoost Leading to Inaccurate Boosted Amounts.

Summary

In the BoostController contract, the calculateBoost() and _calculateBoost() functions calculate a user's boost without capping the boosted amount when it falls below the MIN_BOOST or exceeds the MAX_BOOST. This uncapped calculation can lead to inaccurate boost allocations, potentially impacting reward distribution and governance weight calculations.

Vulnerability Details

Missing Cap in _calculateBoost and calculateBoost

Both _calculateBoost() and calculateBoost() functions are responsible for calculating the boosted amount for a user in a pool. However, they lack proper boundary checks for the calculated boost:

  • _calculateBoost() does not cap the boosted amount to MIN_BOOST, though it caps the maximum boosted amount to a user-specified limit.

  • calculateBoost() entirely omits capping for both MIN_BOOST and MAX_BOOST.

This could lead to scenarios where a user receives a boost below the allowed MIN_BOOST, affecting their reward share negatively or, conversely, exceeding the MAX_BOOST, giving them an unfair advantage.

BoostController::_calculateBoost:

function _calculateBoost(address user, address pool, uint256 amount) internal view returns (uint256) {
if (amount == 0) revert InvalidBoostAmount();
if (!supportedPools[pool]) revert PoolNotSupported();
// Get current weights without modifying state
(uint256 totalWeight, uint256 totalVotingPower, uint256 votingPower) = updateTotalWeight();
// @info: using stale voting power == user balance
uint256 userBalance = IERC20(address(veToken)).balanceOf(user);
uint256 totalSupply = IERC20(address(veToken)).totalSupply();
if (userBalance == 0 || totalSupply == 0) {
return amount;
}
// Create parameters struct for calculation
BoostCalculator.BoostParameters memory params = BoostCalculator.BoostParameters({
maxBoost: boostState.maxBoost,
minBoost: boostState.minBoost,
boostWindow: boostState.boostWindow,
totalWeight: totalWeight,
totalVotingPower: totalVotingPower,
votingPower: votingPower
});
(uint256 boostBasisPoints, uint256 boostedAmount) =
BoostCalculator.calculateTimeWeightedBoost(params, userBalance, totalSupply, amount);
@> // @info: doesn't cap boostedAmount to MIN_BOOST
// instead capping to given amount.
if (boostedAmount < amount) {
return amount;
}
uint256 maxBoostAmount = amount * MAX_BOOST / 10000;
if (boostedAmount > maxBoostAmount) {
return maxBoostAmount;
}
return boostedAmount;
}

BoostController::calculateBoost:

function calculateBoost(address user, address pool, uint256 amount)
external
view
override
returns (uint256 boostBasisPoints, uint256 boostedAmount)
{
if (!supportedPools[pool]) revert UnsupportedPool();
// Get current weights without modifying state
(uint256 totalWeight, uint256 totalVotingPower, uint256 votingPower) = updateTotalWeight();
uint256 userVotingPower = veToken.getVotingPower(user, block.timestamp);
// Create parameters struct for calculation
BoostCalculator.BoostParameters memory params = BoostCalculator.BoostParameters({
maxBoost: boostState.maxBoost,
minBoost: boostState.minBoost,
boostWindow: boostState.boostWindow,
totalWeight: totalWeight,
totalVotingPower: totalVotingPower,
votingPower: votingPower
});
return BoostCalculator.calculateTimeWeightedBoost(params, userVotingPower, totalVotingPower, amount);
@> // @info: missing min and max boost amount cap
}

Proof of Concept

Scenario 1: Boost Below MIN_BOOST

  1. Alice delegates her tokens to a pool with a small amount.

  2. Her calculated boost falls below the defined MIN_BOOST due to her low voting power.

  3. Since _calculateBoost() does not cap to MIN_BOOST, Alice’s effective boost is lower than intended, reducing her rewards.

Scenario 2: Boost Above MAX_BOOST

  1. Bob, a whale, delegates a significant amount of tokens.

  2. The calculated boost exceeds the MAX_BOOST limit.

  3. In calculateBoost(), there is no capping mechanism, resulting in an unfairly high boost for Bob.

Impact

  • Users could receive boosts lower than MIN_BOOST, impacting their reward distribution.

  • Users could exceed the MAX_BOOST, leading to governance and reward distribution imbalances.

Tools Used

  • Manual Review

  • Foundry

Recommendations

Fix for _calculateBoost

- if (boostedAmount < amount) {
- return amount;
+ if (boostedAmount < MIN_BOOST) {
+ return MIN_BOOST;
}

Fix for calculateBoost

+ if (boostedAmount < MIN_BOOST) {
+ boostedAmount = MIN_BOOST;
+ } else if (boostedAmount > MAX_BOOST) {
+ boostedAmount = MAX_BOOST;
+ }

These changes ensure that the calculated boost stays within the allowed range, maintaining protocol stability and fairness.

Updates

Lead Judging Commences

inallhonesty Lead Judge
9 months ago
inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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

Give us feedback!