UNPKG

@matterlabs/hardhat-zksync-deploy

Version:
220 lines 10.4 kB
"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 (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createProviders = exports._extractFactoryDepsRecursive = exports._extractFactoryDeps = exports.estimateDeployGas = exports.estimateDeployFee = exports.deploy = exports.loadArtifact = void 0; const zk = __importStar(require("zksync-ethers")); const ethers = __importStar(require("ethers")); const errors_1 = require("./errors"); const utils_1 = require("./utils"); const deployment_saver_1 = require("./deployment-saver"); const constants_1 = require("./constants"); const ZKSOLC_ARTIFACT_FORMAT_VERSION = 'hh-zksolc-artifact-1'; const ZKVYPER_ARTIFACT_FORMAT_VERSION = 'hh-zkvyper-artifact-1'; const SUPPORTED_L1_TESTNETS = ['mainnet', 'rinkeby', 'ropsten', 'kovan', 'goerli', 'sepolia']; /** * Loads an artifact and verifies that it was compiled by `zksolc`. * * @param contractNameOrFullyQualifiedName The name of the contract. * It can be a contract bare contract name (e.g. "Token") if it's * unique in your project, or a fully qualified contract name * (e.g. "contract/token.sol:Token") otherwise. * * @throws Throws an error if a non-unique contract name is used, * indicating which fully qualified names can be used instead. * * @throws Throws an error if an artifact was not compiled by `zksolc`. */ async function loadArtifact(hre, contractNameOrFullyQualifiedName) { const artifact = await hre.artifacts.readArtifact(contractNameOrFullyQualifiedName); // Verify that this artifact was compiled by the ZKsync compiler, and not `solc` or `vyper`. if (artifact._format !== ZKSOLC_ARTIFACT_FORMAT_VERSION && artifact._format !== ZKVYPER_ARTIFACT_FORMAT_VERSION) { throw new errors_1.ZkSyncDeployPluginError(`Artifact ${contractNameOrFullyQualifiedName} was not compiled by zksolc or zkvyper`); } return artifact; } exports.loadArtifact = loadArtifact; /** * Sends a deploy transaction to the ZKsync network. * For now, it will use defaults for the transaction parameters: * - fee amount is requested automatically from the ZKsync server. * * @param artifact The previously loaded artifact object. * @param constructorArguments List of arguments to be passed to the contract constructor. * @param overrides Optional object with additional deploy transaction parameters. * @param additionalFactoryDeps Additional contract bytecodes to be added to the factory dependencies list. * * @returns A contract object. */ async function deploy(hre, contractNameOrArtifact, constructorArguments = [], zkWallet, deploymentType = 'create', overrides, additionalFactoryDeps) { const artifact = typeof contractNameOrArtifact === 'string' ? await loadArtifact(hre, contractNameOrArtifact) : contractNameOrArtifact; const baseDeps = await _extractFactoryDeps(hre, artifact); const additionalDeps = additionalFactoryDeps ? additionalFactoryDeps.map((val) => ethers.hexlify(val)) : []; const factoryDeps = [...baseDeps, ...additionalDeps]; const deploymentEntry = await (0, deployment_saver_1.loadCache)(hre, artifact, deploymentType, constructorArguments, overrides?.customData?.salt ?? ethers.ZeroHash, factoryDeps); if (!hre.network.forceDeploy && deploymentEntry) { return new zk.Contract(deploymentEntry.address, artifact.abi, zkWallet); } const factory = new zk.ContractFactory(artifact.abi, artifact.bytecode, zkWallet, deploymentType); const { customData, ..._overrides } = overrides ?? {}; // Encode and send the deploy transaction providing factory dependencies. const contract = await factory.deploy(...constructorArguments, { ..._overrides, customData: { ...customData, factoryDeps, }, }); await contract.waitForDeployment(); await (0, deployment_saver_1.saveCache)(hre, artifact, { constructorArgs: constructorArguments, salt: overrides?.customData?.salt ?? ethers.ZeroHash, deploymentType, factoryDeps, address: await contract.getAddress(), txHash: contract.deploymentTransaction().hash, }); return contract; } exports.deploy = deploy; /** * Estimates the price of calling a deploy transaction in ETH. * * @param artifact The previously loaded artifact object. * @param constructorArguments List of arguments to be passed to the contract constructor. * * @returns Calculated fee in ETH wei */ async function estimateDeployFee(hre, artifact, constructorArguments, zkWallet) { const gas = await estimateDeployGas(hre, artifact, constructorArguments, zkWallet); const gasPrice = await zkWallet.provider.getGasPrice(); return gas * gasPrice; } exports.estimateDeployFee = estimateDeployFee; /** * Estimates the amount of gas needed to execute a deploy transaction. * * @param artifact The previously loaded artifact object. * @param constructorArguments List of arguments to be passed to the contract constructor. * * @returns Calculated amount of gas. */ async function estimateDeployGas(hre, artifact, constructorArguments, zkWallet, deploymentType = 'create') { const factoryDeps = await _extractFactoryDeps(hre, artifact); const factory = new zk.ContractFactory(artifact.abi, artifact.bytecode, zkWallet, deploymentType); // Encode deploy transaction so it can be estimated. const deployTx = await factory.getDeployTransaction(...constructorArguments, { customData: { factoryDeps, }, }); deployTx.from = zkWallet.address; return await zkWallet.provider.estimateGas(deployTx); } exports.estimateDeployGas = estimateDeployGas; /** * Extracts factory dependencies from the artifact. * * @param artifact Artifact to extract dependencies from * * @returns Factory dependencies in the format expected by SDK. */ async function _extractFactoryDeps(hre, artifact) { const visited = new Set(); visited.add(`${artifact.sourceName}:${artifact.contractName}`); return await _extractFactoryDepsRecursive(hre, artifact, visited); } exports._extractFactoryDeps = _extractFactoryDeps; async function _extractFactoryDepsRecursive(hre, artifact, visited) { // Load all the dependency bytecodes. // We transform it into an array of bytecodes. const factoryDeps = []; for (const dependencyHash in artifact.factoryDeps) { if (!dependencyHash) continue; const dependencyContract = artifact.factoryDeps[dependencyHash]; if (!visited.has(dependencyContract)) { const dependencyArtifact = await loadArtifact(hre, dependencyContract); factoryDeps.push(dependencyArtifact.bytecode); visited.add(dependencyContract); const transitiveDeps = await _extractFactoryDepsRecursive(hre, dependencyArtifact, visited); factoryDeps.push(...transitiveDeps); } } return factoryDeps; } exports._extractFactoryDepsRecursive = _extractFactoryDepsRecursive; function createProviders(networks, network) { const networkName = network.name; if (!network.zksync) { throw new errors_1.ZkSyncDeployPluginError(`Only deploying to ZKsync network is supported.\nNetwork '${networkName}' in 'hardhat.config' needs to have 'zksync' flag set to 'true'.`); } if (networkName === 'hardhat') { return { ethWeb3Provider: _createDefaultEthProvider(), zkWeb3Provider: _createDefaultZkProvider(), }; } const networkConfig = network.config; if (!(0, utils_1.isHttpNetworkConfig)(networkConfig)) { throw new errors_1.ZkSyncDeployPluginError(`Only deploying to ZKsync network is supported.\nNetwork '${networkName}' in 'hardhat.config' needs to have 'url' specified.`); } if (networkConfig.ethNetwork === undefined) { throw new errors_1.ZkSyncDeployPluginError(`Only deploying to ZKsync network is supported.\nNetwork '${networkName}' in 'hardhat.config' needs to have 'ethNetwork' (layer 1) specified.`); } let ethWeb3Provider; const ethNetwork = networkConfig.ethNetwork; if (SUPPORTED_L1_TESTNETS.includes(ethNetwork)) { ethWeb3Provider = ethNetwork in networks && (0, utils_1.isHttpNetworkConfig)(networks[ethNetwork]) ? new ethers.JsonRpcProvider(networks[ethNetwork].url) : ethers.getDefaultProvider(ethNetwork); } else { if (ethNetwork === 'localhost' || ethNetwork === '') { ethWeb3Provider = _createDefaultEthProvider(); } else if ((0, utils_1.isValidEthNetworkURL)(ethNetwork)) { ethWeb3Provider = new ethers.JsonRpcProvider(ethNetwork); } else { ethWeb3Provider = ethNetwork in networks && (0, utils_1.isHttpNetworkConfig)(networks[ethNetwork]) ? new ethers.JsonRpcProvider(networks[ethNetwork].url) : ethers.getDefaultProvider(ethNetwork); } } const zkWeb3Provider = new zk.Provider(network.config.url); return { ethWeb3Provider, zkWeb3Provider }; } exports.createProviders = createProviders; function _createDefaultEthProvider() { return new ethers.JsonRpcProvider(constants_1.ETH_DEFAULT_NETWORK_RPC_URL); } function _createDefaultZkProvider() { return zk.Provider.getDefaultProvider(); } //# sourceMappingURL=deployer-helper.js.map