Due to how the veFXS contract works, if you lock more FXS or increase the duration of your lock, you have to delegate your voting weight again using the
VeFxsVotingDelegationcontract. To delegate back to yourself, call the
delegate()function with your address as the delegatee.
Delegations can also be done by signature. See
When your veFXS lock expires, your balance is equal to the amount of FXS you locked. In Frax Governance, as soon as your lock expires your voting weight goes to 0. You need to have an active lock to have voting weight in Frax Governance.
- 2.Click Propose
- 3.Make sure your voting weight is above the proposal threshold
- 4.Fill out your transaction data
This allows for users to split their voting power between for/against/abstain. It also allows smart contracts/custodians to pass through the voting power to liquidity providers based on their relative LP stake.
For a Safe to be properly configured for frxGov, it must have the FraxGuard installed, have FraxGovernorOmega as a signer, have FraxGovernorAlpha’s TimelockController installed as a module, and have FraxCompatibilityFallbackHandler set as the fallbackHandler. Safes can be sunset similarly through Alpha proposals by removing the configuration and removing them from the allowlist.
FraxGovernorOmega and FraxGovernorAlpha uses OpenZeppelin Governor and the following extensions:
In addition, Alpha uses these Governor extensions:
See their configuration here:
All of the following functions must be called from an Alpha proposal.
Alpha and Omega:
See the frxGov codebase for explanation of each of these functions.
See the Gnosis Safe codebase for Safe configuration that Alpha controls.
Identical to OpenZeppelin Governor with GovernorTimelockControl.
- Create proposal -
- Vote -
- If fails do nothing
- If succeeds
- Wait Timelock's
- 1.An owner uses the Gnosis Safe to initiate a DeFi transaction. This produces a transaction hash that identifies the action to be approved or rejected by the other Safe owners.
- 2.⅗ EOA sign the transaction through the UI
- 3.After 3 signatures are collected, anyone can call
fraxGovernorOmega.addTransaction(address teamSafe, TxHashArgs calldata args, bytes calldata signatures)to begin onchain governance. The team is incentivized to do so because they cannot execute any Gnosis transaction without FraxGovernorOmega’s approval.
- 4.veFXS voters have a 2-day window of time to vote on the proposal.
- 5.If no quorum is met during the voting window, or there are more for than against votes on the proposal, anyone can call
execute(). This calls
safe.approveHash()from Omega under the hood. It provides the needed approval from FraxGovernorOmega, which will allow the gnosis transaction to be executed through the Gnosis UI.
- 1.If quorum is met and there are more against than for votes. The proposal gets vetoed by anyone calling
fraxGovernorOmega.rejectTransaction (address teamSafe, uint256 nonce). This will cause FraxGovernorOmega to sign a zero ETH transfer Safe transaction with the same nonce. Safe owners can then sign the same transaction in the UI using the “replace transaction” functionality. Safe owners can then execute the zero ETH transfer, incrementing the nonce. The original transaction can never be executed, because there is no approval from FraxGovernorOmega and the nonce has moved on, invalidating the original transaction.
Gnosis Safes can provide smart contract signatures. The typical mechanism is contained in Safe’s CompatibilityFallbackHandler, which checks if the threshold number of signatures is met from the owners, and then the Safe provides its approval. This mechanism was not sufficient for frxGov because we want Omega + owners to provide approval OR Alpha alone to provide approval.
To solve this we wrote FraxCompatibilityFallbackHandler, which only checks if
safe.signedMessages(messageHash)is set. Alpha and Omega can both call the setter of this state using
FraxGovernorAlpha could be used to create a proposal that essentially shuts down the entire Frax protocol and returns all protocol owned liquidity to FXS holders. We have the Timelock delay on Alpha for situations like this. It will take a day from when this proposal passes to when it can be executed, giving Frax users time to exit the protocol via various liquidity pools. We also added in the OpenZeppelin Governor extension GovernorPreventLateQuorum. If a proposal reaches quorum late in the voting period, the voting period will get extended by 2 days. This stops malicious user(s) from voting for a malicious proposal at the last second. It gives time for the community to react in such a scenario.
We also created the frxEth redemption queue to allow users to exit frxEth if a malicious actor gets 51% of veFXS voting power and passes a proposal to infinite mint frxEth in an attempt to steal the treasury.
To conform to the ERC5805 standard, an implementing contract must implement several functions including function
getPastTotalSupply(uint256 timepoint) external view returns (uint256). We use timestamps throughout our Governor contracts, however this function is the one exception and it must accept a
veFXS.totalSupply(timestamp)doesn't work for historical values, so we must use
This also impacts quorum values. Typically quorum is calculated from voting start timestamp (snapshot). We allow similar functionality by making the
$votingDelayBlocksvalue configurable by governance, so it mirrors the timestamp functionality.