Core Contracts

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

Pool boost working supply not updated correctly, in `BoostController.sol::updateUserBoost`.

Contract - BoostController.sol

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; // Set working supply directly to new boost
poolBoost.lastUpdateTime = block.timestamp;
emit BoostUpdated(user, pool, newBoost);
emit PoolBoostUpdated(pool, poolBoost.totalBoost, poolBoost.workingSupply);
}

The purpose of poolBoost.workingSupply is to track total boosts of all users in action, it's not designed for to track for
single user, in the current implementation the poolBoost working supply is being updated to newBoost (boost of single user).

Vulnerability Details

  1. poolBoost.workingSupply is supposed to take care of all user's boost.

  2. In current implementation poolBoost.workingSupply is being updated with newBoost of a single user.

Impact

  • poolBoost.workingSupply isn't behaving as it should behave.

  • The expected behaviour should be summation and substraction of newBoost, on poolBoost.workingSupply; like this -

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

Tools Used

Manual

Recommendations

Implement this way instead -

- poolBoost.workingSupply = newBoost;
+ if (newBoost >= oldBoost) {
+ poolBoost.workingSupply = poolBoost.workingSupply + (newBoost - oldBoost);
+ } else {
+ poolBoost.workingSupply = 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.