Contract Factory

Learn how to deploy and manage multiple smart contracts on ZKsync using a contract factory.

This second ZKsync 101 installment advances from your introductory exploration of smart contract deployment to dive into the utility of contract factories. Through this guide, you'll learn how to streamline the deployment of multiple crowdfunding campaigns using a single contract factory, leveraging the foundational CrowdfundingCampaign contract in the first guide.

Advance your ZKsync development journey with contract factories.

Construct a contract factory to create multiple crowdfunding campaigns.

Seamlessly deploy your contract factory on ZKsync Era, using either Hardhat or Foundry.

Let's explore the efficiency and scalability that contract factories bring.

What is a contract factory?

A contract factory is a design pattern that allows for the creation of multiple contract instances from a single "factory" contract. It's essentially a contract that creates other contracts, streamlining and organizing the deployment of numerous similar contracts efficiently.


Setup the project

Select the framework you want to get started using ZKsync Era with.

Run the following command in your terminal to initialize the project.

npx zksync-cli@latest create --template qs-factories contract-factory-quickstart
cd contract-factory-quickstart

Set up your wallet

Deploying contracts on the ZKsync Sepolia Testnet requires having testnet ETH. If you're working within the local development environment, you can utilize pre-configured rich wallets and skip this step. For testnet deployments, you should have your wallet funded from the previous step.


Compile the contracts

This section will focus on compiling and deploying the CrowdfundingFactory.sol contract that is provided under the /contracts directory.

The CrowdfundingFactory.solcontract will be used to deploy multiple instances of the CrowdfundingCampaign.sol contract from the previous guide. This contract factory approach streamlines the deployment of crowdfunding campaigns, making it efficient to launch and manage multiple campaigns.

The CrowdfundingFactory contract automates the creation and oversight of CrowdfundingCampaign contracts, each with their own distinct funding goals. The factory contract features:

  • Campaign Creation: Utilizes the createCampaign method to initiate a new CrowdfundingCampaign contract. This function takes a fundingGoal as an argument, deploys a new campaign contract with this goal, and tracks the created campaign in the campaigns array.
  • Campaign Tracking: The getCampaigns method offers a view into all the campaigns created by the factory, allowing for easy access and management of multiple crowdfunding initiatives.

Smart contracts deployed to ZKsync must be compiled using our custom compiler. zksolc is the compiler used for Solidity.

To compile the contracts in a project, run the following command:

npm run compile

Upon successful compilation, you'll receive output detailing the zksolc and solc versions used during compiling and the number of Solidity files compiled.

Compiling contracts for ZKsync Era with zksolc v1.4.1 and solc v0.8.17
Compiling 15 Solidity files
Successfully compiled 15 Solidity files

The compiled artifacts will be located in the /artifacts-zk folder.

Deploy CrowdfundingCampaigns via the CrowdfundingFactory

This section outlines the steps to deploy the CrowdfundingCampaign contract using our new CrowdfundingFactory.

The deployment script is located at /deploy/deployUsingFactory.ts.

  • The deployUsingFactory.ts script deploys the CrowdfundingFactory through the deployContract method.
  • An instance of the factory is assigned to factoryContract. This gives us access to the factory's functionalities.
  • The createCampaign method is called on this instance to create and deploy a new crowdfunding campaign contract.

Run the deployment command. The default command deploys to the configured network in your Hardhat setup. For local deployment, append --network inMemoryNode to deploy to the local in-memory node running.

npx hardhat deploy-zksync --script deployUsingFactory.ts
# To deploy the contract on local in-memory node:
# npx hardhat deploy-zksync --script deployUsingFactory.ts --network inMemoryNode

Upon successful deployment, you'll receive output detailing the deployment process, including the contract address, source, and encoded constructor arguments:

Starting deployment process of "CrowdfundingFactory"...
Estimated deployment cost: 0.0002500236 ETH

"CrowdfundingFactory" was successfully deployed:
 - Contract address: 0xD084EF36f8F5353f70498cD84cb8D2B844C120a8
 - Contract source: contracts/CrowdfundFactory.sol:CrowdfundingFactory
 - Encoded constructor arguments: 0x

Requesting contract verification...
Your verification ID is: 10097
Contract successfully verified on ZKsync block explorer!
🏭 CrowdfundingFactory address: 0xD084EF36f8F5353f70498cD84cb8D2B844C120a8
🚀 New CrowdfundingCampaign deployed at: 0x060B748eC3512795E94045c406CFd5877DD84e4D
 Deployment and campaign creation complete!

🌟 Brilliant! Your contract factory and its first crowdfunding campaign are now operational.

foundry-zksync is still in an alpha stage, so some features might not be fully supported yet and may not work as fully intended. It is open-sourced and contributions are welcomed.

Run the following command in your terminal to initialize the Foundry project.

npx zksync-cli@latest create --template qs-fs-factories foundry-contract-factory-quickstart
cd foundry-contract-factory-quickstart

Set up your wallet

Deploying contracts on the ZKsync Sepolia Testnet requires having testnet ETH. If you're working within the local development environment, you can utilize pre-configured rich wallets and skip this step. For testnet deployments, you should have your wallet funded from the previous step.


Review the CrowdfundingFactory contract

The CrowdfundingFactory.sol we will compile and deploy is provided under the /src directory.

The CrowdfundingFactory.solcontract will be used to deploy multiple instances of the CrowdfundingCampaign.sol contract from the previous guide.

The CrowdfundingFactory contract automates the creation and oversight of CrowdfundingCampaign contracts, each with its distinct funding goals, it features:

  • Campaign Creation: Utilizes the createCampaign method to initiate a new CrowdfundingCampaign contract. This function takes a fundingGoal as an argument, deploys a new campaign contract with this goal, and tracks the created campaign in the campaigns array.
  • Campaign Tracking: The getCampaigns method offers a view into all the campaigns created by the factory, allowing for easy access and management of multiple crowdfunding initiatives.

This contract factory approach streamlines the deployment of crowdfunding campaigns, making it efficient to launch and manage multiple campaigns.

Compile contract

Smart contracts deployed to ZKsync must be compiled using our custom compiler. For this particular guide we are making use of zksolc.

To compile the contracts in the project, run the following command:

forge build --zksync --use 0.8.20

Upon successful compilation, you'll receive output detailing the zksolc and solc versions used during compiling and the number of Solidity files compiled.

[⠒] Compiling...
[⠃] Compiling 3 files with 0.8.20
[⠊] Solc 0.8.20 finished in 336.48ms
Compiler run successful!
Compiling contracts for ZKsync Era with zksolc v1.4.0

The compiled zkEVM artifacts will be located in the /zkout folder, and the solc artifacts will be located in the /out folder.


Deploy a CrowdfundingCampaign with CrowdfundingFactory

This section outlines the steps to deploy the CrowdfundingCampaign contract using our new CrowdfundingFactory.

  1. Let's start by deploying the CrowdfundingFactory contract. Execute the following command:
    forge create src/CrowdfundFactory.sol:CrowdfundingFactory --factory-deps src/CrowdfundingCampaign.sol:CrowdfundingCampaign --account myKeystore --sender <KEYSTORE_ADDRESS> --rpc-url zkSyncSepoliaTestnet --chain 300 --zksync
    # To deploy the contract on local in-memory node:
    # forge script script/DeployFactory.s.sol:DeployFactoryAndCreateCampaign --account myKeystore --sender <KEYSTORE_ADDRESS> --rpc-url inMemoryNode --broadcast --zksync
    

    Upon a successfull deployment you'll receive details of the deploying address, the contract address, and the transaction hash, like so:
    Deployer: 0x89E0Ff69Cc520b55C9F7Bcd3EAC17e81d9bB8dc2
    Deployed to: 0x607545Fd35ef49d7445555ddFa22938fD4Efb219
    Transaction hash: 0x94e7a97bb64c2bacffbd2a47f3c10021a80156d11082c079046a426c99518d28
    
  2. Using the CrowdfundingFactory contract address let's deploy our CrowdfundingCampaign:
    cast send 0x607545Fd35ef49d7445555ddFa22938fD4Efb219 "createCampaign(uint256)" "1" --rpc-url zkSyncSepoliaTestnet --chain 300 --account myKeystore --sender <KEYSTORE_ADDRESS>
    # To use the contract factory on local in-memory node:
    # cast send 0x607545Fd35ef49d7445555ddFa22938fD4Efb219 "createCampaign(uint256)" "1" --rpc-url inMemoryNode --chain 260 --account myKeystore --sender <KEYSTORE_ADDRESS>
    

    Upon a successfull deployment you'll receive details of the transaction, including the contract address of our crowdfunding campaign:
    blockHash               0x7f8dfcd365b4ba5ac690e94aedb5fdb2bdb5ef12b2ff68672ab58c7a89738161
    blockNumber             1576375
    contractAddress         0x95f83473b88B5599cdB273F976fB3DC66DEA1c1D
    ...
    ...
    

🌟 Brilliant! Your contract factory and its first crowdfunding campaign are now operational.

Takeaways

  • Contract Factories: Utilizing contract factories significantly streamlines the deployment process, allowing for the creation of multiple instances of a contract, like the CrowdfundingCampaign, with varied parameters.
  • Scalability and Management: Contract factories offer a scalable solution to manage numerous contract instances, enhancing project organization and efficiency.
  • Event-Driven Insights: The CampaignCreated event in the factory contract provides a transparent mechanism to track each crowdfunding campaign's deployment, useful for off-chain monitoring and interaction.

Next steps

With the contract factory in your ZKsync development arsenal, you're set to elevate your smart contract projects. Here's how you can further your journey:

  • Contract Testing: Progress to the next guide focused on testing your contracts. Ensuring the reliability and security of your CrowdfundingCampaign through comprehensive tests is critical.
  • Advanced ZKsync Integrations: Explore deeper into ZKsync's ecosystem by implementing features like account abstraction and paymasters to enhance user experience and contract flexibility.
  • Community Engagement and Contribution: Join the vibrant ZKsync community. Participate in forums, Discord, or GitHub discussions. Sharing insights, asking queries, and contributing can enrich the ecosystem and your understanding of ZKsync.

Made with ❤️ by the ZKsync Community