Core Contracts

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

`increase` will revert in most cases due to an underflow when it tries to mint tokens to the user

Summary

increase will revert in most cases due to an underflow when it tries to mint tokens to the user

Vulnerability Details

increase will revert in most cases due to an underflow when it tries to mint tokens to the user:

function increase(uint256 amount) external nonReentrant whenNotPaused {
_lockState.increaseLock(msg.sender, amount);
_updateBoostState(msg.sender, locks[msg.sender].amount);
LockManager.Lock memory userLock = _lockState.locks[msg.sender];
(int128 newBias, int128 newSlope) = _votingState.calculateAndUpdatePower(
msg.sender,
userLock.amount + amount,
userLock.end
);
uint256 newPower = uint256(uint128(newBias));
// ...
//@audit this will underflow as most of the time we will calculate a new lower newPower than the current user balance
_mint(msg.sender, newPower - balanceOf(msg.sender));
emit LockIncreased(msg.sender, amount);
}

The underflow occurs because we use the live bias math which calculates out initial amount, lowered by the slope * timeDelta, or simply if we have locked 10k tokes for 1 year at 1:1 rate, and 6 months have passed we would have 5k voting power.

uint256 duration = unlockTime - block.timestamp;
uint256 initialPower = (amount * duration) / MAX_LOCK_DURATION; // Normalize by max duration
bias = int128(int256(initialPower));
slope = int128(int256(initialPower / duration)); // Power per second decay

Now when we get back to the first piece of code we can see that if out user makes an increase smaller than his decay the function would revert.

Example:

  1. User locks 12k tokens for 4 year at 1:1 ratio and gets minted 12k veRAAC tokens

  2. 3 years pass and he want's to increase his voting power, so he calls increase with 2k RAAC

  3. The new bias will be 3.5k

// duration = 1 year (as that's how much is left)
uint256 duration = unlockTime - block.timestamp;
// (12k + 2k) * 1 year / 4 years = 3.5k
uint256 initialPower = (amount * duration) / MAX_LOCK_DURATION;
bias = int128(int256(initialPower));
slope = int128(int256(initialPower / duration));
  1. And when we reach mint it would underflow

// 3.5k - 12k -> underflow
_mint(msg.sender, newPower - balanceOf(msg.sender));

Impact

Function is broken, will revert most of the times
Users will not be able to increase their voting power, but be forced to wait so their lock can expire and to make a new one.

Tools Used

Manual review

Recommendations

Have the same if condition extend uses:

if (newPower > oldPower) {
_mint(msg.sender, newPower - oldPower);
} else if (newPower < oldPower) {
_burn(msg.sender, oldPower - newPower);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 7 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.

Give us feedback!