---
title: Use Hardhat with Polkadot Hub
description: Learn how to create, compile, test, and deploy smart contracts on Polkadot Hub using Hardhat, a powerful development environment for blockchain developers.
categories: Smart Contracts, Tooling
url: https://developer.polkadot.com/smart-contracts/dev-environments/hardhat/
word_count: 2301
token_estimate: 4195
version_hash: sha256:81112c9679a123eb53c89b4b04925481e418e67d4dcf48c1905a5e5c9d5e8862
last_updated: 2026-10-28T08:43:55+00:00
---

# Hardhat

## Introduction

[Hardhat](https://hardhat.org/) is a flexible development environment for building, testing, and deploying smart contracts on Polkadot. Its task runner and plugin system support organizing contract code, running tests, managing deployments, and adding custom tooling. This page demonstrates how to set up a Hardhat project for Polkadot Hub.

!!! info "Testing and debugging against Polkadot"
    When using standard Hardhat against Polkadot nodes, some behaviors differ (e.g., network helpers like `time.increase()` or `loadFixture` may not work). See [Differences between Ethereum-native tools and Polkadot EVM networks](/smart-contracts/get-started/#differences-between-ethereum-native-tools-and-polkadot-evm-networks) for details.

## Prerequisites

Before setting up Hardhat, make sure the following are installed:

- [Node.js](https://nodejs.org/) (Hardhat requires an LTS Node version, even major numbers like 18.x, 20.x, or 22.x)
- A package manager like [npm](https://www.npmjs.com/), [pnpm](https://pnpm.io/), or [yarn](https://yarnpkg.com/)

## Initialize a Hardhat Project

1. Create a directory to hold your project files:

    ```bash
    mkdir hardhat-example
    cd hardhat-example
    ```

2. Initialize a Hardhat project:

    === "npm"

        This single command sets up your project, installs Hardhat (and optionally the Toolbox), and intializes the project:

        ```bash
        npx hardhat@^2.27.0 init
        ```

    === "pnpm"

        This single command sets up your project, installs Hardhat (and optionally the Toolbox), and intializes the project:

        ```bash
        pnpm dlx hardhat@^2.27.0 init
        ```

    === "yarn"

        These commands manually set up your project, install Hardhat (and optionally the Toolbox), and initializes the project:

        ```bash
        # Initialize a new Node.js project
        yarn init -y

        # Install Hardhat and the Hardhat Toolbox locally
        yarn add --dev hardhat@^2.27.0 @nomicfoundation/hardhat-toolbox

        # Initialize a Hardhat project
        npx hardhat init
        ```

3. You will be prompted to select certain configurations for your project. To quickly create a working setup, you can accept the default answers, which will create a JavaScript project, initialize it in the current directory, add a `.gitignore`, and install all dependencies.

After completing the setup, your Hardhat project will be fully initialized with all necessary files and dependencies. You'll see the following core components in your project:

- **`contracts`**: Stores your Solidity smart contracts.
- **`ignition`**: Contains deployment modules for safely deploying your contracts to various networks.
- **`test`**: Contains test files that validate contract functionality.
- **`hardhat.config.js | .ts`**: Defines your project's settings, including networks, compiler options, and plugins.

## Configure Hardhat for Polkadot Hub

To use Hardhat with Polkadot Hub, define the network configuration in your `hardhat.config.ts` file:

=== "Polkadot TestNet"

    ```ts title='hardhat.config.ts'
    import type { HardhatUserConfig } from 'hardhat/config';
    import '@nomicfoundation/hardhat-toolbox';

    // If you want to use a variable for your private key
    import { vars } from 'hardhat/config';

    const config: HardhatUserConfig = {
      solidity: '0.8.28',
      networks: {
        polkadotTestnet: {
          url: 'https://services.polkadothub-rpc.com/testnet',
          chainId: 420420417,
          accounts: [vars.get('PRIVATE_KEY')],
        },
      },
    };

    export default config;
    ```

!!! tip

    To define a [configuration variable](https://v2.hardhat.org/hardhat-runner/docs/guides/configuration-variables) for your private key, run:

    ```bash
    npx hardhat vars set PRIVATE_KEY
    ```

    Hardhat will prompt you to enter your private key and store it so it can be referenced in your configuration file.

## Verify a Contract

To verify your deployed contract on Polkadot Hub, install the Hardhat verification plugin and add the explorer configuration to your config.

### Install the Verification Plugin

```bash
npm install --save-dev @nomicfoundation/hardhat-verify@^2.0.0
```

!!! note "Hardhat 2 Compatibility"
    Use `@nomicfoundation/hardhat-verify@^2.0.0` for Hardhat 2.x. The 3.x release requires Hardhat 3.

Add the plugin to your config file:

```ts
import "@nomicfoundation/hardhat-verify";
```

### Add Verification Config

Add the `etherscan` configuration to your `hardhat.config.ts`. Choose Blockscout or Routescan:

=== "Blockscout"

    Blockscout does not require an API key. Add the following to your config:

    ```ts title='hardhat.config.ts'
    import type { HardhatUserConfig } from 'hardhat/config';
    import '@nomicfoundation/hardhat-toolbox';
    import '@nomicfoundation/hardhat-verify';
    import { vars } from 'hardhat/config';

    const config: HardhatUserConfig = {
      solidity: '0.8.28',
      networks: {
        polkadotTestnet: {
          url: 'https://services.polkadothub-rpc.com/testnet',
          chainId: 420420417,
          accounts: [vars.get('PRIVATE_KEY')],
        },
      },
      etherscan: {
        apiKey: {
          polkadotTestnet: 'no-api-key-needed',
        },
        customChains: [
          {
            network: 'polkadotTestnet',
            chainId: 420420417,
            urls: {
              apiURL: 'https://blockscout-testnet.polkadot.io/api',
              browserURL: 'https://blockscout-testnet.polkadot.io/',
            },
          },
        ],
      },
    };

    export default config;
    ```

=== "Routescan"

    Routescan uses an Etherscan-compatible API. Get an API key from [Routescan](https://routescan.io/) or use `verifyContract` for testnets:

    ```ts title='hardhat.config.ts'
    import type { HardhatUserConfig } from 'hardhat/config';
    import '@nomicfoundation/hardhat-toolbox';
    import '@nomicfoundation/hardhat-verify';
    import { vars } from 'hardhat/config';

    const config: HardhatUserConfig = {
      solidity: '0.8.28',
      networks: {
        polkadotTestnet: {
          url: 'https://services.polkadothub-rpc.com/testnet',
          chainId: 420420417,
          accounts: [vars.get('PRIVATE_KEY')],
        },
      },
      etherscan: {
        apiKey: {
          polkadotTestnet: 'verifyContract',
        },
        customChains: [
          {
            network: 'polkadotTestnet',
            chainId: 420420417,
            urls: {
              apiURL: 'https://api.routescan.io/v2/network/testnet/evm/420420417/etherscan',
              browserURL: 'https://polkadot.testnet.routescan.io/',
            },
          },
        ],
      },
    };

    export default config;
    ```

### Basic Verification

Replace `INSERT_CONTRACT_ADDRESS` with your deployed contract's address. For contracts without constructor arguments:

```bash
npx hardhat verify --network polkadotTestnet INSERT_CONTRACT_ADDRESS
```

### Verification with Constructor Arguments

For contracts with constructor arguments, pass them as additional arguments:

```bash
npx hardhat verify --network polkadotTestnet INSERT_CONTRACT_ADDRESS "arg1" "arg2"
```

Example for a contract with constructor `(uint256 initialValue, address owner)`:

```bash
npx hardhat verify --network polkadotTestnet INSERT_CONTRACT_ADDRESS "42" "0x1234567890123456789012345678901234567890"
```

## Where to Go Next

<div class="grid cards" markdown>

-   <span class="badge guide">Guide</span> __Deploy a Basic Contract__

    ---

    Ready to start using Hardhat? Learn how to compile, test, and deploy a basic contract.

    [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-basic/basic-hardhat/)

-   <span class="badge guide">Guide</span> __Deploy an ERC-20__

    ---

    Walk through deploying a fully-functional ERC-20 to Polkadot Hub using Hardhat.

    [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-hardhat/)

-   <span class="badge guide">Guide</span> __Deploy an NFT__

    ---

    Walk through deploying an NFT to Polkadot Hub using Hardhat.

    [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-nft/nft-hardhat/)

-   <span class="badge guide">Guide</span> __Create a DApp__

    ---

    Learn step-by-step how to build a fully functional dApp that interacts with a smart contract deployed via Hardhat.

    [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/dapps/zero-to-hero/)

</div>

# Hardhat Polkadot

## Introduction

[Hardhat](https://hardhat.org/) is a flexible development environment for building, testing, and deploying smart contracts. With the [`@parity/hardhat-polkadot`](https://github.com/paritytech/hardhat-polkadot) plugin, you can compile Solidity contracts to PVM bytecode and deploy them to Polkadot Hub. This page demonstrates how to set up a Hardhat project for PVM development.

## Prerequisites

Before setting up Hardhat, make sure the following are installed:

- [Node.js](https://nodejs.org/) version 22.5+ and [npm](https://www.npmjs.com/) version 10.9.0+ to avoid issues with the Polkadot plugin
- A package manager like npm, [pnpm](https://pnpm.io/), or [yarn](https://yarnpkg.com/)

## Initialize a Hardhat Project

1. Create a directory to hold your project files:

    ```bash
    mkdir hardhat-pvm-example
    cd hardhat-pvm-example
    ```

2. Initialize a new npm project:

    ```bash
    npm init -y
    ```

3. Install the Polkadot plugin for Hardhat:

    ```bash
    npm install --save-dev @parity/hardhat-polkadot@0.3.0
    ```

4. Install the resolc compiler (required for compiling Solidity to PVM):

    ```bash
    npm install --save-dev @parity/resolc@1.4.0
    ```

5. Initialize a Hardhat project:

    ```bash
    npx hardhat-polkadot init
    ```

    Follow the project creation wizard. Your project will be created with three main folders:

    - **`contracts`**: Stores your Solidity smart contracts.
    - **`ignition`**: Contains deployment modules for safely deploying your contracts to various networks.
    - **`test`**: Contains test files that validate contract functionality.

6. Add the following folder to the `.gitignore` file if it is not already there:

    ```bash
    echo '/ignition/deployments/' >> .gitignore
    ```

7. Complete the setup by installing all dependencies:

    ```bash
    npm install
    ```

## Compile Your Contract

The plugin will compile your Solidity contracts (version `0.8.0` and higher) to PVM bytecode using the resolc compiler:

```bash
npx hardhat compile
```

After successful compilation, you'll see the artifacts generated in the `artifacts` directory:

```bash
ls artifacts/contracts/*.sol/
```

You should see JSON files containing the contract ABIs and bytecodes for the contracts you compiled.

## Test Your Contract Locally

Hardhat provides a local testing environment through the `hardhat-polkadot` plugin, which spins up a local Substrate node with an ETH-RPC adapter.

### Start a Local Node

To obtain the `dev-node` and `eth-rpc` binaries, check this [release](https://github.com/paritytech/hardhat-polkadot/releases/tag/nodes-19071579107) and download the binaries for your platform, then update the paths in your config.

!!! note
    You might need to give executable permissions to the binaries:
    
    ```bash
    chmod +x /path/to/your/binary
    ```
    
    In macOS environments, binaries are sometimes quarantined. To remove this, run:
    
    ```bash
    xattr -d com.apple.quarantine /path/to/your/binary
    ```

Once you have set up the binaries, start your local testing node:

```bash
npx hardhat node
```

This command launches a local node with the ETH-RPC adapter. By default, the Substrate node runs on `localhost:8000`, and the ETH-RPC adapter on `localhost:8545`.

The output will be something like this:

<div id="termynal" data-termynal>
    <span data-ty="input"><span class="file-path"></span>npx hardhat node</span>
    <br />
    <span data-ty>Starting server at 127.0.0.1:8000</span>
    <span data-ty>../bin/substrate-node --rpc-port=8000 --dev</span>
    <span data-ty>Starting the Eth RPC Adapter at 127.0.0.1:8545</span>
    <span data-ty>../bin/eth-rpc --node-rpc-url=ws://localhost:8000 --dev</span>
    <span data-ty>2025-05-29 13:00:32 Running in --dev mode, RPC CORS has been disabled.</span>
    <span data-ty>2025-05-29 13:00:32 Running in --dev mode, RPC CORS has been disabled.</span>
    <span data-ty>2025-05-29 13:00:32 🌐 Connecting to node at: ws://localhost:8000 ...</span>
    <span data-ty>2025-05-29 13:00:32 Substrate Node</span>
    <span data-ty>2025-05-29 13:00:32 ✌️ version 3.0.0-dev-f73c228b7a1</span>
    <span data-ty>2025-05-29 13:00:32 ❤️ by Parity Technologies &lt;admin@parity.io&gt;, 2017-2025</span>
    <span data-ty>2025-05-29 13:00:32 📋 Chain specification: Development</span>
    <span data-ty>2025-05-29 13:00:32 🏷 Node name: electric-activity-4221</span>
    <span data-ty>2025-05-29 13:00:32 👤 Role: AUTHORITY</span>
    <span data-ty>2025-05-29 13:00:32 💾 Database: RocksDb at /var/folders/f4/7rdt2m9d7j361dm453cpggbm0000gn/T/substrateOaoecu/chains/dev/db/full</span>
    <span data-ty>2025-05-29 13:00:36 [0] 💸 generated 1 npos voters, 1 from validators and 0 nominators</span>
    <span data-ty>...</span>
  </div>

### Run Tests

To run your contract tests:

```bash
npx hardhat test
```

!!! warning "Compatibility Note"
    Be aware that [`@nomicfoundation/hardhat-toolbox/network-helpers`](https://hardhat.org/hardhat-network-helpers/docs/overview) is not fully compatible with Polkadot Hub's available RPCs. Specifically, helpers like `time` and `loadFixture` may not work due to missing RPC calls in the node. For a broader overview of how Ethereum-native tools differ when used against Polkadot EVM networks, see [Differences between Ethereum-native tools and Polkadot EVM networks](/smart-contracts/get-started/#differences-between-ethereum-native-tools-and-polkadot-evm-networks). For plugin-specific details, refer to the [Compatibility](https://github.com/paritytech/hardhat-polkadot/tree/main/packages/hardhat-polkadot-node#compatibility) section in the `hardhat-polkadot` documentation.

### Deploy to Local Node

Before deploying to a live network, you can deploy your contract to a local node using [Ignition](https://hardhat.org/ignition/docs/getting-started#overview) modules:

1. Ensure your local node is running:

    ```bash
    npx hardhat node
    ```

2. In a new terminal window, deploy the contract using Ignition:

    ```bash
    npx hardhat ignition deploy ./ignition/modules/MyToken.js --network localNode
    ```

!!! tip
    The `ignition.requiredConfirmations: 1` setting in your config ensures that deployment doesn't hang on local nodes that only produce blocks when transactions are submitted.

## Deploy to Polkadot Hub TestNet

After testing locally, you can deploy to the Polkadot Hub TestNet:

1. Fund your deployment account with PAS test tokens from the [Polkadot faucet](https://faucet.polkadot.io/).

2. Set your private key as a configuration variable:

    ```bash
    npx hardhat vars set PRIVATE_KEY
    ```

    !!! warning
        Never reveal your private key. Anyone with access to it can control your wallet and steal your funds. Store it securely and never share it publicly or commit it to version control systems.

3. Verify your private key is set:

    ```bash
    npx hardhat vars get PRIVATE_KEY
    ```

4. Deploy your contract:

    ```bash
    npx hardhat ignition deploy ./ignition/modules/MyToken.js --network polkadotTestnet
    ```

### Common Issues

- **Compilation fails with resolc errors**: Ensure you have `@parity/resolc@1.4.0` installed and the version is specified in your `hardhat.config.js`
- **Deployment hangs on local node**: You might need to set `ignition.requiredConfirmations: 1` in your config file
- **Binary permission issues**: Run `chmod +x /path/to/your/binary` and on macOS, use `xattr -d com.apple.quarantine /path/to/your/binary`

## Where to Go Next

<div class="grid cards" markdown>

-   <span class="badge guide">Guide</span> __Deploy a Basic Contract__

    ---

    Ready to start using Hardhat with PVM? Learn how to compile, test, and deploy a basic contract.

    [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-basic/basic-hardhat/)

-   <span class="badge guide">Guide</span> __Deploy an ERC-20__

    ---

    Walk through deploying a fully-functional ERC-20 to Polkadot Hub using Hardhat.

    [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-hardhat/)

-   <span class="badge external">External</span> __Hardhat Documentation__

    ---

    Learn more about Hardhat's advanced features and best practices.

    [:octicons-arrow-right-24: Get Started](https://hardhat.org/docs)

-   <span class="badge external">External</span> __Hardhat Polkadot Plugin__

    ---

    Explore the full capabilities of the Hardhat Polkadot plugin.

    [:octicons-arrow-right-24: Get Started](https://github.com/paritytech/hardhat-polkadot)

</div>
