Core Contracts

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

Voting Power Decay Issue in Gauge Voting System

Voting Power Decay Issue in Gauge Voting System

Issue Summary

The current implementation of the voting mechanism in the GaugeController contract uses the raw token balance from the veRAACToken instead of applying time-weighted voting power. This oversight leads to several vulnerabilities, including the retention of voting power after the expiration of token locks, which contradicts the intended design of time-weighted voting.

Vulnerabilities Identified

  1. Balance Not Reset After Lock Expiration

    • Location: veToken.balanceOf(user1)

    • Problem: The contract does not automatically update the balance after the lock expires.

    • Impact: Users retain voting power even after their lock period ends, leading to incorrect weight calculations.

  2. Missing Expiration Check in balanceOf

    • Location: veToken.balanceOf retrieval

    • Problem: The function returns the stored balance without checking if the lock has expired.

    • Impact: Users can continue voting even when they should have lost eligibility.

Proposed Fix

To address these vulnerabilities, the following changes are recommended:

  1. Implement a Function to Update Balance

    • Create a function (updateBalance) that resets the voting power to zero after the lock period expires. This function should be called whenever a user attempts to vote or check their voting power.

  2. Modify balanceOf to Include Expiration Check

    • Update the balanceOf function to check if the lock has expired before returning the stored balance. If the lock has expired, the function should return zero.

Example Code Implementation

function updateBalance(address user) internal {
// Check if the user's lock has expired
if (hasLockExpired(user)) {
// Reset voting power to zero
votingPower[user] = 0;
}
}
function balanceOf(address user) external view returns (uint256) {
// Check if the user's lock has expired
if (hasLockExpired(user)) {
return 0; // Return zero if the lock has expired
}
return storedBalance[user]; // Return the stored balance if the lock is still active
}
function vote(address gauge, uint256 weight) external override whenNotPaused {
if (!isGauge(gauge)) revert GaugeNotFound();
if (weight > WEIGHT_PRECISION) revert InvalidWeight();
// Update the user's balance before voting
updateBalance(msg.sender);
// Retrieve the voting power
uint256 votingPower = veRAACToken.balanceOf(msg.sender);
// Additional logic for voting...
}

Conclusion

Implementing these changes will ensure fair voting weight calculations and prevent expired tokens from influencing governance decisions. By enforcing the correct handling of voting power based on lock status, the integrity of the voting process will be maintained, aligning with the intended design of time-weighted voting.

Updates

Lead Judging Commences

inallhonesty Lead Judge 3 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.