1- import { HardhatUpgrades } from "@openzeppelin/hardhat-upgrades" ;
21import dotenv from "dotenv" ;
32import { Wallet } from "ethers" ;
43import fs from "fs" ;
54import { task , types } from "hardhat/config" ;
6- import type { RunTaskFunction , TaskArguments } from "hardhat/types" ;
5+ import { HardhatRuntimeEnvironment , TaskArguments } from "hardhat/types" ;
76
87import { 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
2120async 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+
5781task ( "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
86121task ( "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
115161task ( "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
144201task ( "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
173241task ( "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
202281task ( "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