Core Contracts

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

### Incorrect Pool Boost Calculation in `BoostController::updateUserBoost()`

Overview

The updateUserBoost function is designed to update a user's boost for a specific pool based on their veToken balance. However, the function contains several issues that can lead to incorrect boost calculations and potential economic imbalances. The primary issues are:

  1. Incorrect Update of poolBoost.workingSupply:

    • The workingSupply is directly set to the user's new boost (newBoost), which is incorrect. The workingSupply should represent the total boosted supply of the pool, not just the user's boost.

  2. Lack of Validation for poolBoost.totalBoost:

    • The function does not ensure that poolBoost.totalBoost remains non-negative when subtracting the old boost (oldBoost). This can lead to underflow errors or incorrect calculations.

  3. Potential for Manipulation:

    • The function does not validate whether the user's boost (newBoost) is within reasonable bounds, which could allow malicious users to manipulate the boost system.

Vulnerability Details

  1. Functionality of updateUserBoost:

    • The function updates a user's boost for a specific pool based on their veToken balance.

    • It calculates the new boost using _calculateBoost and updates the user's boost (userBoost.amount) and the pool's total boost (poolBoost.totalBoost).

    • It also updates the pool's workingSupply and emits events to log the changes.

  2. Issue with workingSupply:

    • The line poolBoost.workingSupply = newBoost directly sets the workingSupply to the user's new boost, which is incorrect.

    • The workingSupply should represent the total boosted supply of the pool, not just the user's boost. This mistake can lead to incorrect calculations of rewards and other pool-related metrics.

  3. Issue with totalBoost Calculation:

    • The function updates poolBoost.totalBoost by adding or subtracting the difference between the new boost (newBoost) and the old boost (oldBoost).

    • However, it does not ensure that poolBoost.totalBoost remains non-negative when subtracting the old boost. This can lead to underflow errors or incorrect calculations.

  4. Impact:

    • Incorrect Reward Distribution: The incorrect workingSupply can lead to inaccurate reward calculations, causing users to receive more or fewer rewards than they are entitled to.

    • Economic Imbalance: The incorrect totalBoost calculation can lead to imbalances in the pool's boost system, undermining its fairness and functionality.

    • Potential Exploitation: Malicious users could manipulate the boost system to gain unfair advantages or disrupt the pool's operations.

Here is the problematic code snippet:

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);
}
@> poolBoost.workingSupply = newBoost; // Incorrect: workingSupply should be total boosted supply
poolBoost.lastUpdateTime = block.timestamp;
emit BoostUpdated(user, pool, newBoost);
emit PoolBoostUpdated(pool, poolBoost.totalBoost, poolBoost.workingSupply);
}
  • Issue 1: poolBoost.workingSupply = newBoost incorrectly sets the workingSupply to the user's new boost instead of the total boosted supply of the pool.

  • Issue 2: The calculation of poolBoost.totalBoost does not ensure non-negativity, which can lead to underflow errors or incorrect values.

  • Issue 3: The function does not validate whether newBoost is within reasonable bounds, leaving it open to manipulation.

Recommendations

To fix these issues, make the following changes:

  1. Correct workingSupply Calculation:

    • The workingSupply should represent the total boosted supply of the pool, not just the user's boost. Update it accordingly.

    • Example:

      poolBoost.workingSupply = poolBoost.workingSupply + (newBoost - oldBoost);
  2. Ensure Non-Negative totalBoost:

    • Add a check to ensure that poolBoost.totalBoost does not underflow when subtracting the old boost.

    • Example:

      if (newBoost >= oldBoost) {
      poolBoost.totalBoost = poolBoost.totalBoost + (newBoost - oldBoost);
      } else {
      require(poolBoost.totalBoost >= (oldBoost - newBoost), "Underflow in totalBoost");
      poolBoost.totalBoost = poolBoost.totalBoost - (oldBoost - newBoost);
      }
  3. Validate newBoost:

    • Add validation to ensure that newBoost is within reasonable bounds (e.g., non-negative and not excessively large).

    • Example:

      require(newBoost <= MAX_BOOST, "Boost exceeds maximum allowed");
  4. Test the Fix:

    • Write unit tests to verify that the workingSupply and totalBoost are updated correctly and that the function handles edge cases (e.g., underflow) properly.

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.