The veRAACToken::lock function has no limit to how many times it can be called. When a user calls it each subsequent time, the users' Lock gets overridden. When they call the withdraw function after the duration, they lose all of their previous locked amount.
The veRAACToken contract contains a critical vulnerability in its lock mechanism that leads to permanent token loss when users create multiple lock positions. The core issue lies in how the contract handles subsequent calls to the lock() function:
When a user calls lock() for the second time, the following occurs:
The previous lock position is overwritten in the lock mapping
The record of the initially locked tokens is lost
The tokens from the first lock remain in the contract but become irretrievable
Example scenario demonstrating the vulnerability:
Bob calls the lock function with 500 tokens for 400 days
Lock state: amount = 500, end = timestamp + 400 days
After some time passes Bob calls the lock function again with 300 tokens, for 750 days
Lock state: amount = 300, end = timestamp + 750 days
When the 750 days pass, Bob calls the withdraw function which only withdraws the 300 tokens and the previous 500 tokens are permanently locked, because of the state overriding.
The user loses all of his previous locked amounts
This test demonstrates the scenario in Vulnerability Details.
Foundry Test Used:
Manual Review, Foundry Test
Make sure users can call the lock function only when their previous lock has expired and they have withdrawn their tokens.
Add a mapping tracking if a user has an active 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.