Core Contracts

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

BoostController Bypasses Boost State Tracking System

Relevant GitHub Links

https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/governance/boost/BoostController.sol#L154-L161

Summary

The BoostController contract bypasses the entire BoostState tracking system by using memory parameters instead of storage state for boost calculations, breaking core boost mechanics and enabling potential reward manipulation.

Important note: using memory instead of state is main vulnerability here as it bypasses time-weighted average tracking and state updates (the fact it uses test version of calculation function is not relevant to the root cause).

Vulnerability Details

The BoostController calculates boosts using memory parameters instead of the intended storage-based BoostState tracking system:

function calculateBoost(
address user,
address pool,
uint256 amount
) external view override returns (uint256 boostBasisPoints, uint256 boostedAmount) {
// Creates memory params instead of using storage state
BoostCalculator.BoostParameters memory params = BoostCalculator.BoostParameters({
maxBoost: boostState.maxBoost,
minBoost: boostState.minBoost,
boostWindow: boostState.boostWindow,
totalWeight: totalWeight,
totalVotingPower: totalVotingPower,
votingPower: votingPower
});
// Uses testing version meant for unit tests
return BoostCalculator.calculateTimeWeightedBoost(
params,
userVotingPower,
totalVotingPower,
amount
);
}

The internal _calculateBoost function has the same issue:

function _calculateBoost(
address user,
address pool,
uint256 amount
) internal view returns (uint256) {
// Also creates memory params instead of using storage
BoostCalculator.BoostParameters memory params = ...;
}

Key Issues:

  1. Uses testing version of boost calculation in production

  2. Bypasses all time-weighted average tracking

  3. No period tracking for boost evolution

  4. Missing historical boost data recording

  5. Makes boost manipulation possible through rapid balance changes

Impact

  1. Instant boost changes possible instead of gradual changes

  2. No protection against boost manipulation through quick deposits/withdrawals

  3. Missing audit trail of boost changes

  4. Core boost mechanics broken

  5. Reward gaming possible through boost manipulation

Tools Used

Manual Review

Recommendations

  1. Modify BoostController to use storage-based state tracking:

function calculateBoost(
address user,
address pool,
uint256 amount
) external view override returns (uint256 boostBasisPoints, uint256 boostedAmount) {
if (!supportedPools[pool]) revert UnsupportedPool();
return boostState.calculateTimeWeightedBoost(
veToken.getVotingPower(user, block.timestamp),
veToken.getTotalVotingPower(),
amount
);
}
  1. Remove memory parameter version of calculateTimeWeightedBoost from production code

  2. Ensure all boost calculations use storage state

  3. Add proper period tracking for boosts

  4. Implement time delay requirements for boost changes

Updates

Lead Judging Commences

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

Protocol contains competing boost calculation implementations in different contracts that bypass each other, creating inconsistent rewards and breaking delegation mechanics

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

Protocol contains competing boost calculation implementations in different contracts that bypass each other, creating inconsistent rewards and breaking delegation mechanics

Support

FAQs

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