origin-dollar
origin-dollar copied to clipboard
Document shortend/clean deploy process
In the past we've used a large spreadsheet for each deploy. However, we've now moved many of the steps out of being run only at deploy time and into the CI system.
I'd love your review and additions to this process.
Deploy Process
- Set environment variables
git checkout -B {{YOURHANDLE}}/deploy_{{DEPLOY_NUMBER}}
export PROVIDER_URL="https://eth-mainnet.alchemyapi.io/v2/{{ALCHEMY_KEY}}"
export HARDHAT_NETWORK=mainnet
export ETHERSCAN_API_KEY={{ETHERSCAN_KEY}}
export VERBOSE=true
export GAS_PRICE_MULTIPLIER=1.15
- Set deploy keys
I usually change my terminal color to a danger color before loading keys.
Different shells have ways of not recording commands into history. On the fish shell, a space in front of the command will keep it out of history. You can check after running that the export command that the key has not been saved.
On OSx iTerm add the following entry to ~/.profile file:
export HISTCONTROL=ignorespace
and space before a cli command will skip recording it to history.
export DEPLOYER_PK={{pk1}}
export GOVERNOR_PK={{pk1}}
export MAINNET_DEPLOYER_OVERRIDE {{YOUR DEPLOYER ADDRESS}}
npx hardhat accounts
npx hardhat env
- Do the deploy
yarn run deploy:mainnet | tee mainnet.out
- Verify
# For each deployed contract, verify it.
# Sample contract verification below
npx hardhat --network mainnet verify --contract contracts/strategies/VaultValueChecker.sol:OETHVaultValueChecker 0x31FD8618379D8e473Ec2B1540B906E8e11D2A99b
- Governance proposal
If the deploy had a governance action, edit the deploy file, and add the newly created proposalId to the options for deploymentWithGovernanceProposal. Then save the deploy file, and add the change to the file to git.
- Git
cp ../dapp/network.mainnet.json ../dapp/prod.network.json
git add deployments/mainnet/*.json
git add deployments/mainnet/solcInputs/*.json
git add deployments/mainnet/.migrations.json
git add storageLayout/mainnet/*.json
git commit -m "mainnet deploy {{DEPLOY NUMBER}}"
Thanks for documenting this. Its very useful for a noob like me.
Key management is an interesting one. At mStable we used Open Zeppelin's Defender Relay product. "The Defender Relay service allows you to send transactions via a regular HTTP API, and takes care of private key secure storage, transaction signing, nonce management, gas pricing estimation, and resubmissions. This way you don’t need to worry about securing your private keys in your backend scripts, or by monitoring your transactions to ensure they get mined." https://docs.openzeppelin.com/defender/relay
What's nice about Relay is it keeps private keys off developer machine. An access API can be generated when an account needs to be used and then deleted after use. A developer's access can be removed from the Defender platform if they leave the organisation. This means they no longer have access to the account.
Some more info about how Defender manages the keys: "All private keys are stored in the AWS Key Management Service. Keys are generated within the KMS and never leave it, i.e., all sign operations are executed within the KMS. Furthermore, we rely on dynamically generated AWS Identity and Access Management policies to isolate access to the private keys among tenants." https://docs.openzeppelin.com/defender/relay#security-considerations
Relay has a client that includes a custom ethers.js signer. Some investigation would have to be done to see how that can be integrated with the Hardhat Deploy plug-in. https://docs.openzeppelin.com/defender/relay#using-ethers.js
The free Defender plan is pretty generous All supported L1s, L2s, and sidechains 20 users per team 5 relayers and up to 120 TXs/hour
It gets expensive if more accounts are required.
The private keys in this case are just your deployer private keys - which has no special privileges in any of the contracts. It does own the contracts until the governance action to take over ownership is executed ofc. The relay service would be a nice upgrade to our process.
@DanielVF soon we will move ownership of contracts to the timelock and after that any governance deploy will be utilising the deploymentWithProposal deploy utility function that also has a proposalId option. Good to note that deploymentWithGovernanceProposal has a proposalId that is a very long hash and deploymentWithProposal's id is just a number that increases with each proposal.
Also I still run sourcify on the contracts. It is a public source code repo that Blockscout and Otterscan use. Not sure if that is still important
Also Notion would probably be a nice place to put docs like this one?