Skip to content

Commit f83a6cf

Browse files
authored
feat(deploy): add multi-chain deployment workflow with configuration management (#218)
* fix: rename avalancheFuji to avalancheFujiTestnet in network configurations * feat: implement robust deployment workflow with GitHub Actions * feat: create update-config.ts script to maintain deployment configurations * feat: integrate contract verification into the deployment process * feat: add support for additional networks including Avalanche Fuji and Arbitrum Sepolia * feat: implement mainnet deployment safeguards requiring main branch for Bellecour * fix: enhance error handling and logging in deployment scripts * fix: ensure bytecode and constructor args are saved during deployment * refactor: simplify environment variable handling in CI workflow * docs: update documentation with improved deployment instructions * test: skip tests for mainnet environments in deployment workflow
1 parent 85844a4 commit f83a6cf

40 files changed

+276
-37
lines changed
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
name: Deploy PoCo Contracts
2+
on:
3+
workflow_dispatch:
4+
inputs:
5+
network:
6+
description: 'Network'
7+
required: true
8+
type: choice
9+
options:
10+
- hardhat
11+
- avalancheFujiTestnet
12+
- arbitrumSepolia
13+
- bellecour
14+
default: 'hardhat'
15+
environment:
16+
description: 'Environment'
17+
required: true
18+
type: choice
19+
options:
20+
- testnets
21+
- mainnets
22+
default: 'testnets'
23+
24+
jobs:
25+
validate:
26+
runs-on: ubuntu-latest
27+
steps:
28+
- name: Checkout code
29+
uses: actions/checkout@v4
30+
31+
- name: Validate mainnet deployment conditions
32+
run: |
33+
#TODO remove this when we have other mainnets
34+
if [[ "${{ inputs.environment }}" == "mainnets" && !("${{ inputs.network }}" == "bellecour" && "${{ github.ref }}" == "refs/heads/main") ]]; then
35+
echo "::error::Bellecour mainnet deployments must be made from the main branch. Current branch: ${GITHUB_REF#refs/heads/}"
36+
exit 1
37+
fi
38+
39+
echo "Deployment validation passed!"
40+
deploy:
41+
needs: validate
42+
runs-on: ubuntu-latest
43+
permissions:
44+
contents: write # Required for saving deployment
45+
environment: ${{ inputs.environment }} # Use the selected environment
46+
steps:
47+
- name: Checkout
48+
uses: actions/checkout@v4
49+
50+
- name: Set up Nodejs
51+
uses: actions/setup-node@v4
52+
with:
53+
node-version: 20
54+
cache: 'npm' # Cache dependencies
55+
56+
- name: Install dependencies
57+
run: npm ci
58+
59+
- name: Run tests
60+
run: |
61+
if [ "${{ inputs.network }}" == "arbitrumSepolia" ]; then
62+
npm run test:arbitrumSepolia
63+
elif [ "${{ inputs.network }}" == "avalancheFujiTestnet" ]; then
64+
npm run test:fuji
65+
else
66+
npm run test
67+
fi
68+
69+
- name: Set environment variables
70+
id: set-env
71+
run: |
72+
echo "PRIVATE_KEY=${{ secrets.PRIVATE_KEY }}" >> $GITHUB_ENV
73+
if [ "${{ inputs.network }}" == "avalancheFujiTestnet" ]; then
74+
echo "FUJI_RPC_URL=${{ secrets.FUJI_RPC_URL }}" >> $GITHUB_ENV
75+
echo "SNOWTRACE_API_KEY=${{ secrets.SNOWTRACE_API_KEY }}" >> $GITHUB_ENV
76+
fi
77+
78+
if [ "${{ inputs.network }}" == "arbitrumSepolia" ]; then
79+
echo "ARBITRUM_SEPOLIA_RPC_URL=${{ secrets.ARBITRUM_SEPOLIA_RPC_URL }}" >> $GITHUB_ENV
80+
echo "ARBISCAN_API_KEY=${{ secrets.ARBISCAN_API_KEY }}" >> $GITHUB_ENV
81+
fi
82+
83+
if [ "${{ inputs.network }}" == "bellecour" ]; then
84+
echo "BELLECOUR_RPC_URL=${{ secrets.BELLECOUR_RPC_URL }}" >> $GITHUB_ENV
85+
fi
86+
87+
- name: Deploy contracts
88+
run: |
89+
echo "Deploying to: ${{ inputs.network }} with ${{ inputs.environment }} environment"
90+
npm run deploy -- --network ${{ inputs.network }}
91+
92+
- name: Update config.json with ERC1538Proxy address
93+
if: inputs.network != 'hardhat'
94+
run: npx hardhat run scripts/tools/update-config.ts --network ${{ inputs.network }}
95+
96+
- name: Save deployment artifacts and updated config
97+
if: inputs.network != 'hardhat'
98+
uses: stefanzweifel/git-auto-commit-action@v5
99+
with:
100+
commit_message: 'chore: save deployment artifacts for ${{ inputs.network }} (${{ inputs.environment }}, ${{ github.run_id }})'
101+
file_pattern: 'deployments/${{ inputs.network }}/* config/config.json'
102+
commit_user_name: 'GitHub Actions Bot'
103+
commit_user_email: 'github-actions[bot]@users.noreply.github.com'
104+
commit_author: 'GitHub Actions Bot <github-actions[bot]@users.noreply.github.com>'

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
- [x] `IexecPoco2Delegate.sol`
1010

1111
### Features
12+
- Add gitub action workflow for deployment (#218)
1213
- Fix new testnets chain name (#217)
1314
- Deploy on new testnet chains using CreateX factory (#216)
1415
- Add CreateX factory for new chain deployment (#215)

README.md

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# iExec PoCo Smart Contracts
2+
13
[![codecov](https://codecov.io/github/iExecBlockchainComputing/PoCo/graph/badge.svg)](https://codecov.io/github/iExecBlockchainComputing/PoCo)
24

35
# Introduction
@@ -117,23 +119,40 @@ npm run test
117119
118120
## Deploy
119121
120-
You can deploy the smart contracts according to the [deploy/0_deploy.ts](./deploy/0_deploy.ts) content. This will automatically save some addresses of the deployed artifacts to the `./build` folder.
122+
The iExec PoCo contracts support automated deployment through both command-line interface and GitHub Actions workflows.
123+
124+
### Command Line Deployment
125+
126+
You can deploy the smart contracts according to the [deploy/0_deploy.ts](./deploy/0_deploy.ts) content. This will automatically save some addresses of the deployed artifacts to the `./deployments` folder.
121127
122-
To do so:
128+
To deploy using the CLI:
123129
124-
1. Make sure you followed the "Configure a deployment" section;
125-
2. Enter your targeted blockchain parameters in `hardhat.config.ts` configuration file;
130+
1. Make sure you followed the "Configure a deployment" section above
131+
2. Enter your targeted blockchain parameters in `hardhat.config.ts`
126132
3. Run the deployment using:
133+
127134
```
128135
npx hardhat deploy --network <your network name>
129136
```
130137
131-
Example of "complex" deployment:
138+
Example with custom salt:
132139
133140
```
134141
SALT=0x0000000000000000000000000000000000000000000000000000000000000001 npx hardhat deploy --network hardhat
135142
```
136143
144+
145+
### Manual Verification
146+
147+
To manually verify contracts:
148+
149+
```
150+
npx hardhat run ./scripts/verify.ts --network <your network name>
151+
```
152+
153+
This script automatically reads all deployed contract addresses and their constructor arguments from the deployment artifacts and verifies them on the relevant block explorer.
154+
155+
137156
## Formatting
138157
139158
Format a specific file or files in a directory:

deploy/0_deploy.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ import { linkContractToProxy } from '../utils/proxy-tools';
5353
*/
5454
export default async function deploy() {
5555
console.log('Deploying PoCo..');
56-
const chainId = (await ethers.provider.getNetwork()).chainId;
56+
const network = await ethers.provider.getNetwork();
57+
const chainId = network.chainId;
5758
const [owner] = await ethers.getSigners();
5859
const deploymentOptions = config.getChainConfigOrDefault(chainId);
5960
const factoryDeployer = new FactoryDeployer(owner, chainId);
@@ -209,6 +210,12 @@ export default async function deploy() {
209210
for (let i = 0; i < Number(catCountAfter); i++) {
210211
console.log(`Category ${i}: ${await iexecAccessorsInstance.viewCategory(i)}`);
211212
}
213+
214+
if (network.name !== 'hardhat' && network.name !== 'localhost') {
215+
console.log('Waiting for block explorer to index the contracts...');
216+
await new Promise((resolve) => setTimeout(resolve, 60000));
217+
await import('../scripts/verify').then((module) => module.default());
218+
}
212219
}
213220

214221
async function getOrDeployRlc(token: string, owner: SignerWithAddress) {
File renamed without changes.
File renamed without changes.

deployments/avalancheFuji/ENSIntegrationDelegate.json renamed to deployments/avalancheFujiTestnet/ENSIntegrationDelegate.json

File renamed without changes.
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)