@mahadao/governance

2.0.2 • Public • Published

MahaDAO Governance Contracts

This repository contains the smart-contracts that are responsible for MahaDAO's governance. This includes voting, staking, gauges and pool incentives.

  • Registry.sol: This contract holds the addresses of all the deployed contracts and is referenced by the various components. Etherscan
  • MAHAXLocker.sol: This contract locks MAHA and mints a NFT for every lock. Etherscan
  • MAHAXStaker.sol: This contract tracks votes for every address whenever a user stakes his/her NFT. Etherscan
  • MAHAXGovernor.sol: Openzepplin's governor contract that creates and executes proposals. Etherscan
  • BaseV2Voter.sol: This contract is responsible for tracking votes for every address. Etherscan
  • LockMigrator.sol: A migrator contract with permissions to mint NFTs that match a merkle proof. Etherescan

Deployment Instructions

For deployment to mainnet run the following script.

yarn install
yarn compile
npx hardhat run scripts/mainnet/deploy.ts --network <network>

You'd need to keep a file in the ./deployments/<network>.json folder with all ERC20 token addresses that you'll use. See template.json for a reference on what to start with.

Also keep a .env file with values mentioned in the .env.example file.

Contracts Overview

The governance contracts was built keeping in mind security and upgradability for future robustness of the governance. In this section we describe what each contracts does and if there's any special attention that should be given to it.

Registry.sol

This contract maintains the registry of all contract addresses. It used to allow for an easy way of upgrading the various components of the govenrance. In the unlikely event there is a bug or one of the contract needs to be upgraded, an update to the Registry will update the reference for all the other currently deployed contracts.

The contracts contains functionality to pause governance by an address that has the EMERGENCY_STOP_ROLE role. This is used in the unlikely event that governance itself has been compromised and the protocol needs to wind down.

Source Code - Etherscan

MAHAXLocker.sol

This contract (also called as the locker) locks MAHA and mints a NFT for every lock.

Upon interacting with the locks (minting, burning, extending the lock or increasing the MAHA), a call to the MAHAXStaker contract is made, allowing a user to stake or update his stake in the same transaction itself.

Furthermore, the locker also checks the MAHAXStaker contract to understand if the NFT has staked. If a NFT is staked, then a user:

  • Cannot transfer the NFT
  • Cannot withdraw the underlying MAHA
  • Cannot merge the NFT with another NFT

Calculating MAHAX

Every user that locks their MAHA gets a balance assigned to them. This balance represents their voting power and it decays over time (from a max period of 4 years). The balance is retrived by calling the balanceOf(...) function which calculates using a linear function that takes into account current time, lock duration and lock amount.

The maximum duration a user can lock for is 4 years. There is no upper limit for the amount of MAHA that can be lcoked however there is a minimum amount of 100 MAHAX that a NFT needs to maintain. This can be changed at any time by the governance. Lock expiry times are rounded off by the week and the minimum lock time can be 1 week.

NFTs and Staking

Each MAHA lock is represented as a NFT which is carries the details about the lock such as amount and expiry date. NFTs can be moved around which means a NFT holder that locks their MAHA can also transfer the lock to another wallet by simply transferring their NFT.

NFTs can be staked onto the MAHAXStaker contract which allows the NFT holder to access other utilities such as fees and voting from the protocol.

Emergency Refund

The locker contract contains an emergencyRefund() which is used to refund all the MAHA in the contract in the unlikely event of an emergency. This function can only be called by governance and can be disabled for good by calling the stopBootstrapMode() function which triggers a flag that disables the emergencyRefund() function. In the unlikely event that there is a flaw in the locker's business logic, this function can be called as part of the migration process to a new governance implementation.

The moment there is enough confidence in the contract's business logic, the stopBootstrapMode() can be called by the community and the emergencyRefund() will become disabled permanently.

Considering a modular approach, in an unlikely event that other smart contracts within the governance fails to function, the locker contract should still be able to allow users to withdraw their MAHA once their lock expires without any issues.

Source Code - Etherscan

MAHAXStaker.sol

The main purpose of this contract (also called as the staker contract) is to stake NFTs, calculating voting power and to allow for delegation. It has functions to unstake(...) and stake(...) which can get called by a NFT holder and also a function called _stakeFromLock(..) which is called by the MAHAXLocker.sol whenever (for example) it decides to stake a NFT in the same transaction as minitng a NFT.

When a NFT is staked, the staker contract captures the user's MAHAX balance (or voting power) and records it in the contract. On blockexplorers such as Etherscan, this can be seen as MAHAXvp (short for MAHAX Voting Power).

Whenever a NFT is staked or unstaked, the voting power balance gets updated with whatever is the latest value coming from the locker contract.

Attachments

A user can unstake his NFT at anytime from the staker contract but needs to make sure that the NFT is not attached to any liquidity position within a gauge (called as attachments). This is done so that users who have their liquidity staked and are boosting their yield don't unstake their NFT and share it across to other users who'd like to 'share' the boost.

If in the unlikely event that the attachment calculation becomes prone to errors, governance can always trigger the toggleAttachmentCheck() which disables this check. This keeps the staking contract semi-independent of the activity from the BaseV2Voter.sol contract.

Delegation

The staker contract also supports delegation. Which means that if you staked your NFTs and recieve some voting power, then that voting power can get delegated to another user without giving the ownership of the underlying NFT.

Delegated voting power can be queried using the getVotes(...) function and delegation can be assigned using the delegate(...) function.

Source Code - Etherscan

MAHAXGovernor.sol

The governor contract is responsible for handling votes, creating proposals and executing them via the timelock. It operates using the following parameters.

  • A 4 day voting period
  • A 1 day voting delay
  • A 100,000 MAHAX quorum
  • A 250 MAHAX proposal threshold
  • A 12 day timelock

Source Code - Etherscan

MAHAXVetoGovernor.sol

The governor contract is a special governor responsible mainly for vetoing proposals that are already in the timelock. It operates using the following parameters

  • A 4 day voting period
  • No voting delay (Proposal go live for a vote once they are created)
  • A 150,000 MAHAX quorum
  • A 1,000 MAHAX proposal threshold

Source Code

Readme

Keywords

none

Package Sidebar

Install

npm i @mahadao/governance

Weekly Downloads

0

Version

2.0.2

License

ISC

Unpacked Size

33.5 MB

Total Files

848

Last publish

Collaborators

  • enamakel