Core Contracts

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

Users may fail to increase their veRAAC token in some cases

Summary

Users may fail to increase their veRAAC token because of revert

Vulnerability Details

In veRAACToken::increase(), users can increase their voting power via increasing RAAC token locked. We will re-calculate the new bias according to the updated locked amount and the left lock duration. And we will mint the added veRAAC token. The total veRAAC token should equal to the initial bias.

The problem happens in the calculation of newPower - balanceOf(msg.sender). Here balanceOf(msg.sender) is the initial bias. And newPower is the updated bias. It's possible that the newPower will be less than balanceOf(msg.sender) because the left lock period is less than the initial lock period. This will cause that users fail to increase.

For example:

  1. Alice locks 1000 RAAC token for 4 years. Then Alice will get 1000 initial power, 1000 veRAAC Token.

  2. 2 years later, Alice want to increase 500 RAAC token to increase her voting power, the initial power will become 1500 * 2 years/ 4 years = 750. This increase transaction will be reverted because the newPower is less than balanceOf(msg.sender).

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
);
....
_mint(msg.sender, newPower - balanceOf(msg.sender));
emit LockIncreased(msg.sender, amount);
}
function calculateAndUpdatePower(
VotingPowerState storage state,
address user,
uint256 amount,
uint256 unlockTime
) internal returns (int128 bias, int128 slope) {
if (amount == 0 || unlockTime <= block.timestamp) revert InvalidPowerParameters();
uint256 MAX_LOCK_DURATION = 1460 days; // 4 years
uint256 duration = unlockTime - block.timestamp;
uint256 initialPower = (amount * duration) / MAX_LOCK_DURATION; // Normalize by max duration
bias = int128(int256(initialPower));
// slope per second. When we reach the end, the voting power will be decreased to 0.
slope = int128(int256(initialPower / duration)); // Power per second decay
uint256 oldPower = getCurrentPower(state, user, block.timestamp);
state.points[user] = RAACVoting.Point({
bias: bias,
slope: slope,
timestamp: block.timestamp
});
_updateSlopeChanges(state, unlockTime, 0, slope);
return (bias, slope);
}

Impact

Users may fail to increase their lock positions in some cases.

Tools Used

Manual

Recommendations

Compare newPower with balanceOf(msg.sender), we need to burn the related veRAAC token if newPower is less than balanceOf(msg.sender).

Updates

Lead Judging Commences

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

veRAACToken::increase underflows on newPower - balanceOf(msg.sender)

Support

FAQs

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