Hello ZKsync!

Learn to deploy smart contracts efficiently in the ZKsync environment.

Welcome to ZKsync 101 for deploying smart contracts on ZKsync! In this series, we'll walk you through the process of creating and deploying a simple smart contract that creates a crowdfunding campaign for Zeek. In this section you will learn how to:

Craft a smart contract to fund Zeek's latest adventure.

Deploy the contract onto your local in memory node.

Interact with the contract with ZKsync CLI

Let's dive in and start your developer journey on ZKsync!


This series requires some initial setup of tools to enhance your development experience building for ZKsync. Make sure to go through the setup provided in the initial Getting started section.

Compile the CrowdfundingCampaign.sol contract

This guide introduces a crowdfunding campaign contract aimed at supporting Zeek's creative ventures. Let's start by reviewing the starter contract CrowdfundingCampaign.sol in the contracts/1-hello-zksync/CrowdfundingCampaign.sol directory.

The CrowdfundingCampaign contract is designed for a simple crowdfunding campaign. This contract features:

  • A constructor to initialize the campaign's funding target.
  • The contribute method to log funds, triggering ContributionReceived and GoalReached events.
  • The withdrawFunds method, allowing the owner to collect accumulated funds post-goal achievement.
  • The getTotalFundsRaised method to return the total amount of funds that's been raised.
  • The getFundingGoal method to return the goal for the campaign to reach.

Run the compile script from your project in the terminal:

npm
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.

Smart contracts deployed to ZKsync must be compiled using our custom compiler. zksolc is the compiler used for Solidity. This is why they're placed in the artifacts-zk folder!

Deploy the contract

The deployment script is located at /deploy/1-hello-zksync/deploy.ts.

Key Components:

  • contractArtifactName: Identifies the CrowdfundingCampaign contract for deployment.
  • constructorArguments: Sets initialization parameters for the contract. In this case, the fundraising goal, converted from ether to wei to match Solidity's uint256 type.
  1. Execute the deployment command from package.json.
npm
npm run deploy:hello-zksync

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

Starting deployment process of "CrowdfundingCampaign"...
Estimated deployment cost: 0.0065057128 ETH

"CrowdfundingCampaign" was successfully deployed:
 - Contract address: 0x26b368C3Ed16313eBd6660b72d8e4439a697Cb0B
 - Contract source: contracts/1-hello-zksync/CrowdfundingCampaign.sol:CrowdfundingCampaign
 - Encoded constructor arguments: 0x00000000000000000000000000000000000000000000000000470de4df820000

Interact with the contract

Now that our contract is deployed to our local in memory node, let's interact with it! We initially set up the crowdfunding campaign with an amount of .02 ETH for the goal.

Read from the contract using ZKsync CLI

We can confirm the amount by calling the getFundingGoal method using ZKsync CLI.

In the terminal, run the following in your project directory, replacing the contract address with your contract's address:

zksync-cli contract read \
--chain in-memory-node \
--contract <0xYOUR_CONTRACT_ADDRESS> \
--abi artifacts-zk/contracts/1-hello-zksync/CrowdfundingCampaign.sol/CrowdfundingCampaign.json

The CLI will prompt you with a list of available methods to select from. Navigate with the arrow keys and press Enter on the method getFundingGoal().

Using provided ABI file
? Contract method to call (Use arrow keys)
  ──────────────── Provided contract ────────────────
 getFundingGoal() view returns (uint256)
  getTotalFundsRaised() view returns (uint256)
  owner() view returns (address)
  ───────────────────────────────────────────────────
  Type method manually
  • The --chain option defines the network we want to use, which is our local in-memory node.
  • The --contract is the address of the contract you just deployed.
  • The --abi provides the ABI to decode the contract and provide the list of methods to select from. Without the ABI provided, you will have to manually type out the method name.

You will get a response with the amount that we passed in to the constructor on deploy:

? Contract method to call getFundingGoal() view returns (uint256)

 Method response (raw): 0x00000000000000000000000000000000000000000000000000470de4df820000
 Decoded method response: 20000000000000000

Write to the contract using ZKsync CLI

Let's fund this crowdfunding campaign and make Zeek happy!

We will write to the contract using ZKsync CLI, which requires a private key. In this demonstration we will use the second wallet provided in the list of rich wallets.

In the terminal, run the following command with your deployed contract's address:

zksync-cli contract write \
--chain in-memory-node \
--contract <0xCONTRACT_ADDRESS> \
--abi artifacts-zk/contracts/1-hello-zksync/CrowdfundingCampaign.sol/CrowdfundingCampaign.json \
--pk 0xac1e735be8536c6534bb4f17f06f6afc73b2b5ba84ac2cfb12f7461b20c0bbe3 \
--value 0.5

In the prompt, press Enter on the contribute() payable method. The CLI will then output the transaction information upon success.

We can read the transaction data of the contribution with the following:

zksync-cli transaction info \
--tx <0xTRANSACTION_HASH> \
--chain in-memory-node

Our crowdfund has reached its funding goal! Let's withdraw the funds for the owner:

zksync-cli contract write \
--chain in-memory-node \
--contract <0xCONTRACT_ADDRESS> \
--pk 0x7726827caac94a7f9e1b160f7ea819f172f7b6f9d2a97f992c38edeab82d4110

The CLI will prompt for the method to call, we will call withdrawFunds():

? Enter method to call withdrawFunds()

Congratulations! You've deployed a crowdfunding contract and learned how to interact with the deployed contract using ZKsync CLI!

Takeaways

  • EVM Compatibility: ZKsync is EVM compatible and you can write smart contracts in Solidity or Vyper.
  • Custom Compilation: Contracts deployed to ZKsync are compiled using zksolc or zkvyper as they generate a special bytecode for ZKsync's ZKEVM.
  • Development Tools: In memory node is a quick and easy local node environment to deploy to, saving costs on deployment while developing.
  • ZKsync CLI: A powerful command line tool to interact with contracts easily.

Next steps

Having successfully deployed your first contract on ZKsync, you're well on your way to becoming a proficient ZKsync developer. To expand your expertise:

  • Explore Contract Factories: Enhance your project by building a contract factory for the CrowdfundingCampaign contract in the next guide. This will allow you to efficiently manage multiple crowdfunding campaigns, each with their own unique parameters.
  • Dive Deeper into ZKsync Features: Investigate advanced ZKsync features such as account abstraction, and paymasters.
  • Join the Community: Engage with the ZKsync developer community through forums, Discord channels, Dev Discussions, or GitHub repositories. Share your experiences, ask questions, and collaborate on projects.

Made with ❤️ by the ZKsync Community