Core Contracts

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

Underflow in `veRAACToken::increase` leads to failed token minting

Summary

The increase() function in veRAACToken fails to handle the case where the new voting power is less than the current power due to linear decay over time, leading to an underflow when minting tokens.

Vulnerability Details

In veRAACToken::increase(), after calculating the new voting power, the function attempts to mint the difference between the new power and current balance:

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);
}

However, due to the linear decay of voting power implemented in VotingPowerLib::calculateAndUpdatePower(), the new power can be less than the current balance, causing an underflow in the subtraction operation.

The root cause is that the function assumes the new power will always be greater than the initial power, but this is not true due to the time-based decay of voting power.

Impact

  • Users attempting to increase their lock amount may have their transactions revert due to underflow

  • This effectively prevents users from increasing their lock amounts after a certain time period

  • The contract becomes partially unusable as one of its core functions fails

Proof of Concept

Add the following test to the veRAACToken.test.js file:

describe("Increase Lock issue", () => {
it("should revert when increasing lock amount due to underflow", async () => {
const amount = ethers.parseEther("1000");
const additionalAmount = ethers.parseEther("5");
const duration = 365 * 24 * 3600;
const user1 = users[0];
await veRAACToken.connect(user1).lock(amount, duration);
await ethers.provider.send("evm_increaseTime", [30 * 24 * 60 * 60]);
await ethers.provider.send("evm_mine");
expect(veRAACToken.connect(user1).increase(additionalAmount)).to.be.revertedWithPanic(0x11); //0x11 is the panic code for underflow
});
});

Recommendation

Handle power decrease similar to the extend() function:

- _mint(msg.sender, newPower - balanceOf(msg.sender));
+ uint256 oldPower = balanceOf(msg.sender);
+ if (newPower > oldPower) {
+ _mint(msg.sender, newPower - oldPower);
+ } else if (newPower < oldPower) {
+ _burn(msg.sender, oldPower - newPower);
+ }
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.