Skip to content

Hardhat

PolkaVM Preview Release

PolkaVM smart contracts with Ethereum compatibility are in early-stage development and may be unstable or incomplete.

  • Test and Deploy with Hardhat


    Master Solidity smart contract development with Hardhat. Learn testing, deployment, and network interaction in one comprehensive tutorial.


    Get Started

Contracts Code Blob Size Disclaimer

The maximum contract code blob size on Polkadot Hub networks is 100 kilobytes, significantly larger than Ethereum’s EVM limit of 24 kilobytes.

For detailed comparisons and migration guidelines, see the EVM vs. PolkaVM documentation page.

Overview

Hardhat is a robust development environment for Ethereum-compatible chains that makes smart contract development more efficient. This guide walks you through the essentials of using Hardhat to create, compile, test, and deploy smart contracts on Polkadot Hub.

Prerequisites

Before getting started, ensure you have:

  • Node.js (v16.0.0 or later) and npm installed.
    • Note: Use Node.js 22.5+ and npm version 10.9.0+ to avoid issues with the Polkadot plugin.
  • Basic understanding of Solidity programming.
  • Some PAS test tokens to cover transaction fees (easily obtainable from the Polkadot faucet). To learn how to get test tokens, check out the Test Tokens section.

Set Up Hardhat

  1. Create a new directory for your project and navigate into it:

    mkdir hardhat-example
    cd hardhat-example
    
  2. Initialize a new npm project:

    npm init -y
    
  3. To interact with Polkadot, Hardhat requires the following plugin to compile contracts and to spawn a local node for testing:

    npm install --save-dev @parity/hardhat-polkadot@latest
    
  4. Create a Hardhat project:

    npx hardhat-polkadot init
    

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

    • contracts: Where your Solidity smart contracts live.
    • test: Contains your test files that validate contract functionality.
    • ignition: Deployment modules for safely deploying your contracts to various networks.
  5. Add the following folder to the .gitignore file if it is not already there:

    echo '/ignition/deployments/' >> .gitignore
    
  6. Finish the setup by installing all the dependencies:

    npm install
    

    Note

    This last step is needed to set up the hardhat-polkadot plugin. It will install the @parity/hardhat-polkadot package and all its dependencies. In the future, the plugin will handle this automatically.

Compile Your Contract

The plugin will compile your Solidity contracts for Solidity versions 0.8.0 and higher. To compile your project, follow these instructions:

  1. Make sure your Hardhat configuration file looks like the following. Note that it may differ slightly based on the language choice made during the init step of setting up Hardhat:

    hardhat.config.js
    module.exports = {
      solidity: '0.8.28',
      networks: {
        hardhat: {
          polkadot: {
            target: 'evm',
          },
          nodeConfig: {
            nodeBinaryPath: './bin/dev-node',
            rpcPort: 8000,
            dev: true,
          },
          adapterConfig: {
            adapterBinaryPath: './bin/eth-rpc',
            dev: true,
          },
        },
        localNode: {
          polkadot: {
            target: 'evm',
          },
          url: `http://127.0.0.1:8545`,
        },
        polkadotHubTestnet: {
          polkadot: {
            target: 'evm',
          },
          url: 'https://testnet-passet-hub-eth-rpc.polkadot.io',
          accounts: [vars.get('PRIVATE_KEY')],
        },
      },
    };
    

    To obtain the dev-node and eth-rpc binaries required in nodeConfig and adapterConfig respectively, check this release and download the binaries as per your development platform and update the paths in your Hardhat config.

    Note

    You might have to give executable permissions to the binaries:

    chmod +x /path/to/your/binary
    
    In macOS environments, binaries are sometimes quarantined. To remove this, run:
    xattr -d com.apple.quarantine /path/to/your/binary
    

  2. Compile the contract with Hardhat:

    npx hardhat compile
    
  3. After successful compilation, you'll see the artifacts generated in the artifacts directory:

    ls artifacts/contracts/*.sol/
    

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

Set Up a Testing Environment

Hardhat lets you spin up a local testing environment to test and validate your smart contract functionality before deploying to live networks. The hardhat-polkadot plugin allows you to spin up a local node with an ETH-RPC adapter for running local tests.

Once you have set up the binaries as per the Compile Your Contract section, start your local testing node with:

npx hardhat node

This command launches a local node with the ETH-RPC adapter, providing a complete testing environment ready for contract deployment and interaction. By default, the Substrate node runs on localhost:8000, and the ETH-RPC adapter on localhost:8545.

The output will be something like this:

npx hardhat node
Starting server at 127.0.0.1:8000 ../bin/substrate-node --rpc-port=8000 --dev Starting the Eth RPC Adapter at 127.0.0.1:8545 ../bin/eth-rpc --node-rpc-url=ws://localhost:8000 --dev 2025-05-29 13:00:32 Running in --dev mode, RPC CORS has been disabled. 2025-05-29 13:00:32 Running in --dev mode, RPC CORS has been disabled. 2025-05-29 13:00:32 🌐 Connecting to node at: ws://localhost:8000 ... 2025-05-29 13:00:32 Substrate Node 2025-05-29 13:00:32 ✌️ version 3.0.0-dev-f73c228b7a1 2025-05-29 13:00:32 ❀️ by Parity Technologies <admin@parity.io>, 2017-2025 2025-05-29 13:00:32 πŸ“‹ Chain specification: Development 2025-05-29 13:00:32 🏷 Node name: electric-activity-4221 2025-05-29 13:00:32 πŸ‘€ Role: AUTHORITY 2025-05-29 13:00:32 πŸ’Ύ Database: RocksDb at /var/folders/f4/7rdt2m9d7j361dm453cpggbm0000gn/T/substrateOaoecu/chains/dev/db/full 2025-05-29 13:00:36 [0] πŸ’Έ generated 1 npos voters, 1 from validators and 0 nominators ...

Test Your Contract

When testing your contract, be aware that @nomicfoundation/hardhat-toolbox/network-helpers is not fully compatible with Polkadot Hub's available RPCs. Specifically, Hardhat-only helpers like time and loadFixture may not work due to missing RPC calls in the node. For more details, refer to the Compatibility section in the hardhat-revive docs. You should avoid using helpers like time and loadFixture when writing tests.

To run your test:

  1. Update the hardhat.config.js file as per the Compile Your Contract section.

  2. Execute the following command to run your tests:

    npx hardhat test
    

Deploy to a Local Node

Before deploying to a live network, you can deploy your contract to a local node using Ignition modules:

  1. Make sure that the local network is added as a target in your Hardhat configuration file for local deployment:

    hardhat.config.js
    localNode: {
      polkadot: {
        target: 'evm',
      },
      url: `http://127.0.0.1:8545`,
    },
    
  2. Start a local node:

    npx hardhat node
    

    This command will spawn a local Substrate node along with the ETH-RPC adapter.

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

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

Deploying to a Live Network

After testing your contract locally, you can deploy it to a live network. This guide will use the Polkadot Hub TestNet as the target network. Here's how to configure and deploy:

  1. Fund your deployment account with enough tokens to cover gas fees. In this case, the needed tokens are PAS (on Polkadot Hub TestNet). You can use the Polkadot faucet to obtain testing tokens.

  2. Export your private key and save it in your Hardhat environment:

    npx hardhat vars set PRIVATE_KEY "INSERT_PRIVATE_KEY"
    

    Replace INSERT_PRIVATE_KEY with your actual private key. For further details on private key exportation, refer to the article How to export an account's private key.

    Warning

    Never reveal your private key, otherwise 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. Check that your private key has been set up successfully by running:

    npx hardhat vars get PRIVATE_KEY
    
  4. Make sure the Polkadot Hub TestNet is added as a target in your Hardhat configuration file:

    hardhat.config.js
    polkadotHubTestnet: {
      polkadot: {
        target: 'evm',
      },
      url: 'https://testnet-passet-hub-eth-rpc.polkadot.io',
      accounts: [vars.get('PRIVATE_KEY')],
    },
    
  5. Deploy your contract using Ignition:

    npx hardhat ignition deploy ./ignition/modules/MyToken.js --network polkadotHubTestnet
    

Interacting with Your Contract

Once deployed, you can create a script to interact with your contract. To do so, create a file called scripts/interact.js and add some logic to interact with the contract.

For example, for the default MyToken.sol contract, you can use the following file that connects to the contract at its address and retrieves the unlockTime, which represents when funds can be withdrawn. The script converts this timestamp into a readable date and logs it. It then checks the contract's balance and displays it. Finally, it attempts to call the withdrawal function on the contract, but it catches and logs the error message if the withdrawal is not yet allowed (e.g., before unlockTime).

interact.js
const hre = require('hardhat');

async function main() {
  // Get the contract factory
  const MyToken = await hre.ethers.getContractFactory('MyToken');

  // Replace with your deployed contract address
  const contractAddress = 'INSERT_CONTRACT_ADDRESS';

  // Attach to existing contract
  const token = await MyToken.attach(contractAddress);

  // Get signers
  const [deployer] = await hre.ethers.getSigners();

  // Read contract state
  const name = await token.name();
  const symbol = await token.symbol();
  const totalSupply = await token.totalSupply();
  const balance = await token.balanceOf(deployer.address);

  console.log(`Token: ${name} (${symbol})`);
  console.log(
    `Total Supply: ${hre.ethers.formatUnits(totalSupply, 18)} tokens`,
  );
  console.log(
    `Deployer Balance: ${hre.ethers.formatUnits(balance, 18)} tokens`,
  );
}

main().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});

Run your interaction script:

npx hardhat run scripts/interact.js --network polkadotHubTestnet

Upgrading the Plugin

If you already have a Hardhat Polkadot project and want to upgrade to a newer version of the plugin, to avoid errors (for example, Cannot find module 'run-container'), you can clean your dependencies by running the following commands:

rm -rf node_modules package-lock.json

After that, you can upgrade the plugin to the latest version by running the following commands:

npm install --save-dev @parity/hardhat-polkadot@latest
npm install

Consider using Node.js 22.18+ and npm version 10.9.0+ to avoid issues with the plugin.

Where to Go Next

Hardhat provides a powerful environment for developing, testing, and deploying smart contracts on Polkadot Hub. Its plugin architecture allows seamless integration with PolkaVM through the hardhat-resolc and hardhat-revive-node plugins.

Explore more about smart contracts through these resources:

  • Guide Smart Contracts on Polkadot


    Dive into advanced smart contract concepts.

    Get Started

  • External Hardhat Documentation


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

    Get Started

  • External OpenZeppelin Contracts


    Test your skills by deploying contracts with prebuilt templates.

    Get Started

Last update: November 13, 2025
| Created: June 11, 2025