Core Contracts

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

Extend duration allows Users to mint New powers above the Max power total supply

Summary

The max total supply can be bypassed by extending and updating their locked time.

Vulnerability Details

/**
* @notice Maximum total supply of veRAACToken // note max supply of veraactoken
*/
uint256 private constant MAX_TOTAL_SUPPLY = 100_000_000e18; // 100M
/**
* @notice Extends the duration of an existing lock
* @dev Increases the lock duration which results in updated voting power
* @param newDuration The new total duration for the lock, in seconds
*/
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
@audit>> if (newPower > oldPower) { // extension can either increase/ decrease power what of increasing amount what can happen for increase amoun tot decrease power
@audit>> _mint(msg.sender, newPower - oldPower); // we might be minting more check total supply before
} else if (newPower < oldPower) {
_burn(msg.sender, oldPower - newPower);
}
emit LockExtended(msg.sender, newUnlockTime);
}

Duration extension can mint a user more power

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
// FIXME: Get me to uncomment me when able
// bias = RAACVoting.calculateBias(amount, unlockTime, block.timestamp);
// slope = RAACVoting.calculateSlope(amount);
// Calculate initial voting power that will decay linearly to 0 at unlock time note
uint256 duration = unlockTime - block.timestamp; //note vote decay
@audit>>. uint256 initialPower = (amount * duration) / MAX_LOCK_DURATION; // Normalize by max duration
@audit>> bias = int128(int256(initialPower));
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);
emit VotingPowerUpdated(user, oldPower, uint256(uint128(bias)));
return (bias, slope);
}

Impact

Bypass the 100M max vetoken supply.

Tools Used

Manual Review

Recommendations

Nest a check to ensure that total supply is always below or equal to the max vetoken supply.

Updates

Lead Judging Commences

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

Incorrect `MAX_TOTAL_SUPPLY` check in the `veRAACToken::lock/extend` function of `veRAACToken` could harm locking functionality

Support

FAQs

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