---
description: Learn how to use Hardhat with ZKsync.
---

# Getting started

***

{% hint style="info" %}
If you are using Windows, we strongly recommend you use Windows Subsystem for Linux (also known as WSL 2). You can use <mark style="color:blue;">`Hardhat`</mark> and <mark style="color:blue;">`Hardhat ZKsync plugins`</mark> without it, but it will work better if you use it.To install Node.js using WSL 2, please read this [guide](https://learn.microsoft.com/en-us/windows/dev-environment/javascript/nodejs-on-wsl).
{% endhint %}

[Hardhat](https://hardhat.org/) is an Ethereum development environment, designed for easy smart contract development. One of its most prominent features is extendability: you can easily add new plugins to your hardhat project.

Along with the official plugins, there are [other plugins from the community](../plugins/hardhat-community-plugins) that you can use with Validium.

To learn more about Hardhat itself, check out [the official documentation](https://hardhat.org/getting-started/).

This tutorial shows you how to setup a Validium Solidity project with Hardhat using the [ZKsync CLI](../../../cli/getting-started).

If you are using Vyper, check out the [Vyper plugin documentation](../plugins/hardhat-zksync-vyper) or the [vyper-example](https://github.com/matter-labs/hardhat-zksync/tree/main/examples/vyper-example) in GitHub!

### Project setup <a href="#project-setup" id="project-setup"></a>

To create a new project run the `zksync-cli create` command, passing a project name:

**Solidity project**

```bash
npx zksync-cli create demo --template hardhat_solidity
```

**Vyper project**

```bash
npx zksync-cli create demo --template hardhat_vyper
```

This command creates a `demo` folder and clones a Hardhat template project inside it. The downloaded project is already configured and contains all the required plugins.

If you want to migrate an existing project, please check the [project migration guide](migrating-hardhat-project-to-validium).

### Hardhat configuration <a href="#hardhat-configuration" id="hardhat-configuration"></a>

The `hardhat.config.ts` file contains some Validium specific configurations:

The Validium deployment and compiler plugin imports:

**Solidity project**

```javascript
import "@matterlabs/hardhat-zksync";
```

The `zksolc` block contains the minimal configuration for the compiler.

```javascript
zksolc: {
  version: "latest", // Uses latest available in https://github.com/matter-labs/zksolc-bin
  settings: {},
},
```

**Vyper project**

```javascript
import "@nomiclabs/hardhat-vyper";
import "@matterlabs/hardhat-zksync-deploy";
import "@matterlabs/hardhat-zksync-vyper";
```

The `zkvyper` block contains the minimal configuration for the compiler.

```javascript
zkvyper: {
  version: "latest", // Uses latest available in https://github.com/matter-labs/zkvyper-bin
  settings: {},
},
```

**Network**

The network endpoints of the `zkSyncTestnet` network change dynamically for local tests.

```javascript
// dynamically changes endpoints for local tests
const zkSyncTestnet =
  process.env.NODE_ENV == "test"
    ? {
        url: "http://localhost:3050",
        ethNetwork: "http://localhost:8545",
        zksync: true,
      }
    : {
        url: "https://sepolia.era.zksync.dev",
        ethNetwork: "sepolia",
        zksync: true,
      };
```

For local Validium testing, modify `url` and `ethNetwork` in `hardhat.config.ts` to align with your local Validium and Ethereum node's L2 and L1 RPC URLs, respectively.This template project includes a basic unit test in the `/test` folder that runs with the local-setup and can be executed with `yarn test`.

### Set your Private Key <a href="#set-your-private-key" id="set-your-private-key"></a>

Rename `.env.example` to `.env` and set your private key:

```bash
WALLET_PRIVATE_KEY=YourPrivateKeyHere
```

Your private key will be used for paying the costs of deploying the smart contract.

### Compile and deploy a contract <a href="#compile-and-deploy-a-contract" id="compile-and-deploy-a-contract"></a>

Smart contracts belong in the `contracts` folder.

**1. To compile the contract, run**

```bash
yarn hardhat compile
```

You'll see the following output:

```bash
Compiling 1 Solidity file
Successfully compiled 1 Solidity file
// Successfully compiled 1 Vyper file - Vyper project
✨  Done in 1.09s.
```

The `artifacts-zk` and `cache-zk` folders appear in the root directory (instead of the regular Hardhat's `artifacts` and `cache`). These folders contain the compilation artifacts (including contract's ABIs) and compiler cache files.

The `artifacts-zk` and `cache-zk` folders are included in the `.gitignore` file.

The `deploy-greeter.ts` script is in the `deploy` folder. This script uses the `Deployer` class from the `hardhat-zksync-deploy` package to deploy the `Greeter.sol`/`Greeter.vy` contract.

```javascript
import { Wallet, utils } from "zksync-ethers";
import * as ethers from "ethers";
import { HardhatRuntimeEnvironment } from "hardhat/types";
import { Deployer } from "@matterlabs/hardhat-zksync-deploy";

// load env file
import dotenv from "dotenv";
dotenv.config();

// load wallet private key from env file
const PRIVATE_KEY = process.env.WALLET_PRIVATE_KEY || "";

if (!PRIVATE_KEY) throw "⛔️ Private key not detected! Add it to the .env file!";

// 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(PRIVATE_KEY);

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

  // Estimate contract deployment fee
  const greeting = "Hi there!";
  const deploymentFee = await deployer.estimateDeployFee(artifact, [greeting]);

  // ⚠️ OPTIONAL: You can skip this block if your account already has funds in L2
  // const depositHandle = await deployer.zkWallet.deposit({
  //   to: deployer.zkWallet.address,
  //   token: utils.ETH_ADDRESS,
  //   amount: deploymentFee.mul(2),
  // });
  // // Wait until the deposit is processed on ZKsync
  // await depositHandle.wait();

  // Deploy this contract. The returned object will be of a `Contract` type, similar to ones in `ethers`.
  // `greeting` is an argument for contract constructor.
  const parsedFee = ethers.formatEther(deploymentFee);
  console.log(`The deployment is estimated to cost ${parsedFee} ETH`);

  const greeterContract = await deployer.deploy(artifact, [greeting]);

  // obtain the Constructor Arguments
  console.log("constructor args:" + greeterContract.interface.encodeDeploy([greeting]));

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

**2. To execute the deployment script run**

```bash
yarn hardhat deploy-zksync --script deploy-greeter.ts
```

This script deploys the `Greeting` contract with the message "Hi there!" to Validium Sepolia Testnet.

You should see something like this:

```bash
Running deploy script for the Greeter contract
The deployment is estimated to cost 0.00579276320831943 ETH
constructor args:0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000094869207468657265210000000000000000000000000000000000000000000000
Greeter was deployed to 0x46f1d2d8A16DBD8b47e9D61175a826ac667288Be4D1293a22E8

✨  Done in 12.69s.
```

Congratulations! You have deployed a smart contract project to Validium Sepolia Testnet with Hardhat 🎉

**Request-Rate Exceeded message**:

* This message is caused by using the default RPC endpoints provided by ethers.
* To avoid this, use your own Sepolia RPC endpoint in the `hardhat.config.ts` file.
* Find multiple [node providers here](https://github.com/arddluma/awesome-list-rpc-nodes-providers).

### Interact with the contract <a href="#interact-with-the-contract" id="interact-with-the-contract"></a>

The template project contains another script to interact with the contract.

1.  Enter the address of the deployed Greeter contract in the `CONTRACT_ADDRESS` variable of the `use-greeter.ts` script:use-greeter.ts

    ```javascript
    import { Provider } from "zksync-ethers";
    import * as ethers from "ethers";
    import { HardhatRuntimeEnvironment } from "hardhat/types";

    // load env file
    import dotenv from "dotenv";
    dotenv.config();

    // load contract artifact. Make sure to compile first! - Solidity Project
    import * as ContractArtifact from "../artifacts-zk/contracts/Greeter.sol/Greeter.json";
    // load contract artifact. Make sure to compile first! - Vyper Project
    //import * as ContractArtifact from "../artifacts-zk/contracts/Greeter.vy/Greeter.json";

    const PRIVATE_KEY = process.env.WALLET_PRIVATE_KEY || "";

    if (!PRIVATE_KEY) throw "⛔️ Private key not detected! Add it to the .env file!";

    // Address of the contract on Validium testnet
    const CONTRACT_ADDRESS = "";

    if (!CONTRACT_ADDRESS) throw "⛔️ Contract address not provided";

    // An example of a deploy script that will deploy and call a simple contract.
    export default async function (hre: HardhatRuntimeEnvironment) {
      console.log(`Running script to interact with contract ${CONTRACT_ADDRESS}`);

      // Initialize the provider.
      // @ts-ignore
      const provider = new Provider(hre.userConfig.networks?.zkSyncTestnet?.url);
      const signer = new ethers.Wallet(PRIVATE_KEY, provider);

      // Initialise contract instance
      const contract = new ethers.Contract(CONTRACT_ADDRESS, ContractArtifact.abi, signer);

      // Read message from contract
      console.log(`The message is ${await contract.greet()}`);

      // send transaction to update the message
      const newMessage = "Hello people!";
      const tx = await contract.setGreeting(newMessage);

      console.log(`Transaction to change the message is ${tx.hash}`);
      await tx.wait();

      // Read message after transaction
      console.log(`The message now is ${await contract.greet()}`);
    }
    ```
2.  To execute the script, run:

    ```bash
    yarn hardhat deploy-zksync --script use-greeter.ts
    ```

    \
    The script will:

    * Retrieve the message from the contract by calling the `greet()` method.
    * Update the greeting message in the contract with the `setGreeting()` method.
    * Retrieve the message from the contract again.

    \
    You should see something like this:

    ```bash
    Running script to interact with contract Greeter
    The message is Hello there!
    Transaction to change the message is 0x12f16578A16DB0f47e9D61175a823ac214288Af
    The message now is Hello people!

    ✨  Done in 14.32s.
    ```

### Learn more <a href="#learn-more" id="learn-more"></a>

* To learn more about the ZKsync Hardhat plugins check out the [plugins documentation](getting-started).
* If you want to know more about how to interact with ZKsync using Javascript, check out the [zksync-ethers Javascript SDK documentation](https://sdk.zksync.io/js/ethers).

Check the [installation guide](../installation) for instructions!
