Core Contracts

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

`_updateBoostState()` is not called in `extend()` which results in incorrect rewards calculations

Summary

When users extend their veRAAC locks, an important function is not invoked when it should be.

Vulnerability Details

Whenever users initially lock RAAC tokens for veRAAC tokens or increase their lock after that, the boost state is updated with a call to _updateBoostState(). This is an important call since it updates the global boost state which is used in calculations for rewards.

Let's take a look at what happens when users extend() their lock:

function extend(uint256 newDuration) external nonReentrant whenNotPaused {
// Extend lock using LockManager
uint256 newUnlockTime = _lockState.extendLock(msg.sender, newDuration);
// Update voting power
LockManager.Lock memory userLock = _lockState.locks[msg.sender];
(int128 newBias, int128 newSlope) = _votingState.calculateAndUpdatePower(
msg.sender,
userLock.amount,
newUnlockTime
);
// Update checkpoints
uint256 oldPower = balanceOf(msg.sender);
uint256 newPower = uint256(uint128(newBias));
_checkpointState.writeCheckpoint(msg.sender, newPower);
// Update veToken balance
if (newPower > oldPower) {
_mint(msg.sender, newPower - oldPower);
} else if (newPower < oldPower) {
_burn(msg.sender, oldPower - newPower);
}
emit LockExtended(msg.sender, newUnlockTime);
}

The update to boost state call is completely missing, meanwhile it is making changes to:

  1. Total voting power (by minting/burning tokens)

  2. Total locked amount of tokens (by changing user locked amount based on duration extension)

Both of which must be reflected and updated in the boost state:

function _updateBoostState(address user, uint256 newAmount) internal {
// Update boost calculator state
_boostState.votingPower = _votingState.calculatePowerAtTimestamp(user, block.timestamp);
@> _boostState.totalVotingPower = totalSupply();
@> _boostState.totalWeight = _lockState.totalLocked;
_boostState.updateBoostPeriod();
}

Any time users extend their lock, the global boost state will not be updated to reflect the new changes in minted/burned tokens and locked tokens. Since the boost state is used in rewards calculations, this will completely mess them up.

Impact

Incorrect rewards calculations and distributions due to missing updates to important parameters when users extend their lock. These updates exist in lock() and increase() but are missing in extend().

Tools Used

Manual Review

Recommendations

Call _updateBoostState towards the end of the functin flow of extend(), after _checkpointState.writeCheckpoint().

Updates

Lead Judging Commences

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

veRAACToken::_updateBoostState not called in extend/withdraw

Support

FAQs

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

Give us feedback!