From 64284ff63ce395b24713d56c1a9342933cbebe75 Mon Sep 17 00:00:00 2001 From: David Rodriguez <70919589+daveroga@users.noreply.github.com> Date: Fri, 1 Nov 2024 10:12:15 +0100 Subject: [PATCH] Remove create2 deployment for groth16 verifiers (#308) * remove create2 deployment for groth16 verifiers * update validators deployment only write output if needed --- helpers/DeployHelper.ts | 230 +++++++++++---------------- helpers/constants.ts | 8 +- ignition/index.ts | 1 - ignition/modules/groth16Verifiers.ts | 33 ---- scripts/deploy/deployLibraries.ts | 34 ---- scripts/deploy/deployState.ts | 87 ++++++---- scripts/deploy/deployValidators.ts | 68 ++++---- 7 files changed, 180 insertions(+), 281 deletions(-) delete mode 100644 ignition/modules/groth16Verifiers.ts diff --git a/helpers/DeployHelper.ts b/helpers/DeployHelper.ts index 773e9c72..f32315b3 100644 --- a/helpers/DeployHelper.ts +++ b/helpers/DeployHelper.ts @@ -5,9 +5,6 @@ import { deployPoseidons } from "./PoseidonDeployHelper"; import { GenesisUtilsWrapper, PrimitiveTypeUtilsWrapper } from "../typechain-types"; import { SmtLibModule, - Groth16VerifierMTPWrapperModule, - Groth16VerifierSigWrapperModule, - Groth16VerifierV3WrapperModule, VCPaymentModule, StateProxyModule, IdentityTreeStoreProxyModule, @@ -15,7 +12,6 @@ import { CredentialAtomicQuerySigV2ValidatorProxyModule, CredentialAtomicQueryV3ValidatorProxyModule, UniversalVerifierProxyModule, - Groth16VerifierStateTransitionModule, } from "../ignition"; import { chainIdInfoMap, contractsInfo } from "./constants"; import { @@ -77,31 +73,32 @@ export class DeployHelper { deployStrategy, ); - const groth16VerifierStateTransition = await this.deployGroth16VerifierStateTransition( - g16VerifierContractName, + const { + state, + stateLib, + stateCrossChainLib, + crossChainProofValidator, + groth16VerifierStateTransition, + defaultIdType, + } = await this.deployState( + supportedIdTypes, deployStrategy, + await smtLib.getAddress(), + await poseidon1Elements.getAddress(), + g16VerifierContractName, ); - const { state, stateLib, stateCrossChainLib, crossChainProofValidator, defaultIdType } = - await this.deployState( - supportedIdTypes, - deployStrategy, - await smtLib.getAddress(), - await poseidon1Elements.getAddress(), - await groth16VerifierStateTransition.getAddress(), - ); - return { state, - stateLib, - stateCrossChainLib, - crossChainProofValidator, + stateLib: stateLib!, + stateCrossChainLib: stateCrossChainLib!, + crossChainProofValidator: crossChainProofValidator!, defaultIdType, smtLib, poseidon1: poseidon1Elements, poseidon2: poseidon2Elements, poseidon3: poseidon3Elements, - groth16verifier: groth16VerifierStateTransition, + groth16verifier: groth16VerifierStateTransition!, }; } @@ -110,12 +107,15 @@ export class DeployHelper { deployStrategy: "basic" | "create2" = "basic", smtLibAddress: string, poseidon1Address: string, - groth16verifierAddress: string, + g16VerifierContractName: + | "Groth16VerifierStateTransition" + | "Groth16VerifierStub" = "Groth16VerifierStateTransition", ): Promise<{ state: Contract; - stateLib: Contract; - stateCrossChainLib: Contract; - crossChainProofValidator: Contract; + stateLib: Contract | null; + stateCrossChainLib: Contract | null; + crossChainProofValidator: Contract | null; + groth16VerifierStateTransition: Contract | null; defaultIdType; }> { this.log("======== State: deploy started ========"); @@ -129,6 +129,42 @@ export class DeployHelper { const owner = this.signers[0]; + let state; + let create2AlreadyDeployed = false; + if (deployStrategy === "create2") { + state = await getUnifiedContract(contractsInfo.STATE.name); + + if (state) { + let version; + try { + version = await state.VERSION(); + } catch (e) { + create2AlreadyDeployed = true; + Logger.warning( + `Create2AnchorAddress implementation already deployed to TransparentUpgradeableProxy of ${contractsInfo.STATE.name}.`, + ); + } + + if (version) { + tmpContractDeployments.remove(); + Logger.warning( + `${contractsInfo.STATE.name} found already deployed to: ${await state?.getAddress()}`, + ); + return { + state, + stateLib: null, + stateCrossChainLib: null, + crossChainProofValidator: null, + groth16VerifierStateTransition: null, + defaultIdType, + }; + } + } + } + + const groth16VerifierStateTransition = + await this.deployGroth16VerifierStateTransition(g16VerifierContractName); + let stateLib; stateLib = await tmpContractDeployments.getContract(contractsInfo.STATE_LIB.name); if (stateLib) { @@ -190,8 +226,6 @@ export class DeployHelper { contractsInfo.CREATE2_ADDRESS_ANCHOR.name, ); - let state; - let create2AlreadyDeployed = false; if (deployStrategy === "create2") { this.log("deploying with CREATE2 strategy..."); @@ -199,34 +233,6 @@ export class DeployHelper { const tx = await crossChainProofValidator.deploymentTransaction(); await waitNotToInterfereWithHardhatIgnition(tx as ContractTransactionResponse); - state = await getUnifiedContract(contractsInfo.STATE.name); - - if (state) { - let version; - try { - version = await state.VERSION(); - } catch (e) { - create2AlreadyDeployed = true; - Logger.warning( - `Create2AnchorAddress implementation already deployed to TransparentUpgradeableProxy of ${contractsInfo.STATE.name}.`, - ); - } - - if (version) { - tmpContractDeployments.remove(); - Logger.warning( - `${contractsInfo.STATE.name} found already deployed to: ${await state?.getAddress()}`, - ); - return { - state, - stateLib, - stateCrossChainLib, - crossChainProofValidator, - defaultIdType, - }; - } - } - if (!create2AlreadyDeployed) { state = ( await ignition.deploy(StateProxyModule, { @@ -246,7 +252,7 @@ export class DeployHelper { call: { fn: "initialize", args: [ - groth16verifierAddress, + await groth16VerifierStateTransition.getAddress(), defaultIdType, await owner.getAddress(), await crossChainProofValidator.getAddress(), @@ -259,7 +265,7 @@ export class DeployHelper { state = await upgrades.deployProxy( StateFactory, [ - groth16verifierAddress, + await groth16VerifierStateTransition.getAddress(), defaultIdType, await owner.getAddress(), await crossChainProofValidator.getAddress(), @@ -293,6 +299,7 @@ export class DeployHelper { stateLib, stateCrossChainLib, crossChainProofValidator, + groth16VerifierStateTransition, defaultIdType, }; } @@ -522,37 +529,18 @@ export class DeployHelper { g16VerifierContractName: | "Groth16VerifierStateTransition" | "Groth16VerifierStub" = "Groth16VerifierStateTransition", - deployStrategy: "basic" | "create2" = "basic", ): Promise { const owner = this.signers[0]; let g16Verifier; - if (deployStrategy === "create2") { - this.log("deploying with CREATE2 strategy..."); - // Check that contract exists and skip deployment in this case - g16Verifier = await getUnifiedContract(g16VerifierContractName); - if (g16Verifier) { - Logger.warning( - `${g16VerifierContractName} found already deployed to: ${await g16Verifier?.getAddress()}`, - ); - return g16Verifier; - } + this.log("deploying Groth16VerifierStateTransition..."); - g16Verifier = ( - await ignition.deploy(Groth16VerifierStateTransitionModule, { - strategy: deployStrategy, - }) - ).verifier; + if ( + ["Groth16VerifierStateTransition", "Groth16VerifierStub"].includes(g16VerifierContractName) + ) { + g16Verifier = await ethers.deployContract(g16VerifierContractName); } else { - this.log("deploying Groth16VerifierStateTransition..."); - - if ( - ["Groth16VerifierStateTransition", "Groth16VerifierStub"].includes(g16VerifierContractName) - ) { - g16Verifier = await ethers.deployContract(g16VerifierContractName); - } else { - throw new Error("invalid verifierContractName"); - } + throw new Error("invalid verifierContractName"); } await g16Verifier.waitForDeployment(); @@ -601,7 +589,7 @@ export class DeployHelper { return verification; } - getValidatorVerification(verifierType: "mtpV2" | "sigV2" | "v3"): { + getValidatorVerification(validatorType: "mtpV2" | "sigV2" | "v3"): { contract: string; constructorArgsImplementation: any[]; constructorArgsProxy?: any[]; @@ -609,7 +597,7 @@ export class DeployHelper { libraries: any; } { let verification; - switch (verifierType) { + switch (validatorType) { case "mtpV2": verification = contractsInfo.VALIDATOR_MTP.verificationOpts; break; @@ -623,48 +611,11 @@ export class DeployHelper { return verification; } - async deployGroth16VerifierWrapper( - verifierType: "mtpV2" | "sigV2" | "v3", - deployStrategy: "basic" | "create2" = "basic", - ): Promise { + async deployGroth16VerifierWrapper(verifierType: "mtpV2" | "sigV2" | "v3"): Promise { const g16VerifierContractWrapperName = this.getGroth16VerifierWrapperName(verifierType); - let groth16VerifierWrapper; - if (deployStrategy === "create2") { - this.log("deploying with CREATE2 strategy..."); + const groth16VerifierWrapper = await ethers.deployContract(g16VerifierContractWrapperName); - let g16VerifierWrapperModule; - switch (verifierType) { - case "mtpV2": - g16VerifierWrapperModule = Groth16VerifierMTPWrapperModule; - break; - case "sigV2": - g16VerifierWrapperModule = Groth16VerifierSigWrapperModule; - break; - case "v3": - g16VerifierWrapperModule = Groth16VerifierV3WrapperModule; - break; - } - - await waitNotToInterfereWithHardhatIgnition(undefined); - - // Check that contract exists and skip deployment in this case - groth16VerifierWrapper = await getUnifiedContract(g16VerifierContractWrapperName); - if (groth16VerifierWrapper) { - Logger.warning( - `${g16VerifierContractWrapperName} found already deployed to: ${await groth16VerifierWrapper?.getAddress()}`, - ); - return groth16VerifierWrapper; - } - groth16VerifierWrapper = ( - await ignition.deploy(g16VerifierWrapperModule, { - strategy: deployStrategy, - }) - ).wrapper; - } else { - this.log("deploying with BASIC strategy..."); - groth16VerifierWrapper = await ethers.deployContract(g16VerifierContractWrapperName); - } await groth16VerifierWrapper.waitForDeployment(); Logger.success( `${g16VerifierContractWrapperName} Wrapper deployed to: ${await groth16VerifierWrapper.getAddress()}`, @@ -682,21 +633,16 @@ export class DeployHelper { groth16VerifierWrapper: any; validator: any; }> { - const groth16VerifierWrapper = await this.deployGroth16VerifierWrapper( - validatorType, - deployStrategy, - ); - const contracts = await this.deployValidatorContracts( validatorType, stateAddress, - await groth16VerifierWrapper.getAddress(), + deployStrategy, ); const state = await ethers.getContractAt("State", stateAddress); return { validator: contracts.validator, - groth16VerifierWrapper, + groth16VerifierWrapper: contracts.groth16VerifierWrapper, state, }; } @@ -704,11 +650,11 @@ export class DeployHelper { async deployValidatorContracts( validatorType: "mtpV2" | "sigV2" | "v3", stateAddress: string, - groth16VerifierWrapperAddress: string, deployStrategy: "basic" | "create2" = "basic", ): Promise<{ state: any; validator: any; + groth16VerifierWrapper: Contract | null; }> { const owner = this.signers[0]; @@ -725,17 +671,10 @@ export class DeployHelper { break; } - const ValidatorFactory = await ethers.getContractFactory(validatorContractName); - const Create2AddressAnchorFactory = await ethers.getContractFactory( - contractsInfo.CREATE2_ADDRESS_ANCHOR.name, - ); - let validator; let create2AlreadyDeployed = false; if (deployStrategy === "create2") { - this.log("deploying with CREATE2 strategy..."); - let validatorModule; switch (validatorType) { case "mtpV2": @@ -770,9 +709,23 @@ export class DeployHelper { return { validator, state: await ethers.getContractAt("State", stateAddress), + groth16VerifierWrapper: null, }; } } + } + + const groth16VerifierWrapper = await this.deployGroth16VerifierWrapper(validatorType); + + const ValidatorFactory = await ethers.getContractFactory(validatorContractName); + const Create2AddressAnchorFactory = await ethers.getContractFactory( + contractsInfo.CREATE2_ADDRESS_ANCHOR.name, + ); + + if (deployStrategy === "create2") { + this.log("deploying with CREATE2 strategy..."); + + await waitNotToInterfereWithHardhatIgnition(undefined); if (!create2AlreadyDeployed) { // Deploying Validator contract to predictable address but with dummy implementation @@ -792,14 +745,14 @@ export class DeployHelper { redeployImplementation: "always", call: { fn: "initialize", - args: [groth16VerifierWrapperAddress, stateAddress, await owner.getAddress()], + args: [await groth16VerifierWrapper.getAddress(), stateAddress, await owner.getAddress()], }, }); } else { this.log("deploying with BASIC strategy..."); validator = await upgrades.deployProxy(ValidatorFactory, [ - groth16VerifierWrapperAddress, + await groth16VerifierWrapper.getAddress(), stateAddress, await owner.getAddress(), ]); @@ -812,6 +765,7 @@ export class DeployHelper { return { validator, state, + groth16VerifierWrapper, }; } diff --git a/helpers/constants.ts b/helpers/constants.ts index 28d914f3..ba5ee4f1 100644 --- a/helpers/constants.ts +++ b/helpers/constants.ts @@ -272,7 +272,7 @@ export const contractsInfo = Object.freeze({ }, GROTH16_VERIFIER_STATE_TRANSITION: { name: "Groth16VerifierStateTransition", - unifiedAddress: "0xAE950A9B8F48bC4519820728E210515a07F7cB71", + unifiedAddress: "", create2Calldata: "", verificationOpts: { contract: @@ -283,7 +283,7 @@ export const contractsInfo = Object.freeze({ }, GROTH16_VERIFIER_MTP: { name: "Groth16VerifierMTPWrapper", - unifiedAddress: "0x1205B90121cAbB2B7e6f1828005AC00D8927796F", + unifiedAddress: "", create2Calldata: "", verificationOpts: { contract: @@ -294,7 +294,7 @@ export const contractsInfo = Object.freeze({ }, GROTH16_VERIFIER_SIG: { name: "Groth16VerifierSigWrapper", - unifiedAddress: "0x0ce200c9557BB64ee9E82452646b084e77Aaeb51", + unifiedAddress: "", create2Calldata: "", verificationOpts: { contract: @@ -305,7 +305,7 @@ export const contractsInfo = Object.freeze({ }, GROTH16_VERIFIER_V3: { name: "Groth16VerifierV3Wrapper", - unifiedAddress: "0x1aA2B5AEAd506D269164958d36Cae04f95F79282", + unifiedAddress: "", create2Calldata: "", verificationOpts: { contract: diff --git a/ignition/index.ts b/ignition/index.ts index a862fe9b..2f3dd7f1 100644 --- a/ignition/index.ts +++ b/ignition/index.ts @@ -1,7 +1,6 @@ export * from "./modules/credentialAtomicQuerySigV2Validator"; export * from "./modules/credentialAtomicQueryMTPV2Validator"; export * from "./modules/credentialAtomicQueryV3Validator"; -export * from "./modules/groth16Verifiers"; export * from "./modules/state"; export * from "./modules/identityTreeStore"; export * from "./modules/libraries"; diff --git a/ignition/modules/groth16Verifiers.ts b/ignition/modules/groth16Verifiers.ts deleted file mode 100644 index 8b1d8647..00000000 --- a/ignition/modules/groth16Verifiers.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; -import { contractsInfo } from "../../helpers/constants"; - -export const Groth16VerifierMTPWrapperModule = buildModule( - "Groth16VerifierMTPWrapperModule", - (m) => { - const g16VerifierMTPWrapper = m.contract(contractsInfo.GROTH16_VERIFIER_MTP.name); - return { wrapper: g16VerifierMTPWrapper }; - }, -); - -export const Groth16VerifierSigWrapperModule = buildModule( - "Groth16VerifierSigWrapperModule", - (m) => { - const g16verifierSigWrapper = m.contract(contractsInfo.GROTH16_VERIFIER_SIG.name); - return { wrapper: g16verifierSigWrapper }; - }, -); - -export const Groth16VerifierV3WrapperModule = buildModule("Groth16VerifierV3WrapperModule", (m) => { - const g16VerifierV3Wrapper = m.contract(contractsInfo.GROTH16_VERIFIER_V3.name); - return { wrapper: g16VerifierV3Wrapper }; -}); - -export const Groth16VerifierStateTransitionModule = buildModule( - "Groth16VerifierStateTransitionModule", - (m) => { - const g16VerifierStateTransition = m.contract( - contractsInfo.GROTH16_VERIFIER_STATE_TRANSITION.name, - ); - return { verifier: g16VerifierStateTransition }; - }, -); diff --git a/scripts/deploy/deployLibraries.ts b/scripts/deploy/deployLibraries.ts index 28f0c385..7015241b 100644 --- a/scripts/deploy/deployLibraries.ts +++ b/scripts/deploy/deployLibraries.ts @@ -25,39 +25,6 @@ async function main() { await verifyContract(await smtLib.getAddress(), contractsInfo.SMT_LIB.verificationOpts); - const groth16VerifierStateTransition = await deployHelper.deployGroth16VerifierStateTransition( - "Groth16VerifierStateTransition", - deployStrategy, - ); - - await verifyContract( - await groth16VerifierStateTransition.getAddress(), - contractsInfo.GROTH16_VERIFIER_STATE_TRANSITION.verificationOpts, - ); - - const groth16Verifiers: ("mtpV2" | "sigV2" | "v3")[] = ["mtpV2", "sigV2", "v3"]; - const groth16verifiersInfo: any = []; - for (const v of groth16Verifiers) { - const groth16VerifierWrapper = await deployHelper.deployGroth16VerifierWrapper( - v, - deployStrategy, - ); - groth16verifiersInfo.push({ - verifierType: v, - groth16verifier: await groth16VerifierWrapper.getAddress(), - }); - - await verifyContract( - await groth16VerifierWrapper.getAddress(), - deployHelper.getGroth16VerifierWrapperVerification(v), - ); - } - - groth16verifiersInfo.push({ - validatorType: "stateTransition", - groth16verifier: await groth16VerifierStateTransition.getAddress(), - }); - const chainId = parseInt(await hre.network.provider.send("eth_chainId"), 16); const networkName = hre.network.name; const outputJson = { @@ -66,7 +33,6 @@ async function main() { poseidon3: await poseidon3Elements.getAddress(), poseidon4: await poseidon4Elements.getAddress(), smtLib: await smtLib.getAddress(), - groth16verifiersInfo, network: networkName, chainId, deployStrategy, diff --git a/scripts/deploy/deployState.ts b/scripts/deploy/deployState.ts index c637c104..c748dc13 100644 --- a/scripts/deploy/deployState.ts +++ b/scripts/deploy/deployState.ts @@ -13,43 +13,60 @@ async function main() { const deployHelper = await DeployHelper.initialize(null, true); - const { state, stateLib, stateCrossChainLib, crossChainProofValidator } = - await deployHelper.deployState( - [], - deployStrategy, - contractsInfo.SMT_LIB.unifiedAddress, - contractsInfo.POSEIDON_1.unifiedAddress, - contractsInfo.GROTH16_VERIFIER_STATE_TRANSITION.unifiedAddress, - ); - - await verifyContract(await state.getAddress(), contractsInfo.STATE.verificationOpts); - await verifyContract(await stateLib.getAddress(), contractsInfo.STATE_LIB.verificationOpts); - await verifyContract( - await stateCrossChainLib.getAddress(), - contractsInfo.STATE_CROSS_CHAIN_LIB.verificationOpts, - ); - await verifyContract( - await crossChainProofValidator.getAddress(), - contractsInfo.CROSS_CHAIN_PROOF_VALIDATOR.verificationOpts, + const { + state, + stateLib, + stateCrossChainLib, + crossChainProofValidator, + groth16VerifierStateTransition, + } = await deployHelper.deployState( + [], + deployStrategy, + contractsInfo.SMT_LIB.unifiedAddress, + contractsInfo.POSEIDON_1.unifiedAddress, ); - const chainId = parseInt(await hre.network.provider.send("eth_chainId"), 16); - const networkName = hre.network.name; - const pathOutputJson = path.join( - __dirname, - `../deployments_output/deploy_state_output_${chainId}_${networkName}.json`, - ); - const outputJson = { - proxyAdminOwnerAddress: await signer.getAddress(), - state: await state.getAddress(), - stateLib: await stateLib.getAddress(), - stateCrossChainLib: await stateCrossChainLib.getAddress(), - crossChainProofValidator: await crossChainProofValidator.getAddress(), - network: networkName, - chainId, - deployStrategy, - }; - fs.writeFileSync(pathOutputJson, JSON.stringify(outputJson, null, 1)); + // if the state contract already exists we won't have new contracts deployed + // to verify and to save the output + if ( + groth16VerifierStateTransition && + stateLib && + stateCrossChainLib && + crossChainProofValidator + ) { + await verifyContract(await state.getAddress(), contractsInfo.STATE.verificationOpts); + await verifyContract( + await groth16VerifierStateTransition.getAddress(), + contractsInfo.GROTH16_VERIFIER_STATE_TRANSITION.verificationOpts, + ); + await verifyContract(await stateLib.getAddress(), contractsInfo.STATE_LIB.verificationOpts); + await verifyContract( + await stateCrossChainLib.getAddress(), + contractsInfo.STATE_CROSS_CHAIN_LIB.verificationOpts, + ); + await verifyContract( + await crossChainProofValidator.getAddress(), + contractsInfo.CROSS_CHAIN_PROOF_VALIDATOR.verificationOpts, + ); + + const chainId = parseInt(await hre.network.provider.send("eth_chainId"), 16); + const networkName = hre.network.name; + const pathOutputJson = path.join( + __dirname, + `../deployments_output/deploy_state_output_${chainId}_${networkName}.json`, + ); + const outputJson = { + proxyAdminOwnerAddress: await signer.getAddress(), + state: await state.getAddress(), + stateLib: await stateLib?.getAddress(), + stateCrossChainLib: await stateCrossChainLib?.getAddress(), + crossChainProofValidator: await crossChainProofValidator?.getAddress(), + network: networkName, + chainId, + deployStrategy, + }; + fs.writeFileSync(pathOutputJson, JSON.stringify(outputJson, null, 1)); + } } main() diff --git a/scripts/deploy/deployValidators.ts b/scripts/deploy/deployValidators.ts index 82b63181..dc620517 100644 --- a/scripts/deploy/deployValidators.ts +++ b/scripts/deploy/deployValidators.ts @@ -3,7 +3,6 @@ import path from "path"; import { DeployHelper } from "../../helpers/DeployHelper"; import hre from "hardhat"; import { getConfig, getStateContractAddress, verifyContract } from "../../helpers/helperUtils"; -import { contractsInfo } from "../../helpers/constants"; async function main() { const config = getConfig(); @@ -11,20 +10,7 @@ async function main() { const stateContractAddress = getStateContractAddress(); const validators: ("mtpV2" | "sigV2" | "v3")[] = ["mtpV2", "sigV2", "v3"]; - const groth16VerifierWrappers = [ - { - validator: "mtpV2", - verifierWrapper: contractsInfo.GROTH16_VERIFIER_MTP.unifiedAddress, - }, - { - validator: "sigV2", - verifierWrapper: contractsInfo.GROTH16_VERIFIER_SIG.unifiedAddress, - }, - { - validator: "v3", - verifierWrapper: contractsInfo.GROTH16_VERIFIER_V3.unifiedAddress, - }, - ]; + const deployStrategy: "basic" | "create2" = config.deployStrategy == "create2" ? "create2" : "basic"; const [signer] = await hre.ethers.getSigners(); @@ -33,34 +19,44 @@ async function main() { const validatorsInfo: any = []; for (const v of validators) { - const groth16VerifierWrapper = groth16VerifierWrappers.find((g) => g.validator === v); - const { validator } = await deployHelper.deployValidatorContracts( + const { validator, groth16VerifierWrapper } = await deployHelper.deployValidatorContracts( v, stateContractAddress, - groth16VerifierWrapper?.verifierWrapper as string, deployStrategy, ); - validatorsInfo.push({ - validatorType: v, - validator: await validator.getAddress(), - groth16verifier: groth16VerifierWrapper?.verifierWrapper as string, - }); + await verifyContract(await validator.getAddress(), deployHelper.getValidatorVerification(v)); + + // only add validators info if groth16VerifierWrapper is deployed + if (groth16VerifierWrapper) { + validatorsInfo.push({ + validatorType: v, + validator: await validator.getAddress(), + groth16verifier: await groth16VerifierWrapper?.getAddress(), + }); + await verifyContract( + await groth16VerifierWrapper.getAddress(), + deployHelper.getGroth16VerifierWrapperVerification(v), + ); + } } - const networkName = hre.network.name; - const pathOutputJson = path.join( - __dirname, - `../deployments_output/deploy_validators_output_${chainId}_${networkName}.json`, - ); - const outputJson = { - proxyAdminOwnerAddress: await signer.getAddress(), - validatorsInfo, - network: networkName, - chainId, - deployStrategy, - }; - fs.writeFileSync(pathOutputJson, JSON.stringify(outputJson, null, 1)); + // only save the output if there are validators deployed + if (validatorsInfo.length > 0) { + const networkName = hre.network.name; + const pathOutputJson = path.join( + __dirname, + `../deployments_output/deploy_validators_output_${chainId}_${networkName}.json`, + ); + const outputJson = { + proxyAdminOwnerAddress: await signer.getAddress(), + validatorsInfo, + network: networkName, + chainId, + deployStrategy, + }; + fs.writeFileSync(pathOutputJson, JSON.stringify(outputJson, null, 1)); + } } main()