-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
GaugeController allows for quick vote and withdraw voting strategy #77
Comments
141345 marked the issue as duplicate of #45 |
141345 marked the issue as not a duplicate |
141345 marked the issue as primary issue |
withdraw() needs to go through locking period. This one does not specifically indicate the |
OpenCoreCH marked the issue as sponsor acknowledged |
OpenCoreCH marked the issue as disagree with severity |
True, but I fail to see why this is a problem in our setup. The only thing that matters is the vote at the epoch end (which is queried within |
Agree with the sponsor. If the warden would like to suggest a different design for the voting system, that would belong in an |
alcueca marked the issue as unsatisfactory: |
alcueca marked issue #45 as primary and marked this issue as a duplicate of 45 |
alcueca marked the issue as selected for report |
From sponsor:
|
this report is open and has selected for report tag, based on this comments above seems like this report can be closed with unsatisfactory tag is correctly applied to this report |
alcueca marked the issue as satisfactory |
alcueca marked the issue as unsatisfactory: |
The |
Lines of code
https://github.com/code-423n4/2023-08-verwa/blob/main/src/GaugeController.sol#L211-L278
Vulnerability details
Impact
The GaugeController voting can be abused to apply all of the user’s weight in every gauge’s vote. GaugeController’s voting changes the weight of the gauges. Each user can split their voting weight power between the gauges. The sum of all the weight used must not exceed 10,000 (this is ensured).
However, there is no incentive to vote early, and no lock to prevent a user from removing their weight after a vote. As a result, an attacker can put 100% of its voting power (10,000) on a gauge’s vote, and remove it right afterwards to re-use all its voting power on another vote.
Proof of Concept
Eve calls vote_for_gauge_weights with a voting power of 10,000 (100%) just before the vote ends.
If the voting ends soon after Eve votes, her weight will have a significant effect for a very short duration. Note that there's a stipulation in the code that the lock end (lock_end) should be greater than next_time (which is roughly the current time rounded to the end of the week). This means Eve should have her tokens locked for a bit longer than a week to even vote.
Once the vote ends, Eve calls vote_for_gauge_weights with a voting power of 0.
In this case, Eve is essentially withdrawing her previously applied voting power. This may reduce the overall influence of her votes, but she's trying to withdraw after the fact, once the vote ends.
The function "vote_for_gauge_weights" checks that the provided _user_weight is in the range [0, 10,000]. This is done via the require statement at the beginning of the function. Each user can split their total power among the gauges. This is reflected in the calculations (slope * _user_weight) / 10_000 which scales the voting power proportionally. There is a mechanism that ensures users don't exceed their allocated voting power, require(power_used >= 0 && power_used <= 10_000, "Used too much power").
However, there's a mechanism to cancel out the effects of old votes. If old_slope.end > block.timestamp, it deducts the old slope values from the changes.
When Eve votes with power 0 after the voting period ends, it might reset her influence on that specific gauge but the results of the voting period would already have been decided by the previous weights.
Tools Used
Manual review + in-house tool
Recommended Mitigation Steps
Voting is always tricky in such scenarios. Maybe two possible solutions work:
Notes
Aragon vote shows the perils of on-chain governance
Assessed type
Invalid Validation
The text was updated successfully, but these errors were encountered: