Core Contracts

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

Using balanceOf Instead of Voting Power

Summary

These contracts (BaseGauge, GaugeController) use veToken.balanceOf() instead of getVotingPower(). This ignores lock expiration decay, leading to incorrect boost and voting power calculations.

Vulnerability Details

The use of balanceOf() instead of getVotingPower() creates significant calculation discrepancies in the protocol.

In BaseGauge.sol#_applyBoost

function _applyBoost(address account, uint256 baseWeight) internal view virtual returns (uint256) {
IERC20 veToken = IERC20(IGaugeController(controller).veRAACToken());
uint256 veBalance = veToken.balanceOf(account); // Should use getVotingPower

In GaugeController.sol#vote

function vote(address gauge, uint256 weight) external override whenNotPaused {
uint256 votingPower = veRAACToken.balanceOf(msg.sender); // Should use getVotingPower

Economic Impact:

  • Boost calculations provide wrong multipliers

  • Reward distributions become inequitable

  • Incentive mechanisms fail to reward lock duration

  • Protocol revenue sharing becomes imbalanced

Impact

Users have no incentive to lock longer

Tools Used

Manual

Recommendations

Replace the instances of balanceOf with getVotingPower(account, block.timestamp) to reflect actual voting power.

// In BaseGauge.sol
function _applyBoost(address account, uint256 baseWeight) internal view returns (uint256) {
uint256 votingPower = veToken.getVotingPower(account, block.timestamp);
uint256 totalVotingPower = veToken.getTotalVotingPower();
return calculateBoost(votingPower, totalVotingPower, baseWeight);
}
// In GaugeController.sol
function vote(address gauge, uint256 weight) external whenNotPaused {
uint256 votingPower = veToken.getVotingPower(msg.sender, block.timestamp);
_updateGaugeWeight(gauge, weight, votingPower);
}
// In BoostController.sol
function calculateBoost(address user, address pool, uint256 amount) external view returns (uint256) {
uint256 votingPower = veToken.getVotingPower(user, block.timestamp);
return _calculateBoost(votingPower, amount);
}
Updates

Lead Judging Commences

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

BaseGauge::_applyBoost, GaugeController::vote, BoostController::calculateBoost use balanceOf() instead of getVotingPower() for vote-escrow tokens, negating time-decay mechanism

Support

FAQs

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