A severe vulnerability in veRAACToken.sol allows users to entirely lose their existing locked data and voting power when calling lock() while already having an existing lock as soon as _lockState.createLock() is invoked.
A user who has previously created a lock calls lock. When _lockState.createLock() is triggered, it does not ensure state.locks[user].exists != true prior to permitting the execution of the function.
Sadly, state.locks[user] is assigned the new struct Lock where the inputted amount is replacing the existing amount.
Next, _votingState.calculateAndUpdatePower() is invoked to calculate bias, i.e. newPower, with the inputted amount that renders the existing voting power obsolete (erased).
Although newPower is minted to the user, when withdraw() is eventually callable, the function will burn all power minted but only userLock.amount, i.e. the last inputted amount of raacToken is transferred to the user.
The user lost the previously existing voting power and would need to sustain the loss of not getting transferred the previous RAAC tokens sent in to the contract.
Such discrepancy also affects all other contracts dependent of getVotingPower() and getTotalVotingPower(). For instance, when calculateing pending rewards for a user using time-weighted average in FeeCollector._calculatePendingRewards(), the pendingAmount returned will be smaller than intended due to a smaller userVotingPower associated now:
Manual
Consider making the following change:
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.