Getting started

Getting started

Hardhatopen in new window is an Ethereum development environment, designed for easy smart contract development in Solidity. One of its most prominent features is extendability: you can easily add new plugins to your hardhat project.

zkSync has has the following plugins for Hardhat:

To learn more about Hardhat itself, check out its official documentationopen in new window.

This tutorial shows how to set up a zkSync Solidity project using Hardhat from scratch. If you are using Vyper, check out the Vyper plugin documentation or this exampleopen in new window in GitHub!


For this tutorial, the following programs must be installed:

Project setup

  1. To initialize the project and install the dependencies, run the following commands in the terminal:
mkdir greeter-example
cd greeter-example
yarn init -y
yarn add -D typescript ts-node @types/node ethers@^5.7.2 zksync-web3 @ethersproject/hash @ethersproject/web hardhat @matterlabs/hardhat-zksync-solc @matterlabs/hardhat-zksync-deploy

The typescript, ts-node and @types/node dependencies are optional - plugins will work fine in a vanilla JavaScript environment. Although, please note that this tutorial does use TypeScript.


If using Yarn 2 and over, you may need to do some extra steps for TypeScript to work as expected in your editor. To learn more, check out Yarn's official documentationopen in new window


  1. Create the hardhat.config.ts file and paste the following code within it:
import "@matterlabs/hardhat-zksync-deploy";
import "@matterlabs/hardhat-zksync-solc";

module.exports = {
  zksolc: {
    version: "1.3.5",
    compilerSource: "binary",
    settings: {},
  defaultNetwork: "zkTestnet",
  networks: {
    zkTestnet: {
      url: "", // URL of the zkSync network RPC
      ethNetwork: "goerli", // Can also be the RPC URL of the Ethereum network (e.g. `<API_KEY>`)
      zksync: true,
  solidity: {
    version: "0.8.17",


To learn more about each specific property in the hardhat.config.ts file, check out the plugins documentation

Write and deploy a contract

  1. Create the contracts and deploy folders. In the contracts folder we will store all the smart contract files. In the deploy folder we'll place all the scripts related to deploying the contracts.

  2. Create the contracts/Greeter.sol contract and paste the following code:

//SPDX-License-Identifier: Unlicensed
pragma solidity ^0.8.0;

contract Greeter {
    string private greeting;

    constructor(string memory _greeting) {
        greeting = _greeting;

    function greet() public view returns (string memory) {
        return greeting;

    function setGreeting(string memory _greeting) public {
        greeting = _greeting;
  1. Run yarn hardhat compile which uses the hardhat-zksync-solc plugin to compile the contract. The artifacts-zk and cache-zk folders will be created in the root directory (instead of the regular Hardhat's artifacts and cache).


Note that the artifacts-zk and cache-zk folders contain compilation artifacts and cache, and should not be added to version control, so it's a good practice to include them in the .gitignore file of your project.

  1. Create the deployment script in deploy/deploy.ts with the following code:
import { utils, Wallet } from "zksync-web3";
import * as ethers from "ethers";
import { HardhatRuntimeEnvironment } from "hardhat/types";
import { Deployer } from "@matterlabs/hardhat-zksync-deploy";

// An example of a deploy script that will deploy and call a simple contract.
export default async function (hre: HardhatRuntimeEnvironment) {
  console.log(`Running deploy script for the Greeter contract`);

  // Initialize the wallet.
  const wallet = new Wallet("<WALLET-PRIVATE-KEY>");

  // Create deployer object and load the artifact of the contract we want to deploy.
  const deployer = new Deployer(hre, wallet);
  const artifact = await deployer.loadArtifact("Greeter");

  // Deposit some funds to L2 in order to be able to perform L2 transactions.
  const depositAmount = ethers.utils.parseEther("0.001");
  const depositHandle = await deployer.zkWallet.deposit({
    to: deployer.zkWallet.address,
    token: utils.ETH_ADDRESS,
    amount: depositAmount,
  // Wait until the deposit is processed on zkSync
  await depositHandle.wait();

  // Deploy this contract. The returned object will be of a `Contract` type, similarly to ones in `ethers`.
  // `greeting` is an argument for contract constructor.
  const greeting = "Hi there!";
  const greeterContract = await deployer.deploy(artifact, [greeting]);

  // Show the contract info.
  const contractAddress = greeterContract.address;
  console.log(`${artifact.contractName} was deployed to ${contractAddress}`);

  // Call the deployed contract.
  const greetingFromContract = await greeterContract.greet();
  if (greetingFromContract == greeting) {
    console.log(`Contract greets us with ${greeting}!`);
  } else {
    console.error(`Contract said something unexpected: ${greetingFromContract}`);

  // Edit the greeting of the contract
  const newGreeting = "Hey guys";
  const setNewGreetingHandle = await greeterContract.setGreeting(newGreeting);
  await setNewGreetingHandle.wait();

  const newGreetingFromContract = await greeterContract.greet();
  if (newGreetingFromContract == newGreeting) {
    console.log(`Contract greets us with ${newGreeting}!`);
  } else {
    console.error(`Contract said something unexpected: ${newGreetingFromContract}`);
  1. After replacing the WALLET-PRIVATE-KEY text with the private key of your Ethereum wallet, run the script using the following command: yarn hardhat deploy-zksync. This script will:
  • Transfer 0.001 ETH from Goerli to zkSync.
  • Deploy the Greeting contract with the message "Hi there!" to zkSync Era Testnet.
  • Retrieve the message from the contract calling the greet() method.
  • Update the greet message in the contract with the setGreeting() method.
  • Retrieve the message from the contract again.

Congratulations! Your Hardhat project is now running on zkSync Era Testnet 🎉

Request-Rate Exceeded message

This message is caused by using the default RPC endpoints provided by ethers. To avoid this, use your own Goerli RPC endpoint.You can find multiple node providers hereopen in new window.

Learn more

Future releases

There are two major points of improvement for the plugins which will be released in the future:

  • Composability with the existing hardhat plugins. Compatibility with other hardhat plugins is planned for the future but has not been a focus yet.
  • Improved cross-platform support.
Last update:
Contributors: Antonio,Blessing Krofegha,Lyova Potyomkin,Stanislav Bezkorovainyi,A.L.I.E.Z,AnastasiiaVashchuk,Bence Haromi,FilipTxFusion,Jay Welsh,Roman Brodetski,barakshani,botdad,mpavlovic-txfusion,mpopovac-txfusion,robriks