Summary
The updateUserBoost
function incorrectly sets poolBoost.workingSupply = newBoost
, overwriting the total instead of accumulating user boosts. This corrupts the pool's working supply, leading to miscalculations in rewards.
Vulnerability Details
Current problematic implementation: /BoostController.sol#updateUserBoost
function updateUserBoost(address user, address pool) external override nonReentrant whenNotPaused {
UserBoost storage userBoost = userBoosts[user][pool];
PoolBoost storage poolBoost = poolBoosts[pool];
uint256 oldBoost = userBoost.amount;
uint256 newBoost = _calculateBoost(user, pool, 10000);
userBoost.amount = newBoost;
userBoost.lastUpdateTime = block.timestamp;
if (newBoost >= oldBoost) {
poolBoost.totalBoost = poolBoost.totalBoost + (newBoost - oldBoost);
} else {
poolBoost.totalBoost = poolBoost.totalBoost - (oldBoost - newBoost);
}
poolBoost.workingSupply = newBoost;
Impact
All reward calculations using workingSupply become inaccurate
Users receive incorrect boost multipliers
Reward distribution becomes unfairly skewed
Tools Used
Manual
Recommendations
Track workingSupply
as the sum of all userBoost.amount
in the pool, adjusting it by the difference between oldBoost
and newBoost
.
function updateUserBoost(address user, address pool) external override nonReentrant whenNotPaused {
UserBoost storage userBoost = userBoosts[user][pool];
PoolBoost storage poolBoost = poolBoosts[pool];
uint256 oldBoost = userBoost.amount;
uint256 newBoost = _calculateBoost(user, pool, userBoost.stakedAmount);
userBoost.amount = newBoost;
userBoost.lastUpdateTime = block.timestamp;
poolBoost.workingSupply = poolBoost.workingSupply - oldBoost + newBoost;
poolBoost.totalBoost = poolBoost.totalBoost + newBoost - oldBoost;
poolBoost.lastUpdateTime = block.timestamp;
emit BoostUpdated(user, pool, newBoost);
emit PoolBoostUpdated(pool, poolBoost.totalBoost, poolBoost.workingSupply);
}