In the veRAACToken contract, when users withdraw their locked RAAC tokens (either through regular withdraw() or emergencyWithdraw()), the contract fails to decrease the totalLocked state variable in the LockManager.LockState struct. This leads to an incorrect accounting of the total locked tokens in the system.
The veRAACToken contract uses the LockManager library to manage token lock positions. The LockState struct in LockManager maintains a totalLocked variable that tracks the total amount of RAAC tokens locked in the system:
When new tokens are locked via the lock() function, the totalLocked is correctly increased in LockManager.createLock():
However, in veRAACToken's withdraw() and emergencyWithdraw() functions, when users withdraw their tokens, the contract only deletes the individual lock mapping but fails to decrease the totalLocked counter:
Similarly in emergencyWithdraw():
This causes the totalLocked to become permanently inflated as it never decreases when tokens are withdrawn. The inflated totalLocked value is used in boost calculations through _updateBoostState():
Alice locks 1000 RAAC tokens - totalLocked = 1000
Bob locks 2000 RAAC tokens - totalLocked = 3000
Alice's lock expires and she withdraws - totalLocked remains at 3000 instead of decreasing to 2000
Future boost calculations will use an incorrectly inflated totalLocked value
The inflated totalLocked value affects boost calculations in the system since the total weight is used as a denominator in boost computations. This results in users receiving lower boost multipliers than they should, as the total locked amount appears larger than it actually is.
Manual code review
Add _lockState.totalLocked -= amount before the delete operations in both withdraw() and emergencyWithdraw() functions:
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.