Summary
Incorrect implementation of removeBoostDelegation. removeBoostDelegation need to add one more param for pool address to fix it. Additionally, poolBoost.workingSupply
is intended to represent the token amount, but it is also subtracted by the boost amount.
Vulnerability Details
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
Incorrect implemenation of removeBoostDelegation caused many issues like manipulating poolBoost.totalBoost and workingSupply.
Tools Used
Manual Review
Recommendations
Correct implementaion with adding pool address as user params.
function removeBoostDelegation(address from, address pool) external override nonReentrant {
UserBoost storage delegation = userBoosts[from][pool];
if (delegation.delegatedTo != msg.sender) revert DelegationNotFound();
if (delegation.expiry > block.timestamp) revert InvalidDelegationDuration();
PoolBoost storage poolBoost = poolBoosts[pool];
if (poolBoost.totalBoost >= delegation.amount) {
poolBoost.totalBoost -= delegation.amount;
}
poolBoost.lastUpdateTime = block.timestamp;
emit DelegationRemoved(from, pool, delegation.amount);
delete userBoosts[from][pool];
}