Summary
Missing boundary checks in removeBoostDelegation() can lead to incorrect pool boost state calculations when delegation amounts exceed current totals, potentially affecting boost accounting for all users.
Root Cause
In BoostController.sol, the removeBoostDelegation() function fails to properly handle cases where delegation.amount exceeds poolBoost.totalBoost or poolBoost.workingSupply, leading to incorrect state updates.
Vulnerability Detail
The function decrements state values without checking if the subtraction would underflow:
function removeBoostDelegation(address from) external override nonReentrant {
UserBoost storage delegation = userBoosts[from][msg.sender];
if (delegation.delegatedTo != msg.sender) revert DelegationNotFound();
if (delegation.expiry > block.timestamp) revert InvalidDelegationDuration();
PoolBoost storage poolBoost = poolBoosts[msg.sender];
-> if (poolBoost.totalBoost >= delegation.amount) {
poolBoost.totalBoost -= delegation.amount;
}
-> if (poolBoost.workingSupply >= delegation.amount) {
poolBoost.workingSupply -= delegation.amount;
}
poolBoost.lastUpdateTime = block.timestamp;
emit DelegationRemoved(from, msg.sender, delegation.amount);
delete userBoosts[from][msg.sender];
}
Impact
If delegation.amount exceeds either poolBoost.totalBoost or poolBoost.workingSupply, the state values will be left at incorrect values instead of being properly zeroed out.
Recommended Mitigation
Add else clauses to set values to zero when delegation amount exceeds current totals:
function removeBoostDelegation(address from) external override nonReentrant {
UserBoost storage delegation = userBoosts[from][msg.sender];
if (delegation.delegatedTo != msg.sender) revert DelegationNotFound();
if (delegation.expiry > block.timestamp) revert InvalidDelegationDuration();
PoolBoost storage poolBoost = poolBoosts[msg.sender];
if (poolBoost.totalBoost >= delegation.amount) {
poolBoost.totalBoost -= delegation.amount;
}
+ else{
+ poolBoost.totalBoost = 0;
+ }
if (poolBoost.workingSupply >= delegation.amount) {
poolBoost.workingSupply -= delegation.amount;
}
+ else{
+ poolBoost.workingSupply = 0;
+ }
poolBoost.lastUpdateTime = block.timestamp;
emit DelegationRemoved(from, msg.sender, delegation.amount);
delete userBoosts[from][msg.sender];
}