Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deployments/simpler deployment #581

Closed
wants to merge 38 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
039cbe6
modify deployment script for more flexibility
novaknole Apr 3, 2024
c18a063
remove comments
novaknole Apr 3, 2024
5cb8a86
skip multisig
novaknole Apr 5, 2024
2c891a1
uncomment comment
novaknole Apr 5, 2024
86af1e0
comment managing-dao upgrade tests
novaknole Apr 6, 2024
fd84941
feat: update checklist and modify managing dao test
novaknole Apr 8, 2024
7dde6e5
feat: update checklist
novaknole Apr 8, 2024
2845e42
feat: remove comment from test
novaknole Apr 8, 2024
8c36a1a
feat: remove unused comment
novaknole Apr 8, 2024
83bc585
enable root permission on deployer
novaknole Apr 10, 2024
d1d4fcf
Update DEPLOYMENT_CHECKLIST.md
novaknole Apr 11, 2024
a78beb4
Update packages/contracts/deploy/helpers.ts
novaknole Apr 11, 2024
d4380eb
Update packages/contracts/deploy/helpers.ts
novaknole Apr 11, 2024
e03bad8
fix: remove commented code
novaknole Apr 12, 2024
f0f9d67
Update DEPLOYMENT_CHECKLIST.md
novaknole Apr 12, 2024
5ed8514
Update packages/contracts/deploy/new/10_framework/01_ens_subdomains.ts
novaknole Apr 12, 2024
80872d0
update comments
novaknole Apr 12, 2024
6450fce
Merge branch 'deployments/old-contracts' of https://github.com/aragon…
novaknole Apr 12, 2024
9b98b9a
Update DEPLOYMENT_CHECKLIST.md
novaknole Apr 12, 2024
c116cf8
Update DEPLOYMENT_CHECKLIST.md
novaknole Apr 12, 2024
a953ba8
Update DEPLOYMENT_CHECKLIST.md
novaknole Apr 12, 2024
db0b239
Update DEPLOYMENT_CHECKLIST.md
novaknole Apr 16, 2024
5202a3c
Update DEPLOYMENT_CHECKLIST.md
brickpop Apr 16, 2024
4c40500
Update DEPLOYMENT_CHECKLIST.md
brickpop Apr 16, 2024
eaacb7b
Update DEPLOYMENT_CHECKLIST.md
brickpop Apr 16, 2024
6e6a795
Update DEPLOYMENT_CHECKLIST.md
brickpop Apr 16, 2024
da14c4d
Update DEPLOYMENT_CHECKLIST.md
brickpop Apr 16, 2024
8c92391
Update DEPLOYMENT_CHECKLIST.md
brickpop Apr 16, 2024
1865845
Update 50_save-contract-addresses.ts
brickpop Apr 16, 2024
df29a93
Update DEPLOYMENT_CHECKLIST.md
brickpop Apr 16, 2024
3c06990
Update DEPLOYMENT_CHECKLIST.md
brickpop Apr 16, 2024
1ecd628
Update DEPLOYMENT_CHECKLIST.md
brickpop Apr 16, 2024
9743f2a
Update DEPLOYMENT_CHECKLIST.md
brickpop Apr 16, 2024
1fb6493
Update DEPLOYMENT_CHECKLIST.md
brickpop Apr 16, 2024
74f7bd5
show the error message for ens
novaknole Apr 17, 2024
ade7d68
Merge branch 'deployments/simpler-deployment' of https://github.com/a…
novaknole Apr 17, 2024
104f3cd
Removing the IPFS pin step for the Managing DAO
brickpop Apr 17, 2024
3559b7c
Improving the deployment checklist
brickpop Apr 17, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
192 changes: 89 additions & 103 deletions DEPLOYMENT_CHECKLIST.md
Original file line number Diff line number Diff line change
@@ -1,108 +1,94 @@
# Deployment Checklist

This checklist is seen as a guide to deploy the stack to a new chain.

## Pre-Deployment

- [ ] Verify that the deployers wallet has enough funds.
- [ ] Check that the subgraph hoster supports the network OSx is deployed to.
- [ ] Make sure you are using Node v16
- [ ] Bump the OSx protocol version in the `ProtocolVersion.sol` file.
- [ ] Check that version tags are set correctly in the plugin repo deploy scripts `packages/contracts/deploy/new/30_plugins/10_plugin-repos` to ensure synchronized version numbers across all supported networks.
- [ ] Choose an ENS domain for DAOs
- [ ] Choose an ENS domain for plugins
- [ ] Check if there is an official ENS deployment for the chosen chain and if yes:
- [ ] Check if there is already an entry for it in `packages/contracts/deploy/helpers.ts`
- [ ] Check that the owner of the DAO domain is the deployer
- [ ] Check that the owner of the plugin domain is the deployer
- [ ] Run `yarn` in the repository root to install the dependencies
- [ ] Run `yarn build` in `packages/contracts` to make sure the contracts compile
- [ ] Check that the compiler version in `hardhat.config.ts` is set to at least `0.8.17` and on the [known solidity bugs page](https://docs.soliditylang.org/en/latest/bugs.html) that no relevant vulnerabilities exist that are fixed in later versions. If the latter is not the case, consider updating the compiler pragmas to a safe version and rolling out fixes for affected contracts.
- [ ] Run `yarn test` in `packages/contracts` to make sure the contract tests succeed
- [ ] Run `yarn deploy --deploy-scripts deploy/new --network hardhat --reset` to make sure the deploy scripts work
- [ ] Set `ETH_KEY` in `.env` to the deployers private key
- [ ] Set the right API key for the chains blockchain explorer in `.env` (e.g. for mainnet it is `ETHERSCAN_KEY`)
- [ ] Set the chosen DAO ENS domain (in step 1) to `NETWORK_DAO_ENS_DOMAIN` in `.env` and replace `NETWORK` with the correct network name (e.g. for mainnet it is `MAINNET_DAO_ENS_DOMAIN`)
- [ ] Set the chosen Plugin ENS domain (in step 2) to `NETWORK_PLUGIN_ENS_DOMAIN` in `.env` and replace `NETWORK` with the correct network name (e.g. for mainnet it is `MAINNET_PLUGIN_ENS_DOMAIN`)
- [ ] Set the subdomain to be used of the managing DAO to `MANAGINGDAO_SUBDOMAIN` in `.env`. If you want to use `management.dao.eth` put only `management`
- [ ] Set the multisig members of the managing DAO as a comma (`,`) separated list to `MANAGINGDAO_MULTISIG_APPROVERS` in `.env`
- [ ] Set the amount of minimum approvals the managing DAO needs to `MANAGINGDAO_MULTISIG_MINAPPROVALS` in `.env`
- [ ] If new plugin builds are released
- [ ] Double-check that the build- and release-metadata is published correctly by the deploy script and contracts
This checklist is seen as a guide to deploy the contracts to a new chain.

## Pre deployment

- [ ] Run `yarn` in the repository root to install the dependencies.
- [ ] Run `yarn build` in `packages/contracts` to make sure the contracts compile.
- [ ] Run `yarn test` in `packages/contracts` to make sure the contract tests succeed.
- To run the tests, edit `packages/contracts/.env` to contain:

```env
HARDHAT_DAO_ENS_DOMAIN="testdao.eth"
HARDHAT_PLUGIN_ENS_DOMAIN="testpluginrepo.eth"

MANAGINGDAO_SUBDOMAIN="management"
```
- [ ] Edit `packages/contracts/networks.json` and add your custom network to which you want to deploy to.

If contract verification is not available for your chain:

- Ensure that the `deploy` key for the new network looks exactly like: <br>
`"deploy": ["./deploy/new"]`

If contract verification is available:

- Define the `deploy` key like: <br>
`"deploy": ["./deploy/new", "./deploy/verification"]`.
- Define the `ETHERSCAN_KEY` variable for contract verification on the `.env` file. [Follow the HardHat guide](https://hardhat.org/hardhat-runner/plugins/nomicfoundation-hardhat-verify) in such case.

- [ ] Define the settings of the ENS domain used by OSx.

- Define the following ENS names in the `packages/contracts/.env` file, by replacing `SEPOLIA` with the name of the network name you’re deploying to:

```env
SEPOLIA_DAO_ENS_DOMAIN="my-dao.eth"
SEPOLIA_PLUGIN_ENS_DOMAIN="my-dao.eth"
```

- Ensure that domains end with a suffix like `.eth`

- If the target chain does not have an official ENS registry:
- A new, unofficial ENS registry will be deployed, along with a resolver
- No ownership is needed, the Managing DAO will own them
- If the target chain does have an official ENS registry:
- Ensure that the wallet under `ETH_KEY` owns the domain
- If you created the domains via the ENS app, they will be owned by an ENS wrapper which would cause the script to fail
- [Open the ENS app](https://app.ens.domains/) and click `unwrap` for each of these domains.
- [Example](https://app.ens.domains/morpheusplugin3.eth?tab=more)

- [ ] If desired, update `MANAGINGDAO_SUBDOMAIN` on `packages/contracts/.env`.
- In case you want the Managing DAO to use a different subdomain than the default one (`management`):
```env
MANAGINGDAO_SUBDOMAIN="root" # would be root.my-dao.eth
```
- [ ] Define the the deployment wallet's private key on the `.env` file
```env
ETH_KEY="your-private-key-here" # without the 0x prefix
```
- [ ] Verify that the deployment wallet has sufficient funds to complete a protocol deployment.

## Deployment

To deploy run `yarn deploy --network NETWORK` in `packages/contracts` and replace `NETWORK` with the correct network name (e.g. for mainnet it is `yarn deploy --network mainnet`)

## After-Deployment

### Configuration updates

- [ ] Take the addresses from this file `packages/contracts/deployed_contracts.json`
- [ ] Update `active_contracts.json` with the new deployed addresses
- [ ] Update `packages/contracts/Releases.md` with the new deployed addresses
- [ ] Add the managing DAOs' multisig address to `packages/contracts/.env.example` in the format `{NETWORK}_MANAGINGDAO_MULTISIG`

### Verification

- [ ] Take the addresses from this file `packages/contracts/deployed_contracts.json`
- [ ] Wait for the deployment script finishing verification
- [ ] Go to the blockchain explorer and verify that each address is verified
- [ ] If it is not try to verfiy it with `npx hardhat verify --network NETWORK ADDRESS CONTRUCTOR-ARGS`. More infos on how to use this command can be found here: [https://hardhat.org/hardhat-runner/docs/guides/verifying](https://hardhat.org/hardhat-runner/docs/guides/verifying)
- [ ] If it is a proxy try to activate the blockchain explorer's proxy feature
- [ ] If the proxies are not verified with the `Similar Match Source Code` feature
- [ ] Verify one of the proxies
- [ ] Check if the other proxies are now verified with `Similar Match Source Code`
- [ ] If it is a `PluginSetup`, check that the implementation is verified.

### Configurations

- [ ] Check that all managing DAO signers are members of the managing DAO multisig and no one else.
- [ ] Check if the managing DAO is set in the `DAO_ENSSubdomainRegistrar`
- [ ] Check if the managing DAO is set in the `Plugin_ENSSubdomainRegistrar`
- [ ] Check if the managing DAO is set in the `DAORegistry`
- [ ] Check if the `DAO_ENSSubdomainRegistrar` is set in the `DAORegistry`
- [ ] Check if the managing DAO set in the `PluginRepoRegistry`
- [ ] Check if the `Plugin_ENSSubdomainRegistrar` is set in the `PluginRepoRegistry`
- [ ] Check if the `PluginRepoRegistry` is set in the `PluginRepoFactory`
- [ ] Check if the `PluginRepoRegistry` is set in the `PluginSetupProcessor`
- [ ] Check if the `DAORegistry` is set in the `DAOFactory`
- [ ] Check if the `PluginSetupProcessor` is set in the `DAOFactory`
- [ ] Check that the versions (and eventual `PlaceholderSetup` builds) are published correctly in the `token-voting-repo`, `address-list-voting-repo`, `multisig-repo`, and `admin-repo` and are synchronized across all supported networks.

### Permissions

- [ ] Check that the deployer has not the ROOT permission on the managing DAO
- [ ] Check if `DAO_ENSSubdomainRegistrar` is approved for all for the DAO' ENS domain. Call `isApprovedForAll` on the ENS registry with the managing DAO as the owner and the `DAO_ENSSubdomainRegistrar` as the operator.
- [ ] Check if `Plugin_ENSSubdomainRegistrar` is approved for all for the plugin' ENS domain. Call `isApprovedForAll` on the ENS registry with the managing DAO as the owner and the `Plugin_ENSSubdomainRegistrar` as the operator.
- [ ] Check if the `DAORegistry` has `REGISTER_ENS_SUBDOMAIN_PERMISSION` on `DAO_ENSSubdomainRegistrar`
- [ ] Check if the `PluginRepoRegistry` has `REGISTER_ENS_SUBDOMAIN_PERMISSION` on `Plugin_ENSSubdomainRegistrar`
- [ ] Check if the `DAOFactory` has `REGISTER_DAO_PERMISSION` on `DAORegistry`
- [ ] Check if the `PluginRepoFactory` has `REGISTER_PLUGIN_REPO_PERMISSION` on `PluginRepoRegistry`

### Packages

- [ ] Publish a new version of `@aragon/osx-artifacts` (`./packages/contracts`) to NPM
- [ ] Publish a new version of `@aragon/osx` (`./packages/contracts/src`) to NPM
- [ ] Publish a new version of `@aragon/osx-ethers` (`./packages/contracts-ethers`) to NPM
- [ ] Update the changelog with the new version

### Subgraph

- [ ] Update `packages/subgraph/manifest/data/NETWORK.json` where `NETWORK` is replaced with the deployed network with the new contract addresses. If the file doesn't exist create a new one.
- [ ] Update the version in `packages/subgraph/package.json`
- [ ] Update `packages/subgraph/.env` with the correct values
- [ ] set `NETWORK_NAME` to the deployed network
- [ ] set `SUBGRAPH_NAME` to `osx`
- [ ] set `GRAPH_KEY` with the value obtained from the [Satsuma Dashboard](https://app.satsuma.xyz/dashboard)
- [ ] set the `SUBGRAPH_VERSION` to the same value as in `packages/subgraph/package.json`
- [ ] Run `yarn manifest` in `packages/subgraph` to generate the manifest
- [ ] Run `yarn build` in `packages/subgraph` to build the subgraph
- [ ] Run `yarn test` in `packages/subgraph` to test the subgraph
- [ ] Run `yarn deploy` in `packages/subgraph` to deploy the subgraph
- [ ] Test the new deployed subgraph with the frontend team
- [ ] Promote the new subgraph to live in the [Satsuma Dashboard](https://app.satsuma.xyz/dashboard)

## Appendix

- Changing the owner of the chosen ENS domains will also revoke the permissions of the `DAO_ENSSubdomainRegistrar` and `Plugin_ENSSubdomainRegistrar`. Therefore if the ownership gets transfered, restore the approval for these 2 contracts.
When the settings above are correctly set:

```sh
cd packages/contracts # if needed
yarn deploy --network <NETWORK> # Replace with mainnet, polygon, sepolia, etc
```

## Post deployment

- After the script has exited, the deployment wallet will be the only one with `ROOT_PERMISSION` on your Managing DAO.
- This allows the deployent wallet to manually install plugins to it.
- After the required plugins are installed, `ROOT_PERMISSION` has to be revoked on the deployment wallet.
- Should the script encounter any issues, the deployment should be re-run again.
- The script would detect and re-use any already deployed contracts.
- After the process completes, check out the `packages/contracts/deployed_contracts.json` file to see the deployed contract addresses.

## Other

### Rerunning the deployment script

If you need to restart the redeployment process and want HardHat to not reuse the existing contracts:

```sh
rm -R deployments/<network-name> # replace with the actual name
```

### Running the deployment script on a testnet

If you want to simulate an L3 deployment within a testnet (sepolia) which has official ENS support, you may want to force the deployment of a new ENS Registry.

Edit the `packages/contracts/deploy/helpers.ts` file and comment out the relevant line from `ENS_ADDRESSES` and `ENS_PUBLIC_RESOLVERS`.
118 changes: 76 additions & 42 deletions packages/contracts/deploy/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,3 @@
import {promises as fs} from 'fs';
import {ethers} from 'hardhat';
import {Contract} from 'ethers';
import {SignerWithAddress} from '@nomiclabs/hardhat-ethers/signers';
import {HardhatRuntimeEnvironment} from 'hardhat/types';
import IPFS from 'ipfs-http-client';

import {findEvent, findEventTopicLog} from '../utils/event';
import {Operation} from '../utils/types';
import {VersionTag} from '../test/test-utils/psp/types';
import {
ENSRegistry__factory,
Expand All @@ -16,6 +7,14 @@ import {
} from '../typechain';
import {VersionCreatedEvent} from '../typechain/PluginRepo';
import {PluginRepoRegisteredEvent} from '../typechain/PluginRepoRegistry';
import {findEvent, findEventTopicLog} from '../utils/event';
import {Operation} from '../utils/types';
import {SignerWithAddress} from '@nomiclabs/hardhat-ethers/signers';
import {Contract} from 'ethers';
import {promises as fs} from 'fs';
import {ethers} from 'hardhat';
import {HardhatRuntimeEnvironment} from 'hardhat/types';
import IPFS from 'ipfs-http-client';

// TODO: Add support for L2 such as Arbitrum. (https://discuss.ens.domains/t/register-using-layer-2/688)
// Make sure you own the ENS set in the {{NETWORK}}_ENS_DOMAIN variable in .env
Expand All @@ -31,24 +30,6 @@ export const ENS_PUBLIC_RESOLVERS: {[key: string]: string} = {
sepolia: '0x8FADE66B79cC9f707aB26799354482EB93a5B7dD',
};

export const MANAGING_DAO_METADATA = {
name: 'Aragon Managing DAO',
description:
'Aragon OSx includes a group of global smart contracts that allow for a DAO ecosystem to be built on top. These contracts will require future improvements and general maintenance. The Managing DAO is intended to perform such maintenance tasks and holds the permissions to deliver any new capabilities that are added in the future.',
avatar:
'https://ipfs.eth.aragon.network/ipfs/QmVyy3ci7F2zHG6JUJ1XbcwLKuxWrQ6hqNvSnjmDmdYJzP/',
links: [
{
name: 'Web site',
url: 'https://www.aragon.org',
},
{
name: 'Developer Portal',
url: 'https://devs.aragon.org/',
},
],
};

export const DAO_PERMISSIONS = [
'ROOT_PERMISSION',
'UPGRADE_DAO_PERMISSION',
Expand Down Expand Up @@ -189,21 +170,9 @@ export async function createPluginRepo(
pluginName: string
): Promise<void> {
const {network} = hre;
const signers = await ethers.getSigners();
const {deployer} = await hre.getNamedAccounts();

const pluginDomain =
process.env[`${network.name.toUpperCase()}_PLUGIN_ENS_DOMAIN`] || '';
if (
await isENSDomainRegistered(
`${pluginName}.${pluginDomain}`,
await getENSAddress(hre),
signers[0]
)
) {
// not beeing able to register the plugin repo means that something is not right with the framework deployment used.
// Either a frontrun happened or something else. Thus we abort here
throw new Error(`${pluginName} is already present! Aborting...`);
}
const signers = await ethers.getSigners();

const pluginRepoFactoryAddress = await getContractAddress(
'PluginRepoFactory',
Expand All @@ -215,12 +184,58 @@ export async function createPluginRepo(
pluginRepoFactoryAddress
);

const {deployer} = await hre.getNamedAccounts();
const pluginDomain =
process.env[`${network.name.toUpperCase()}_PLUGIN_ENS_DOMAIN`];

const node = ethers.utils.namehash(`${pluginName}.${pluginDomain}`);

const pluginSubdomainRegistrar = await getContractAddress(
'Plugin_ENSSubdomainRegistrar',
hre
);

const ensRegistryContract = ENSRegistry__factory.connect(
await getENSAddress(hre),
signers[0]
);

const owner = await ensRegistryContract.owner(node);

// ENS subdomain has already been registered by pluginSubdomainRegistrar.
// Running the `createPluginRepo` will fail unless skipped.
// Since `aragonPluginRepos` is filled in run-time, we still need to refill it.
if (owner === pluginSubdomainRegistrar) {
const pluginRepoRegistryFactory = new PluginRepoRegistry__factory(
signers[0]
);
const pluginRepoRegistry = pluginRepoRegistryFactory.attach(
await getContractAddress('PluginRepoRegistry', hre)
);
let events = await pluginRepoRegistry.queryFilter(
pluginRepoRegistry.filters.PluginRepoRegistered(null, null)
);
const found = events.filter(event => event?.args?.subdomain == pluginName);
if (found && found.length == 1) {
hre.aragonPluginRepos[pluginName] = found[0].args.pluginRepo;
return;
}
throw new Error(
`Critical: Either the event was not found or none of the plugin repo deployment corresponds to your domain.`
);
}

// The owner of the node is already set to someone who is not pluginSubdomainRegistrar.
if (owner !== ethers.constants.AddressZero) {
throw new Error(
`${pluginName}.${pluginDomain} is already owned by someone other than pluginSubdomainRegistrar`
);
}

const tx = await pluginRepoFactoryContract.createPluginRepo(
pluginName,
deployer
);

console.log(
`Creating & registering repo for ${pluginName} with tx ${tx.hash}`
);
Expand All @@ -244,6 +259,7 @@ export async function createVersion(
pluginRepoContract: string,
pluginSetupContract: string,
releaseNumber: number,
buildNumber: number,
releaseMetadata: string,
buildMetadata: string
): Promise<void> {
Expand All @@ -252,6 +268,18 @@ export async function createVersion(
const PluginRepo = new PluginRepo__factory(signers[0]);
const pluginRepo = PluginRepo.attach(pluginRepoContract);

try {
// getVersion reverts if the version doesn't exist.
await pluginRepo['getVersion((uint8,uint16))']({
release: releaseNumber,
build: buildNumber,
});
console.log(
`Version Already Deployed, skipping the 'createVersion' call on pluginRepo`
);
return;
} catch (err) {}

const tx = await pluginRepo.createVersion(
releaseNumber,
pluginSetupContract,
Expand Down Expand Up @@ -330,6 +358,7 @@ export async function populatePluginRepo(
hre.aragonPluginRepos[pluginRepoName],
placeholderSetup,
releaseNumber,
i,
emptyJsonObject,
ethers.utils.hexlify(
ethers.utils.toUtf8Bytes(`ipfs://${hre.placeholderBuildCIDPath}`)
Expand All @@ -342,6 +371,7 @@ export async function populatePluginRepo(
hre.aragonPluginRepos[pluginRepoName],
latestVersion.pluginSetupContract,
releaseNumber,
latestBuildNumber,
latestVersion.releaseMetadata,
latestVersion.buildMetadata
);
Expand Down Expand Up @@ -614,5 +644,9 @@ export function getManagingDAOMultisigAddress(
return address;
}

export function skipDeploy(hre: HardhatRuntimeEnvironment) {
return Promise.resolve(true);
}

// exports dummy function for hardhat-deploy. Otherwise we would have to move this file
export default function () {}
Loading
Loading