Core Contracts

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

Boost State Updates Use Single User Voting Power Instead of Global Total

Summary

The BoostState in the veRAACToken contract is updated with a single user's voting power instead of the global total.

Vulnerability Details

The Issue is in _updateBoostState function in the veRAACToken contract and BoostCalculator.calculateTimeWeightedBoost function.

  • _updateBoostState is called in lock, increase, and extend after modifying a user’s lock.

Update:

  • _updateBoostState sets:

    • _boostState.votingPower = _votingState.calculatePowerAtTimestamp(user, block.timestamp) → Individual user’s current voting power

    • _boostState.totalVotingPower = totalSupply() → Total veRAAC supply (system-wide voting power)

    • _boostState.totalWeight = _lockState.totalLocked → Total locked RAAC tokens

  • Each call overwrites votingPower with the latest user’s power, not an aggregate or system total.

  • Boost Calculation:

    • calculateTimeWeightedBoost passes BoostState.votingPower into params.votingPower, but calculateBoost doesn’t use params.votingPower. It uses veBalance (user’s current balance) and totalVeSupply (passed as totalSupply).

    • Thus, while votingPower is incorrectly set to a single user’s value, it doesn’t directly affect the boost calculation in the current implementation.

  • BoostState has both votingPower and totalVotingPower, suggesting votingPower might have been intended for per-user tracking. However, it’s not used in calculateBoost.

  • If votingPower were meant to be the system total, the bug would cause params.votingPower to reflect one user’s power, but this isn’t the case here.

Impact

  • this doesn’t currently affect boost calculations because calculateBoost ignores params.votingPower, relying on veBalance and totalVeSupply.

Tools Used

Recommendations

  • Modify the _updateBoostState function to use totalSupply() instead of balanceOf(user) when updating BoostState.totalVotingPower.

Updates

Lead Judging Commences

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

BoostController::updateUserBoost overwrites workingSupply with single user's boost value instead of accumulating, breaking reward multipliers and allowing last updater to capture all benefits

Support

FAQs

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