ShareClassGovernor
Inherits: StartupGovernor, ProposalGovernor, IShareClassGovernor
Author: Daniel Yamagata
A governance contract that enables the execution of arbitrary transactions by a super-majority of a treasury's signers. However, the management of the treasury's board members requires a proposal proccess. A preferred share class can be allocated control of up to three board seats, while the common shares do not have a limit on the number of seats that can be allocated. Once allocated, seats cannot be decreased. For example, if Preferred Shares Class A is allocated control over 2 board seats, its allocation cannot be decreased to 1 board seat. The allocation of seats is done directly by the board of directors. However, the assignment of the allocated board seats is left to the proposal process.
The following contract is heavily based on OZ's Governor Upgradeable, the Late Stage governor, and the Startup Governor The primary difference is proposals are fragmented by share classes. Therefore, direct inheritance from OZ's governor was not possible
State Variables
BALLOT_TYPEHASH
EXTENDED_BALLOT_TYPEHASH
ShareClassGovernorStorageLocation
Functions
_getShareClassGovernorStorage
constructor
init
Intializes the Governor's state
Parameters
Name | Type | Description |
---|---|---|
|
| The address of the Treasury that the Governor is in charge of |
|
|
__ShareClassGovernor_init
The 'params' argument is maintained in case future versions require additional initialization parameters
state
Returns the state of a proposal associated with 'proposalId' as a ProposalState enum
increaseBoardSeatsForShareClass
Increases the board seats for a given share class.
This function should be called with caution: the number of board seats for a given share class cannot be decreased. Only callable by governance, itself.
Parameters
Name | Type | Description |
---|---|---|
|
| The share class to increase the allocated board seats for |
|
| The amount to increase the allocated board seats by |
proposeBoardMemberChange
Proposes a board member change for a given 'shareClass'. The 'action' must be releated to adding a board member, removing a board member, or swapping a board member.
If the threshold is n, where n is the total number of board members, the new threshold will be n - 1. Otherwise, the threshold of the treasury will not change. The 'action' needs to be one that manages the owners of a team. These are defined in _validateAction(...)
Parameters
Name | Type | Description |
---|---|---|
|
| The share class to propose a board member change for |
|
| The action for managing the treasury's owners |
|
| The abi.encoded parameters for the given 'action' |
|
| The description of the proposal |
Returns
Name | Type | Description |
---|---|---|
|
| The proposal ID |
cancelProposal
Cancels a pending proposal for 'shareClass'.
The caller must be the Proposal's proposer or the Mezz Hub's owner. The params are solely used to re-create the proposal's ID
Returns
Name | Type | Description |
---|---|---|
|
| The proposal ID |
executeProposal
Executes a proposal that succeeded.
The caller is not access controlled. However, the proposal must have succeeded and cannot have been executed To succeed, the proposal's for-votes must have reached the quorum and must exceed its against votes. Unless the proposal, has a super-majority, which is 75% in this case, of the votes, it will only be executable once the votiing period has passed. The params and actions are re-validated. The 'target' will also be the treasury
executeTx
Same as StartupGovernor's executeTx(...) except with further data validation. Specifically, the management of the treasury's owners and its threshold are disabled. To change these, the proposal process is required.
changeTreasuryThreshold
Changes the Treasury's security threshold. Must be called by the governor, itself.
Meant to be called via the Share Class Governor's executeTx()
Parameters
Name | Type | Description |
---|---|---|
|
| The new threshold for the treasury |
getVotes
Returns the number of votes for an 'account' given a 'shareClass' and 'timepoint'
_getVotes
Non-adjusted for voting weight, since all proposals are separated by share classes
quorum
Returns the nominal quorum for a proposal given a 'shareClass' and 'timepoint'. The nominal quorum is the minimum number of for-votes that a proposal needs to succeed It is based off the quorum percentage, which is set by governance, itself
_quorum
proposalThreshold
Returns the nominal proposal threshold given a 'shareClass' The nominal proposal threshold is the minimum number of votes that the sender must have for a proposal to be created It is based off the proposal threshold percentage, which is set by governance, itself
_proposalThreshold
superMajority
Returns the nominal super majority given a 'shareClass' and 'timepoint' A super majority in this context is 75% of the total votes for a share class. It a proposal has >75% of for-votes of the outstanding total votes, it is able to skip the voting period and be executed immediately
_superMajority
_castVote
'params' are unused outside of event emission
hashProposal
Returns the hash of a proposal given a 'shareClass', 'action', 'params', and 'descriptionHash' All of the aforementioned argumetns can be found via events emitted by the Share Class Governor for existing proposals
Returns
Name | Type | Description |
---|---|---|
|
| The proposal ID as a uint256 |
proposalSnapshot
Returns a proposal's snapshot, which is the time at which votes are counted. Any votes accumulated past this point are not counted towards the proposal
The snapshot is set during the proposal's and is the sum of the voting delay and block.timestamp
Parameters
Name | Type | Description |
---|---|---|
|
| The ID of the proposal |
Returns
Name | Type | Description |
---|---|---|
|
| The snapshot of the proposal, which is measured in seconds from the Unix epoch |
proposalDeadline
Returns a proposal's deadline, which is the time at which the proposal can no longer be voted on
The deadline is set during the proposal's creation and is the sum of the voting delay, voting period, and block.timestamp
Parameters
Name | Type | Description |
---|---|---|
|
| The ID of the proposal |
Returns
Name | Type | Description |
---|---|---|
|
| The deadline of the proposal, which is measured in seconds from the Unix epoch |
proposalProposer
Returns the proposer of a proposal
Returns
Name | Type | Description |
---|---|---|
|
| The address of the proposer |
proposalShareClass
Returns the share class associated with a proposal
Parameters
Name | Type | Description |
---|---|---|
|
| The ID of the proposal |
Returns
Name | Type | Description |
---|---|---|
|
| The address of the share class |
allocatedBoardSeats
Returns the total number of allocated board seats across all share classes
This does not include the board seats that have been set. For example, company Foo can have 5 allocated seats yet only 4 members set
_allocatedBoardSeats
getAllocatedSeatsByShareClass
Returns the number of allocated board seats for a given share class
getBoardMembersByShareClass
Returns the board members that have been set by a given share class
coreId
Returns the coreId of the implementation as a bytes32
The core ID is the keccak256 hash of the contract name followed by a version under the following syntax: "mezzanine.coreId.ContractName.vX" For example, the core ID of the 2nd version of the Treasury would be the following: keccak256(abi.encodePacked("mezzanine.coreId.Treasury.v2"))
version
Returns the version of the implementation as a uint256
COUNTING_MODE
Returns a URL-encoded sequence of key-value pairs that each describe one aspect of voting
Mezzanine Proposal Governors use votes in line with Bravo. The quorum also only counts for votes, like in Bravo. Reference: https://docs.openzeppelin.com/contracts/4.x/api/governance#IGovernor-COUNTING_MODE--
Returns
Name | Type | Description |
---|---|---|
|
| The URL-encoded sequence of key-value pairs |
_updateBoardMembers
Updates state. Also reconstructs the params for a given proposal such that it includes the Treasury's threshold, if needed
Returns
Name | Type | Description |
---|---|---|
|
| The calldata for the execution of the transaction |
_addOwnerForShareClass
Adds 'ownerToAdd' to the board members for 'shareClass'
_removeOwnerForShareClass
Removes 'ownerToRemove' from the board members for 'shareClass'
_checkInvariants
Reverts if the Treasury's total number of owners is greater than the allocated number of board seats
_validateShareClass
Reverts if 'shareClass' is not tracked by 'treasuryCache'
_validateAction
Validates that an action to manage the Treasury's owners. Unlike in TeamLogic's manageOwners(), the params for adding an owner and removing an owner do not include arguments to change the threshold for the treasury. This is to prevent a malicious proposal by a preferred share class that adds or switches an owner and then changes the threshold to 1. This would effectively enable them to control the treasury without the consent of the other signers. The threshold param is reconstructed in _updateBoardMembers(...) to include the Treasury's current threshold. If the threshold is the same as the number of owners, then the threshold is decreased by 1
_encodeStateBitmap
_getTotalVotesAtTimepoint
Returns the past total votes for the 'shareClass' at timepoint. The voting weight of the shares is ignored
_superMajorityReached
Returns whether or not a super majority has been reached for a given proposal. Only for-votes are counted towards the super majority
Returns
Name | Type | Description |
---|---|---|
|
| True if the for-votes are greater than the super majority, false otherwise |
_quorumReached
Returns whether or not the quourum has been reached for a given proposal. Only for-votes are counted towards the quorum
Returns
Name | Type | Description |
---|---|---|
|
| True if the for votes are greater than the quorum, false otherwise |
supportsInterface
ERC165 support
Structs
ShareClassGovernorStorage
Last updated