From 2012a357fb448d27c5ec98a31810c8db139e37c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8r=E2=88=82=C2=A1?= Date: Fri, 5 Apr 2024 11:32:09 +0200 Subject: [PATCH 1/2] Using Sepolia as the testnet --- .env.example | 4 ++-- packages/contracts/hardhat.config.ts | 10 +++++----- packages/contracts/utils/helpers.ts | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.env.example b/.env.example index e8e7cb0..530e2d8 100644 --- a/.env.example +++ b/.env.example @@ -1,7 +1,7 @@ # GENERAL ## The network used for testing purposes -NETWORK_NAME="mainnet" # ["mainnet", "goerli", "polygon", "polygonMumbai"] +NETWORK_NAME="mainnet" # ["mainnet", "sepolia", "polygon", "polygonMumbai"] # CONTRACTS @@ -28,4 +28,4 @@ GRAPH_KEY="zzzzzzzzzzzz" ## Subgraph SUBGRAPH_NAME="osx" SUBGRAPH_VERSION="alice-debug-1s" -SUBGRAPH_NETWORK_NAME="goerli" # ["mainnet", "goerli", "polygon", "polygonMumbai"] +SUBGRAPH_NETWORK_NAME="sepolia" # ["mainnet", "sepolia", "polygon", "polygonMumbai"] diff --git a/packages/contracts/hardhat.config.ts b/packages/contracts/hardhat.config.ts index c3bb40d..18311a2 100644 --- a/packages/contracts/hardhat.config.ts +++ b/packages/contracts/hardhat.config.ts @@ -22,7 +22,7 @@ if (!process.env.INFURA_API_KEY) { const apiUrls: NetworkNameMapping = { mainnet: 'https://mainnet.infura.io/v3/', - goerli: 'https://goerli.infura.io/v3/', + sepolia: 'https://sepolia.infura.io/v3/', polygon: 'https://polygon-mainnet.infura.io/v3/', polygonMumbai: 'https://polygon-mumbai.infura.io/v3/', baseGoerli: 'https://goerli.base.org', @@ -41,9 +41,9 @@ export const networks: {[index: string]: NetworkUserConfig} = { chainId: 1, url: `${apiUrls.mainnet}${process.env.INFURA_API_KEY}`, }, - goerli: { - chainId: 5, - url: `${apiUrls.goerli}${process.env.INFURA_API_KEY}`, + sepolia: { + chainId: 11155111, + url: `${apiUrls.sepolia}${process.env.INFURA_API_KEY}`, }, polygon: { chainId: 137, @@ -86,7 +86,7 @@ const config: HardhatUserConfig = { etherscan: { apiKey: { mainnet: process.env.ETHERSCAN_API_KEY || '', - goerli: process.env.ETHERSCAN_API_KEY || '', + sepolia: process.env.ETHERSCAN_API_KEY || '', polygon: process.env.POLYGONSCAN_API_KEY || '', polygonMumbai: process.env.POLYGONSCAN_API_KEY || '', baseGoerli: process.env.BASESCAN_API_KEY || '', diff --git a/packages/contracts/utils/helpers.ts b/packages/contracts/utils/helpers.ts index 1f0a9cd..f4552ee 100644 --- a/packages/contracts/utils/helpers.ts +++ b/packages/contracts/utils/helpers.ts @@ -24,7 +24,7 @@ export const osxContracts: ContractList = activeContractsList; export const networkNameMapping: NetworkNameMapping = { mainnet: 'mainnet', - goerli: 'goerli', + sepolia: 'sepolia', polygon: 'polygon', polygonMumbai: 'mumbai', baseGoerli: 'baseGoerli', From f13ca6d0b73e523c6cd05757de1c10e3a1089a77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8r=E2=88=82=C2=A1?= Date: Fri, 5 Apr 2024 18:15:29 +0200 Subject: [PATCH 2/2] Adding custom network deployment and instructions --- .env.example | 18 +-- README.md | 111 ++++++++++++++++++ .../deploy/01_repo/10_create_repo.ts | 24 +++- .../contracts/deploy/02_setup/10_setup.ts | 16 ++- 4 files changed, 154 insertions(+), 15 deletions(-) diff --git a/.env.example b/.env.example index 530e2d8..c572777 100644 --- a/.env.example +++ b/.env.example @@ -1,25 +1,27 @@ # GENERAL ## The network used for testing purposes -NETWORK_NAME="mainnet" # ["mainnet", "sepolia", "polygon", "polygonMumbai"] +NETWORK_NAME="sepolia" # ["mainnet", "sepolia", "polygon", "polygonMumbai"] -# CONTRACTS +# PROTOCOL CONTRACTS + +PLUGIN_REPO_FACTORY_ADDRESS="0xA69347F49dD618cb4577670D0728684AfAa01197" +PLUGIN_SETUP_PROCESSOR_ADDRESS="0xAc7e4fB4a2f58b7EA5516f47b6f804956Faf0134" ## Hex encoded private keys separated by a comma `,`a PRIVATE_KEY="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" # Default hardhat account 0 private key. DON'T USE FOR DEPLOYMENTS -## Infura credentials +## API keys INFURA_API_KEY="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" +ETHERSCAN_API_KEY="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" # Needed for contract verification +POLYGONSCAN_API_KEY="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" +BASESCAN_API_KEY="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" + ## Gas Reporting REPORT_GAS='true' COINMARKETCAP_API_KEY="zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz" -## Block explorers -ETHERSCAN_API_KEY="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" -POLYGONSCAN_API_KEY="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" -BASESCAN_API_KEY="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" - # SUBGRAPH ## The Graph credentials diff --git a/README.md b/README.md index 7f60c1d..aeb3507 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,8 @@ yarn build yarn test ``` +See [Deployment](#deployment) below + ## Overview A Space is composed by a DAO and several plugins installed on it. The [DAO](https://github.com/aragon/osx/blob/develop/packages/contracts/src/core/dao/DAO.sol) contract holds all the assets and rights to act on external components, while plugins are custom, composable, opt-in pieces of logic that can perform certain actions governed by the DAO's permission database. @@ -772,3 +774,112 @@ The plugins from this repo are built on top of many contract primitives from Ara - `minProposerVotingPower` wasn't used The rest of dependencies are imported directly from Aragon or from OpenZeppelin. + +## Deployment + +### On a blockchain supported by Aragon + +If the current contracts are meant to be deployed on a blockchain like Mainnet, Sepolia, Polygon, Base, etc, the only step needed is to define the relevant env vars on `.env` and run the following command: + +```sh +cd packages/contracts +npx hardhat deploy --network +``` + +### On a custom blockchain + +In the case of specific blockchains where OSx support is not officially available, you will need to deploy it first. The high level process looks like: + +0. Prepare a wallet for the whole deployment process +1. Deploy OSx + 1. This will create a Managing DAO, where the deployer wallet can `execute()` actions +2. Deploy the plugins of this project +3. Install the plugin that will control the Managing DAO +4. Revoke the `ROOT_PERMISSION` from the deployment wallet on the DAO + +#### 1) Deploy OSx + +Clone [https://github.com/aragon/osx](the OSx repo) into a separate folder. + +```sh +yarn +cd packages/contracts +yarn build +yarn test +``` + +- Edit the `packages/contracts/hardhat.config.ts` to include the details of your target network. +- Edit the `.env` file to make use of the deployment wallet's private key. + +```sh +npx hardhat deploy --network +``` + +Write down the address of the deployed contracts. The result should look similar to this: + +```json +{ + "managingDAOImplementation": "0x731b7F3d74C9dc25A90af73B960ad51f42481d6c", + "managingDAO": "0x1C57A251B1902656693f689aA69389f2a6f2a432", + "ENSRegistry": "0xE847017f1e18F7bF35b180fD45b4dAC18E81d568", + "PublicResolver": "0xE3B1288048f898A28a78FCf9942E14Cc853fFEF2", + "DAO_ENSSubdomainRegistrar_Implementation": "0xd92C33f309D6e795DCe1980aBc42D3431b0af0e7", + "DAO_ENSSubdomainRegistrar": "0xcf9D94Ddd248694B66D1D445b85ccbE385634Cc8", + "Plugin_ENSSubdomainRegistrar_Implementation": "0x7BC82fCba3521B15792423ac4E6076582235263B", + "Plugin_ENSSubdomainRegistrar": "0xd14C706586c6177d54D201df009b75FB14E8AB5E", + "DAORegistry_Implementation": "0x66a19CC345dAB31dfb6295017819d54dB594DE56", + "DAORegistry": "0x11d3B1B24C19B5672b92CD535d2F1F35C53AC543", + "PluginRepoRegistry_Implementation": "0x38b112318cfd563Fa5de538E7c219bf72F1CcA6a", + "PluginRepoRegistry": "0x9b51505f7bf3A45BC92F6bE269324096abEC0A73", + "PluginRepoFactory": "0xA69347F49dD615cb4577670D0728684AfAa01197", + "PluginSetupProcessor": "0xAc7e4fB4a2158b7EA5516f47b6f804956Faf0134", + "DAOFactory": "0x2d11E9413264e3814C2a21160cBCcb9Dc3C96890" +} +``` + +You are going to need the `PluginRepoFactory`, the `PluginSetupProcessor` and the `managingDAO`. + +#### 2) Deploy your plugins + +On this repository: + +- Edit the `packages/contracts/hardhat.config.ts` to include the details of your target network. +- Edit the `packages/contracts/plugin-setup-params.ts` to define the details of your new plugins + - Make sure that you don't deploy the same plugin repo twice, since this will cause an ENS collision + - In such case, either define a new ENS subdomain or consider running the step 1 again +- Edit the `.env` file + - Define the deployment wallet's private key + - Define the `PLUGIN_REPO_FACTORY_ADDRESS` and the `PLUGIN_SETUP_PROCESSOR_ADDRESS` from the contracts [deployed above](#1-deploy-osx) + +```sh +cd packages/contracts +yarn build +npx hardhat deploy --network +``` + +With this step, the deployment would be technically done. + +However, as the maintainer of the deployment, you are strongly encouraged to configure the Managing DAO such in a way that updates are approved by a group of people. + +#### 3) Install a governance plugin to the Managing DAO + +The Managing DAO is the contract that has the role of managing certain protocol modules, like the Plugin Registry, the DAO registry, etc. In case a new OSx version is available, only that DAO is be able to push upgrades and perform certain management tasks, which makes it a key component. + +The Managing DAO will be created with the following permissions: + +- The Managing DAO holds `ROOT_PERMISSION` on itself +- The deployer address holds `EXECUTE_PERMISSION` on the Managing DAO + +Among the plugins deployed [in the step above](#2-deploy-your-plugins), one of them should be installed to the Managing DAO. + +In your custom script make sure to: + +1. Use the same deployment wallet as before +2. Call `prepareInstallation()` on the Plugin Setup Processor deployed during the [Deploy OSX](#1-deploy-osx) step +3. Call `execute()` on the Managing DAO, with an action that calls `applyInstallation()` on the Plugin Setup Processor + +#### 4) Drop the ROOT permission of the deployer + +In the same custom script as before: + +1. Call `execute()` on the Managing DAO, with an action that calls `revoke(dao, deploymentWalletAddr, ROOT_PERMISSION_ID)` on the DAO itself diff --git a/packages/contracts/deploy/01_repo/10_create_repo.ts b/packages/contracts/deploy/01_repo/10_create_repo.ts index 09a0cc1..dc2731f 100644 --- a/packages/contracts/deploy/01_repo/10_create_repo.ts +++ b/packages/contracts/deploy/01_repo/10_create_repo.ts @@ -30,16 +30,28 @@ async function deployRepo( hre: HardhatRuntimeEnvironment, ensSubdomain: string ) { + const {network} = hre; + let pluginRepoFactoryAddr: string; + + if (!process.env.PLUGIN_REPO_FACTORY_ADDRESS) { + pluginRepoFactoryAddr = getPluginRepoFactoryAddress(network.name); + if (!pluginRepoFactoryAddr) + throw new Error( + 'PLUGIN_REPO_FACTORY_ADDRESS is empty and no default value is available for ' + + network.name + ); + + console.log( + 'Using the default Plugin Repo Factory address (PLUGIN_REPO_FACTORY_ADDRESS is empty)' + ); + } else { + pluginRepoFactoryAddr = process.env.PLUGIN_REPO_FACTORY_ADDRESS; + } + console.log(`\nDeploying the "${ensSubdomain}" plugin repo`); - const {network} = hre; const [deployer] = await hre.ethers.getSigners(); - // Get the PluginRepoFactory address - const pluginRepoFactoryAddr: string = getPluginRepoFactoryAddress( - network.name - ); - const pluginRepoFactory = PluginRepoFactory__factory.connect( pluginRepoFactoryAddr, deployer diff --git a/packages/contracts/deploy/02_setup/10_setup.ts b/packages/contracts/deploy/02_setup/10_setup.ts index 9f3b18d..d45e48f 100644 --- a/packages/contracts/deploy/02_setup/10_setup.ts +++ b/packages/contracts/deploy/02_setup/10_setup.ts @@ -12,7 +12,21 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const {deploy} = deployments; const {deployer} = await getNamedAccounts(); - const pspAddress = getPluginSetupProcessorAddress(network.name); + let pspAddress: string; + if (!process.env.PLUGIN_SETUP_PROCESSOR_ADDRESS) { + pspAddress = getPluginSetupProcessorAddress(network.name); + if (!pspAddress) + throw new Error( + 'PLUGIN_SETUP_PROCESSOR_ADDRESS is empty and no default value is available for ' + + network.name + ); + + console.log( + 'Using the default Plugin Setup Processor address (PLUGIN_SETUP_PROCESSOR_ADDRESS is empty)' + ); + } else { + pspAddress = process.env.PLUGIN_SETUP_PROCESSOR_ADDRESS; + } // Space Setup console.log(