Core Contracts

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

Incorrect boost power release in removeBoostDelegation permanently locks or incorrectly releases boost power

Relevant GitHub Links

https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/governance/boost/BoostController.sol#L247-L253

Summary

The removeBoostDelegation() function in BoostController.sol directly updates pool metrics before removing delegation state, leading to permanent locking or incorrect release of boost power. The function fails to properly recalculate voting power and boost metrics after delegation removal.

Vulnerability Details

The vulnerability exists in how removeBoostDelegation() handles boost power release:

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();
// @audit Updates pool metrics directly without proper recalculation
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];
}

Key issues:

  1. Pool metrics (totalBoost, workingSupply) are updated with raw delegation amount without considering time-weighted decay

  2. No recalculation of boost power using BoostCalculator after delegation removal

Verified impacts:

Impact

  1. Incorrect reward distributions due to wrong boost calculations - since pool total metrics are wrong

  2. The impact compounds over time as more delegations expire and are removed with incorrect amounts

Tools Used

Manual Review

Recommendations

Refactor removeBoostDelegation() to properly handle boost power release (treat this as a pseudocode).

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();
uint256 delegationAmount = delegation.amount;
// Clear delegation state first
delete userBoosts[from][msg.sender];
// Recalculate voting power for delegator
_updateVotingPower(from);
// Recalculate boost for recipient
_updateUserBoost(msg.sender);
// Update pool metrics using BoostCalculator
PoolBoost storage poolBoost = poolBoosts[msg.sender];
poolBoost.totalBoost = _calculateTimeWeightedBoost(poolBoost.totalBoost, delegationAmount);
poolBoost.workingSupply = _calculateWorkingSupply(msg.sender);
poolBoost.lastUpdateTime = block.timestamp;
emit DelegationRemoved(from, msg.sender, delegationAmount);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
Assigned finding tags:

BoostController::removeBoostDelegation reduces pool boost metrics with raw values without time-weighted recalculation, causing incorrect reward calculations that compound over time

inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
Assigned finding tags:

BoostController::removeBoostDelegation reduces pool boost metrics with raw values without time-weighted recalculation, causing incorrect reward calculations that compound over time

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.