The veRAACToken::increase function calculates voting power based on both the locked token amount and the remaining lock duration. When a user locks tokens with the maximum allowed duration, their initial voting power is equal to the token amount. However, as time passes, the voting power decays while the minted veRAAC token balance remains unchanged. This discrepancy causes the newly recalculated voting power to be lower than the existing balance when a user attempts to increase their lock, leading to an underflow in the minting logic.
In the increase function, after a user increases their locked amount, the contract recalculates voting power using the calculateAndUpdatePower function. This function computes the new voting power as follows:
It determines the remaining duration by subtracting the current block timestamp from the fixed unlock time.
It then calculates the initial voting power as:
initialPower = (newTotalAmount * remainingDuration) / MAX_LOCK_DURATION
For a user who initially locked tokens for the maximum duration, the voting power at the time of locking equals the locked amount. However, due to time decay, when the user later calls increase, the remaining duration is reduced. Consequently, the recalculated voting power (newPower) becomes lower than the balance minted during the initial lock.
The function then attempts to mint additional tokens by executing:
_mint(msg.sender, newPower - balanceOf(msg.sender));
If newPower is lower than the current balance, the subtraction underflows, causing the transaction to revert. This makes it impossible for users with maximum duration locks to increase their locked token value.
Initial Lock Creation:
At Time T:
A user locks 100 tokens with MAX_LOCK_DURATION (1460 days).
Calculation in calculateAndUpdatePower:
initialPower = (100 * 1460) / 1460 = 100
The user receives 100 veRAAC tokens.
Attempt to Increase Lock:
At Time T + 1 Year (≈365 days later):
The remaining duration is now approximately 1095 days.
The user calls increase(10) to add 10 tokens.
New Calculation:
New total locked amount = 100 + 10 = 110 tokens.
New voting power = (110 * 1095) / 1460 ≈ 82.5 tokens.
Comparison:
The existing balance is 100 veRAAC tokens, so the contract computes:
newPower - balanceOf(msg.sender) ≈ 82.5 - 100 = -17.5 tokens
Result:
The negative value triggers an underflow during the minting process, causing the transaction to revert.
Users who initially lock tokens for the maximum duration cannot subsequently increase their locked amount. This limits their ability to boost their voting power as intended.
Manual Review
Implement a safeguard in the increase function to ensure that the recalculated voting power does not fall below the current veRAAC token balance. This could involve adjusting the minting logic to prevent underflow or disallowing increases for maximum duration locks unless additional adjustments to voting power calculations are made.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.