The lock function in the veRAACToken contract calculates the number of veTokens minted using integer division, which can result in zero veTokens being issued when small amounts or short durations are used. This occurs because the formula (amount * duration) / MAX_LOCK_DURATION truncates fractional results, leading to a loss of funds for users locking small amounts.
The issue stem from lock function in the veRAACToken contract and the calculateAndUpdatePower function in the VotingPowerLib library.
The formula (amount * duration) / MAX_LOCK_DURATION is used to calculate the initial voting power (bias).
Solidity performs integer division, truncating any fractional result to the nearest lower integer.
For small values of amount or duration, the numerator (amount * duration) may be smaller than MAX_LOCK_DURATION, resulting in a truncated value of zero.
Example Scenarios :
Lock 1 Token for 1 Year :
amount = 1e18
duration = 31,536,000 seconds
initialPower = (1e18 * 31,536,000) / 126,144,000 ≈ 0.25e18 → 0 (truncated)
Lock 0.1 Token for 1 Year :
amount = 1e17
duration = 31,536,000 seconds
initialPower = (1e17 * 31,536,000) / 126,144,000 ≈ 0.025e18 → 0 (truncated)
Users who lock small amounts or short durations receive no veRAAC tokens, meaning they cannot participate in governance or benefit from boosts.
The issue could lead to frustration among users, as they expect to receive proportional voting power for their locked tokens but instead receive none.
Small holders are disproportionately affected, as they are more likely to lock small amounts. This undermines the inclusivity of the system.
Manual Review
Implement the minimum value fix (newPower = 1 when truncated to 0) for simplicity and user fairness. Scaling is an option but requires careful overflow handling given the large numbers involved
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.