"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.deployMaci = exports.deployPollFactory = exports.deployContractWithLinkedLibraries = exports.deployPoseidonContracts = exports.deployAnonAadhaarPolicy = exports.deployERC20Policy = exports.deployERC20VotesPolicy = exports.deploySignupTokenPolicy = exports.deployHatsSignupPolicy = exports.deploySemaphoreSignupPolicy = exports.deployMerkleProofPolicy = exports.deployGitcoinPassportPolicy = exports.deployZupassSignUpPolicy = exports.deployEASSignUpPolicy = exports.deployFreeForAllSignUpPolicy = exports.getDeployedPolicyProxyFactories = exports.deployMockERC20Votes = exports.deploySignupToken = exports.deployERC20VotesInitialVoiceCreditProxy = exports.deployConstantInitialVoiceCreditProxy = exports.deployVerifier = exports.deployMockVerifier = exports.deployVerifyingKeysRegistry = exports.deployContract = exports.createContractFactory = void 0;
const contracts_1 = require("@excubiae/contracts");
const ContractStorage_1 = require("../tasks/helpers/ContractStorage");
const Deployment_1 = require("../tasks/helpers/Deployment");
const types_1 = require("../tasks/helpers/types");
const typechain_types_1 = require("../typechain-types");
const generateEmptyBallotRoots_1 = require("./generateEmptyBallotRoots");
const logger_1 = require("./logger");
/**
 * Creates contract factory from abi and bytecode
 *
 * @param abi - Contract abi
 * @param bytecode - Contract bytecode
 * @param signer - the signer to use to deploy the contract
 * @returns a contract factory with the libraries linked
 */
const createContractFactory = async (abi, bytecode, signer) => {
    const hre = await Promise.resolve().then(() => __importStar(require("hardhat")));
    const deployment = Deployment_1.Deployment.getInstance({ hre });
    deployment.setHre(hre);
    const deployer = signer || (await deployment.getDeployer());
    return deployment.createContractFactory(abi, bytecode, deployer);
};
exports.createContractFactory = createContractFactory;
/**
 * Deploy a Smart Contract given a name and some arguments
 * @param contractName - the name of the contract
 * @param signer - the signer to use to deploy the contract
 * @param quiet - whether to suppress console output
 * @param args - the constructor arguments of the contract
 */
const deployContract = async (contractName, signer, quiet = false, ...args) => {
    (0, logger_1.logMagenta)({ text: `Deploying ${contractName}`, quiet });
    const hre = await Promise.resolve().then(() => __importStar(require("hardhat")));
    const deployment = Deployment_1.Deployment.getInstance({ hre });
    deployment.setHre(hre);
    return deployment.deployContract({ name: contractName, signer }, ...args);
};
exports.deployContract = deployContract;
/**
 * Deploy a VerifyingKeysRegistry contract
 * @param signer - the signer to use to deploy the contract
 * @param quiet - whether to suppress console output
 * @returns the deployed VerifyingKeysRegistry contract
 */
const deployVerifyingKeysRegistry = async (signer, quiet = false) => (0, exports.deployContract)("VerifyingKeysRegistry", signer, quiet, await signer?.getAddress());
exports.deployVerifyingKeysRegistry = deployVerifyingKeysRegistry;
/**
 * Deploy a MockVerifier contract (testing only)
 * @param signer - the signer to use to deploy the contract
 * @param quiet - whether to suppress console output
 * @returns the deployed MockVerifier contract
 */
const deployMockVerifier = async (signer, quiet = false) => (0, exports.deployContract)("MockVerifier", signer, quiet);
exports.deployMockVerifier = deployMockVerifier;
/**
 * Deploy a Verifier contract
 * @param signer - the signer to use to deploy the contract
 * @param quiet - whether to suppress console output
 * @returns the deployed Verifier contract
 */
const deployVerifier = async (signer, quiet = false) => (0, exports.deployContract)("Verifier", signer, quiet);
exports.deployVerifier = deployVerifier;
/**
 * Deploy a constant initial voice credit proxy contract
 * @param args - the deploy constant initial voice credit proxy arguments
 * @param signer - the signer to use to deploy the contract
 * @param proxyFactory - the optional proxy factory to reuse for deployment
 * @param quiet - whether to suppress console output
 * @returns the deployed ConstantInitialVoiceCreditProxy contract
 */
const deployConstantInitialVoiceCreditProxy = async (args, signer, proxyFactory, quiet = false) => {
    if (!signer) {
        throw new Error("Signer is not provided");
    }
    const initialVoiceCreditProxyFactory = proxyFactory ??
        (await (0, exports.deployContract)(types_1.EInitialVoiceCreditProxiesFactories.Constant, signer, quiet));
    const initialVoiceCreditProxy = await (0, contracts_1.deployProxyClone)({
        factory: new typechain_types_1.ConstantInitialVoiceCreditProxy__factory(signer),
        proxyFactory: initialVoiceCreditProxyFactory,
        args: [args.amount],
        signer,
    });
    return [initialVoiceCreditProxy, initialVoiceCreditProxyFactory];
};
exports.deployConstantInitialVoiceCreditProxy = deployConstantInitialVoiceCreditProxy;
/**
 * Deploy a ERC20VotesInitialVoiceCreditProxy contract
 * @param args - the deploy ERC20VotesInitialVoiceCreditProxy arguments
 * @param signer - the signer to use to deploy the contract
 * @param proxyFactory - the optional proxy factory to reuse for deployment
 * @param quiet - whether to suppress console output
 * @returns the deployed ERC20VotesInitialVoiceCreditProxy contract
 */
const deployERC20VotesInitialVoiceCreditProxy = async (args, signer, proxyFactory, quiet = false) => {
    if (!signer) {
        throw new Error("Signer is not provided");
    }
    const erc20VotesInitialVoiceCreditProxyFactory = proxyFactory ??
        (await (0, exports.deployContract)(types_1.EInitialVoiceCreditProxiesFactories.ERC20Votes, signer, quiet));
    const erc20VotesInitialVoiceCreditProxy = await (0, contracts_1.deployProxyClone)({
        factory: new typechain_types_1.ERC20VotesInitialVoiceCreditProxy__factory(signer),
        proxyFactory: erc20VotesInitialVoiceCreditProxyFactory,
        args: [args.snapshotBlock, args.token, args.factor],
        signer,
    });
    return [erc20VotesInitialVoiceCreditProxy, erc20VotesInitialVoiceCreditProxyFactory];
};
exports.deployERC20VotesInitialVoiceCreditProxy = deployERC20VotesInitialVoiceCreditProxy;
/**
 * Deploy a MockToken contract
 * @param signer - the signer to use to deploy the contract
 * @param quiet - whether to suppress console output
 * @returns the deployed MockToken contract
 */
const deploySignupToken = async (signer, quiet = false) => (0, exports.deployContract)("MockToken", signer, quiet);
exports.deploySignupToken = deploySignupToken;
/**
 * Deploy a MockERC20Votes contract
 * @param signer - the signer to use to deploy the contract
 * @param quiet - whether to suppress console output
 * @returns the deployed MockERC20Votes contract
 */
const deployMockERC20Votes = async (signer, quiet = false) => (0, exports.deployContract)("MockERC20Votes", signer, quiet, "MockERC20Votes", "MTV");
exports.deployMockERC20Votes = deployMockERC20Votes;
/**
 * Deploy policy and checker contracts.
 *
 * @param args deploy policy arguments
 * @returns policy and checker contracts
 */
const deployPolicy = async ({ policyFactoryName, checkerFactoryName, policyFactory, checkerFactory, signer, policyArgs = [], checkerArgs = [], factories, quiet = true, }) => {
    const checkerProxyFactory = factories?.checker ?? (await (0, exports.deployContract)(checkerFactoryName, signer, quiet));
    const checker = await (0, contracts_1.deployProxyClone)({
        factory: checkerFactory,
        proxyFactory: checkerProxyFactory,
        args: checkerArgs,
        signer,
    });
    const policyProxyFactory = factories?.policy ?? (await (0, exports.deployContract)(policyFactoryName, signer, quiet));
    const policy = await (0, contracts_1.deployProxyClone)({
        factory: policyFactory,
        proxyFactory: policyProxyFactory,
        args: policyArgs.concat(await checker.getAddress()),
        signer,
    });
    return {
        checker,
        policy,
        checkerProxyFactory,
        policyProxyFactory,
    };
};
/**
 * Get deployed proxy factories for policy contracts to reuse them.
 *
 * @param args - the argument to get deployed policy proxy factories
 * @returns reusable policy proxy factories or undefined if not deployed
 */
const getDeployedPolicyProxyFactories = async ({ policy, checker, signer, network, }) => {
    const contractStorage = ContractStorage_1.ContractStorage.getInstance();
    const deployment = Deployment_1.Deployment.getInstance();
    const [policyFactoryAddress, checkerFactoryAddress] = contractStorage.getAddresses([policy, checker], network);
    const [policyFactory, checkerFactory] = await Promise.all([
        policyFactoryAddress
            ? await deployment.getContract({
                name: policy.toString(),
                address: policyFactoryAddress,
                signer,
            })
            : undefined,
        checkerFactoryAddress
            ? await deployment.getContract({
                name: checker.toString(),
                address: checkerFactoryAddress,
                signer,
            })
            : undefined,
    ]);
    return {
        checker: checkerFactory,
        policy: policyFactory,
    };
};
exports.getDeployedPolicyProxyFactories = getDeployedPolicyProxyFactories;
/**
 * Deploy a FreeForAllPolicy contract
 * @param factories - the optional proxy factories to reuse for deployment
 * @param signer - the signer to use to deploy the contract
 * @param quiet - whether to suppress console output
 * @returns the deployed FreeForAllPolicy contracts
 */
const deployFreeForAllSignUpPolicy = async (factories, signer, quiet = false) => {
    const { policy, checker, policyProxyFactory, checkerProxyFactory } = await deployPolicy({
        policyFactoryName: types_1.EPolicyFactories.FreeForAll,
        checkerFactoryName: types_1.ECheckerFactories.FreeForAll,
        checkerFactory: new typechain_types_1.FreeForAllChecker__factory(signer),
        policyFactory: new typechain_types_1.FreeForAllPolicy__factory(signer),
        factories,
        signer: signer,
        quiet,
    });
    return [policy, checker, policyProxyFactory, checkerProxyFactory];
};
exports.deployFreeForAllSignUpPolicy = deployFreeForAllSignUpPolicy;
/**
 * Deploy a EASPolicy contract
 * @param args - the arguments to deploy policy
 * @param factories - the optional proxy factories to reuse for deployment
 * @param signer - the signer to use to deploy the contract
 * @param quiet - whether to suppress console output
 * @returns the deployed EASPolicy contracts
 */
const deployEASSignUpPolicy = async (args, factories, signer, quiet = false) => {
    const { policy, checker, policyProxyFactory, checkerProxyFactory } = await deployPolicy({
        policyFactoryName: types_1.EPolicyFactories.EAS,
        checkerFactoryName: types_1.ECheckerFactories.EAS,
        checkerFactory: new typechain_types_1.EASChecker__factory(signer),
        policyFactory: new typechain_types_1.EASPolicy__factory(signer),
        checkerArgs: [args.eas, args.attester, args.schema],
        factories,
        signer: signer,
        quiet,
    });
    return [policy, checker, policyProxyFactory, checkerProxyFactory];
};
exports.deployEASSignUpPolicy = deployEASSignUpPolicy;
/**
 * Deploy a ZupassPolicy contract
 * @param args - the arguments to deploy policy
 * @param factories - the optional proxy factories to reuse for deployment
 * @param signer - the signer to use to deploy the contract
 * @param quiet - whether to suppress console output
 * @returns the deployed ZupassPolicy contracts
 */
const deployZupassSignUpPolicy = async (args, factories, signer, quiet = false) => {
    const { policy, checker, checkerProxyFactory, policyProxyFactory } = await deployPolicy({
        policyFactoryName: types_1.EPolicyFactories.Zupass,
        checkerFactoryName: types_1.ECheckerFactories.Zupass,
        checkerFactory: new typechain_types_1.ZupassChecker__factory(signer),
        policyFactory: new typechain_types_1.ZupassPolicy__factory(signer),
        signer: signer,
        checkerArgs: [args.eventId, args.signer1, args.signer2, args.verifier],
        factories,
        quiet,
    });
    return [policy, checker, policyProxyFactory, checkerProxyFactory];
};
exports.deployZupassSignUpPolicy = deployZupassSignUpPolicy;
/**
 * Deploy a GitcoinPassportPolicy contract
 * @param args - the arguments to deploy policy
 * @param factories - the optional proxy factories to reuse for deployment
 * @param signer - the signer to use to deploy the contract
 * @param quiet - whether to suppress console output
 * @returns the deployed GitcoinPassportPolicy contracts
 */
const deployGitcoinPassportPolicy = async (args, factories, signer, quiet = false) => {
    const { policy, checker, checkerProxyFactory, policyProxyFactory } = await deployPolicy({
        policyFactoryName: types_1.EPolicyFactories.GitcoinPassport,
        checkerFactoryName: types_1.ECheckerFactories.GitcoinPassport,
        checkerFactory: new typechain_types_1.GitcoinPassportChecker__factory(signer),
        policyFactory: new typechain_types_1.GitcoinPassportPolicy__factory(signer),
        signer: signer,
        checkerArgs: [args.decoderAddress, args.minimumScore.toString()],
        factories,
        quiet,
    });
    return [policy, checker, policyProxyFactory, checkerProxyFactory];
};
exports.deployGitcoinPassportPolicy = deployGitcoinPassportPolicy;
/**
 * Deploy a MerkleProofPolicy contract
 * @param args - the arguments to deploy policy
 * @param factories - the optional proxy factories to reuse for deployment
 * @param signer - the signer to use to deploy the contract
 * @param quiet - whether to suppress console output
 * @returns the deployed MerkleProofPolicy contracts
 */
const deployMerkleProofPolicy = async (args, factories, signer, quiet = false) => {
    const { policy, checker, checkerProxyFactory, policyProxyFactory } = await deployPolicy({
        policyFactoryName: types_1.EPolicyFactories.MerkleProof,
        checkerFactoryName: types_1.ECheckerFactories.MerkleProof,
        checkerFactory: new typechain_types_1.MerkleProofChecker__factory(signer),
        policyFactory: new typechain_types_1.MerkleProofPolicy__factory(signer),
        checkerArgs: [args.root],
        factories,
        signer: signer,
        quiet,
    });
    return [policy, checker, policyProxyFactory, checkerProxyFactory];
};
exports.deployMerkleProofPolicy = deployMerkleProofPolicy;
/**
 * Deploy a SemaphorePolicy contract
 * @param args - the arguments to deploy policy
 * @param factories - the optional proxy factories to reuse for deployment
 * @param signer - the signer to use to deploy the contract
 * @param quiet - whether to suppress console output
 * @returns the deployed SemaphorePolicy contracts
 */
const deploySemaphoreSignupPolicy = async (args, factories, signer, quiet = false) => {
    const { policy, checker, checkerProxyFactory, policyProxyFactory } = await deployPolicy({
        policyFactoryName: types_1.EPolicyFactories.Semaphore,
        checkerFactoryName: types_1.ECheckerFactories.Semaphore,
        checkerFactory: new typechain_types_1.SemaphoreChecker__factory(signer),
        policyFactory: new typechain_types_1.SemaphorePolicy__factory(signer),
        checkerArgs: [args.semaphore, args.groupId.toString()],
        factories,
        signer: signer,
        quiet,
    });
    return [policy, checker, policyProxyFactory, checkerProxyFactory];
};
exports.deploySemaphoreSignupPolicy = deploySemaphoreSignupPolicy;
/**
 * Deploy a HatsPolicy contract
 * @param args - the arguments to deploy policy
 * @param factories - the optional proxy factories to reuse for deployment
 * @param signer - the signer to use to deploy the contract
 * @param quiet - whether to suppress console output
 * @returns the deployed HatsPolicy contracts
 */
const deployHatsSignupPolicy = async (args, factories, signer, quiet = false) => {
    const { policy, checker, checkerProxyFactory, policyProxyFactory } = await deployPolicy({
        policyFactoryName: types_1.EPolicyFactories.Hats,
        checkerFactoryName: types_1.ECheckerFactories.Hats,
        checkerFactory: new typechain_types_1.HatsChecker__factory(signer),
        policyFactory: new typechain_types_1.HatsPolicy__factory(signer),
        checkerArgs: [args.hats, args.criterionHats],
        factories,
        signer: signer,
        quiet,
    });
    return [policy, checker, policyProxyFactory, checkerProxyFactory];
};
exports.deployHatsSignupPolicy = deployHatsSignupPolicy;
/**
 * Deploy a TokenPolicy contract
 * @param args - the arguments to deploy policy
 * @param factories - the optional proxy factories to reuse for deployment
 * @param signer - the signer to use to deploy the contract
 * @param quiet - whether to suppress console output
 * @returns the deployed SignupTokenPolicy contract
 */
const deploySignupTokenPolicy = async (args, factories, signer, quiet = false) => {
    const { policy, checker, checkerProxyFactory, policyProxyFactory } = await deployPolicy({
        policyFactoryName: types_1.EPolicyFactories.Token,
        checkerFactoryName: types_1.ECheckerFactories.Token,
        checkerFactory: new typechain_types_1.TokenChecker__factory(signer),
        policyFactory: new typechain_types_1.TokenPolicy__factory(signer),
        checkerArgs: [args.token],
        factories,
        signer: signer,
        quiet,
    });
    return [policy, checker, policyProxyFactory, checkerProxyFactory];
};
exports.deploySignupTokenPolicy = deploySignupTokenPolicy;
/**
 * Deploy a ERC20VotesPolicy contract
 * @param args - the arguments to deploy policy
 * @param factories - the optional proxy factories to reuse for deployment
 * @param signer - the signer to use to deploy the contract
 * @param quiet - whether to suppress console output
 * @returns the deployed ERC20VotesPolicy contracts
 */
const deployERC20VotesPolicy = async (args, factories, signer, quiet = false) => {
    const { policy, checker, checkerProxyFactory, policyProxyFactory } = await deployPolicy({
        policyFactoryName: types_1.EPolicyFactories.ERC20Votes,
        checkerFactoryName: types_1.ECheckerFactories.ERC20Votes,
        checkerFactory: new typechain_types_1.ERC20VotesChecker__factory(signer),
        policyFactory: new typechain_types_1.ERC20VotesPolicy__factory(signer),
        signer: signer,
        checkerArgs: [args.token, args.snapshotBlock, args.threshold],
        factories,
        quiet,
    });
    return [policy, checker, policyProxyFactory, checkerProxyFactory];
};
exports.deployERC20VotesPolicy = deployERC20VotesPolicy;
/**
 * Deploy a ERC20Policy contract
 * @param args - the arguments to deploy policy
 * @param factories - the optional proxy factories to reuse for deployment
 * @param signer - the signer to use to deploy the contract
 * @param quiet - whether to suppress console output
 * @returns the deployed ERC20Policy contracts
 */
const deployERC20Policy = async (args, factories, signer, quiet = false) => {
    const { policy, checker, checkerProxyFactory, policyProxyFactory } = await deployPolicy({
        policyFactoryName: types_1.EPolicyFactories.ERC20,
        checkerFactoryName: types_1.ECheckerFactories.ERC20,
        checkerFactory: new typechain_types_1.ERC20Checker__factory(signer),
        policyFactory: new typechain_types_1.ERC20Policy__factory(signer),
        signer: signer,
        checkerArgs: [args.token, args.threshold],
        factories,
        quiet,
    });
    return [policy, checker, policyProxyFactory, checkerProxyFactory];
};
exports.deployERC20Policy = deployERC20Policy;
/**
 * Deploy an AnonAadhaarPolicy contract
 * @param args - the arguments to deploy policy
 * @param factories - the optional proxy factories to reuse for deployment
 * @param signer - the signer to use to deploy the contract
 * @param quiet - whether to suppress console output
 * @returns the deployed AnonAadhaarPolicy contracts
 */
const deployAnonAadhaarPolicy = async (args, factories, signer, quiet = false) => {
    const { policy, checker, policyProxyFactory, checkerProxyFactory } = await deployPolicy({
        policyFactoryName: types_1.EPolicyFactories.AnonAadhaar,
        checkerFactoryName: types_1.ECheckerFactories.AnonAadhaar,
        checkerFactory: new typechain_types_1.AnonAadhaarChecker__factory(signer),
        policyFactory: new typechain_types_1.AnonAadhaarPolicy__factory(signer),
        checkerArgs: [args.verifierAddress, args.nullifierSeed],
        factories,
        signer: signer,
        quiet,
    });
    return [policy, checker, policyProxyFactory, checkerProxyFactory];
};
exports.deployAnonAadhaarPolicy = deployAnonAadhaarPolicy;
/**
 * Deploy Poseidon contracts
 * @param signer - the signer to use to deploy the contracts
 * @param quiet - whether to suppress console output
 * @returns the deployed Poseidon contracts
 */
const deployPoseidonContracts = async (signer, { poseidonT3, poseidonT4, poseidonT5, poseidonT6 } = {}, quiet = false) => {
    const PoseidonT3Contract = !poseidonT3
        ? await (0, exports.deployContract)("PoseidonT3", signer, quiet)
        : typechain_types_1.PoseidonT3__factory.connect(poseidonT3);
    const PoseidonT4Contract = !poseidonT4
        ? await (0, exports.deployContract)("PoseidonT4", signer, quiet)
        : typechain_types_1.PoseidonT4__factory.connect(poseidonT4);
    const PoseidonT5Contract = !poseidonT5
        ? await (0, exports.deployContract)("PoseidonT5", signer, quiet)
        : typechain_types_1.PoseidonT5__factory.connect(poseidonT5);
    const PoseidonT6Contract = !poseidonT6
        ? await (0, exports.deployContract)("PoseidonT6", signer, quiet)
        : typechain_types_1.PoseidonT6__factory.connect(poseidonT6);
    return {
        PoseidonT3Contract,
        PoseidonT4Contract,
        PoseidonT5Contract,
        PoseidonT6Contract,
    };
};
exports.deployPoseidonContracts = deployPoseidonContracts;
/**
 * Deploy a contract with linked libraries
 * @param contractFactory - the contract factory to use
 * @param signer - the signer to use for deployment (optional)
 * @param args - the constructor arguments of the contract
 * @returns the deployed contract instance
 */
const deployContractWithLinkedLibraries = async (contractFactory, signer, ...args) => {
    const hre = await Promise.resolve().then(() => __importStar(require("hardhat")));
    const deployment = Deployment_1.Deployment.getInstance({ hre });
    deployment.setHre(hre);
    return deployment.deployContractWithLinkedLibraries({ contractFactory, signer }, ...args);
};
exports.deployContractWithLinkedLibraries = deployContractWithLinkedLibraries;
/**
 * Deploy a Poll Factory contract
 * @param signer - the signer object to use to deploy the contract
 * @param quiet - whether to suppress console output
 * @returns the deployed Poll Factory contract
 */
const deployPollFactory = async (signer, factory, quiet = false) => {
    const poseidonContracts = await (0, exports.deployPoseidonContracts)(signer, {}, quiet);
    const [poseidonT3Contract, poseidonT4Contract, poseidonT5Contract, poseidonT6Contract] = await Promise.all([
        poseidonContracts.PoseidonT3Contract.getAddress(),
        poseidonContracts.PoseidonT4Contract.getAddress(),
        poseidonContracts.PoseidonT5Contract.getAddress(),
        poseidonContracts.PoseidonT6Contract.getAddress(),
    ]);
    const pollFactory = factory || typechain_types_1.PollFactory__factory;
    const contractFactory = await (0, exports.createContractFactory)(pollFactory.abi, pollFactory.linkBytecode({
        "contracts/crypto/PoseidonT3.sol:PoseidonT3": poseidonT3Contract,
        "contracts/crypto/PoseidonT4.sol:PoseidonT4": poseidonT4Contract,
        "contracts/crypto/PoseidonT5.sol:PoseidonT5": poseidonT5Contract,
        "contracts/crypto/PoseidonT6.sol:PoseidonT6": poseidonT6Contract,
    }), signer);
    return (0, exports.deployContractWithLinkedLibraries)(contractFactory);
};
exports.deployPollFactory = deployPollFactory;
/**
 * Deploy a MACI contract
 * @param {IDeployMaciArgs} args - deploy arguments
 * @returns {IDeployedMaci} the deployed MACI contract
 */
const deployMaci = async ({ policyContractAddress, signer, poseidonAddresses, stateTreeDepth = 10, factories, quiet = true, }) => {
    const emptyBallotRoots = (0, generateEmptyBallotRoots_1.generateEmptyBallotRoots)(stateTreeDepth);
    const { PoseidonT3Contract, PoseidonT4Contract, PoseidonT5Contract, PoseidonT6Contract } = await (0, exports.deployPoseidonContracts)(signer, poseidonAddresses, quiet);
    const poseidonAddrs = await Promise.all([
        PoseidonT3Contract.getAddress(),
        PoseidonT4Contract.getAddress(),
        PoseidonT5Contract.getAddress(),
        PoseidonT6Contract.getAddress(),
    ]).then(([poseidonT3, poseidonT4, poseidonT5, poseidonT6]) => ({
        poseidonT3,
        poseidonT4,
        poseidonT5,
        poseidonT6,
    }));
    const contractsToLink = [typechain_types_1.MACI__factory, typechain_types_1.PollFactory__factory, typechain_types_1.MessageProcessorFactory__factory, typechain_types_1.TallyFactory__factory];
    // Link Poseidon contracts to MACI
    const linkedContractFactories = factories ||
        (await Promise.all(contractsToLink.map(async (factory) => (0, exports.createContractFactory)(factory.abi, factory.linkBytecode({
            "contracts/crypto/PoseidonT3.sol:PoseidonT3": poseidonAddrs.poseidonT3,
            "contracts/crypto/PoseidonT4.sol:PoseidonT4": poseidonAddrs.poseidonT4,
            "contracts/crypto/PoseidonT5.sol:PoseidonT5": poseidonAddrs.poseidonT5,
            "contracts/crypto/PoseidonT6.sol:PoseidonT6": poseidonAddrs.poseidonT6,
        }), signer))));
    const [maciContractFactory, pollFactoryContractFactory, messageProcessorFactory, tallyFactory] = linkedContractFactories;
    const pollFactoryContract = await (0, exports.deployContractWithLinkedLibraries)(pollFactoryContractFactory);
    const messageProcessorFactoryContract = await (0, exports.deployContractWithLinkedLibraries)(messageProcessorFactory);
    const tallyFactoryContract = await (0, exports.deployContractWithLinkedLibraries)(tallyFactory);
    const [pollAddress, messageProcessorAddress, tallyAddress] = await Promise.all([
        pollFactoryContract.getAddress(),
        messageProcessorFactoryContract.getAddress(),
        tallyFactoryContract.getAddress(),
    ]);
    const maciContract = await (0, exports.deployContractWithLinkedLibraries)(maciContractFactory, signer, pollAddress, messageProcessorAddress, tallyAddress, policyContractAddress, stateTreeDepth, emptyBallotRoots);
    return {
        maciContract,
        pollFactoryContract,
        messageProcessorFactoryContract,
        tallyFactoryContract,
        poseidonAddrs,
    };
};
exports.deployMaci = deployMaci;
//# sourceMappingURL=deploy.js.map