Skip to content

Commit d7b5090

Browse files
committed
feat(gateway-contracts): refactor and add new argument for using env variables for proxy addresses
1 parent e3dd6b1 commit d7b5090

1 file changed

Lines changed: 182 additions & 92 deletions

File tree

Lines changed: 182 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
1-
import { HardhatUpgrades } from "@openzeppelin/hardhat-upgrades";
21
import dotenv from "dotenv";
32
import { Wallet } from "ethers";
43
import fs from "fs";
54
import { task, types } from "hardhat/config";
6-
import type { RunTaskFunction, TaskArguments } from "hardhat/types";
5+
import { HardhatRuntimeEnvironment, TaskArguments } from "hardhat/types";
76

87
import { getRequiredEnvVar } from "./utils/loadVariables";
98

109
// This file defines generic tasks that can be used to upgrade the implementation of already deployed contracts.
1110

12-
function stripContractName(input: string): string {
11+
function getImplementationDirectory(input: string): string {
1312
const colonIndex = input.lastIndexOf("/");
1413
if (colonIndex !== -1) {
1514
return input.substring(0, colonIndex);
@@ -20,40 +19,65 @@ function stripContractName(input: string): string {
2019
// Upgrades the implementation of the proxy
2120
async function upgradeCurrentToNew(
2221
proxyAddress: string,
23-
currentImplem: string,
24-
newImplem: string,
22+
currentImplementation: string,
23+
newImplementation: string,
2524
verifyContract: boolean,
26-
upgrades: HardhatUpgrades,
27-
run: RunTaskFunction,
28-
ethers: any,
25+
hre: HardhatRuntimeEnvironment,
2926
) {
3027
const deployerPrivateKey = getRequiredEnvVar("DEPLOYER_PRIVATE_KEY");
31-
const deployer = new Wallet(deployerPrivateKey).connect(ethers.provider);
28+
const deployer = new Wallet(deployerPrivateKey).connect(hre.ethers.provider);
3229

33-
await run("compile:specific", { contract: stripContractName(currentImplem) });
34-
await run("compile:specific", { contract: stripContractName(newImplem) });
35-
36-
console.log(`Importing ${currentImplem} contract implementation at address ${proxyAddress}...`);
37-
const currentImplementation = await ethers.getContractFactory(currentImplem, deployer);
38-
const proxy = await upgrades.forceImport(proxyAddress, currentImplementation);
30+
console.log(`Importing ${currentImplementation} contract implementation at address ${proxyAddress}...`);
31+
const currentImplementationFactory = await hre.ethers.getContractFactory(currentImplementation, deployer);
32+
const currentProxyContract = await hre.upgrades.forceImport(proxyAddress, currentImplementationFactory);
3933
console.log("Proxy contract successfully loaded!");
4034

41-
console.log(`Upgrading proxy to ${newImplem} contract implementation...`);
42-
const newImplementationFactory = await ethers.getContractFactory(newImplem, deployer);
43-
await upgrades.upgradeProxy(proxy, newImplementationFactory);
35+
console.log(`Upgrading proxy to ${newImplementation} contract implementation...`);
36+
const newImplementationFactory = await hre.ethers.getContractFactory(newImplementation, deployer);
37+
await hre.upgrades.upgradeProxy(currentProxyContract, newImplementationFactory);
4438
console.log("Proxy contract successfully upgraded!");
4539

4640
if (verifyContract) {
4741
console.log("Waiting 2 minutes before contract verification... Please wait...");
4842
await new Promise((resolve) => setTimeout(resolve, 2 * 60 * 1000));
49-
const implementationAddress = await upgrades.erc1967.getImplementationAddress(proxyAddress);
50-
await run("verify:verify", {
43+
const implementationAddress = await hre.upgrades.erc1967.getImplementationAddress(proxyAddress);
44+
await hre.run("verify:verify", {
5145
address: implementationAddress,
5246
constructorArguments: [],
5347
});
5448
}
5549
}
5650

51+
async function compileImplementations(
52+
currentImplementation: string,
53+
newImplementation: string,
54+
hre: HardhatRuntimeEnvironment,
55+
): Promise<void> {
56+
await hre.run("compile:specific", { contract: getImplementationDirectory(currentImplementation) });
57+
await hre.run("compile:specific", { contract: getImplementationDirectory(newImplementation) });
58+
}
59+
60+
async function checkImplementationArtifacts(
61+
expectedArtifactName: string,
62+
currentImplementation: string,
63+
newImplementation: string,
64+
hre: HardhatRuntimeEnvironment,
65+
): Promise<void> {
66+
const currentImplementationArtifact = await hre.artifacts.readArtifact(currentImplementation);
67+
if (currentImplementationArtifact.contractName !== expectedArtifactName) {
68+
throw new Error(
69+
`The current implementation artifact does not match the expected contract name "${expectedArtifactName}". Found: ${currentImplementationArtifact.contractName}`,
70+
);
71+
}
72+
73+
const newImplementationArtifact = await hre.artifacts.readArtifact(newImplementation);
74+
if (newImplementationArtifact.contractName !== expectedArtifactName) {
75+
throw new Error(
76+
`The new implementation artifact does not match the expected contract name "${expectedArtifactName}". Found: ${newImplementationArtifact.contractName}`,
77+
);
78+
}
79+
}
80+
5781
task("task:upgradeMultichainAcl")
5882
.addParam(
5983
"currentImplementation",
@@ -63,24 +87,35 @@ task("task:upgradeMultichainAcl")
6387
"newImplementation",
6488
"The new implementation solidity contract path and name, eg: contracts/examples/MultichainAclUpgradedExample.sol:MultichainAclUpgradedExample",
6589
)
90+
.addOptionalParam(
91+
"useInternalProxyAddress",
92+
"If proxy address from the /addresses directory should be used",
93+
false,
94+
types.boolean,
95+
)
6696
.addOptionalParam(
6797
"verifyContract",
6898
"Verify new implementation on Etherscan (for eg if deploying on Sepolia or Mainnet)",
6999
false,
70100
types.boolean,
71101
)
72-
.setAction(async function (taskArguments: TaskArguments, { ethers, upgrades, run }) {
73-
const parsedEnv = dotenv.parse(fs.readFileSync("addresses/.env.multichain_acl"));
74-
const proxyAddress = parsedEnv.MULTICHAIN_ACL_ADDRESS;
75-
await upgradeCurrentToNew(
76-
proxyAddress,
77-
taskArguments.currentImplementation,
78-
taskArguments.newImplementation,
79-
taskArguments.verifyContract,
80-
upgrades,
81-
run,
82-
ethers,
83-
);
102+
.setAction(async function (
103+
{ currentImplementation, newImplementation, useInternalProxyAddress, verifyContract }: TaskArguments,
104+
hre,
105+
) {
106+
await compileImplementations(currentImplementation, newImplementation, hre);
107+
108+
await checkImplementationArtifacts("MultichainAcl", currentImplementation, newImplementation, hre);
109+
110+
let proxyAddress: string;
111+
if (useInternalProxyAddress) {
112+
const parsedEnv = dotenv.parse(fs.readFileSync("addresses/.env.multichain_acl"));
113+
proxyAddress = parsedEnv.MULTICHAIN_ACL_ADDRESS;
114+
} else {
115+
proxyAddress = getRequiredEnvVar("MULTICHAIN_ACL_ADDRESS");
116+
}
117+
118+
await upgradeCurrentToNew(proxyAddress, currentImplementation, newImplementation, verifyContract, hre);
84119
});
85120

86121
task("task:upgradeCiphertextCommits")
@@ -92,24 +127,35 @@ task("task:upgradeCiphertextCommits")
92127
"newImplementation",
93128
"The new implementation solidity contract path and name, eg: contracts/examples/CiphertextCommitsUpgradedExample.sol:CiphertextCommitsUpgradedExample",
94129
)
130+
.addOptionalParam(
131+
"useInternalProxyAddress",
132+
"If proxy address from the /addresses directory should be used",
133+
false,
134+
types.boolean,
135+
)
95136
.addOptionalParam(
96137
"verifyContract",
97138
"Verify new implementation on Etherscan (for eg if deploying on Sepolia or Mainnet)",
98139
false,
99140
types.boolean,
100141
)
101-
.setAction(async function (taskArguments: TaskArguments, { ethers, upgrades, run }) {
102-
const parsedEnv = dotenv.parse(fs.readFileSync("addresses/.env.ciphertext_commits"));
103-
const proxyAddress = parsedEnv.CIPHERTEXT_COMMITS_ADDRESS;
104-
await upgradeCurrentToNew(
105-
proxyAddress,
106-
taskArguments.currentImplementation,
107-
taskArguments.newImplementation,
108-
taskArguments.verifyContract,
109-
upgrades,
110-
run,
111-
ethers,
112-
);
142+
.setAction(async function (
143+
{ currentImplementation, newImplementation, useInternalProxyAddress, verifyContract }: TaskArguments,
144+
hre,
145+
) {
146+
await compileImplementations(currentImplementation, newImplementation, hre);
147+
148+
await checkImplementationArtifacts("CiphertextCommits", currentImplementation, newImplementation, hre);
149+
150+
let proxyAddress: string;
151+
if (useInternalProxyAddress) {
152+
const parsedEnv = dotenv.parse(fs.readFileSync("addresses/.env.ciphertext_commits"));
153+
proxyAddress = parsedEnv.CIPHERTEXT_COMMITS_ADDRESS;
154+
} else {
155+
proxyAddress = getRequiredEnvVar("CIPHERTEXT_COMMITS_ADDRESS");
156+
}
157+
158+
await upgradeCurrentToNew(proxyAddress, currentImplementation, newImplementation, verifyContract, hre);
113159
});
114160

115161
task("task:upgradeDecryption")
@@ -121,24 +167,35 @@ task("task:upgradeDecryption")
121167
"newImplementation",
122168
"The new implementation solidity contract path and name, eg: contracts/examples/DecryptionUpgradedExample.sol:DecryptionUpgradedExample",
123169
)
170+
.addOptionalParam(
171+
"useInternalProxyAddress",
172+
"If proxy address from the /addresses directory should be used",
173+
false,
174+
types.boolean,
175+
)
124176
.addOptionalParam(
125177
"verifyContract",
126178
"Verify new implementation on Etherscan (for eg if deploying on Sepolia or Mainnet)",
127179
false,
128180
types.boolean,
129181
)
130-
.setAction(async function (taskArguments: TaskArguments, { ethers, upgrades, run }) {
131-
const parsedEnv = dotenv.parse(fs.readFileSync("addresses/.env.decryption"));
132-
const proxyAddress = parsedEnv.DECRYPTION_ADDRESS;
133-
await upgradeCurrentToNew(
134-
proxyAddress,
135-
taskArguments.currentImplementation,
136-
taskArguments.newImplementation,
137-
taskArguments.verifyContract,
138-
upgrades,
139-
run,
140-
ethers,
141-
);
182+
.setAction(async function (
183+
{ currentImplementation, newImplementation, useInternalProxyAddress, verifyContract }: TaskArguments,
184+
hre,
185+
) {
186+
await compileImplementations(currentImplementation, newImplementation, hre);
187+
188+
await checkImplementationArtifacts("Decryption", currentImplementation, newImplementation, hre);
189+
190+
let proxyAddress: string;
191+
if (useInternalProxyAddress) {
192+
const parsedEnv = dotenv.parse(fs.readFileSync("addresses/.env.decryption"));
193+
proxyAddress = parsedEnv.DECRYPTION_ADDRESS;
194+
} else {
195+
proxyAddress = getRequiredEnvVar("DECRYPTION_ADDRESS");
196+
}
197+
198+
await upgradeCurrentToNew(proxyAddress, currentImplementation, newImplementation, verifyContract, hre);
142199
});
143200

144201
task("task:upgradeGatewayConfig")
@@ -150,24 +207,35 @@ task("task:upgradeGatewayConfig")
150207
"newImplementation",
151208
"The new implementation solidity contract path and name, eg: contracts/examples/GatewayConfigUpgradedExample.sol:GatewayConfigUpgradedExample",
152209
)
210+
.addOptionalParam(
211+
"useInternalProxyAddress",
212+
"If proxy address from the /addresses directory should be used",
213+
false,
214+
types.boolean,
215+
)
153216
.addOptionalParam(
154217
"verifyContract",
155218
"Verify new implementation on Etherscan (for eg if deploying on Sepolia or Mainnet)",
156219
false,
157220
types.boolean,
158221
)
159-
.setAction(async function (taskArguments: TaskArguments, { ethers, upgrades, run }) {
160-
const parsedEnv = dotenv.parse(fs.readFileSync("addresses/.env.gateway_config"));
161-
const proxyAddress = parsedEnv.GATEWAY_CONFIG_ADDRESS;
162-
await upgradeCurrentToNew(
163-
proxyAddress,
164-
taskArguments.currentImplementation,
165-
taskArguments.newImplementation,
166-
taskArguments.verifyContract,
167-
upgrades,
168-
run,
169-
ethers,
170-
);
222+
.setAction(async function (
223+
{ currentImplementation, newImplementation, useInternalProxyAddress, verifyContract }: TaskArguments,
224+
hre,
225+
) {
226+
await compileImplementations(currentImplementation, newImplementation, hre);
227+
228+
await checkImplementationArtifacts("GatewayConfig", currentImplementation, newImplementation, hre);
229+
230+
let proxyAddress: string;
231+
if (useInternalProxyAddress) {
232+
const parsedEnv = dotenv.parse(fs.readFileSync("addresses/.env.gateway_config"));
233+
proxyAddress = parsedEnv.GATEWAY_CONFIG_ADDRESS;
234+
} else {
235+
proxyAddress = getRequiredEnvVar("GATEWAY_CONFIG_ADDRESS");
236+
}
237+
238+
await upgradeCurrentToNew(proxyAddress, currentImplementation, newImplementation, verifyContract, hre);
171239
});
172240

173241
task("task:upgradeKmsManagement")
@@ -179,24 +247,35 @@ task("task:upgradeKmsManagement")
179247
"newImplementation",
180248
"The new implementation solidity contract path and name, eg: contracts/examples/KmsManagementUpgradedExample.sol:KmsManagementUpgradedExample",
181249
)
250+
.addOptionalParam(
251+
"useInternalProxyAddress",
252+
"If proxy address from the /addresses directory should be used",
253+
false,
254+
types.boolean,
255+
)
182256
.addOptionalParam(
183257
"verifyContract",
184258
"Verify new implementation on Etherscan (for eg if deploying on Sepolia or Mainnet)",
185259
false,
186260
types.boolean,
187261
)
188-
.setAction(async function (taskArguments: TaskArguments, { ethers, upgrades, run }) {
189-
const parsedEnv = dotenv.parse(fs.readFileSync("addresses/.env.kms_management"));
190-
const proxyAddress = parsedEnv.KMS_MANAGEMENT_ADDRESS;
191-
await upgradeCurrentToNew(
192-
proxyAddress,
193-
taskArguments.currentImplementation,
194-
taskArguments.newImplementation,
195-
taskArguments.verifyContract,
196-
upgrades,
197-
run,
198-
ethers,
199-
);
262+
.setAction(async function (
263+
{ currentImplementation, newImplementation, useInternalProxyAddress, verifyContract }: TaskArguments,
264+
hre,
265+
) {
266+
await compileImplementations(currentImplementation, newImplementation, hre);
267+
268+
await checkImplementationArtifacts("KmsManagement", currentImplementation, newImplementation, hre);
269+
270+
let proxyAddress: string;
271+
if (useInternalProxyAddress) {
272+
const parsedEnv = dotenv.parse(fs.readFileSync("addresses/.env.kms_management"));
273+
proxyAddress = parsedEnv.KMS_MANAGEMENT_ADDRESS;
274+
} else {
275+
proxyAddress = getRequiredEnvVar("KMS_MANAGEMENT_ADDRESS");
276+
}
277+
278+
await upgradeCurrentToNew(proxyAddress, currentImplementation, newImplementation, verifyContract, hre);
200279
});
201280

202281
task("task:upgradeInputVerification")
@@ -208,22 +287,33 @@ task("task:upgradeInputVerification")
208287
"newImplementation",
209288
"The new implementation solidity contract path and name, eg: contracts/examples/InputVerificationUpgradedExample.sol:InputVerificationUpgradedExample",
210289
)
290+
.addOptionalParam(
291+
"useInternalProxyAddress",
292+
"If proxy address from the /addresses directory should be used",
293+
false,
294+
types.boolean,
295+
)
211296
.addOptionalParam(
212297
"verifyContract",
213298
"Verify new implementation on Etherscan (for eg if deploying on Sepolia or Mainnet)",
214299
false,
215300
types.boolean,
216301
)
217-
.setAction(async function (taskArguments: TaskArguments, { ethers, upgrades, run }) {
218-
const parsedEnv = dotenv.parse(fs.readFileSync("addresses/.env.input_verification"));
219-
const proxyAddress = parsedEnv.INPUT_VERIFICATION_ADDRESS;
220-
await upgradeCurrentToNew(
221-
proxyAddress,
222-
taskArguments.currentImplementation,
223-
taskArguments.newImplementation,
224-
taskArguments.verifyContract,
225-
upgrades,
226-
run,
227-
ethers,
228-
);
302+
.setAction(async function (
303+
{ currentImplementation, newImplementation, useInternalProxyAddress, verifyContract }: TaskArguments,
304+
hre,
305+
) {
306+
await compileImplementations(currentImplementation, newImplementation, hre);
307+
308+
await checkImplementationArtifacts("InputVerification", currentImplementation, newImplementation, hre);
309+
310+
let proxyAddress: string;
311+
if (useInternalProxyAddress) {
312+
const parsedEnv = dotenv.parse(fs.readFileSync("addresses/.env.input_verification"));
313+
proxyAddress = parsedEnv.INPUT_VERIFICATION_ADDRESS;
314+
} else {
315+
proxyAddress = getRequiredEnvVar("INPUT_VERIFICATION_ADDRESS");
316+
}
317+
318+
await upgradeCurrentToNew(proxyAddress, currentImplementation, newImplementation, verifyContract, hre);
229319
});

0 commit comments

Comments
 (0)