Eco Governance Proposal #001
This post briefly summarizes the Eco Governance Proposal submitted on Nov 13th, 2022 and enacted on Nov 17th, 2022 during the second Eco Generation. Due to the details of the vulnerabilities, this post was published after the proposal had already been enacted.
Summary
Two bugs were discovered through Immunefi bug bounty submissions:
- When using
delegateAmount
on an attacker address who has (or later sets) a primary delegate, the attacker could self transfer to cause the voting power given bydelegateAmount
to be transferred to the primary delegate. This not only violated the principles of delegation, but disallowed the victim from callingundelegate
in any form, leaving the amount untransferable. The offending code was in_afterTokenTransfer
inVoteCheckpoints.sol
which used_balances[from] + amount
to calculate the pre-transfer balance offrom
.
This issue was fixed by an early exit of _afterTokenTransfer
on self transfers as there would be no need to re-calculate delegation. We acknowledge that this would allow a user to self transfer funds that would not be transferrable to any other address (in the case of them being locked by using delegateAmount
), but would have no further effect on the system.
- If an attacker is able to atomically call the
incrementGeneration
call, they would have access to the new clone ofPolicyProposals.sol
for that generation in a block that was equal toblockNumber
where the voting power is measured. This would allow the user to submit a proposal, support it, transfer tokens to another address, and then support it again with the same tokens. This process could be extended as far as gas and contract size limits would allow for the sandwich transaction. This attack is detailed in the test contractInfiniteVote.sol
.
This issue was fixed by restricting the voting calculation. Two offending functions created this vulnerability: getPastVotingGons
and getPastTotalSupply
. These functions are used in VotingPower.sol
to determine voting power during the community governance process. They were changed to respect their respective names and require the block submitted to be strictly before the current block. This means that any attempts to perform the exploit above will fail in the calculation of the addresses’s voting power. If someone did want to see voting power for the current block, they could use getVotingGons
or totalSupply
. Note that getPastLinearInflation
was not changed in this update, as it did not have a corresponding function for the current block and therefore is used in a number of places to access the amount of linear inflation in the current block.
Additionally the ECOxStaking contract was proxied to allow for easy upgradeability.
Status: Resolved
These issues were addressed in generation 1002 via the proposal VoteCheckpointsUpgrade.propo.sol
whose deployment can be found here . The PR for updating the codebase with this fix can be found here. The proposal can also be seen in Eco Community Governance Interface linked here.