Skip to content

Commit

Permalink
Manageent DAO post install script
Browse files Browse the repository at this point in the history
  • Loading branch information
brickpop committed Apr 9, 2024
1 parent 6d5a0ee commit 50913e7
Show file tree
Hide file tree
Showing 9 changed files with 374 additions and 115 deletions.
14 changes: 9 additions & 5 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
# GENERAL

## The network used for testing purposes
## The network used
NETWORK_NAME="sepolia" # ["mainnet", "sepolia", "polygon", "polygonMumbai"]

# PROTOCOL CONTRACTS
## DEPLOYMENT
DEPLOYMENT_RPC_ENDPOINT="https://host/path"

## Hex encoded private keys separated by a comma `,`
## The first item will be the deployment wallet
PRIVATE_KEY="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"

# OSx 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
MANAGING_DAO_ADDRESS="0x617e4fB3a2358b7EA5a16f47b6f1f4956Faf0162"

## API keys
INFURA_API_KEY="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"
Expand Down
111 changes: 1 addition & 110 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ yarn build
yarn test
```

See [Deployment](#deployment) below
See the [deployment checklist](./README_DEPLOYMENT.md)

## Overview

Expand Down Expand Up @@ -774,112 +774,3 @@ 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 <replace-the-name>
```

### 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 <replace-the-name>
```

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 <replace-the-name>
```

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
108 changes: 108 additions & 0 deletions README_DEPLOYMENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# Geo Browser - Aragon OSx

## 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 <replace-the-name>
```

### 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
git checkout simpler-deployment
cd packages/contracts
cp .env.example .env
nano .env # Update the values
yarn build
# yarn test (optional)
```

- 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.
- Open the `DEPLOYMENT_CHECKLIST.md` file and follow the instructions

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"
}
```

Copy the `PluginRepoFactory`, the `PluginSetupProcessor` and the `managingDAO` addresses for the next step.

#### 2) Run the plugin deployment script

Back to this repository:

- Update the `.env` file with the values that correspond to your target blockchain
- `NETWORK_NAME` and `DEPLOYMENT_RPC_ENDPOINT`
- Alternatively, edit the `packages/contracts/hardhat.config.ts` to manually customize the HardHat client
- Define the deployment wallet's `PRIVATE_KEY`
- Define the protocol addresses [you copied before](#1-deploy-osx):
- `PLUGIN_REPO_FACTORY_ADDRESS`, `PLUGIN_SETUP_PROCESSOR_ADDRESS` and `MANAGING_DAO_ADDRESS`
- Edit the `packages/contracts/plugin-setup-params.ts` to define the details of the plugins to depoy
- If you try to deploy the same plugin repo twice, you will encounter an ENS collision
- In such case, either define a new unique ENS subdomain or consider rerunning the step 1 and trying again

```sh
cd packages/contracts
yarn build
npx hardhat deploy --network <replace-the-name>
```

In addition to deploying the plugins, the script will internally perform two more things:

#### 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.

The script takes care of:

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. Ask the Managing DAO to `execute()` an action that calls `applyInstallation()` of the new plugin

#### 4) Revoke the EXECUTE permission granted to the deployer wallet

The script calls `execute()` on the Managing DAO, with an action that calls `revoke(dao, deploymentWalletAddr, ROOT_PERMISSION_ID)` on the DAO itself
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import {GovernancePluginsSetupParams} from '../../plugin-setup-params';
import {
GovernancePluginsSetup__factory,
MajorityVotingBase,
PluginSetupProcessor__factory,
} from '../../typechain';
import {
InstallationPreparedEvent,
PluginSetupRefStruct,
} from '../../typechain/@aragon/osx/framework/plugin/setup/PluginSetupProcessor';
import {findEvent, hashHelpers} from '../../utils/helpers';
import {getPluginRepoInfo} from '../../utils/plugin-repo-info';
import {IDAO, IDAO__factory, PluginSetupProcessor} from '@aragon/osx-ethers';
import {DeployFunction} from 'hardhat-deploy/types';
import {HardhatRuntimeEnvironment} from 'hardhat/types';

const MANAGING_DAO_ADDRESS = process.env.MANAGING_DAO_ADDRESS ?? '';
const PLUGIN_SETUP_PROCESSOR_ADDRESS =
process.env.PLUGIN_SETUP_PROCESSOR_ADDRESS ?? '';
const MGMT_DAO_PROPOSAL_DURATION =
parseInt(process.env.MGMT_DAO_PROPOSAL_DURATION ?? '604800') ||
60 * 60 * 24 * 7;
const MGMT_DAO_MIN_PROPOSAL_PARTICIPATION =
parseInt(process.env.MGMT_DAO_MIN_PROPOSAL_PARTICIPATION ?? '500000') ||
500_000; // 50%
const MGMT_DAO_PROPOSAL_SUPPORT_THRESHOLD =
parseInt(process.env.MGMT_DAO_PROPOSAL_SUPPORT_THRESHOLD ?? '500000') ||
500_000; // 50%

// Main function
const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
const {deployments, network} = hre;
const [deployer] = await hre.ethers.getSigners();

// Locate the plugin setup address
const setupDeployment = await deployments.get(
GovernancePluginsSetupParams.PLUGIN_SETUP_CONTRACT_NAME
);
const pluginSetup = GovernancePluginsSetup__factory.connect(
setupDeployment.address,
deployer
);

// Call prepare installation
const settings: MajorityVotingBase.VotingSettingsStruct = {
duration: MGMT_DAO_PROPOSAL_DURATION,
minParticipation: MGMT_DAO_MIN_PROPOSAL_PARTICIPATION,
supportThreshold: MGMT_DAO_PROPOSAL_SUPPORT_THRESHOLD,
votingMode: 1, // Early execution
};
const initialEditors = [] as string[];
const memberAccessProposalDuration = MGMT_DAO_PROPOSAL_DURATION * 3; // Time before expired
const pluginUpgrader = '0x0000000000000000000000000000000000000000'; // Only the DAO
const installData = await pluginSetup.encodeInstallationParams(
settings,
initialEditors,
memberAccessProposalDuration,
pluginUpgrader
);

if (!PLUGIN_SETUP_PROCESSOR_ADDRESS)
throw new Error('PLUGIN_SETUP_PROCESSOR_ADDRESS cannot be empty');

console.log('Preparing an installation of the standard governance plugin');
const psp = PluginSetupProcessor__factory.connect(
PLUGIN_SETUP_PROCESSOR_ADDRESS,
deployer
);

const pluginRepoInfo = getPluginRepoInfo(
GovernancePluginsSetupParams.PLUGIN_REPO_ENS_NAME,
network.name
);
if (!pluginRepoInfo) throw new Error('The plugin repo cannot be found');

const pluginSetupRef: PluginSetupRefStruct = {
pluginSetupRepo: pluginRepoInfo.address,
versionTag: GovernancePluginsSetupParams.VERSION,
};

const tx = await psp.prepareInstallation(MANAGING_DAO_ADDRESS, {
pluginSetupRef,
data: installData,
});
await tx.wait();

const preparedEvent = await findEvent<InstallationPreparedEvent>(
tx,
'InstallationPrepared'
);
if (!preparedEvent) {
throw new Error('Failed to get InstallationPrepared event');
}

const pluginAddress = preparedEvent.args.plugin;
const helpers = preparedEvent.args.preparedSetupData.helpers;
const permissions = preparedEvent.args.preparedSetupData.permissions;

// Encode a call to execute() > applyInstallation
console.log('Installing the plugin to the managing DAO');
const applyParams: PluginSetupProcessor.ApplyInstallationParamsStruct = {
plugin: pluginAddress,
helpersHash: hashHelpers(helpers),
permissions,
pluginSetupRef: {
pluginSetupRepo: pluginRepoInfo.address,
versionTag: GovernancePluginsSetupParams.VERSION,
},
};

const actions: IDAO.ActionStruct[] = [
{
to: PLUGIN_SETUP_PROCESSOR_ADDRESS,
value: 0,
data: PluginSetupProcessor__factory.createInterface().encodeFunctionData(
'applyInstallation',
[MANAGING_DAO_ADDRESS, applyParams]
),
},
];

const tx2 = await IDAO__factory.connect(
MANAGING_DAO_ADDRESS,
deployer
).execute(
'0x0000000000000000000000000000000000000000000000000000000000000000',
actions,
0
);
await tx2.wait();

hre.managingDao.address = MANAGING_DAO_ADDRESS;
hre.managingDao.governancePlugin = pluginAddress;
};

export default func;
func.tags = [
GovernancePluginsSetupParams.PLUGIN_SETUP_CONTRACT_NAME,
'ManagingDAO',
];
Loading

0 comments on commit 50913e7

Please sign in to comment.