Core Contracts

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

Inconsistent Boost Accounting in `delegateBoost()` and `removeBoostDelegation()`

Summary

when we call delegateBoost, we do not update total boost and working supply. but when delegation gets expired we call removeBoostDelegation, we decrease poolBoost.totalBoost and poolBoost.workingSupply.

Vulnerability Details

The delegateBoost() function does not update totalBoost and workingSupply when a boost is delegated. However, removeBoostDelegation() decreases these values upon expiration, leading to an inconsistency in boost accounting.

When a boost is delegated, poolBoost.totalBoost and poolBoost.workingSupply remain unchanged. This can be seen in the below code:

/contracts/core/governance/boost/BoostController.sol:213
213: function delegateBoost(
214: address to,
215: uint256 amount,
216: uint256 duration
217: ) external override nonReentrant {
218: if (paused()) revert EmergencyPaused();
219: if (to == address(0)) revert InvalidPool();
220: if (amount == 0) revert InvalidBoostAmount();
221: if (duration < MIN_DELEGATION_DURATION || duration > MAX_DELEGATION_DURATION)
222: revert InvalidDelegationDuration();
223:
224: uint256 userBalance = IERC20(address(veToken)).balanceOf(msg.sender);
225: console.log("userBalance",userBalance,amount);
226: if (userBalance < amount) revert InsufficientVeBalance();
227:
228: UserBoost storage delegation = userBoosts[msg.sender][to];
229: if (delegation.amount > 0) revert BoostAlreadyDelegated();
230:
231: delegation.amount = amount;
232: delegation.expiry = block.timestamp + duration;
233: delegation.delegatedTo = to;
234: delegation.lastUpdateTime = block.timestamp;
235:
236: emit BoostDelegated(msg.sender, to, amount, duration);
237: }

When the delegation expires and removeBoostDelegation() is called, these values are reduced as seen in the below code:

/contracts/core/governance/boost/BoostController.sol:244
244: function removeBoostDelegation(address from) external override nonReentrant {
245: UserBoost storage delegation = userBoosts[from][msg.sender];
246: if (delegation.delegatedTo != msg.sender) revert DelegationNotFound();
247: if (delegation.expiry > block.timestamp) revert InvalidDelegationDuration();
248:
249: // Update pool boost totals before removing delegation
250: PoolBoost storage poolBoost = poolBoosts[msg.sender];
251: if (poolBoost.totalBoost >= delegation.amount) {
252: poolBoost.totalBoost -= delegation.amount;
253: }
254: if (poolBoost.workingSupply >= delegation.amount) {
255: poolBoost.workingSupply -= delegation.amount;
256: }
257: poolBoost.lastUpdateTime = block.timestamp;
258:
259: emit DelegationRemoved(from, msg.sender, delegation.amount);
260: delete userBoosts[from][msg.sender];
261: }

Impact

Incorrect boost tracking may lead to governance miscalculations, unfair voting power distribution, or inaccurate working supply calculations.

Tools Used

Manual Review, Unit Testing

Recommendations

Update delegateBoost() to increase totalBoost and workingSupply when a boost is delegated.

Updates

Lead Judging Commences

inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Validated
Assigned finding tags:

BoostController removes pool boost on delegation removal without adding it on delegation creation, leading to accounting inconsistencies and potential underflows

inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Validated
Assigned finding tags:

BoostController removes pool boost on delegation removal without adding it on delegation creation, leading to accounting inconsistencies and potential underflows

Support

FAQs

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

Give us feedback!