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

feat: localhost and hardhat deploy can be run with zero config #539

Merged
merged 19 commits into from
Feb 19, 2024
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
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
44 changes: 18 additions & 26 deletions packages/contracts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`
jordaniza marked this conversation as resolved.
Show resolved Hide resolved
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

Expand Down
53 changes: 53 additions & 0 deletions packages/contracts/deploy/env/00-env-check.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import {
jordaniza marked this conversation as resolved.
Show resolved Hide resolved
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'];
9 changes: 6 additions & 3 deletions packages/contracts/deploy/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
} from '../typechain';
import {VersionCreatedEvent} from '../typechain/PluginRepo';
import {PluginRepoRegisteredEvent} from '../typechain/PluginRepoRegistry';
import {pluginDomainEnv} from '../utils/environment';
import {
getNetworkNameByAlias,
getLatestNetworkDeployment,
Expand Down Expand Up @@ -129,7 +130,7 @@ export function getLatestContractAddress(

const osxNetworkName = getNetworkNameByAlias(networkName);
if (!osxNetworkName) {
if (networkName === 'hardhat') {
if (networkName === 'hardhat' || networkName === 'localhost') {
jordaniza marked this conversation as resolved.
Show resolved Hide resolved
return '';
}
throw new Error(`Failed to find network ${networkName}`);
Expand Down Expand Up @@ -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}`,
Expand Down Expand Up @@ -585,3 +585,6 @@ export function getManagementDAOMultisigAddress(
}
return address;
}

// hh-deploy cannot process files without default exports
export default async () => {};
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,4 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
};
export default func;
func.tags = ['New', 'ManagementDao'];
func.dependencies = ['Env'];
12 changes: 3 additions & 9 deletions packages/contracts/deploy/new/10_framework/00_ens_registry.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {setupENS} from '../../../utils/ens';
import {daoDomainEnv, pluginDomainEnv} from '../../../utils/environment';
import {ENS_ADDRESSES} from '../../helpers';
import {DeployFunction} from 'hardhat-deploy/types';
import {HardhatRuntimeEnvironment} from 'hardhat/types';
Expand All @@ -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];

Expand Down
11 changes: 3 additions & 8 deletions packages/contracts/deploy/new/10_framework/01_ens_subdomains.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {ENSRegistry__factory} from '../../../typechain';
import {daoDomainEnv, pluginDomainEnv} from '../../../utils/environment';
import {
getContractAddress,
getENSAddress,
Expand All @@ -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(
Expand Down
Original file line number Diff line number Diff line change
@@ -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 '../../../utils/environment';
import {getContractAddress, getENSAddress} from '../../helpers';
import {DeployFunction} from 'hardhat-deploy/types';
import {HardhatRuntimeEnvironment} from 'hardhat/types';
Expand All @@ -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,
Expand Down
9 changes: 3 additions & 6 deletions packages/contracts/deploy/new/10_framework/99_verifiy_step.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
PluginRepoRegistry__factory,
PluginSetupProcessor__factory,
} from '../../../typechain';
import {daoDomainEnv, pluginDomainEnv} from '../../../utils/environment';
import {checkSetManagementDao, getContractAddress} from '../../helpers';
import {DeployFunction} from 'hardhat-deploy/types';
import {HardhatRuntimeEnvironment} from 'hardhat/types';
Expand Down Expand Up @@ -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})`
Expand Down Expand Up @@ -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})`
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import {DAO__factory, DAORegistry__factory} from '../../../typechain';
import {
daoDomainEnv,
managementDaoSubdomainEnv,
} from '../../../utils/environment';
import {
getContractAddress,
getENSAddress,
Expand All @@ -14,9 +18,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');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import {
PluginSetupProcessor__factory,
} from '../../../typechain';
import {InstallationPreparedEvent} from '../../../typechain/PluginSetupProcessor';
import {
managementDaoMultisigApproversEnv,
managementDaoMultisigMinApprovalsEnv,
} from '../../../utils/environment';
import {hashHelpers} from '../../../utils/psp';
import {checkPermission, getContractAddress} from '../../helpers';
import {findEvent} from '@aragon/osx-commons-sdk';
Expand All @@ -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)) {
Copy link
Contributor

@heueristik heueristik Feb 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (
!('MANAGEMENT_DAO_MULTISIG_LISTEDONLY' in process.env) ||
!('MANAGEMENT_DAO_MULTISIG_MINAPPROVALS' in process.env) ||
Expand All @@ -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,
];
jordaniza marked this conversation as resolved.
Show resolved Hide resolved
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.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {DAO__factory, PluginRepo__factory} from '../../../typechain';
import {managementDaoSubdomainEnv} from '../../../utils/environment';
import {getContractAddress, managePermissions, Permission} from '../../helpers';
import {Operation} from '@aragon/osx-commons-sdk';
import {DeployFunction} from 'hardhat-deploy/types';
Expand All @@ -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');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,4 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
};
export default func;
func.tags = ['DAOFactory', 'v1.3.0'];
func.dependencies = ['Env'];
7 changes: 6 additions & 1 deletion packages/contracts/hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
},
Expand Down
1 change: 1 addition & 0 deletions packages/contracts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
35 changes: 9 additions & 26 deletions packages/contracts/src/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down
Loading
Loading