The veRAACToken contract allows users to lock RAAC tokens for voting power. However, if a user is not whitelisted, the tax deduction mechanism in RAACToken causes fewer tokens to be transferred to the contract than expected. This discrepancy is not accounted for in the lock state, leading to a situation where the contract tracks a higher locked balance than the actual RAAC tokens it holds.
As a result:
Early users can withdraw successfully.
Later users will experience transaction failures due to insufficient contract balance.
The contract eventually runs out of RAAC tokens, causing irreversible loss for users.
When a user calls lock() or increase(), the amount of RAAC tokens to lock or increase is transferred to the contract:
veRAACToken.sol#L220
veRAACToken.sol#L269
If either the user or veRAACToken contract is not whitelisted, the overridden _update() in RAACToken applies a swap and burn tax before transferring the tokens:
As a matter of fact, the contract receives less than the intended amount:
However, the stored lock amount remains the full amount, causing a discrepancy between the stored balance and the actual token balance. As evidenced from the code logic below, _lockState.createLock() and _lockState.increaseLock() store the full amount without deducting the tax:
In the end, when withdraw() is called, the function tries to transfer the full stored amount back as retrieved from userLock.amount:
Since the contract does not actually have this amount, the transaction will succeed because the contract still has RAAC tokens. As more users withdraw, the contract’s RAAC balance depletes. At some point, a user will try to withdraw, but the contract won’t have enough RAAC left, causing the transaction to revert.
Users who withdraw early after lock periods get their full amount. Users who withdraw late get nothing because the contract runs out of RAAC. There is no mechanism to recover the lost tokens unless an admin manually replenishes the contract at the protocol's expense.
When emergencyWithdraw() is enabled, users will rush to withdraw their locked RAAC, and since withdrawals operate on a first-come, first-served basis, the contract’s balance will rapidly deplete.
Manual
Consider enforcing only whitelisted users can call lock:
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.