-
Notifications
You must be signed in to change notification settings - Fork 3
Description
When a proposal is made, it is required for the sending address to have quorum votes for making a proposal, i.e. staked GRG which cannot be unlocked for at least 1 epoch.
An edge-case scenario involves a rogue voter trying to influence the outcome of a vote by waiting for a proposal to be active while at the same time, the staking epoch end time is passed. An attacker would need to borrow and stake enough GRG to gain the majority of voting power, he would call the method endEpoch to activate his stake and vote. While his stake is still locked for at least 1 epoch, he would be able to manipulate the result of voting. When a proposal has the state "Qualified" it is final and such manipulation would not work. Technically, we'd want only votes active prior to the proposal to be accounted for. This can be achieved by making sure that when a proposal is made, the epoch in the staking proxy is finalized. This could be easily done by adding a callback method to the strategy contract and calling it from the proxy when a proposal is made or when a user votes on a proposal. This attack entails a user borrowing a very big amount of GRG, which is not possible at the moment.
Another edge-case scenario is where an attacker borrows enough votes to make a proposal. He makes a proposal to take over the governance and then waits for the epoch to end. He then flash-borrows 2x all current voting power, stakes and ends epoch to activate stake, then votes, and since the proposal state is "Qualified", he can immediately execute the call. His stake is locked, but since he took over the proxy, he can unstake. This can be fixed by ending an epoch when a user votes on a proposal and the epoch end time is passed, by using the same callback as proposed before. Alternatively, the _castVote method could be modified here to set proposal end time at next block (block.timestamp + 1 or block.number + 1) so that it cannot be executed in the same block. This attack assumes a user can flash borrow 2x current active stake, which is not possible currently.