Skip to content
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

Decentralised governance of 0x protocol and treasury #641

Merged
merged 106 commits into from
Mar 22, 2023

Conversation

elenadimitrova
Copy link
Collaborator

@elenadimitrova elenadimitrova commented Jan 14, 2023

Description

Decentralises governance of 0x Protocol and Treasury. This is enabled via a wrapped ZRX token and a Compound-like governors design. There are two separate governors for Protocol - ZeroExProtocolGovernor and Treasury - ZeroExTreasuryGovernor respectively working with two separate Timelock instances of the same contract implementation - ZeroExTimelock.

Upgradability

ZRXWrappedToken , ZeroExProtocolGovernor and ZeroExTreasuryGovernor governors are non-upgradable by design. However the voting implementation the governors use - ZeroExVotes is upgradable and using the OZ ERC1967Proxy.

Wrapped ZRX

wZRX will be issued 1-to-1 for ZRX. No locking/vesting mechanisms will exist between wZRX and ZRX and the two will be freely interchangeable. The ZRX token is non-upgradable and same will be valid for its wrapped equivalent.

The token supports delegation which allows a user to delegate their entire voting power to another account (which doesn't necessarily need to be a token holder). This is modelled on the standard openzeppelin ERC20Votes implementation. We have added logic for block number stamping delegators' balance changes stored in the DelegateInfo.balanceLastUpdated property. This block number information is sent in calls to ZeroExVotes.moveVotingPower in order to provide support for future upgrades to the vote power calculation.
Note that for consistency block.number is used for the governor settings, voting checkpoints and this delegators' balance last updated property while timelock logic for the governor uses block.timestamp.

Governors' settings

Changing governors' settings for votingDelay, votingPeriod and proposalThreshold can be done via the normal proposal mechanism. Governors are deployed with the following initial settings:

voting delay voting period proposal threshold
Protocol governor 2 days 7 days 1000000e18
Treasury governor 2 days 7 days 250000e18

This is using standard openzeppelin GovernorSettings implementation.

Quorum

Quorum for Protocol is fixed at 10m (10000000e18) while for Treasury this is calculated as 10% of voting power of the total supply (see voting strategies below for quadratic voting power implementation specifics). The quorum calculations for Treasury are using openzeppelin's GovernorVotesQuorumFraction.

Note that in-place updates to the quorum are not supported and will need to go through a governance upgrade. Reasoning behind this can be found in this discussion https://forum.openzeppelin.com/t/quorum-default-behaviour-on-governors/34560.

Voting strategies

The voting strategy will be linear 1-token-1-vote for Protocol and quadratic with threshold of 1000000e18 for Treasury (i.e. voting weight is linear up to 1m tokens and balance above that threshold is quadratic).

Worth noting is the Checkpoint struct design. For packing every Checkpoint into a single storage slot we are using the minimum uint type size for votes and quadraticVotes members, e.g.

struct Checkpoint {
        uint32 fromBlock;
        uint96 votes;
        uint96 quadraticVotes;
    }

since the maximum token supply is 1bn we can have maximum value for:
votes : 1bn *10^18 => can be stored in 90 bits
quadraticVotes : due to the likelihood of threshold changing and potentially bringing it closer to a linear vote, we are preemptively keeping this to the same size as linear votes slot.

Time locks

Governance proposals are subject to a 3 days delay for Protocol and 2 days for Treasury. This delay allows Security Council time to review passed proposals and take action where needed.

Security Council

The concept of a Security council is introduced which allows a multisig of security council members to cancel a proposal on the treasury or protocol governors and also rollback the protocol to an earlier version.

When no security council is assigned the following apply:

  • ongoing proposals can still be voted on
  • new proposals cannot be created - except assignSecurityCouncil
  • expired proposals that are successful cannot be queued - excepted assignSecurityCouncil

There is a provision for the governors to have different security council set although initially these are expected to be the same.

Related design discussions
Quadratic voting implementation https://forum.openzeppelin.com/t/quadratic-voting/34580
Governor administering another governor's settings https://forum.openzeppelin.com/t/governor-governing-another-governor-pattern/34683

Closes https://linear.app/0xproject/issue/GOV-62/contracts-implementation

@elenadimitrova elenadimitrova self-assigned this Jan 14, 2023
@elenadimitrova elenadimitrova force-pushed the feature/governance branch 4 times, most recently from ef119ee to 9c96569 Compare January 19, 2023 13:30
@elenadimitrova elenadimitrova force-pushed the feature/governance branch 2 times, most recently from 9ea5310 to 31c3f5e Compare January 24, 2023 13:22
@elenadimitrova elenadimitrova force-pushed the feature/governance branch 2 times, most recently from 56a4436 to 9ec364e Compare February 1, 2023 13:01
contracts/governance/src/IZeroExVotes.sol Outdated Show resolved Hide resolved
contracts/governance/src/IZeroExVotes.sol Outdated Show resolved Hide resolved
contracts/governance/src/ZeroExVotes.sol Outdated Show resolved Hide resolved
contracts/governance/foundry.toml Show resolved Hide resolved
contracts/governance/src/ZeroExVotes.sol Outdated Show resolved Hide resolved
contracts/governance/src/ZeroExVotes.sol Outdated Show resolved Hide resolved
contracts/governance/src/ZeroExVotes.sol Outdated Show resolved Hide resolved
contracts/governance/test/BaseTest.t.sol Outdated Show resolved Hide resolved
@elenadimitrova elenadimitrova force-pushed the feature/governance branch 4 times, most recently from c83d66d to 75cacdc Compare February 7, 2023 16:00
@gabririgo
Copy link

I would like to propose the following suggestion: a proposal that has already reached final status during voting period, i.e. that has reached quorum and > 2/3 of all voting power (in the context of this project 2/3 of WZRX total supply) should be executable during from the block after the one where final status has been reached. This is particularly relevant for protocol bugfixes, as those should reach quick consensus and be pushed forward as soon as possible.

@elenadimitrova elenadimitrova force-pushed the feature/governance branch 6 times, most recently from e2a2e89 to bdba015 Compare February 14, 2023 08:48
@elenadimitrova elenadimitrova requested review from duncancmt and SHA-2048 and removed request for dextracker and SHA-2048 March 14, 2023 12:22
elenadimitrova and others added 12 commits March 20, 2023 20:19
without "memory-safe" the IR optimizer produces significantly worse code and it disables the stack limit evader

Co-authored-by: duncancmt <1207590+duncancmt@users.noreply.github.com>
* Make addresses immutable

* Fix linting issues

---------

Co-authored-by: elenadimitrova <elena@arenabg.com>
* Gas optimization

* Minimal change to prevent malicious ZeroExVotes from griefing

* Add demonstration of griefing upgrade

* Fix rebase issues with tests

* Fix prettier issues

* Add checks to test

---------

Co-authored-by: elenadimitrova <elena@arenabg.com>
elenadimitrova and others added 3 commits March 21, 2023 18:27
* Add Emacs files to .gitignore

* Make some functions unproected to demonstrate a migration

* Add example (broken) migration

* Add migration test for voting logic

* Try to simplify tests

* Fix compilation errors

* Fix underflow test with new logic

* Flesh out migration test for voting

* Replace cube root library

* Fix stack too deep in coverage

---------

Co-authored-by: elenadimitrova <elena@arenabg.com>
Co-authored-by: duncancmt <1207590+duncancmt@users.noreply.github.com>
Copy link
Collaborator

@duncancmt duncancmt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My concerns have been addressed. Due to how the branch protection rules are set up (and how I can't change them), we'll be merging this PR as a code freeze for audit. Subsequent integration tests and any fixes suggested by auditors will go in a separate PR

@elenadimitrova elenadimitrova merged commit bcbfbfa into development Mar 22, 2023
@elenadimitrova elenadimitrova deleted the feature/governance branch March 22, 2023 13:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants