From 8589782bd38cb8178dd21d732cb8efd76eac83c2 Mon Sep 17 00:00:00 2001 From: jordan Date: Tue, 13 Feb 2024 13:26:56 +0400 Subject: [PATCH 01/18] simplified readme --- packages/contracts/src/README.md | 35 ++++++++------------------------ 1 file changed, 9 insertions(+), 26 deletions(-) diff --git a/packages/contracts/src/README.md b/packages/contracts/src/README.md index cc433e9be..cc151ef84 100644 --- a/packages/contracts/src/README.md +++ b/packages/contracts/src/README.md @@ -14,38 +14,21 @@ yarn add @aragon/osx-artifacts ## Get Started -To get started running your repository locally: - -Copy `.env.example` into a file called `.env` or create a new one with these 3 keys defined: +To get started running your repository locally, run these commands on the project's root folder in your terminal: ```sh -# keys used for running tests -HARDHAT_DAO_ENS_DOMAIN=dao.eth -HARDHAT_PLUGIN_ENS_DOMAIN=plugin.eth -MANAGEMENT_DAO_SUBDOMAIN=management -``` +# compile contracts +yarn build -Run these commands on the project's root folder in your terminal: +# run tests +yarn test -```shell -npx hardhat accounts -npx hardhat compile -npx hardhat clean -npx hardhat test -npx hardhat node -npx hardhat help -REPORT_GAS=true npx hardhat test -npx hardhat coverage -npx hardhat run scripts/deploy.ts -TS_NODE_FILES=true npx ts-node scripts/deploy.ts -npx eslint '**/*.{js,ts}' -npx eslint '**/*.{js,ts}' --fix -npx prettier '**/*.{json,sol,md}' --check -npx prettier '**/*.{json,sol,md}' --write -npx solhint 'contracts/**/*.sol' -npx solhint 'contracts/**/*.sol' --fix +# deploy locally +yarn deploy ``` +See the [package.json](./package.json) for all available scripts. Alternatively, consult the hardhat documentation for additional tasks and commands. + ## Documentation You can find all documentation regarding how to use this protocol in [Aragon's Developer Portal here](https://devs.aragon.org). From 681b16e09cb76cfdc19e900728d671f23f89c5cd Mon Sep 17 00:00:00 2001 From: jordaniza Date: Tue, 13 Feb 2024 15:33:34 +0400 Subject: [PATCH 02/18] tested helper for envOr --- packages/contracts/deploy/environment.ts | 28 ++++++++++ .../contracts/test/deploy/detect-network.ts | 52 +++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 packages/contracts/deploy/environment.ts create mode 100644 packages/contracts/test/deploy/detect-network.ts diff --git a/packages/contracts/deploy/environment.ts b/packages/contracts/deploy/environment.ts new file mode 100644 index 000000000..6f5a5af50 --- /dev/null +++ b/packages/contracts/deploy/environment.ts @@ -0,0 +1,28 @@ +import {Network} from 'hardhat/types'; + +/** + * Provides default values for environment variables if running against a hardhat node + * else requires that the environment variables are set + * @param network the hardhat network object + * @param name of the environment variable + * @param defaultValue the fallback value to be used if not set and in development mode + * @returns the value of the environment variable, or a fallback if possible + */ +export function envOr( + network: Network, + name: string, + defaultValue: string +): string { + const value = process.env[name]; + const isHardhat = network.name === 'hardhat'; + if (!isHardhat && !value) { + throw new Error(`Missing env var: ${name}`); + } + return process.env[name] || defaultValue; +} + +export const ensOr = ( + network: Network, + name: string, + defaultValue: string +): string => envOr(network, name, defaultValue); diff --git a/packages/contracts/test/deploy/detect-network.ts b/packages/contracts/test/deploy/detect-network.ts new file mode 100644 index 000000000..daa111a91 --- /dev/null +++ b/packages/contracts/test/deploy/detect-network.ts @@ -0,0 +1,52 @@ +import {expect} from 'chai'; +import {network} from 'hardhat'; +import {Network} from 'hardhat/types'; + +/** + * Provides default values for environment variables if running against a hardhat node + * else requires that the environment variables are set + * @param network the hardhat network object + * @param name of the environment variable + * @param defaultValue the fallback value to be used if not set and in development mode + * @returns the value of the environment variable, or a fallback if possible + */ +function envOr(network: Network, name: string, defaultValue: string): string { + const value = process.env[name]; + const isHardhat = network.name === 'hardhat'; + if (!isHardhat && !value) { + throw new Error(`Missing env var: ${name}`); + } + return process.env[name] || defaultValue; +} + +describe('detect network', () => { + it('should detect the hardhat network', () => { + expect(network.name).to.equal('hardhat'); + }); + + it('provides default values for env vars if using the hardhat network', () => { + const daoDomain = envOr(network, 'DAO_ENS_DOMAIN', 'dao.eth'); + expect(daoDomain).to.equal('dao.eth'); + }); + + it('uses the environment variable if set', () => { + process.env['DAO_ENS_DOMAIN'] = 'mydao.eth'; + const daoDomain = envOr(network, 'DAO_ENS_DOMAIN', 'dao.eth'); + expect(daoDomain).to.equal('mydao.eth'); + }); + + it("Throws if env vars aren't set for the network other than hardhat", () => { + const network = {name: 'mainnet'} as unknown as Network; + delete process.env['DAO_ENS_DOMAIN']; + expect(() => envOr(network, 'DAO_ENS_DOMAIN', 'dao.eth')).to.throw( + 'Missing env var: DAO_ENS_DOMAIN' + ); + }); + + it("Doesn't throw if env vars are set for the network other than hardhat", () => { + const network: Network = {name: 'mainnet'} as unknown as Network; + process.env['DAO_ENS_DOMAIN'] = 'mydao.eth'; + const daoDomain = envOr(network, 'DAO_ENS_DOMAIN', 'dao.eth'); + expect(daoDomain).to.equal('mydao.eth'); + }); +}); From 3c43dc94bcade606af3596f4c28e1e03fc46b5b8 Mon Sep 17 00:00:00 2001 From: jordaniza Date: Tue, 13 Feb 2024 15:54:14 +0400 Subject: [PATCH 03/18] helpers for fallbacks --- packages/contracts/deploy/environment.ts | 32 ++++++++--- .../contracts/test/deploy/detect-network.ts | 53 +++++++++++-------- 2 files changed, 58 insertions(+), 27 deletions(-) diff --git a/packages/contracts/deploy/environment.ts b/packages/contracts/deploy/environment.ts index 6f5a5af50..993010151 100644 --- a/packages/contracts/deploy/environment.ts +++ b/packages/contracts/deploy/environment.ts @@ -8,7 +8,7 @@ import {Network} from 'hardhat/types'; * @param defaultValue the fallback value to be used if not set and in development mode * @returns the value of the environment variable, or a fallback if possible */ -export function envOr( +export function env( network: Network, name: string, defaultValue: string @@ -21,8 +21,28 @@ export function envOr( return process.env[name] || defaultValue; } -export const ensOr = ( - network: Network, - name: string, - defaultValue: string -): string => envOr(network, name, defaultValue); +/// fallback values for the environment variables + +export const daoDomainEnv = (network: Network): string => + env(network, `${network.name.toUpperCase()}_DAO_ENS_DOMAIN`, 'dao.eth'); + +export const pluginDomainEnv = (network: Network): string => + env(network, `${network.name.toUpperCase()}_PLUGIN_ENS_DOMAIN`, 'plugin.eth'); + +export const managementDaoSubdomainEnv = (network: Network): string => + env(network, 'MANAGEMENT_DAO_SUBDOMAIN', 'management'); + +export const managementDaoMultisigApproversEnv = (network: Network): string => + env( + network, + 'MANAGEMENT_DAO_MULTISIG_APPROVERS', + // random address + '0x6B2b5d4F0a40134189330e2d46a9CDD01C01AECD' + ); + +export const managementDaoMultisigMinApprovalsEnv = ( + network: Network +): string => env(network, 'MANAGEMENT_DAO_MULTISIG_MINAPPROVALS', '1'); + +export const managementDaoMultisigListedOnlyEnv = (network: Network): string => + env(network, 'MANAGEMENT_DAO_MULTISIG_LISTEDONLY', 'true'); diff --git a/packages/contracts/test/deploy/detect-network.ts b/packages/contracts/test/deploy/detect-network.ts index daa111a91..e8868c220 100644 --- a/packages/contracts/test/deploy/detect-network.ts +++ b/packages/contracts/test/deploy/detect-network.ts @@ -1,44 +1,36 @@ +import { + daoDomainEnv, + env, + managementDaoMultisigApproversEnv, + managementDaoMultisigListedOnlyEnv, + managementDaoMultisigMinApprovalsEnv, + managementDaoSubdomainEnv, + pluginDomainEnv, +} from '../../deploy/environment'; import {expect} from 'chai'; import {network} from 'hardhat'; import {Network} from 'hardhat/types'; -/** - * Provides default values for environment variables if running against a hardhat node - * else requires that the environment variables are set - * @param network the hardhat network object - * @param name of the environment variable - * @param defaultValue the fallback value to be used if not set and in development mode - * @returns the value of the environment variable, or a fallback if possible - */ -function envOr(network: Network, name: string, defaultValue: string): string { - const value = process.env[name]; - const isHardhat = network.name === 'hardhat'; - if (!isHardhat && !value) { - throw new Error(`Missing env var: ${name}`); - } - return process.env[name] || defaultValue; -} - describe('detect network', () => { it('should detect the hardhat network', () => { expect(network.name).to.equal('hardhat'); }); it('provides default values for env vars if using the hardhat network', () => { - const daoDomain = envOr(network, 'DAO_ENS_DOMAIN', 'dao.eth'); + const daoDomain = env(network, 'DAO_ENS_DOMAIN', 'dao.eth'); expect(daoDomain).to.equal('dao.eth'); }); it('uses the environment variable if set', () => { process.env['DAO_ENS_DOMAIN'] = 'mydao.eth'; - const daoDomain = envOr(network, 'DAO_ENS_DOMAIN', 'dao.eth'); + const daoDomain = env(network, 'DAO_ENS_DOMAIN', 'dao.eth'); expect(daoDomain).to.equal('mydao.eth'); }); it("Throws if env vars aren't set for the network other than hardhat", () => { const network = {name: 'mainnet'} as unknown as Network; delete process.env['DAO_ENS_DOMAIN']; - expect(() => envOr(network, 'DAO_ENS_DOMAIN', 'dao.eth')).to.throw( + expect(() => env(network, 'DAO_ENS_DOMAIN', 'dao.eth')).to.throw( 'Missing env var: DAO_ENS_DOMAIN' ); }); @@ -46,7 +38,26 @@ describe('detect network', () => { it("Doesn't throw if env vars are set for the network other than hardhat", () => { const network: Network = {name: 'mainnet'} as unknown as Network; process.env['DAO_ENS_DOMAIN'] = 'mydao.eth'; - const daoDomain = envOr(network, 'DAO_ENS_DOMAIN', 'dao.eth'); + const daoDomain = env(network, 'DAO_ENS_DOMAIN', 'dao.eth'); expect(daoDomain).to.equal('mydao.eth'); }); + + it('sets the correct fallbacks for each environment variable', () => { + expect(daoDomainEnv(network)).to.equal('dao.eth'); + expect(pluginDomainEnv(network)).to.equal('plugin.eth'); + expect(managementDaoSubdomainEnv(network)).to.equal('management'); + expect(managementDaoMultisigApproversEnv(network)).to.equal( + '0x6B2b5d4F0a40134189330e2d46a9CDD01C01AECD' + ); + expect(managementDaoMultisigMinApprovalsEnv(network)).to.equal('1'); + expect(managementDaoMultisigListedOnlyEnv(network)).to.equal('true'); + }); + + it('string interpolates the ENS subdomains', () => { + const network: Network = {name: 'FakeNet'} as unknown as Network; + process.env['FAKENET_DAO_ENS_DOMAIN'] = 'mydao.eth'; + process.env['FAKENET_PLUGIN_ENS_DOMAIN'] = 'myplugin.eth'; + expect(daoDomainEnv(network)).to.equal('mydao.eth'); + expect(pluginDomainEnv(network)).to.equal('myplugin.eth'); + }); }); From d41325b954eff3eb3607f2f18558592aa1ecc48f Mon Sep 17 00:00:00 2001 From: jordaniza Date: Wed, 14 Feb 2024 10:03:06 +0400 Subject: [PATCH 04/18] make optional Dao ens domain and plugin ens domain: --- packages/contracts/deploy/environment.ts | 2 +- packages/contracts/deploy/helpers.ts | 4 ++-- .../deploy/new/10_framework/00_ens_registry.ts | 12 +++--------- .../deploy/new/10_framework/01_ens_subdomains.ts | 11 +++-------- .../new/10_framework/02_ens_subdomain_registrars.ts | 12 ++++-------- .../deploy/new/10_framework/99_verifiy_step.ts | 9 +++------ .../20_register-management-dao-on-dao-registry.ts | 6 +++--- packages/contracts/test/deploy/detect-network.ts | 4 ++++ 8 files changed, 23 insertions(+), 37 deletions(-) diff --git a/packages/contracts/deploy/environment.ts b/packages/contracts/deploy/environment.ts index 993010151..919b060f8 100644 --- a/packages/contracts/deploy/environment.ts +++ b/packages/contracts/deploy/environment.ts @@ -21,7 +21,7 @@ export function env( return process.env[name] || defaultValue; } -/// fallback values for the environment variables +/// Specific environment variables with hardcoded defaults export const daoDomainEnv = (network: Network): string => env(network, `${network.name.toUpperCase()}_DAO_ENS_DOMAIN`, 'dao.eth'); diff --git a/packages/contracts/deploy/helpers.ts b/packages/contracts/deploy/helpers.ts index 653c9eea6..9a75ca717 100644 --- a/packages/contracts/deploy/helpers.ts +++ b/packages/contracts/deploy/helpers.ts @@ -7,6 +7,7 @@ import { } from '../typechain'; import {VersionCreatedEvent} from '../typechain/PluginRepo'; import {PluginRepoRegisteredEvent} from '../typechain/PluginRepoRegistry'; +import {pluginDomainEnv} from './environment'; import { getNetworkNameByAlias, getLatestNetworkDeployment, @@ -163,8 +164,7 @@ export async function createPluginRepo( const {network} = hre; const signers = await ethers.getSigners(); - const pluginDomain = - process.env[`${network.name.toUpperCase()}_PLUGIN_ENS_DOMAIN`] || ''; + const pluginDomain = pluginDomainEnv(network); if ( await isENSDomainRegistered( `${subdomain}.${pluginDomain}`, diff --git a/packages/contracts/deploy/new/10_framework/00_ens_registry.ts b/packages/contracts/deploy/new/10_framework/00_ens_registry.ts index fb1a4867a..031ffbfcc 100644 --- a/packages/contracts/deploy/new/10_framework/00_ens_registry.ts +++ b/packages/contracts/deploy/new/10_framework/00_ens_registry.ts @@ -1,4 +1,5 @@ import {setupENS} from '../../../utils/ens'; +import {daoDomainEnv, pluginDomainEnv} from '../../environment'; import {ENS_ADDRESSES} from '../../helpers'; import {DeployFunction} from 'hardhat-deploy/types'; import {HardhatRuntimeEnvironment} from 'hardhat/types'; @@ -9,15 +10,8 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const {network} = hre; - // Prepare ENS. - const daoDomain = - process.env[`${network.name.toUpperCase()}_DAO_ENS_DOMAIN`] || ''; - const pluginDomain = - process.env[`${network.name.toUpperCase()}_PLUGIN_ENS_DOMAIN`] || ''; - - if (!daoDomain || !pluginDomain) { - throw new Error('DAO or Plugin ENS domains have not been set in .env'); - } + const daoDomain = daoDomainEnv(network); + const pluginDomain = pluginDomainEnv(network); const officialEnsRegistryAddress = ENS_ADDRESSES[network.name]; diff --git a/packages/contracts/deploy/new/10_framework/01_ens_subdomains.ts b/packages/contracts/deploy/new/10_framework/01_ens_subdomains.ts index e16dda9b6..48042c188 100644 --- a/packages/contracts/deploy/new/10_framework/01_ens_subdomains.ts +++ b/packages/contracts/deploy/new/10_framework/01_ens_subdomains.ts @@ -1,4 +1,5 @@ import {ENSRegistry__factory} from '../../../typechain'; +import {daoDomainEnv, pluginDomainEnv} from '../../environment'; import { getContractAddress, getENSAddress, @@ -14,14 +15,8 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const [deployer] = await ethers.getSigners(); // Get ENS subdomains - const daoDomain = - process.env[`${network.name.toUpperCase()}_DAO_ENS_DOMAIN`] || ''; - const pluginDomain = - process.env[`${network.name.toUpperCase()}_PLUGIN_ENS_DOMAIN`] || ''; - - if (!daoDomain || !pluginDomain) { - throw new Error('DAO or Plugin ENS domains have not been set in .env'); - } + const daoDomain = daoDomainEnv(network); + const pluginDomain = pluginDomainEnv(network); const ensRegistryAddress = await getENSAddress(hre); const ensRegistryContract = ENSRegistry__factory.connect( diff --git a/packages/contracts/deploy/new/10_framework/02_ens_subdomain_registrars.ts b/packages/contracts/deploy/new/10_framework/02_ens_subdomain_registrars.ts index 462f6f12a..668d22498 100644 --- a/packages/contracts/deploy/new/10_framework/02_ens_subdomain_registrars.ts +++ b/packages/contracts/deploy/new/10_framework/02_ens_subdomain_registrars.ts @@ -1,5 +1,6 @@ import ensSubdomainRegistrarArtifact from '../../../artifacts/src/framework/utils/ens/ENSSubdomainRegistrar.sol/ENSSubdomainRegistrar.json'; import {DAO__factory, ENSRegistry__factory} from '../../../typechain'; +import {daoDomainEnv, pluginDomainEnv} from '../../environment'; import {getContractAddress, getENSAddress} from '../../helpers'; import {DeployFunction} from 'hardhat-deploy/types'; import {HardhatRuntimeEnvironment} from 'hardhat/types'; @@ -19,17 +20,12 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const ensRegistryAddress = await getENSAddress(hre); - const daoDomain = - process.env[`${network.name.toUpperCase()}_DAO_ENS_DOMAIN`] || ''; - const pluginDomain = - process.env[`${network.name.toUpperCase()}_PLUGIN_ENS_DOMAIN`] || ''; + const daoDomain = daoDomainEnv(network); + const pluginDomain = pluginDomainEnv(network); + const daoNode = ethers.utils.namehash(daoDomain); const pluginNode = ethers.utils.namehash(pluginDomain); - if (!daoDomain || !pluginDomain) { - throw new Error('DAO or Plugin ENS domains have not been set in .env'); - } - await deploy('DAOENSSubdomainRegistrarProxy', { contract: ensSubdomainRegistrarArtifact, from: deployer.address, diff --git a/packages/contracts/deploy/new/10_framework/99_verifiy_step.ts b/packages/contracts/deploy/new/10_framework/99_verifiy_step.ts index 7a3b8b363..dddb354fc 100644 --- a/packages/contracts/deploy/new/10_framework/99_verifiy_step.ts +++ b/packages/contracts/deploy/new/10_framework/99_verifiy_step.ts @@ -7,6 +7,7 @@ import { PluginRepoRegistry__factory, PluginSetupProcessor__factory, } from '../../../typechain'; +import {daoDomainEnv, pluginDomainEnv} from '../../environment'; import {checkSetManagementDao, getContractAddress} from '../../helpers'; import {DeployFunction} from 'hardhat-deploy/types'; import {HardhatRuntimeEnvironment} from 'hardhat/types'; @@ -48,9 +49,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { } const node = await DAOENSSubdomainRegistrar.node(); - const expectedNode = ethers.utils.namehash( - process.env[`${hre.network.name.toUpperCase()}_DAO_ENS_DOMAIN`] || '' - ); + const expectedNode = ethers.utils.namehash(daoDomainEnv(hre.network)); if (node !== expectedNode) { throw new Error( `DAOENSSubdomainRegistrar node (${node}) doesn't match expected node (${expectedNode})` @@ -86,9 +85,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { } const node = await PluginENSSubdomainRegistrar.node(); - const expectedNode = ethers.utils.namehash( - process.env[`${hre.network.name.toUpperCase()}_PLUGIN_ENS_DOMAIN`] || '' - ); + const expectedNode = ethers.utils.namehash(pluginDomainEnv(hre.network)); if (node !== expectedNode) { throw new Error( `PluginENSSubdomainRegistrar node (${node}) doesn't match expected node (${expectedNode})` diff --git a/packages/contracts/deploy/new/40_finalize-management-dao/20_register-management-dao-on-dao-registry.ts b/packages/contracts/deploy/new/40_finalize-management-dao/20_register-management-dao-on-dao-registry.ts index 4e30a486e..5d8463c36 100644 --- a/packages/contracts/deploy/new/40_finalize-management-dao/20_register-management-dao-on-dao-registry.ts +++ b/packages/contracts/deploy/new/40_finalize-management-dao/20_register-management-dao-on-dao-registry.ts @@ -1,4 +1,5 @@ import {DAO__factory, DAORegistry__factory} from '../../../typechain'; +import {daoDomainEnv, managementDaoSubdomainEnv} from '../../environment'; import { getContractAddress, getENSAddress, @@ -14,9 +15,8 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const [deployer] = await ethers.getSigners(); // Get info from .env - const daoSubdomain = process.env.MANAGEMENT_DAO_SUBDOMAIN || ''; - const daoDomain = - process.env[`${network.name.toUpperCase()}_DAO_ENS_DOMAIN`] || ''; + const daoSubdomain = managementDaoSubdomainEnv(network); + const daoDomain = daoDomainEnv(network); if (!daoSubdomain) throw new Error('ManagementDAO subdomain has not been set in .env'); diff --git a/packages/contracts/test/deploy/detect-network.ts b/packages/contracts/test/deploy/detect-network.ts index e8868c220..c95f36016 100644 --- a/packages/contracts/test/deploy/detect-network.ts +++ b/packages/contracts/test/deploy/detect-network.ts @@ -12,6 +12,10 @@ import {network} from 'hardhat'; import {Network} from 'hardhat/types'; describe('detect network', () => { + beforeEach(() => { + process.env = {}; + }); + it('should detect the hardhat network', () => { expect(network.name).to.equal('hardhat'); }); From ecbfe540d88a9d50c0c899e43713c030030439b5 Mon Sep 17 00:00:00 2001 From: jordaniza Date: Wed, 14 Feb 2024 10:04:42 +0400 Subject: [PATCH 05/18] mgmt dao subdomain optional for hh --- .../new/40_finalize-management-dao/40_revoke-permissions.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/contracts/deploy/new/40_finalize-management-dao/40_revoke-permissions.ts b/packages/contracts/deploy/new/40_finalize-management-dao/40_revoke-permissions.ts index 3231b835e..0d5999af6 100644 --- a/packages/contracts/deploy/new/40_finalize-management-dao/40_revoke-permissions.ts +++ b/packages/contracts/deploy/new/40_finalize-management-dao/40_revoke-permissions.ts @@ -1,4 +1,5 @@ import {DAO__factory, PluginRepo__factory} from '../../../typechain'; +import {managementDaoSubdomainEnv} from '../../environment'; import {getContractAddress, managePermissions, Permission} from '../../helpers'; import {Operation} from '@aragon/osx-commons-sdk'; import {DeployFunction} from 'hardhat-deploy/types'; @@ -9,7 +10,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const [deployer] = await ethers.getSigners(); // Get info from .env - const daoSubdomain = process.env.MANAGEMENT_DAO_SUBDOMAIN || ''; + const daoSubdomain = managementDaoSubdomainEnv(hre.network); if (!daoSubdomain) throw new Error('ManagementDAO subdomain has not been set in .env'); From 5bb388c0b241d03ae4b2ef100ae67038fee106f3 Mon Sep 17 00:00:00 2001 From: jordaniza Date: Wed, 14 Feb 2024 10:33:07 +0400 Subject: [PATCH 06/18] modified deploy test and fix fail --- .../30_install-multisig-on-management-dao.ts | 14 ++++++---- .../contracts/test/deploy/managing-dao.ts | 28 +++++++++++-------- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/packages/contracts/deploy/new/40_finalize-management-dao/30_install-multisig-on-management-dao.ts b/packages/contracts/deploy/new/40_finalize-management-dao/30_install-multisig-on-management-dao.ts index 896f4a6d8..45bd72327 100644 --- a/packages/contracts/deploy/new/40_finalize-management-dao/30_install-multisig-on-management-dao.ts +++ b/packages/contracts/deploy/new/40_finalize-management-dao/30_install-multisig-on-management-dao.ts @@ -7,6 +7,10 @@ import { } from '../../../typechain'; import {InstallationPreparedEvent} from '../../../typechain/PluginSetupProcessor'; import {hashHelpers} from '../../../utils/psp'; +import { + managementDaoMultisigApproversEnv, + managementDaoMultisigMinApprovalsEnv, +} from '../../environment'; import {checkPermission, getContractAddress} from '../../helpers'; import {findEvent} from '@aragon/osx-commons-sdk'; import {Operation} from '@aragon/osx-commons-sdk'; @@ -18,7 +22,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const {ethers, network} = hre; const [deployer] = await ethers.getSigners(); - if (network.name !== 'localhost' && network.name !== 'hardhat') { + if (!['localhost', 'hardhat'].includes(network.name)) { if ( !('MANAGEMENT_DAO_MULTISIG_LISTEDONLY' in process.env) || !('MANAGEMENT_DAO_MULTISIG_MINAPPROVALS' in process.env) || @@ -28,11 +32,11 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { } } - const approvers = process.env.MANAGEMENT_DAO_MULTISIG_APPROVERS?.split( - ',' - ) || [deployer.address]; + const approvers = managementDaoMultisigApproversEnv(network).split(',') || [ + deployer.address, + ]; const minApprovals = parseInt( - process.env.MANAGEMENT_DAO_MULTISIG_MINAPPROVALS || '1' + managementDaoMultisigMinApprovalsEnv(hre.network) ); // In case `MANAGEMENT_DAO_MULTISIG_LISTEDONLY` not present in .env // which applies only hardhat/localhost, use `true` setting for extra safety for tests. diff --git a/packages/contracts/test/deploy/managing-dao.ts b/packages/contracts/test/deploy/managing-dao.ts index e042109bb..799033105 100644 --- a/packages/contracts/test/deploy/managing-dao.ts +++ b/packages/contracts/test/deploy/managing-dao.ts @@ -1,3 +1,8 @@ +import { + managementDaoMultisigApproversEnv, + managementDaoMultisigListedOnlyEnv, + managementDaoMultisigMinApprovalsEnv, +} from '../../deploy/environment'; import { DAO, DAORegistry, @@ -63,21 +68,22 @@ describe('Management DAO', function () { // deploy framework await deployAll(); - if ( - process.env.MANAGEMENT_DAO_MULTISIG_APPROVERS === undefined || - process.env.MANAGEMENT_DAO_MULTISIG_MINAPPROVALS === undefined || - process.env.MANAGEMENT_DAO_MULTISIG_LISTEDONLY === undefined - ) { - throw new Error('Management DAO Multisig settings not set in .env'); - } + const approversEnv = managementDaoMultisigApproversEnv(hre.network); + + minApprovals = parseInt(managementDaoMultisigMinApprovalsEnv(hre.network)); - listedOnly = process.env.MANAGEMENT_DAO_MULTISIG_LISTEDONLY === 'true'; + listedOnly = managementDaoMultisigListedOnlyEnv(hre.network) === 'true'; - minApprovals = parseInt(process.env.MANAGEMENT_DAO_MULTISIG_MINAPPROVALS); + if (!approversEnv || !minApprovals || !listedOnly) { + throw new Error( + 'Management DAO Multisig settings not set in .env or fallbacks' + ); + } // Get approver addresses - const approverAddresses = - process.env.MANAGEMENT_DAO_MULTISIG_APPROVERS.split(','); + const approverAddresses = managementDaoMultisigApproversEnv( + hre.network + ).split(','); // Impersonate them as signers approvers = await Promise.all( From fe6fe81440f442e9b0649c333f9f3b1287721a38 Mon Sep 17 00:00:00 2001 From: jordaniza Date: Wed, 14 Feb 2024 11:04:16 +0400 Subject: [PATCH 07/18] adjust test again --- packages/contracts/test/deploy/managing-dao.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/contracts/test/deploy/managing-dao.ts b/packages/contracts/test/deploy/managing-dao.ts index 799033105..bdad5c695 100644 --- a/packages/contracts/test/deploy/managing-dao.ts +++ b/packages/contracts/test/deploy/managing-dao.ts @@ -71,7 +71,6 @@ describe('Management DAO', function () { const approversEnv = managementDaoMultisigApproversEnv(hre.network); minApprovals = parseInt(managementDaoMultisigMinApprovalsEnv(hre.network)); - listedOnly = managementDaoMultisigListedOnlyEnv(hre.network) === 'true'; if (!approversEnv || !minApprovals || !listedOnly) { @@ -81,9 +80,7 @@ describe('Management DAO', function () { } // Get approver addresses - const approverAddresses = managementDaoMultisigApproversEnv( - hre.network - ).split(','); + const approverAddresses = approversEnv.split(','); // Impersonate them as signers approvers = await Promise.all( From 70a5eab50a231dffa8356740a22f6f12d440ba2c Mon Sep 17 00:00:00 2001 From: jordaniza Date: Wed, 14 Feb 2024 11:25:26 +0400 Subject: [PATCH 08/18] moved environment.ts to utils file --- packages/contracts/deploy/helpers.ts | 5 ++++- .../deploy/new/10_framework/00_ens_registry.ts | 2 +- .../deploy/new/10_framework/01_ens_subdomains.ts | 2 +- .../new/10_framework/02_ens_subdomain_registrars.ts | 2 +- .../deploy/new/10_framework/99_verifiy_step.ts | 2 +- .../20_register-management-dao-on-dao-registry.ts | 5 ++++- .../30_install-multisig-on-management-dao.ts | 4 ++-- .../40_revoke-permissions.ts | 2 +- packages/contracts/test/deploy/detect-network.ts | 2 +- packages/contracts/test/deploy/managing-dao.ts | 10 +++++----- packages/contracts/{deploy => utils}/environment.ts | 0 11 files changed, 21 insertions(+), 15 deletions(-) rename packages/contracts/{deploy => utils}/environment.ts (100%) diff --git a/packages/contracts/deploy/helpers.ts b/packages/contracts/deploy/helpers.ts index 9a75ca717..46d198aac 100644 --- a/packages/contracts/deploy/helpers.ts +++ b/packages/contracts/deploy/helpers.ts @@ -7,7 +7,7 @@ import { } from '../typechain'; import {VersionCreatedEvent} from '../typechain/PluginRepo'; import {PluginRepoRegisteredEvent} from '../typechain/PluginRepoRegistry'; -import {pluginDomainEnv} from './environment'; +import {pluginDomainEnv} from '../utils/environment'; import { getNetworkNameByAlias, getLatestNetworkDeployment, @@ -585,3 +585,6 @@ export function getManagementDAOMultisigAddress( } return address; } + +// hh-deploy cannot process files without default exports +export default async () => {}; diff --git a/packages/contracts/deploy/new/10_framework/00_ens_registry.ts b/packages/contracts/deploy/new/10_framework/00_ens_registry.ts index 031ffbfcc..987e71e22 100644 --- a/packages/contracts/deploy/new/10_framework/00_ens_registry.ts +++ b/packages/contracts/deploy/new/10_framework/00_ens_registry.ts @@ -1,5 +1,5 @@ import {setupENS} from '../../../utils/ens'; -import {daoDomainEnv, pluginDomainEnv} from '../../environment'; +import {daoDomainEnv, pluginDomainEnv} from '../../../utils/environment'; import {ENS_ADDRESSES} from '../../helpers'; import {DeployFunction} from 'hardhat-deploy/types'; import {HardhatRuntimeEnvironment} from 'hardhat/types'; diff --git a/packages/contracts/deploy/new/10_framework/01_ens_subdomains.ts b/packages/contracts/deploy/new/10_framework/01_ens_subdomains.ts index 48042c188..21bee6e62 100644 --- a/packages/contracts/deploy/new/10_framework/01_ens_subdomains.ts +++ b/packages/contracts/deploy/new/10_framework/01_ens_subdomains.ts @@ -1,5 +1,5 @@ import {ENSRegistry__factory} from '../../../typechain'; -import {daoDomainEnv, pluginDomainEnv} from '../../environment'; +import {daoDomainEnv, pluginDomainEnv} from '../../../utils/environment'; import { getContractAddress, getENSAddress, diff --git a/packages/contracts/deploy/new/10_framework/02_ens_subdomain_registrars.ts b/packages/contracts/deploy/new/10_framework/02_ens_subdomain_registrars.ts index 668d22498..003b5018d 100644 --- a/packages/contracts/deploy/new/10_framework/02_ens_subdomain_registrars.ts +++ b/packages/contracts/deploy/new/10_framework/02_ens_subdomain_registrars.ts @@ -1,6 +1,6 @@ import ensSubdomainRegistrarArtifact from '../../../artifacts/src/framework/utils/ens/ENSSubdomainRegistrar.sol/ENSSubdomainRegistrar.json'; import {DAO__factory, ENSRegistry__factory} from '../../../typechain'; -import {daoDomainEnv, pluginDomainEnv} from '../../environment'; +import {daoDomainEnv, pluginDomainEnv} from '../../../utils/environment'; import {getContractAddress, getENSAddress} from '../../helpers'; import {DeployFunction} from 'hardhat-deploy/types'; import {HardhatRuntimeEnvironment} from 'hardhat/types'; diff --git a/packages/contracts/deploy/new/10_framework/99_verifiy_step.ts b/packages/contracts/deploy/new/10_framework/99_verifiy_step.ts index dddb354fc..30a961aaf 100644 --- a/packages/contracts/deploy/new/10_framework/99_verifiy_step.ts +++ b/packages/contracts/deploy/new/10_framework/99_verifiy_step.ts @@ -7,7 +7,7 @@ import { PluginRepoRegistry__factory, PluginSetupProcessor__factory, } from '../../../typechain'; -import {daoDomainEnv, pluginDomainEnv} from '../../environment'; +import {daoDomainEnv, pluginDomainEnv} from '../../../utils/environment'; import {checkSetManagementDao, getContractAddress} from '../../helpers'; import {DeployFunction} from 'hardhat-deploy/types'; import {HardhatRuntimeEnvironment} from 'hardhat/types'; diff --git a/packages/contracts/deploy/new/40_finalize-management-dao/20_register-management-dao-on-dao-registry.ts b/packages/contracts/deploy/new/40_finalize-management-dao/20_register-management-dao-on-dao-registry.ts index 5d8463c36..38d56eed5 100644 --- a/packages/contracts/deploy/new/40_finalize-management-dao/20_register-management-dao-on-dao-registry.ts +++ b/packages/contracts/deploy/new/40_finalize-management-dao/20_register-management-dao-on-dao-registry.ts @@ -1,5 +1,8 @@ import {DAO__factory, DAORegistry__factory} from '../../../typechain'; -import {daoDomainEnv, managementDaoSubdomainEnv} from '../../environment'; +import { + daoDomainEnv, + managementDaoSubdomainEnv, +} from '../../../utils/environment'; import { getContractAddress, getENSAddress, diff --git a/packages/contracts/deploy/new/40_finalize-management-dao/30_install-multisig-on-management-dao.ts b/packages/contracts/deploy/new/40_finalize-management-dao/30_install-multisig-on-management-dao.ts index 45bd72327..df46d113c 100644 --- a/packages/contracts/deploy/new/40_finalize-management-dao/30_install-multisig-on-management-dao.ts +++ b/packages/contracts/deploy/new/40_finalize-management-dao/30_install-multisig-on-management-dao.ts @@ -6,11 +6,11 @@ import { PluginSetupProcessor__factory, } from '../../../typechain'; import {InstallationPreparedEvent} from '../../../typechain/PluginSetupProcessor'; -import {hashHelpers} from '../../../utils/psp'; import { managementDaoMultisigApproversEnv, managementDaoMultisigMinApprovalsEnv, -} from '../../environment'; +} from '../../../utils/environment'; +import {hashHelpers} from '../../../utils/psp'; import {checkPermission, getContractAddress} from '../../helpers'; import {findEvent} from '@aragon/osx-commons-sdk'; import {Operation} from '@aragon/osx-commons-sdk'; diff --git a/packages/contracts/deploy/new/40_finalize-management-dao/40_revoke-permissions.ts b/packages/contracts/deploy/new/40_finalize-management-dao/40_revoke-permissions.ts index 0d5999af6..248f2b5c3 100644 --- a/packages/contracts/deploy/new/40_finalize-management-dao/40_revoke-permissions.ts +++ b/packages/contracts/deploy/new/40_finalize-management-dao/40_revoke-permissions.ts @@ -1,5 +1,5 @@ import {DAO__factory, PluginRepo__factory} from '../../../typechain'; -import {managementDaoSubdomainEnv} from '../../environment'; +import {managementDaoSubdomainEnv} from '../../../utils/environment'; import {getContractAddress, managePermissions, Permission} from '../../helpers'; import {Operation} from '@aragon/osx-commons-sdk'; import {DeployFunction} from 'hardhat-deploy/types'; diff --git a/packages/contracts/test/deploy/detect-network.ts b/packages/contracts/test/deploy/detect-network.ts index c95f36016..69877fb54 100644 --- a/packages/contracts/test/deploy/detect-network.ts +++ b/packages/contracts/test/deploy/detect-network.ts @@ -6,7 +6,7 @@ import { managementDaoMultisigMinApprovalsEnv, managementDaoSubdomainEnv, pluginDomainEnv, -} from '../../deploy/environment'; +} from '../../utils/environment'; import {expect} from 'chai'; import {network} from 'hardhat'; import {Network} from 'hardhat/types'; diff --git a/packages/contracts/test/deploy/managing-dao.ts b/packages/contracts/test/deploy/managing-dao.ts index bdad5c695..a82fdcbc5 100644 --- a/packages/contracts/test/deploy/managing-dao.ts +++ b/packages/contracts/test/deploy/managing-dao.ts @@ -1,8 +1,3 @@ -import { - managementDaoMultisigApproversEnv, - managementDaoMultisigListedOnlyEnv, - managementDaoMultisigMinApprovalsEnv, -} from '../../deploy/environment'; import { DAO, DAORegistry, @@ -17,6 +12,11 @@ import { PluginRepoRegistry__factory, PluginRepo__factory, } from '../../typechain'; +import { + managementDaoMultisigApproversEnv, + managementDaoMultisigListedOnlyEnv, + managementDaoMultisigMinApprovalsEnv, +} from '../../utils/environment'; import {initializeDeploymentFixture} from '../test-utils/fixture'; import { DAO_PERMISSIONS, diff --git a/packages/contracts/deploy/environment.ts b/packages/contracts/utils/environment.ts similarity index 100% rename from packages/contracts/deploy/environment.ts rename to packages/contracts/utils/environment.ts From c39e985b0bd7ce1e78cb1738c829b62e20970158 Mon Sep 17 00:00:00 2001 From: jordaniza Date: Wed, 14 Feb 2024 11:28:24 +0400 Subject: [PATCH 09/18] use HH constant for name --- packages/contracts/utils/environment.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/contracts/utils/environment.ts b/packages/contracts/utils/environment.ts index 919b060f8..ac6bc56da 100644 --- a/packages/contracts/utils/environment.ts +++ b/packages/contracts/utils/environment.ts @@ -1,3 +1,4 @@ +import {HARDHAT_NETWORK_NAME} from 'hardhat/plugins'; import {Network} from 'hardhat/types'; /** @@ -14,7 +15,7 @@ export function env( defaultValue: string ): string { const value = process.env[name]; - const isHardhat = network.name === 'hardhat'; + const isHardhat = network.name === HARDHAT_NETWORK_NAME; if (!isHardhat && !value) { throw new Error(`Missing env var: ${name}`); } From 2c7e37c51c7b1c368eaeed6ea2016508f6a278de Mon Sep 17 00:00:00 2001 From: jordaniza Date: Wed, 14 Feb 2024 13:45:02 +0400 Subject: [PATCH 10/18] env check, readme and better structure --- packages/contracts/README.md | 44 +++++++-------- packages/contracts/deploy/env/00-env-check.ts | 53 +++++++++++++++++++ packages/contracts/deploy/helpers.ts | 2 +- .../00_management-dao/00_management-dao.ts | 1 + .../deploy/update/to_v1.3.0/10_DAOFactory.ts | 1 + packages/contracts/hardhat.config.ts | 7 ++- packages/contracts/package.json | 1 + .../{detect-network.ts => default-env.ts} | 4 ++ packages/contracts/utils/environment.ts | 13 ++++- 9 files changed, 96 insertions(+), 30 deletions(-) create mode 100644 packages/contracts/deploy/env/00-env-check.ts rename packages/contracts/test/deploy/{detect-network.ts => default-env.ts} (94%) diff --git a/packages/contracts/README.md b/packages/contracts/README.md index fb5334377..555210ea2 100644 --- a/packages/contracts/README.md +++ b/packages/contracts/README.md @@ -16,35 +16,27 @@ yarn add @aragon/osx-artifacts To get started running your repository locally: -Copy `.env.example` into a file called `.env` or create a new one with these 3 keys defined: +1. Install pacakages from the root folder with `yarn` +2. Change directory into this package (`/pacakages/contracts`) +3. Run `yarn build` to compile the contracts +4. Run `yarn test` to execute the test suite (this can take a while, so see [performance optimizations](#performance-optimizations) for ways to speed up the tests). -```sh -# keys used for running tests -HARDHAT_DAO_ENS_DOMAIN=dao.eth -HARDHAT_PLUGIN_ENS_DOMAIN=plugin.eth -MANAGEMENT_DAO_SUBDOMAIN=management -``` +## Deployment -Run these commands on the project's root folder in your terminal: +Deployments use [hardhat-deploy](https://github.com/wighawag/hardhat-deploy), and follow most of the conventions in the HH deploy docs. -```shell -npx hardhat accounts -npx hardhat compile -npx hardhat clean -npx hardhat test -npx hardhat node -npx hardhat help -REPORT_GAS=true npx hardhat test -npx hardhat coverage -npx hardhat run scripts/deploy.ts -TS_NODE_FILES=true npx ts-node scripts/deploy.ts -npx eslint '**/*.{js,ts}' -npx eslint '**/*.{js,ts}' --fix -npx prettier '**/*.{json,sol,md}' --check -npx prettier '**/*.{json,sol,md}' --write -npx solhint 'contracts/**/*.sol' -npx solhint 'contracts/**/*.sol' --fix -``` +See the [deployment checklist](../../DEPLOYMENT_CHECKLIST.md) for full details on how to deploy the contracts to a proper network. + +When testing locally: + +1. `yarn deploy` will run the test scripts against the local hardhat node. +2. `yarn dev` will spin up a persistent hardhat node and execute the deploy script against it automatically. +3. `yarn deploy:reset` will clear any prior deploy state stored by hardhat deploy. +4. `yarn deploy:local` will deploy a against a persistent localhost fork, clearing the deploy state between runs + +Default values for all required environment variables are provided when running against hardhat, check the [`.env.example`](./.env.example) for details of what these are and what they mean. + +The private key provided by default is a hardhat publically known key for `0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266`. Don't use it outside of a local development context. ## Documentation diff --git a/packages/contracts/deploy/env/00-env-check.ts b/packages/contracts/deploy/env/00-env-check.ts new file mode 100644 index 000000000..35d298ebe --- /dev/null +++ b/packages/contracts/deploy/env/00-env-check.ts @@ -0,0 +1,53 @@ +import { + daoDomainEnv, + ethKeyEnv, + managementDaoMultisigApproversEnv, + managementDaoMultisigListedOnlyEnv, + managementDaoMultisigMinApprovalsEnv, + managementDaoSubdomainEnv, + pluginDomainEnv, +} from '../../utils/environment'; +import {DeployFunction} from 'hardhat-deploy/types'; +import {HardhatRuntimeEnvironment} from 'hardhat/types'; + +/** + * Pre-deployment check for required environment variables + * Although fetching these variables throws during execution, it's nicer + * to fail early and provide a more descriptive error message and avoid submitting + * redundant transactions. + */ +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + console.log('\nChecking Required Env Vars'); + + const {network} = hre; + + // fetch env values: in localhost or hardhat network, these have defaults + const daoDomain = daoDomainEnv(network); + const pluginDomain = pluginDomainEnv(network); + const managementDaoSubdomain = managementDaoSubdomainEnv(network); + const managementDaoMultisigApprovers = + managementDaoMultisigApproversEnv(network); + const managementDaoMultisigMinApprovals = + managementDaoMultisigMinApprovalsEnv(network); + const managementDaoMultisigListedOnly = + managementDaoMultisigListedOnlyEnv(network); + const ethKey = ethKeyEnv(network); + + // technically redundant as the above functions throw if the env var is missing + if ( + !daoDomain || + !pluginDomain || + !managementDaoSubdomain || + !managementDaoMultisigApprovers || + !managementDaoMultisigMinApprovals || + !managementDaoMultisigListedOnly || + !ethKey + ) { + throw new Error('Missing required env vars'); + } + + console.log('✅ All required env vars are set'); +}; +export default func; +// set the dependencies of other functions to `Env` to ensure this check runs first +func.tags = ['Env']; diff --git a/packages/contracts/deploy/helpers.ts b/packages/contracts/deploy/helpers.ts index 46d198aac..1d0a7729c 100644 --- a/packages/contracts/deploy/helpers.ts +++ b/packages/contracts/deploy/helpers.ts @@ -130,7 +130,7 @@ export function getLatestContractAddress( const osxNetworkName = getNetworkNameByAlias(networkName); if (!osxNetworkName) { - if (networkName === 'hardhat') { + if (networkName === 'hardhat' || networkName === 'localhost') { return ''; } throw new Error(`Failed to find network ${networkName}`); diff --git a/packages/contracts/deploy/new/00_management-dao/00_management-dao.ts b/packages/contracts/deploy/new/00_management-dao/00_management-dao.ts index 3c3b12f03..9ccef0ca0 100644 --- a/packages/contracts/deploy/new/00_management-dao/00_management-dao.ts +++ b/packages/contracts/deploy/new/00_management-dao/00_management-dao.ts @@ -52,3 +52,4 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { }; export default func; func.tags = ['New', 'ManagementDao']; +func.dependencies = ['Env']; diff --git a/packages/contracts/deploy/update/to_v1.3.0/10_DAOFactory.ts b/packages/contracts/deploy/update/to_v1.3.0/10_DAOFactory.ts index b2245abeb..fc577ac9e 100644 --- a/packages/contracts/deploy/update/to_v1.3.0/10_DAOFactory.ts +++ b/packages/contracts/deploy/update/to_v1.3.0/10_DAOFactory.ts @@ -65,3 +65,4 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { }; export default func; func.tags = ['DAOFactory', 'v1.3.0']; +func.dependencies = ['Env']; diff --git a/packages/contracts/hardhat.config.ts b/packages/contracts/hardhat.config.ts index 3688f2f95..2250f2ce9 100644 --- a/packages/contracts/hardhat.config.ts +++ b/packages/contracts/hardhat.config.ts @@ -78,7 +78,12 @@ const config: HardhatUserConfig = { gasPrice: 80000000000, deploy: ENABLE_DEPLOY_TEST ? ['./deploy'] - : ['./deploy/new', './deploy/verification'], + : ['./deploy/env', './deploy/new', './deploy/verification'], + }, + localhost: { + deploy: ENABLE_DEPLOY_TEST + ? ['./deploy'] + : ['./deploy/env', './deploy/new', './deploy/verification'], }, ...hardhatNetworks, }, diff --git a/packages/contracts/package.json b/packages/contracts/package.json index f1f1b4c47..ea0a5e48d 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -22,6 +22,7 @@ "flatten": "hardhat flatten", "analyze": "mythx analyze", "deploy": "hardhat deploy", + "deploy:local": "yarn deploy --network localhost --reset", "dev": "yarn hardhat node --hostname 0.0.0.0", "prepublishOnly": "yarn build && yarn build:npm", "docgen": "hardhat docgen", diff --git a/packages/contracts/test/deploy/detect-network.ts b/packages/contracts/test/deploy/default-env.ts similarity index 94% rename from packages/contracts/test/deploy/detect-network.ts rename to packages/contracts/test/deploy/default-env.ts index 69877fb54..37e183614 100644 --- a/packages/contracts/test/deploy/detect-network.ts +++ b/packages/contracts/test/deploy/default-env.ts @@ -1,6 +1,7 @@ import { daoDomainEnv, env, + ethKeyEnv, managementDaoMultisigApproversEnv, managementDaoMultisigListedOnlyEnv, managementDaoMultisigMinApprovalsEnv, @@ -55,6 +56,9 @@ describe('detect network', () => { ); expect(managementDaoMultisigMinApprovalsEnv(network)).to.equal('1'); expect(managementDaoMultisigListedOnlyEnv(network)).to.equal('true'); + expect(ethKeyEnv(network)).to.equal( + '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80' + ); }); it('string interpolates the ENS subdomains', () => { diff --git a/packages/contracts/utils/environment.ts b/packages/contracts/utils/environment.ts index ac6bc56da..925194328 100644 --- a/packages/contracts/utils/environment.ts +++ b/packages/contracts/utils/environment.ts @@ -15,8 +15,9 @@ export function env( defaultValue: string ): string { const value = process.env[name]; - const isHardhat = network.name === HARDHAT_NETWORK_NAME; - if (!isHardhat && !value) { + const isLocal = + network.name === HARDHAT_NETWORK_NAME || network.name === 'localhost'; + if (!isLocal && !value) { throw new Error(`Missing env var: ${name}`); } return process.env[name] || defaultValue; @@ -47,3 +48,11 @@ export const managementDaoMultisigMinApprovalsEnv = ( export const managementDaoMultisigListedOnlyEnv = (network: Network): string => env(network, 'MANAGEMENT_DAO_MULTISIG_LISTEDONLY', 'true'); + +// corresponds to known hardhat account 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 +export const ethKeyEnv = (network: Network): string => + env( + network, + 'ETH_KEY', + '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80' + ); From 45b37593908d704d0a6b124dc1c00a8879bdf35d Mon Sep 17 00:00:00 2001 From: Jordan <45881807+jordaniza@users.noreply.github.com> Date: Wed, 14 Feb 2024 16:06:14 +0400 Subject: [PATCH 11/18] Update packages/contracts/utils/environment.ts Proper punctuation in doc comments Co-authored-by: Michael Heuer <20623991+Michael-A-Heuer@users.noreply.github.com> --- packages/contracts/utils/environment.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/contracts/utils/environment.ts b/packages/contracts/utils/environment.ts index 925194328..f9db6ea2f 100644 --- a/packages/contracts/utils/environment.ts +++ b/packages/contracts/utils/environment.ts @@ -4,10 +4,10 @@ import {Network} from 'hardhat/types'; /** * Provides default values for environment variables if running against a hardhat node * else requires that the environment variables are set - * @param network the hardhat network object - * @param name of the environment variable - * @param defaultValue the fallback value to be used if not set and in development mode - * @returns the value of the environment variable, or a fallback if possible + * @param network The hardhat network object. + * @param name The name of the environment variable. + * @param defaultValue The fallback value to be used if not set and in development mode. + * @returns The value of the environment variable, or a fallback if possible. */ export function env( network: Network, From 751fc979deab43fde5ae8caa302d3e8ef2d15205 Mon Sep 17 00:00:00 2001 From: Jordan <45881807+jordaniza@users.noreply.github.com> Date: Wed, 14 Feb 2024 18:42:51 +0400 Subject: [PATCH 12/18] Update packages/contracts/README.md typo Co-authored-by: Michael Heuer <20623991+Michael-A-Heuer@users.noreply.github.com> --- packages/contracts/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/contracts/README.md b/packages/contracts/README.md index 555210ea2..dcec5871c 100644 --- a/packages/contracts/README.md +++ b/packages/contracts/README.md @@ -16,7 +16,7 @@ yarn add @aragon/osx-artifacts To get started running your repository locally: -1. Install pacakages from the root folder with `yarn` +1. Install packages from the root folder with `yarn` 2. Change directory into this package (`/pacakages/contracts`) 3. Run `yarn build` to compile the contracts 4. Run `yarn test` to execute the test suite (this can take a while, so see [performance optimizations](#performance-optimizations) for ways to speed up the tests). From 17633a0f100b61494c6e40cc8b564661edebd1b8 Mon Sep 17 00:00:00 2001 From: jordaniza Date: Thu, 15 Feb 2024 17:58:05 +0400 Subject: [PATCH 13/18] wip but test broken --- packages/contracts/deploy/helpers.ts | 4 ++-- .../30_install-multisig-on-management-dao.ts | 3 ++- .../verification/99_conclude/10_verify-contracts.ts | 7 ++----- .../02-plugin-development/07-publication/index.md | 2 +- .../test/framework/plugin/plugin-setup-processor.ts | 11 +++++++---- packages/contracts/utils/environment.ts | 7 ++++--- 6 files changed, 18 insertions(+), 16 deletions(-) diff --git a/packages/contracts/deploy/helpers.ts b/packages/contracts/deploy/helpers.ts index 98e14432d..912853157 100644 --- a/packages/contracts/deploy/helpers.ts +++ b/packages/contracts/deploy/helpers.ts @@ -7,7 +7,7 @@ import { } from '../typechain'; import {VersionCreatedEvent} from '../typechain/PluginRepo'; import {PluginRepoRegisteredEvent} from '../typechain/PluginRepoRegistry'; -import {pluginDomainEnv} from '../utils/environment'; +import {isLocal, pluginDomainEnv} from '../utils/environment'; import { getNetworkNameByAlias, getLatestNetworkDeployment, @@ -130,7 +130,7 @@ export function getLatestContractAddress( const osxNetworkName = getNetworkNameByAlias(networkName); if (!osxNetworkName) { - if (networkName === 'hardhat' || networkName === 'localhost') { + if (isLocal(hre.network)) { return ''; } throw new Error(`Failed to find network ${networkName}`); diff --git a/packages/contracts/deploy/new/40_finalize-management-dao/30_install-multisig-on-management-dao.ts b/packages/contracts/deploy/new/40_finalize-management-dao/30_install-multisig-on-management-dao.ts index df46d113c..b9076f9f3 100644 --- a/packages/contracts/deploy/new/40_finalize-management-dao/30_install-multisig-on-management-dao.ts +++ b/packages/contracts/deploy/new/40_finalize-management-dao/30_install-multisig-on-management-dao.ts @@ -7,6 +7,7 @@ import { } from '../../../typechain'; import {InstallationPreparedEvent} from '../../../typechain/PluginSetupProcessor'; import { + isLocal, managementDaoMultisigApproversEnv, managementDaoMultisigMinApprovalsEnv, } from '../../../utils/environment'; @@ -22,7 +23,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const {ethers, network} = hre; const [deployer] = await ethers.getSigners(); - if (!['localhost', 'hardhat'].includes(network.name)) { + if (!isLocal(network)) { if ( !('MANAGEMENT_DAO_MULTISIG_LISTEDONLY' in process.env) || !('MANAGEMENT_DAO_MULTISIG_MINAPPROVALS' in process.env) || diff --git a/packages/contracts/deploy/verification/99_conclude/10_verify-contracts.ts b/packages/contracts/deploy/verification/99_conclude/10_verify-contracts.ts index 779d98715..76e4745b2 100644 --- a/packages/contracts/deploy/verification/99_conclude/10_verify-contracts.ts +++ b/packages/contracts/deploy/verification/99_conclude/10_verify-contracts.ts @@ -1,3 +1,4 @@ +import {isLocal} from '../../../utils/environment'; import {verifyContract} from '../../../utils/etherscan'; import {DeployFunction} from 'hardhat-deploy/types'; import {HardhatRuntimeEnvironment} from 'hardhat/types'; @@ -29,8 +30,4 @@ export default func; func.tags = ['New', 'Verify']; func.runAtTheEnd = true; func.skip = (hre: HardhatRuntimeEnvironment) => - Promise.resolve( - hre.network.name === 'localhost' || - hre.network.name === 'hardhat' || - hre.network.name === 'coverage' - ); + Promise.resolve(isLocal(hre.network)); diff --git a/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/07-publication/index.md b/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/07-publication/index.md index 0b6bf0975..649bdb4bd 100644 --- a/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/07-publication/index.md +++ b/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/07-publication/index.md @@ -63,7 +63,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { // Get the plugin factory address let pluginRepoFactoryAddr: string; - if (network.name === 'localhost' || network.name === 'hardhat' || network.name === 'coverage') { + if (isLocal(network)) { const hardhatForkNetwork = process.env.HARDHAT_FORK_NETWORK ? process.env.HARDHAT_FORK_NETWORK : 'mainnet'; diff --git a/packages/contracts/test/framework/plugin/plugin-setup-processor.ts b/packages/contracts/test/framework/plugin/plugin-setup-processor.ts index fe2d4c7af..f1dac49ad 100644 --- a/packages/contracts/test/framework/plugin/plugin-setup-processor.ts +++ b/packages/contracts/test/framework/plugin/plugin-setup-processor.ts @@ -1992,11 +1992,14 @@ describe('PluginSetupProcessor', function () { ).to.be.reverted; }); - describe('Whether upgrade functions of proxy get called the right way', async () => { + describe.only('Whether upgrade functions of proxy get called the right way', async () => { let fake: any; beforeEach(async () => { // create a fake on the same plugin(proxy) address. + + console.log({proxy, pluginUUPSUpgradeableArtifact}); + fake = await smock.fake(pluginUUPSUpgradeableArtifact, { address: proxy, }); @@ -2005,9 +2008,9 @@ describe('PluginSetupProcessor', function () { // Solidity default values, the below overrides them with the correct data // So when PSP calls it, it can expect the same information as if it would call // the normal/original `proxy/plugin`. - fake.supportsInterface.whenCalledWith('0xffffffff').returns(false); - fake.supportsInterface.whenCalledWith('0x01ffc9a7').returns(true); - fake.supportsInterface.whenCalledWith('0x41de6830').returns(true); + // fake.supportsInterface.whenCalledWith('0xffffffff').returns(false); + // fake.supportsInterface.whenCalledWith('0x01ffc9a7').returns(true); + // fake.supportsInterface.whenCalledWith('0x41de6830').returns(true); }); it('correctly applies updates when plugin setups are same, but UI different', async () => { diff --git a/packages/contracts/utils/environment.ts b/packages/contracts/utils/environment.ts index f9db6ea2f..f94bf80e2 100644 --- a/packages/contracts/utils/environment.ts +++ b/packages/contracts/utils/environment.ts @@ -1,6 +1,9 @@ import {HARDHAT_NETWORK_NAME} from 'hardhat/plugins'; import {Network} from 'hardhat/types'; +export const isLocal = (network: Network): boolean => + [HARDHAT_NETWORK_NAME, 'localhost', 'coverage'].includes(network.name); + /** * Provides default values for environment variables if running against a hardhat node * else requires that the environment variables are set @@ -15,9 +18,7 @@ export function env( defaultValue: string ): string { const value = process.env[name]; - const isLocal = - network.name === HARDHAT_NETWORK_NAME || network.name === 'localhost'; - if (!isLocal && !value) { + if (!isLocal(network) && !value) { throw new Error(`Missing env var: ${name}`); } return process.env[name] || defaultValue; From 2ca435068289396682e8fedd4e69c2b8cddeaabc Mon Sep 17 00:00:00 2001 From: jordaniza Date: Thu, 15 Feb 2024 18:58:09 +0400 Subject: [PATCH 14/18] updated checklist --- UPDATE_CHECKLIST.md | 1 + 1 file changed, 1 insertion(+) diff --git a/UPDATE_CHECKLIST.md b/UPDATE_CHECKLIST.md index 16cdb25eb..1aa8d80c3 100644 --- a/UPDATE_CHECKLIST.md +++ b/UPDATE_CHECKLIST.md @@ -30,6 +30,7 @@ This checklist is seen as a guide to update the existing deployment. - [ ] If new plugin builds are released - [ ] Double-check that the build- and release-metadata is published and updated correctly by the deploy script and contracts - [ ] If the plugin is used by the management DAO and the new build includes security relevant changes it must be applied immediately +- [ ] If adding any new files to the deploy script, check the tags and func.dependencies to ensure the `00-env-check.ts` file can be run. This can be done by adding the `func.dependencies = ['Env']` to the function. ## Update From d10fffb806988542d609b4c5cdf4168d211fe2b4 Mon Sep 17 00:00:00 2001 From: jordaniza Date: Thu, 15 Feb 2024 19:54:32 +0400 Subject: [PATCH 15/18] less magic strings for HH accounts --- packages/contracts/test/deploy/default-env.ts | 7 +++-- .../plugin/plugin-setup-processor.ts | 11 +++----- packages/contracts/utils/environment.ts | 26 ++++++++++++------- 3 files changed, 23 insertions(+), 21 deletions(-) diff --git a/packages/contracts/test/deploy/default-env.ts b/packages/contracts/test/deploy/default-env.ts index 37e183614..f244c67a0 100644 --- a/packages/contracts/test/deploy/default-env.ts +++ b/packages/contracts/test/deploy/default-env.ts @@ -1,4 +1,5 @@ import { + HARDHAT_ACCOUNTS, daoDomainEnv, env, ethKeyEnv, @@ -52,13 +53,11 @@ describe('detect network', () => { expect(pluginDomainEnv(network)).to.equal('plugin.eth'); expect(managementDaoSubdomainEnv(network)).to.equal('management'); expect(managementDaoMultisigApproversEnv(network)).to.equal( - '0x6B2b5d4F0a40134189330e2d46a9CDD01C01AECD' + HARDHAT_ACCOUNTS[0].ADDRESS ); expect(managementDaoMultisigMinApprovalsEnv(network)).to.equal('1'); expect(managementDaoMultisigListedOnlyEnv(network)).to.equal('true'); - expect(ethKeyEnv(network)).to.equal( - '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80' - ); + expect(ethKeyEnv(network)).to.equal(HARDHAT_ACCOUNTS[1].KEY); }); it('string interpolates the ENS subdomains', () => { diff --git a/packages/contracts/test/framework/plugin/plugin-setup-processor.ts b/packages/contracts/test/framework/plugin/plugin-setup-processor.ts index f1dac49ad..fe2d4c7af 100644 --- a/packages/contracts/test/framework/plugin/plugin-setup-processor.ts +++ b/packages/contracts/test/framework/plugin/plugin-setup-processor.ts @@ -1992,14 +1992,11 @@ describe('PluginSetupProcessor', function () { ).to.be.reverted; }); - describe.only('Whether upgrade functions of proxy get called the right way', async () => { + describe('Whether upgrade functions of proxy get called the right way', async () => { let fake: any; beforeEach(async () => { // create a fake on the same plugin(proxy) address. - - console.log({proxy, pluginUUPSUpgradeableArtifact}); - fake = await smock.fake(pluginUUPSUpgradeableArtifact, { address: proxy, }); @@ -2008,9 +2005,9 @@ describe('PluginSetupProcessor', function () { // Solidity default values, the below overrides them with the correct data // So when PSP calls it, it can expect the same information as if it would call // the normal/original `proxy/plugin`. - // fake.supportsInterface.whenCalledWith('0xffffffff').returns(false); - // fake.supportsInterface.whenCalledWith('0x01ffc9a7').returns(true); - // fake.supportsInterface.whenCalledWith('0x41de6830').returns(true); + fake.supportsInterface.whenCalledWith('0xffffffff').returns(false); + fake.supportsInterface.whenCalledWith('0x01ffc9a7').returns(true); + fake.supportsInterface.whenCalledWith('0x41de6830').returns(true); }); it('correctly applies updates when plugin setups are same, but UI different', async () => { diff --git a/packages/contracts/utils/environment.ts b/packages/contracts/utils/environment.ts index f94bf80e2..8d1602328 100644 --- a/packages/contracts/utils/environment.ts +++ b/packages/contracts/utils/environment.ts @@ -4,8 +4,20 @@ import {Network} from 'hardhat/types'; export const isLocal = (network: Network): boolean => [HARDHAT_NETWORK_NAME, 'localhost', 'coverage'].includes(network.name); +// known hardhat accounts and private keys unlocked by default in the HH node +export const HARDHAT_ACCOUNTS: Array<{KEY: string; ADDRESS: string}> = [ + { + KEY: '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80', + ADDRESS: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', + }, + { + KEY: '0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d', + ADDRESS: '0x70997970C51812dc3A010C7d01b50e0d17dc79C8', + }, +] as const; + /** - * Provides default values for environment variables if running against a hardhat node + * Provides default values for environment variables if running in local * else requires that the environment variables are set * @param network The hardhat network object. * @param name The name of the environment variable. @@ -24,7 +36,7 @@ export function env( return process.env[name] || defaultValue; } -/// Specific environment variables with hardcoded defaults +/// Specific environment variables with hardcoded defaults in local environments export const daoDomainEnv = (network: Network): string => env(network, `${network.name.toUpperCase()}_DAO_ENS_DOMAIN`, 'dao.eth'); @@ -39,8 +51,7 @@ export const managementDaoMultisigApproversEnv = (network: Network): string => env( network, 'MANAGEMENT_DAO_MULTISIG_APPROVERS', - // random address - '0x6B2b5d4F0a40134189330e2d46a9CDD01C01AECD' + HARDHAT_ACCOUNTS[0].ADDRESS ); export const managementDaoMultisigMinApprovalsEnv = ( @@ -50,10 +61,5 @@ export const managementDaoMultisigMinApprovalsEnv = ( export const managementDaoMultisigListedOnlyEnv = (network: Network): string => env(network, 'MANAGEMENT_DAO_MULTISIG_LISTEDONLY', 'true'); -// corresponds to known hardhat account 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 export const ethKeyEnv = (network: Network): string => - env( - network, - 'ETH_KEY', - '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80' - ); + env(network, 'ETH_KEY', HARDHAT_ACCOUNTS[1].KEY); From 2b8b7131a15dfbe5aac5adeec314eba125e23dba Mon Sep 17 00:00:00 2001 From: jordaniza Date: Thu, 15 Feb 2024 19:56:18 +0400 Subject: [PATCH 16/18] rm deploy fallback in script --- .../30_install-multisig-on-management-dao.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/contracts/deploy/new/40_finalize-management-dao/30_install-multisig-on-management-dao.ts b/packages/contracts/deploy/new/40_finalize-management-dao/30_install-multisig-on-management-dao.ts index b9076f9f3..055042f68 100644 --- a/packages/contracts/deploy/new/40_finalize-management-dao/30_install-multisig-on-management-dao.ts +++ b/packages/contracts/deploy/new/40_finalize-management-dao/30_install-multisig-on-management-dao.ts @@ -33,9 +33,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { } } - const approvers = managementDaoMultisigApproversEnv(network).split(',') || [ - deployer.address, - ]; + const approvers = managementDaoMultisigApproversEnv(network).split(','); const minApprovals = parseInt( managementDaoMultisigMinApprovalsEnv(hre.network) ); From aec408e9e3789654ca364f0e466ea1eff219352c Mon Sep 17 00:00:00 2001 From: Jordan <45881807+jordaniza@users.noreply.github.com> Date: Fri, 16 Feb 2024 11:03:50 +0400 Subject: [PATCH 17/18] Update UPDATE_CHECKLIST.md Co-authored-by: Michael Heuer <20623991+Michael-A-Heuer@users.noreply.github.com> --- UPDATE_CHECKLIST.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UPDATE_CHECKLIST.md b/UPDATE_CHECKLIST.md index 1aa8d80c3..34124a891 100644 --- a/UPDATE_CHECKLIST.md +++ b/UPDATE_CHECKLIST.md @@ -30,7 +30,7 @@ This checklist is seen as a guide to update the existing deployment. - [ ] If new plugin builds are released - [ ] Double-check that the build- and release-metadata is published and updated correctly by the deploy script and contracts - [ ] If the plugin is used by the management DAO and the new build includes security relevant changes it must be applied immediately -- [ ] If adding any new files to the deploy script, check the tags and func.dependencies to ensure the `00-env-check.ts` file can be run. This can be done by adding the `func.dependencies = ['Env']` to the function. +- [ ] Check all the tags and `func.dependencies` to ensure the `00-env-check.ts` file is executed at the beginning of the deployment. ## Update From c5b5c1bbc60732ae286ce15aff27071d1f0d43fd Mon Sep 17 00:00:00 2001 From: jordaniza Date: Fri, 16 Feb 2024 11:06:02 +0400 Subject: [PATCH 18/18] update deploy to match update cchecklist --- DEPLOYMENT_CHECKLIST.md | 1 + 1 file changed, 1 insertion(+) diff --git a/DEPLOYMENT_CHECKLIST.md b/DEPLOYMENT_CHECKLIST.md index a17077ca5..898368826 100644 --- a/DEPLOYMENT_CHECKLIST.md +++ b/DEPLOYMENT_CHECKLIST.md @@ -32,6 +32,7 @@ This checklist is seen as a guide to deploy the stack to a new chain. - [ ] Set the amount of minimum approvals the management DAO needs to `MANAGEMENT_DAO_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 +- [ ] Check all the tags and `func.dependencies` to ensure the `00-env-check.ts` file is executed at the beginning of the deployment. ## Deployment