Skip to content

Commit

Permalink
Multisig only DAO Factory flow
Browse files Browse the repository at this point in the history
  • Loading branch information
brickpop committed Oct 14, 2024
1 parent abc26c6 commit 0e76c9c
Show file tree
Hide file tree
Showing 57 changed files with 33 additions and 12,001 deletions.
74 changes: 10 additions & 64 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,75 +1,21 @@
# Fork Test mode:
# "fork-deploy" will run against the live network fork, deploying new contracts via a new instance of the factory
# "fork-existing" will run against the live network fork, using the existing factory & therefore the existing contracts
FORK_TEST_MODE="fork-deploy"

# With false, the script will deploy mock tokens with open mint functions
DEPLOY_AS_PRODUCTION=false

# If deploying against a fork, pass the address of a large token holder who will be
# impersonated to distribute tokens to addresses inside test cases
# the whale should have >= 3000 tokens
TOKEN_TEST_WHALE="0x"

# If the factory singleton is deployed, pass the address. "Fork existing" mode will use this previously
# deployed factory, and "fork deploy" will deploy a new factory instance
FACTORY="0x0000000000000000000000000000000000000000"

# NETWORK AND DEPLOYMENT WALLET
DEPLOYMENT_PRIVATE_KEY="..."
DEPLOYMENT_PRIVATE_KEY="..." # tbd
ALCHEMY_API_KEY="..."
ETHERSCAN_API_KEY="..." # tbd
NETWORK="sepolia"

# API Keys (optional)
# Note that having these active will slow down unit tests even when not needed
# So recommended to only activate when needed
# ETHERSCAN_API_KEY="..."
# ALCHEMY_API_KEY="..."

MULTISIG_MEMBERS_JSON_FILE_NAME="/script/multisig-members.json"

# MULTISIG PARAMETERS
# define a list of multisig members - said multisig will be assigned administrator roles of the ve contracts
MULTISIG_MEMBERS_JSON_FILE_NAME="/script/multisig-members.json"
MIN_APPROVALS="1" # How many multisig approvals are required
MIN_APPROVALS="3" # How many multisig approvals are required
MULTISIG_PROPOSAL_EXPIRATION_PERIOD="864000" # How long until a pending proposal expires (10 days)

# GAUGE VOTER PARAMETERS
# The token to be used for the escrow
TOKEN1_ADDRESS="0x0000000000000000000000000000000000000000"
VE_TOKEN1_NAME="Voting Escrow Token 1"
VE_TOKEN1_SYMBOL="veTK1"

# Additional tokens these will have secondary escrow contracts
TOKEN2_ADDRESS="0x0000000000000000000000000000000000000000" # Ignored if 0x0
VE_TOKEN2_NAME="Voting Escrow Token 2"
VE_TOKEN2_SYMBOL="veTK2"

# 10_000 = 100%
FEE_PERCENT="0"

# Min seconds after depositing before voting is possible
WARMUP_PERIOD="259200" # 3 days

# Min seconds after queuing an exit before withdrawing is possible
COOLDOWN_PERIOD="259200" # 3 days

# Min seconds a user must have locked in escrow before they can queue an exit
MIN_LOCK_DURATION="3600" # 1 hour

# Prevent voting until manually activated by the multisig
VOTING_PAUSED=true

# Initial minimum amount needed (in wei) to create a lock
MIN_DEPOSIT="1000000000000000000" # 1 ether

# PLUGIN REPO PARAMETERS (per-network)
# SEPOLIA
MULTISIG_PLUGIN_REPO_ADDRESS="0x9e7956C8758470dE159481e5DD0d08F8B59217A2"

# Ethereum
MULTISIG_PLUGIN_REPO_ADDRESS="0x8c278e37D0817210E18A7958524b7D0a1fAA6F7b"
MULTISIG_PLUGIN_RELEASE="1"
MULTISIG_PLUGIN_BUILD="2"
SIMPLE_GAUGE_VOTER_REPO_ENS_SUBDOMAIN="my-simple-gauge-voter-0"

# OSx IMPLEMENTATIONS ADDRESSES (network dependent, see active_contracts.json on lib/osx)
# SEPOLIA
DAO_FACTORY="0x7a62da7B56fB3bfCdF70E900787010Bc4c9Ca42e"
PLUGIN_SETUP_PROCESSOR="0xC24188a73dc09aA7C721f96Ad8857B469C01dC9f"
PLUGIN_REPO_FACTORY="0x07f49c49Ce2A99CF7C28F66673d406386BDD8Ff4"
DAO_FACTORY="0xf96e6FD76BD0A15580604e1Ea5818D448b1041C0"
PLUGIN_SETUP_PROCESSOR="0xE978942c691e43f65c1B7c7F8f1dc8cDF061B13f"
118 changes: 15 additions & 103 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,6 @@ make coverage
make ft-sepolia-fork
```

## Running fork tests

Fork testing has 2 modes:

1. "fork-deploy" will run against the live network fork, deploying new contracts via a new instance of the factory

2. "fork-existing" will run against the live network fork, using the existing factory & therefore the existing contracts

In both cases, you will need to find the correct Aragon OSx contracts for the chain you wish to fork against. These can be found in the [OSx commons repo](https://github.com/aragon/osx-commons/tree/main/configs/src/deployments/json)

> If running frequent fork tests it's recommended you pass a block number to enable caching
## Deployment

Deployments are done using the deployment factory. This is a singleton contract that will:
Expand All @@ -69,26 +57,17 @@ Deployments are done using the deployment factory. This is a singleton contract
- Transfer ownership to a freshly deployed multisig
- Store the addresses of the deployment in a single, queriable place.

Check the `Makefile` for examples of deployments on different networks.

### Deployment Checklist

- [x] I have reviewed the parameters for the veDAO I want to deploy
- [x] I have reviewed the multisig file for the correct addresses
- [x] I have ensured all multisig members have undergone a proper security review and are aware of the security implications of being on said multisig
- [x] I have updated the `.env` with these parameters
- [x] I have updated the `CurveConstantLib` and `Clock` with any new constants.
- [x] All my unit tests pass
- [x] I have run a fork test in `fork-deploy` mode against the OSx contracts on my target testnet
- [x] I have deployed my contracts successfully to a target testnet
- [x] I have previewed my deploy
- [x] My deployer address is a fresh wallet or setup for repeat production deploys in a safe manner.
- [x] My wallet has sufficient native token for gas
- [] I have confirmed my tests still work in `fork-existing` mode with the live tokens and the factory.

**Puffer Only**

- [] I have deployed the Router contract
- [ ] I have reviewed the parameters for the veDAO I want to deploy
- [ ] I have reviewed the multisig file for the correct addresses
- [ ] I have ensured all multisig members have undergone a proper security review and are aware of the security implications of being on said multisig
- [ ] I have updated the `.env` with these parameters
- [ ] I have reviewed the deployment script and the Factory contract
- [ ] I have deployed my contracts successfully to a target testnet
- [ ] I have previewed my deploy
- [ ] My deployer address is a fresh wallet or setup for repeat production deploys in a safe manner.
- [ ] My wallet has sufficient native token for gas

### Manual from the command line

Expand All @@ -99,24 +78,19 @@ You can of course run all commands from the command line:
source .env
```

```sh
# run unit tests
forge test --no-match-path "test/fork/**/*.sol"
```

```sh
# Set the right RPC URL
RPC_URL="https://eth-sepolia.g.alchemy.com/v2/${ALCHEMY_API_KEY}"
RPC_URL="https://mainnet.mode.network"
```

```sh
# Run the deployment script
# Check the deployment script
make deploy-preview-mode

# If using Etherscan
forge script --chain "$NETWORK" script/Deploy.s.sol:Deploy --rpc-url "$RPC_URL" --broadcast --verify
# Run the deployment

# If using BlockScout
forge script --chain "$NETWORK" script/Deploy.s.sol:Deploy --rpc-url "$RPC_URL" --broadcast --verify --verifier blockscout --verifier-url "https://sepolia.explorer.mode.network/api\?"
# forge script --chain "$NETWORK" script/Deploy.s.sol:Deploy --rpc-url "$RPC_URL" --broadcast --verify --verifier blockscout --verifier-url "https://sepolia.explorer.mode.network/api\?"
make deploy-mode
```

If you get the error Failed to get EIP-1559 fees, add `--legacy` to the command:
Expand All @@ -130,65 +104,3 @@ If some contracts fail to verify on Etherscan, retry with this command:
```sh
forge script --chain "$NETWORK" script/Deploy.s.sol:Deploy --rpc-url "$RPC_URL" --verify --legacy --private-key "$DEPLOYMENT_PRIVATE_KEY" --resume
```

## Contracts Overview

The primary contracts in the governance hub are found in the `src` directory. The key contracts include

- `VotingEscrowIncreasing.sol`: ERC721 veNFT designed to be used with escrow systems that reward users for longer lock times.
- `SimpleGaugeVoter.sol`: allows split voting across arbitrary options. Votes are simply registered in the gauge voter, they do not perform any onchain actions

The main workflow in the Mode Governance build is as follows:

## Escrow

- Users lock a whitelisted token into the Escrow Contract.
- The user is minted a veNFT which stores:
- The amount they locked
- The start of their lock - users begin their locks starting from the next deposit interval
- In the base case, this means a user will start their lock from the start of the upcoming week
- The user's voting power increases over time, starting from a baseline of the locked amount, up to a maximum voting power
- The user is unable to vote during an initial "warmup period".
- The user can exit their position at any time. In this case, they are entered into an "Exit Queue", whereupon their NFT is held in the queue for a "cooldown" period of X Days. After the period ends, they can burn the NFT to receieve their underlying balance back.
- It's possible to add a `minLock` period whereby a user is prevented from entering the exit queue before a certain time. This means they have their NFT available to vote but can't enter the exit process.
- Voting power is removed from the NFT at this time
- The exit queue can optionally set an exit fee that will be charged on exit.

## Voting

- Administrators setup voting options on the `SimpleGaugeVoter.sol`, we call these `gauges`.
- Administrators can activate voting at which point a timestamp is recorded. `EpochDurationbLib` tracks 2 week epochs in single week blocks:
- A Voting phase (default is 1 week), where votes are accepted.
- A distribution phase of (default is 1 week), where votes are not accepted (this is done in order to allow governance to compute and allocate rewards).
- Users can vote as much as they want during the voting period.
- Users' NFTs are locked unless they `reset` their votes and remove their voting power.

## Parameterization

- Various elements of these contracts can be parameterised in order to support different ve mechanisms. These include:

- Custom exit queue logic via custom exit queue managers
- Custom escrow curves
- Custom voting contracts other than SimpleGaugeVoter
- Custom epoch clock logic via the `Clock.sol` contract

- Additionally, we use libraries like `CurveCoefficientLib` and `SignedFixedPointMathLib` that allow users to make minimal, consistent and gas-efficient customisations to things like epoch length and curve shapes.

## Rewards

- The current versions of the contracts assume an offchain rewards distribution mechanism.

## Caveats

- This version of the repository defines user-based logic and initial framework for:
- Voting Escrow Lockers w. veNFT functionality
- Voting Escrow Curves
- Exit Queues
- Rewards and emissions are assumed to be offchain
- veNFT transfers are disabled by default in the current implementation, but can be enabled. Fully supporting transfers would require support for allowing for custom transfer logic (resetting voting power) which is as yet not implemented.
- Delegation checkpointing is not yet implemented.
- Total supply is not yet implemented due to complexities in scheduling slope changes for higher order polynomials. We have setup a user-point system where this can be added in the future: please see the linked research below for details.

## Curve design

To build a flexible approach to curve design, we reviewed implementations such as seen in Curve and Aerodrome and attempted to generalise to higher order polynomials [Details on the curve design research can be found here](https://github.com/jordaniza/ve-explainer/blob/main/README.md)
Loading

0 comments on commit 0e76c9c

Please sign in to comment.