Core Contracts

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

Incorrect workingSupply Adjustment in Boost Delegation

Summary

The BoostController::updateUserBoost function is responsible for recalculating and updating the boost for a user in a specific pool. However, there is a issue where workingSupply is directly set to newBoost, rather than being adjusted incrementally. This could result in incorrect reward calculations or governance weight distributions.

Vulnerability Details

In the function BoostController::updateUserBoost, the workingSupply is set directly to newBoost, leading to incorrect calculations of active boosts in a pool. Unlike totalBoost, which is updated incrementally, workingSupply is being replaced outright, which does not correctly account for cumulative adjustments from multiple users updating their boosts.

Affected Code:

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

function updateUserBoost(address user, address pool) external override nonReentrant whenNotPaused {
if (paused()) revert EmergencyPaused();
if (user == address(0)) revert InvalidPool();
if (!supportedPools[pool]) revert PoolNotSupported();
UserBoost storage userBoost = userBoosts[user][pool];
PoolBoost storage poolBoost = poolBoosts[pool];
uint256 oldBoost = userBoost.amount;
// Calculate new boost based on current veToken balance
uint256 newBoost = _calculateBoost(user, pool, 10000); // Base amount
userBoost.amount = newBoost;
userBoost.lastUpdateTime = block.timestamp;
// Update pool totals safely
if (newBoost >= oldBoost) {
poolBoost.totalBoost = poolBoost.totalBoost + (newBoost - oldBoost);
} else {
poolBoost.totalBoost = poolBoost.totalBoost - (oldBoost - newBoost);
}
// Incorrect adjustment of workingSupply
poolBoost.workingSupply = newBoost; // Should be incrementally adjusted
poolBoost.lastUpdateTime = block.timestamp;
emit BoostUpdated(user, pool, newBoost);
emit PoolBoostUpdated(pool, poolBoost.totalBoost, poolBoost.workingSupply);
}

Impact

This issue lead to inaccurate tracking of the working supply in a pool, potentially affecting:

  • Reward distributions, where incorrect working supply values result in misallocated incentives.

  • Governance weight calculations, where influence is incorrectly distributed due to boost mismanagement.

  • Pool performance metrics, which might not reflect the actual number of active boosted users correctly.

Tools Used

  • Manual code review

Recommendations

  1. Incrementally Adjust workingSupply Like totalBoost:
    Modify workingSupply to be adjusted incrementally, rather than being set directly:

    if (newBoost >= oldBoost) {
    poolBoost.workingSupply += (newBoost - oldBoost);
    } else {
    poolBoost.workingSupply -= (oldBoost - newBoost);
    }
Updates

Lead Judging Commences

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