Core Contracts

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

[H] Incorrect Boost State Update in `_updateBoostState` Function in `veRAACToken`

Summary

The _updateBoostState function in the veRAACToken contract incorrectly updates the boost state. When called after increasing the lock amount, the new tokens are not yet minted, leading to an incorrect totalVotingPower being set to the old totalSupply.

Vulnerability Details

The current _updateBoostState function in the veRAACToken contract is:

function _updateBoostState(address user, uint256 newAmount) internal {
// Update boost calculator state
_boostState.votingPower = _votingState.calculatePowerAtTimestamp(user, block.timestamp);
_boostState.totalVotingPower = totalSupply();
// here totalLocked comprises the new amount, but the totalVotingPower
// is not yet updated because the new amount is not yet minted
>> _boostState.totalWeight = _lockState.totalLocked;
_boostState.updateBoostPeriod();
}

When _updateBoostState is called after increasing the lock amount, the new tokens are not yet minted, leading to an incorrect totalVotingPower being set to the old totalSupply.

For instance, in the increase function:

function increase(uint256 amount) external nonReentrant whenNotPaused {
// Increase lock using LockManager
_lockState.increaseLock(msg.sender, amount);
_updateBoostState(msg.sender, locks[msg.sender].amount);
// Update voting power
LockManager.Lock memory userLock = _lockState.locks[msg.sender];
(int128 newBias, int128 newSlope) = _votingState.calculateAndUpdatePower(
msg.sender,
userLock.amount + amount,
userLock.end
);
// Update checkpoints
uint256 newPower = uint256(uint128(newBias));
_checkpointState.writeCheckpoint(msg.sender, newPower);
// Transfer additional tokens and mint veTokens
raacToken.safeTransferFrom(msg.sender, address(this), amount);
_mint(msg.sender, newPower - balanceOf(msg.sender));
emit LockIncreased(msg.sender, amount);
}

The totalVotingPower is set to the old totalSupply before the new tokens are minted.

Links:

  1. https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/tokens/veRAACToken.sol#L571

  2. https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/tokens/veRAACToken.sol#L227

  3. https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/tokens/veRAACToken.sol#L241

  4. https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/tokens/veRAACToken.sol#L254

  5. https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/tokens/veRAACToken.sol#L270

Impact

This issue can lead to incorrect boost calculations, potentially affecting the rewards and voting power calculations within the protocol.

Tools Used

Manual code review.

Recommendations

Update the _updateBoostState function to correctly handle the new total supply after minting the new tokens. The corrected function should be:

function _updateBoostState(address user, uint256 newAmount) internal {
// Update boost calculator state
_boostState.votingPower = _votingState.calculatePowerAtTimestamp(user, block.timestamp);
// Ensure totalVotingPower includes the new minted tokens
_boostState.totalVotingPower = totalSupply() + newAmount;
_boostState.totalWeight = _lockState.totalLocked;
_boostState.updateBoostPeriod();
}

This ensures that the totalVotingPower correctly includes the new minted tokens, leading to accurate boost calculations.


Updates

Lead Judging Commences

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

veRAACToken::_updateBoostState should be called later inside lock/increase

Support

FAQs

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