Users who wish to vote on proposals must lock RAACTokens for a specified duration to receive veRAACTokens. However, if the token lock duration expires before the proposal ends, users may exploit this to double vote.
If the duration of locked RAACTokens expires before the proposal duration, a user can transfer their RAACTokens to another address, lock them again, receive new veRAACTokens, and vote a second time on the same proposal. This effectively allows vote twice based on the same RAACTokens.
Users can vote twice times on a single proposal using the same RAACTokens.
Consider the following scenario:
Bob locks RAACTokens for the minimum lock duration of 365 days.
After 360 days, Bob's lock duration has only 5 days remaining.
A new proposal is opened with a duration of 4 weeks.
Bob votes on the proposal using his veRAACTokens.
After 1 week, Bob's lock duration expires, allowing him to transfer his RAACTokens to another address.
The second address locks the same RAACTokens, receives veRAACTokens, and votes again on the same proposal.
This creates a scenario where a single set of RAACTokens is used to vote twice
Manual review
To prevent this exploit, implement a check to ensure that users cannot vote if their RAACToken lock duration in veRAACToken.sol expires before the proposal ends.
A potential fix is to use veRAACToken.sol::getLockEndTime() to retrieve the lock expiration timestamp and validate it against the proposal’s end time. The following check can be added to Governance.sol::castVote():
Implementing this check will ensure that users can only vote if their locked tokens remain valid for the entire proposal duration, preventing double voting exploits.
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.