Skip to content

Commit

Permalink
feat: add npm scripts using during live deployments
Browse files Browse the repository at this point in the history
  • Loading branch information
adjisb committed Sep 15, 2023
1 parent f0b742a commit c388bd4
Show file tree
Hide file tree
Showing 5 changed files with 257 additions and 198 deletions.
73 changes: 53 additions & 20 deletions packages/deploy/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,26 +39,59 @@ where:
## Testing

We assume that the imported contracts are well tested in their own package by having enough unit tests and more that 80%
coverage. This repo contains integrations tests and tests that verify the integrity of the system. For example in the
case of the `SignedMultiGiveaway` contract we check the roles and the users assigned to them are correctly configured.

The tests can be run in different contexts:

- on hardhat:
- run all the deployment scripts just to test them: `yarn deploy`
- run the integration tests using `hardhat-deploy` fixtures: `yarn test`
- on a real network `testnet` or `mainnet`, run the integration tests over contracts already deployed and fail if
something is wrong, for example: `yarn test --network mumbai`
- to run on a fork of some network the following environment variables must be set:
- HARDHAT_DEPLOY_FIXTURE=true
- HARDHAT_FORK=mumbai
- HARDHAT_DEPLOY_ACCOUNTS_NETWORK=mumbai

and then `yarn test` can be executed for integration tests or `yarn deploy`
with or without tags to test just the deployment scripts.

To simplify the execution of the integration tests over forks the following targets are added to the package.json
file: `fork:mainnet`, `fork:polygon`, `fork:goerli` and `fork:mumbai`.
coverage. This repo contains integrations tests, tests for the deployment process and tests that verify the integrity of
the system. For example in the case of the `SignedMultiGiveaway` contract we check the roles and the users assigned to
them are correctly configured.

To test the deployment process:

- run all the deployment scripts on the hardhat local node just to test them: `yarn deploy`
- run the deployments scripts over a forks of a live network: `fork:deploy NETWORK` where NETWORK is `mainnet`,`polygon`
,`goerli`,`mumbai`, etc.

The tests the integrity of the system:

- using hardhat local node and `hardhat-deploy` deployment scripts: `yarn test`
- on a live network over contracts that are already deployed: `yarn test --network NETWORK`. Where NETWORK is `mainnet`
, `polygon`, `mumbai`, etc.
- on a fork of a live network and `hardhat-deploy` deployment scripts: `yarn fork:test NETWORK` where NETWORK
is `mainnet`,`polygon`,`goerli`,`mumbai`, etc.

### Tweaking hardhat when forking a live network

We are using some tricks to control the way we run `hardhat` and `hardhat-deploy` when forking live networks. We change
the `hardhat` configuration depending on some environment variables to be able to run the fork, avoid running some
deployment scripts or skip the deployment scripts at all. The following table describes the environment variables and
their use:

| Environment variable | Origin | Description |
|----------------------------------------|-------------------|-----------------------------------------------------|
| HARDHAT_FORK=mumbai | hardhat.config.ts | configure the hardhat network with forking enabled |
| HARDHAT_DEPLOY_ACCOUNTS_NETWORK=mumbai | hardhat-deploy | use this network for [named accounts](https://github.com/wighawag/hardhat-deploy#1-namedaccounts-ability-to-name-addresses)|
| HARDHAT_DEPLOY_FIXTURE=true | hardhat-deploy | run the deployment scripts before running the tests |
| HARDHAT_DEPLOY_NO_IMPERSONATION=true | hardhat-deploy | Optional. Don't [impersonate unknown accounts](https://hardhat.org/hardhat-network/docs/reference#hardhat_impersonateaccount)|
| HARDHAT_FORK_INCLUDE_MOCKS=false | hardhat.config.ts | Optional. Include mock deploy scripts in the fork |
| HARDHAT_SKIP_FIXTURES=false | hardhat.config.ts | Optional. Skip all the deployment scripts |
| HARDHAT_FORK_NUMBER=9999999999 | hardhat.config.ts | Optional. Forking block number |

There is a `npmScriptHlper` script used in the `package.json` file to simplify the execution of hardhat while setting
the right environment variables. Run `node utils/npmScriptHelper.js` to see the script usage.

## Contract verification

To verify the contracts we use
the [hardhat-deploy](https://github.com/wighawag/hardhat-deploy#4-hardhat-etherscan-verify)
plugin support for verification, check the manual for details.

To do the verification on etherscan/polygonscan you must:

- set the environment variable `ETHERSCAN_API_KEY` with the api-key obtained from the etherscan in the `.env` file
- run the following command: `yarn hardhat etherscan-verify --network NETWORK`, where NETWORK is mainnet, polygon,
mumbai, etc.

To verify just one contract add the `--contract-name CONTRACT_NAME` argument where CONTRACT_NAME is the name of the
contract to verify, if you are using upgradable contract you must verify `CONTRACT_NAME_Proxy`
and `CONTRACT_NAME_Implementation` separately.

# Adding contract from a new package

Expand Down
195 changes: 22 additions & 173 deletions packages/deploy/hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ import '@nomicfoundation/hardhat-chai-matchers';
import '@nomicfoundation/hardhat-network-helpers';
import '@nomiclabs/hardhat-ethers';
import 'hardhat-deploy';
import {addForkingSupport, addNodeAndMnemonic} from './utils/hardhatConfig';
import {
addForkingSupport,
addNodeAndMnemonic,
skipDeploymentsOnLiveNetworks,
} from './utils/hardhatConfig';
import './tasks/importedPackages';

// Package name : solidity source code path
Expand All @@ -28,173 +32,16 @@ const namedAccounts = {
mumbai: '0x49c4D4C94829B9c44052C5f5Cb164Fc612181165',
}, // can add super operators and change admin

operationsAdmin: {
default: 2,
mainnet: '0x6ec4090d0F3cB76d9f3D8c4D5BB058A225E560a1',
polygon: 'sandAdmin',
},

upgradeAdmin: 'sandAdmin',

multiGiveawayAdmin: {
default: 'sandAdmin',
mainnet: 'operationsAdmin',
polygon: 'sandAdmin',
},

liquidityRewardProvider: {
default: 'sandBeneficiary',
mainnet: '0x8FFA64FB50559c3Ff09a1022b84B2c5233ed8068',
},
liquidityRewardAdmin: 'sandAdmin',

kyberDepositor: {
default: 'sandBeneficiary',
mainnet: 'liquidityRewardProvider',
},

sandExecutionAdmin: 'sandAdmin', // can add execution extension to SAND (used for Native metatx support)
mintingFeeCollector: 'sandAdmin', // will receiver the fee from Asset minting
sandBeneficiary: 'sandAdmin', // will be the owner of all initial SAND
assetAdmin: 'sandAdmin', // can add super operator and change admin to Asset
assetMinterAdmin: 'sandAdmin', // can set metaTxProcessors & types
assetBouncerAdmin: 'sandAdmin', // setup the contract allowed to mint Assets
sandSaleAdmin: 'sandAdmin', // can pause the sandSale and withdraw SAND
genesisBouncerAdmin: 'sandAdmin', // can set who is allowed to mint
defaultMinterAdmin: 'sandAdmin', // can change the fees
genesisMinter: 'sandAdmin', // the first account allowed to mint genesis Assets
assetAuctionFeeCollector: 'sandSaleBeneficiary', // collect fees from asset auctions
assetAuctionAdmin: 'sandAdmin', // can change fee collector

sandSaleBeneficiary: {
default: 3,
mainnet: '0x0EB04462D69B1D267d269377E34f60b9De1c8510',
polygon: '0xbc4fE9A8a46442eDaF13Bd5c615D7CFe0953885B',
goerli: '0xF22455c7F2a81E197AecD951F588a9B650f5b282',
mumbai: '0xa5Eb9C9Eb4F4c35B9Be8cFaAA7909F9ebe6Cb609',
},

treasury: {
default: 'sandSaleBeneficiary',
mainnet: '0x4489590a116618B506F0EfE885432F6A8ED998E9',
polygon: '0x1b47567CBE36e63293A7A2018F79687f942aB24C',
},

landSaleBeneficiary: {
default: 'sandSaleBeneficiary',
mainnet: 'treasury',
polygon: 'treasury',
}, // updated to company treasury wallet 9th September - collect funds from land sales

catalystAssetFeeRecipient: 'treasury',

landSaleFeeRecipient: {
default: 3,
goerli: 5,
mumbai: 5,
mainnet: 'sandSaleBeneficiary',
polygon: '0x42a4a3795446A4c070565da201c6303fC78a2569',
}, // collect 5% fee from land sales (prior to implementation of FeeDistributor)

landAdmin: {
default: 2,
mainnet: 'sandAdmin',
polygon: '0xe75Ce341C98400a45F579e32C95fF49681Fc93fa',
goerli: 'sandAdmin',
mumbai: 'sandAdmin',
}, // can add super operators and change admin

gemsAndCatalystsAdmin: 'sandAdmin',
assetAttributesRegistryAdmin: 'sandAdmin',
proxyAdminOwner: {
default: 2,
mainnet: 'sandAdmin',
polygon: 'landAdmin',
goerli: 'sandAdmin',
mumbai: 'sandAdmin',
},

landSaleAdmin: 'sandAdmin', // can enable currencies
gameTokenAdmin: 'sandAdmin', // can set minter address
gameTokenFeeBeneficiary: 'treasury', // receives fees from GAME token minting / Mods
estateAdmin: 'sandAdmin', // can add super operators and change admin
P2PERC721SaleAdmin: 'sandAdmin', // can set fees
backendReferralWallet: {
backendCashbackWallet: {
// default is computed from private key:
// "0x4242424242424242424242424242424242424242424242424242424242424242"
default: '0x17c5185167401eD00cF5F5b2fc97D9BBfDb7D025',
mainnet: '0x3044719d139F866a44c988823513eCB93060bF1b',
polygon: '0x3044719d139F866a44c988823513eCB93060bF1b',
polygon: '0x564c8aADBd35b6175C0d18595cc335106AA250Dc',
goerli: '0xB7060D3FeCAC3AE1F0A0AA416E3e8E472257950e',
mumbai: '0xB7060D3FeCAC3AE1F0A0AA416E3e8E472257950e',
},
// To be used with AuthValidator only
backendAuthWallet: {
// default is computed from private key:
// "0x4242424242424242424242424242424242424242424242424242424242424242"
default: 'backendReferralWallet',
mainnet: '0x061872DFd0CAC4Ec7a7c87EEE9B950bb1fAD2906',
goerli: '0x0c72f82B46f034025622731c271bdf06B848Ed77',
polygon: '0x061872DFd0CAC4Ec7a7c87EEE9B950bb1fAD2906',
mumbai: '0x0c72f82B46f034025622731c271bdf06B848Ed77',
},
backendCashbackWallet: {
// default is computed from private key:
// "0x4242424242424242424242424242424242424242424242424242424242424242"
default: 'backendReferralWallet',
polygon: '0x564c8aADBd35b6175C0d18595cc335106AA250Dc',
},
raffleSignWallet: {
// default is computed from private key:
// "0x4242424242424242424242424242424242424242424242424242424242424242"
default: 'backendReferralWallet',
mainnet: '0x4e2422AC29B72290Be28C6a7c3Fad7A7fDA69e7a',
polygon: '0x4e2422AC29B72290Be28C6a7c3Fad7A7fDA69e7a',
},
sandboxAccount: {
default: 4,
mainnet: '0x7A9fe22691c811ea339D9B73150e6911a5343DcA',
polygon: '0x7A9fe22691c811ea339D9B73150e6911a5343DcA',
goerli: '0x5BC3D5A39a50BE2348b9C529f81aE79f00945897', // Leon account on demo.sandbox
},
sandboxFoundation: {
default: 'sandAdmin',
mainnet: 'liquidityRewardProvider',
polygon: 'sandboxAccount', //'0xfe66Ec1B46494FE49F53733a098587bf5D12BD88',
},
extraCatalystAndGemMinter: {
default: null,
mainnet: null,
goerli: 'sandboxAccount', // Leon account on demo.sandbox
},
defaultOperatorFiltererRegistry: '0x000000000000AAeB6D7670E522A718067333cd4E',
defaultOperatorFiltererSubscription:
'0x3cc6CddA760b79bAfa08dF41ECFA224f810dCeB6',
collectionCatalystMigrationsAdmin: 'sandAdmin',
catalystMinter: 'sandAdmin', // account that can mint catalysts
catalystAdmin: 'sandAdmin', // can set minter and admin for catatalyt, as well as super operators
gemAdmin: 'sandAdmin', // can set minter and admin for gems, as well as super operators
gemMinter: 'sandAdmin', // account that can mint gems
catalystRegistryAdmin: 'sandAdmin', // can change the minter
catalystMinterAdmin: 'sandAdmin', // control the fees and which catalyst are allowed
starterPackAdmin: 'sandAdmin', // can change price
starterPackSaleBeneficiary: 'treasury', // collect funds from starter pack sales
backendMessageSigner: 'backendReferralWallet', // account that sign message for the starter pack
kyberLiquidityProvider: 'sandBeneficiary',
gemsCatalystsRegistryAdmin: 'sandAdmin',
ozdRelayer: {
default: 1,
mainnet: '0x0073e6eb087019bdb7bede02d23aeb068b74af99',
polygon: '0x7051cb544c4a8d5aad1be46cc9524e48108e60b4',
goerli: '0x4751d4dc3d8cff421598592b51bb1d9a0fb116e9',
mumbai: '0x3c17c97f29182aec3d16a080cda94d6f773bbd91',
},
landMigrationBatchExecutor: 'ozdRelayer',
nftCollectionAdmin: {
default: 'sandAdmin',
mainnet: null,
polygon: '0xF06dD9b61d480704Cc7bEF717e5Ea6efB6Af75bE', // Final admin should be 0xE79AF6BEb7D31c7faF7a1b891d9684960522D22e
},
upgradeAdmin: 'sandAdmin',
};

/**
Expand Down Expand Up @@ -259,16 +106,18 @@ const compilers = [
},
}));

const config = addForkingSupport({
importedPackages,
namedAccounts,
networks: addNodeAndMnemonic(networks),
mocha: {
timeout: 0,
...(!process.env.CI ? {} : {invert: true, grep: '@skip-on-ci'}),
},
solidity: {
compilers,
},
});
const config = skipDeploymentsOnLiveNetworks(
addForkingSupport({
importedPackages,
namedAccounts,
networks: addNodeAndMnemonic(networks),
mocha: {
timeout: 0,
...(!process.env.CI ? {} : {invert: true, grep: '@skip-on-ci'}),
},
solidity: {
compilers,
},
})
);
export default config;
11 changes: 6 additions & 5 deletions packages/deploy/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,18 @@
],
"scripts": {
"compile": "hardhat compile",
"test": "cross-env NODE_OPTIONS=\"--max-old-space-size=8192 node --unhandled-rejections=strict\" HARDHAT_COMPILE=true NODE_ENV=test hardhat test",
"test": "cross-env NODE_OPTIONS=\"--max-old-space-size=8192 node --unhandled-rejections=strict\" HARDHAT_COMPILE=true hardhat test",
"void:deploy": "cross-env NODE_OPTIONS=\"--max-old-space-size=8192 --unhandled-rejections=strict\" hardhat deploy",
"deploy": "npm run void:deploy",
"hardhat": "hardhat",
"lint": "eslint --max-warnings 0 \"**/*.{js,ts}\"",
"lint:fix": "eslint --fix \"**/*.{js,ts}\"",
"format": "prettier --check \"**/*.{ts,js}\"",
"format:fix": "prettier --write \"**/*.{ts,js}\"",
"fork:mainnet": "cross-env HARDHAT_FORK=mainnet HARDHAT_DEPLOY_ACCOUNTS_NETWORK=mainnet HARDHAT_DEPLOY_FIXTURE=true NODE_OPTIONS=\"--max-old-space-size=8192 node --unhandled-rejections=strict\" HARDHAT_COMPILE=true NODE_ENV=test hardhat test",
"fork:polygon": "cross-env HARDHAT_FORK=polygon HARDHAT_DEPLOY_ACCOUNTS_NETWORK=polygon HARDHAT_DEPLOY_FIXTURE=true NODE_OPTIONS=\"--max-old-space-size=8192 node --unhandled-rejections=strict\" HARDHAT_COMPILE=true NODE_ENV=test hardhat test",
"fork:goerli": "cross-env HARDHAT_FORK=goerli HARDHAT_DEPLOY_ACCOUNTS_NETWORK=goerli HARDHAT_DEPLOY_FIXTURE=true NODE_OPTIONS=\"--max-old-space-size=8192 node --unhandled-rejections=strict\" HARDHAT_COMPILE=true NODE_ENV=test hardhat test",
"fork:mumbai": "cross-env HARDHAT_FORK=mumbai HARDHAT_DEPLOY_ACCOUNTS_NETWORK=mumbai HARDHAT_DEPLOY_FIXTURE=true NODE_OPTIONS=\"--max-old-space-size=8192 node --unhandled-rejections=strict\" HARDHAT_COMPILE=true NODE_ENV=test hardhat test"
"verify": "yarn hardhat etherscan-verify --network",
"live:deploy": "node ./utils/npmScriptHelper.js deploy",
"fork:deploy": "node ./utils/npmScriptHelper.js fork:deploy",
"fork:test": "node ./utils/npmScriptHelper.js fork:test"
},
"devDependencies": {
"@ethersproject/abi": "^5.7.0",
Expand All @@ -51,6 +51,7 @@
"@typescript-eslint/eslint-plugin": "^5.59.8",
"@typescript-eslint/parser": "^5.59.8",
"chai": "^4.3.7",
"child_process": "^1.0.2",
"cross-env": "^7.0.3",
"dotenv": "^16.1.4",
"dotenv-cli": "^7.2.1",
Expand Down
37 changes: 37 additions & 0 deletions packages/deploy/utils/hardhatConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,16 +57,53 @@ export function addNodeAndMnemonic(
return networks;
}

export function skipDeploymentsOnLiveNetworks(
conf: HardhatUserConfig
): HardhatUserConfig {
// We want to run deployments on hardhat but not on live nets
// The problem is that hardhat-deploy always run the fixtures when testing
// maybe there is a better way to do it:
const testingLive =
process.argv.some((x) => x === 'test') &&
process.argv.some((x) => x === '--network');
if (!conf.networks || !testingLive) {
return conf;
}
const networks = conf.networks as NetworksUserConfig;
return {
...conf,
networks: Object.keys(networks).reduce(
(acc, val) => ({
...acc,
[val]: {...networks[val], deploy: []},
}),
{}
),
};
}

export function addForkingSupport(conf: HardhatUserConfig): HardhatUserConfig {
if (!process.env.HARDHAT_FORK) {
return conf;
}
const d =
(conf.networks &&
conf.networks['hardhat'] &&
conf.networks['hardhat']?.deploy) ||
[];
const deploy = typeof d === 'string' ? [d] : d;
return {
...conf,
networks: {
...conf.networks,
hardhat: {
...(conf.networks ? conf.networks['hardhat'] : {}),
deploy: process.env.HARDHAT_FORK_INCLUDE_MOCKS
? deploy
: deploy.filter((x) => !x.includes('mock')),
accounts: {
mnemonic: getMnemonic(process.env.HARDHAT_FORK),
},
forking: process.env.HARDHAT_FORK
? {
enabled: true,
Expand Down
Loading

0 comments on commit c388bd4

Please sign in to comment.