Skip to main content

Deploying and Verifying Contracts - Hardhat V3

Updated over 2 weeks ago

This guide provides a complete procedure for initializing a new Hardhat v3 project, deploying a smart contract, and achieving an "Exact Match" verification on Routescan.

We will use the default files generated by the Hardhat wizard. It presents two methods for securely providing your private key and RPC URL:

  • Option A: Using terminal export commands (temporary, for a single session).

  • Option B: Using a .env file (persistent, stays in your project).

You only need to follow one of these options.

Project Initialization

First, we will create our project folder and initialize it with Hardhat.

  1. Open your Terminal

  2. Create a new project directory

    mkdir my-hardhat-project


    and navigate into it

    cd my-hardhat-project

  3. Initialize a project.

    npm init -y

  4. Install Hardhat.

    npm install --save-dev hardhat

  5. Run the Hardhat wizard.

    npx hardhat --init

  6. Answer the wizard prompts exactly as follows.

  • Which version of Hardhat would you like to use?hardhat-3

  • Where would you like to initialize the project?. (Press Enter)

  • What type of project would you like to initialize?node-test-runner-viem

  • Would you like to change ".\package.json" to turn your project into ESM?true

  • You need to install the necessary dependencies... Do you want to run it now?true

Configure hardhat.config.ts

This is the most important step. We will configure Hardhat to read your secret keys and set up the v3 verification method for Routescan.

Open the hardhat.config.ts file in your code editor and choose one of the two options below.

ℹ️ Custom Network Setup: This guide uses the Sepolia Testnet configuration as a reference. To deploy on your own ecosystem chain, you must replace the example values in hardhat.config.ts and .env with your specific network details:

  • Chain IDs

  • RPC URLs

  • Explorer URLs

  • Network Type (change accordingly to either testnet or mainnet in apiUrl row)

Option A: Configure for Terminal Exports (process.env)

Choose this option if you plan to use export commands in your terminal.

Replace the entire contents of hardhat.config.ts with this code:

import hardhatToolboxViemPlugin from "@nomicfoundation/hardhat-toolbox-viem";
import { configVariable, defineConfig } from "hardhat/config";
import hardhatVerify from "@nomicfoundation/hardhat-verify";

export default defineConfig({
plugins: [
hardhatToolboxViemPlugin,
hardhatVerify,
],

solidity: {
profiles: {
default: {
version: "0.8.28",
},
production: {
version: "0.8.28",
settings: {
optimizer: {
enabled: true,
runs: 200,
},
},
},
},
},

networks: {
routescan: {
type: "http",
chainType: "l1",
url: configVariable("SEPOLIA_RPC_URL"),
accounts: [configVariable("SEPOLIA_PRIVATE_KEY")],
chainId: 11155111,
},
},


verify: {
etherscan: {
apiKey: "ANY_STRING_WORKS",
},
},


chainDescriptors: {
11155111: {
name: "Routescan Sepolia",
blockExplorers: {

etherscan: {
name: "Routescan",
url: "https://11155111.testnet.routescan.io/",
apiUrl: "https://api.routescan.io/v2/network/testnet/evm/11155111/etherscan",
},
},
},
},
});

Save the file.

Option B: Configure for a .env File (configVariable)

Install dotenv. To load the .env file, we first need to install the dotenv package. In your terminal, run the following command from your project's root folder.

npm install dotenv

Replace the entire contents of hardhat.config.ts with this code:

import { HardhatUserConfig } from "hardhat/config";
import hardhatToolboxViemPlugin from "@nomicfoundation/hardhat-toolbox-viem";
import { defineConfig } from "hardhat/config";
import hardhatVerify from "@nomicfoundation/hardhat-verify";

import "dotenv/config";

const SEPOLIA_RPC_URL = process.env.SEPOLIA_RPC_URL || "";
const SEPOLIA_PRIVATE_KEY = process.env.SEPOLIA_PRIVATE_KEY || "";

export default defineConfig({
plugins: [
hardhatToolboxViemPlugin,
hardhatVerify,
],

solidity: {
profiles: {
default: {
version: "0.8.28",
},
production: {
version: "0.8.28",
settings: {
optimizer: {
enabled: true,
runs: 200,
},
},
},
},
},

networks: {
routescan: {
type: "http",
chainType: "l1",
url: SEPOLIA_RPC_URL,
accounts: SEPOLIA_PRIVATE_KEY ? [SEPOLIA_PRIVATE_KEY] : [],
chainId: 11155111,
},
},

ignition: {
explorerUrl: "https://11155111.testnet.routescan.io/address/",
},

verify: {
etherscan: {
apiKey: "ANY_STRING_WORKS",
},
},

chainDescriptors: {
11155111: {
name: "Routescan Sepolia",
blockExplorers: {
etherscan: {
name: "Routescan",
url: "https://11155111.testnet.routescan.io/",
apiUrl: "https://api.routescan.io/v2/network/testnet/evm/11155111/etherscan",
},
},
},
},
});

Save the file.

Set Your Environment Variables

You must now provide your secret keys using the method you just configured.

Option A: Set Terminal Exports

If you chose Option A in Step 2, run these commands in your terminal. They will only be valid for your current session.

export SEPOLIA_RPC_URL="YOUR_SEPOLIA_RPC_URL_HERE"
export SEPOLIA_PRIVATE_KEY="YOUR_WALLET_PRIVATE_KEY_HERE"

Option B: Create a .env File

If you chose Option B in Step 2, create a .env file in your project root.

  1. Create the file in your terminal:

    touch .env

    (Or create it manually in your code editor).

  2. Open the .env file and add your keys:

    SEPOLIA_RPC_URL="YOUR_SEPOLIA_RPC_URL_HERE" SEPOLIA_PRIVATE_KEY="YOUR_WALLET_PRIVATE_KEY_HERE"

  3. Save the file. Hardhat will now automatically load these variables.

Deploy and Verify

Now that your configuration and keys are ready, these final steps are the same for both options.

  1. Deploy the Contract

    • We will use the network name (routescan_sepolia) from our config file and the Counter.ts module file that the Hardhat wizard created.

    npx hardhat ignition deploy ./ignition/modules/Counter.ts --network routescan --verify

    At this stage, we included the --verify flag to tell Hardhat to automatically attempt verification on Routescan immediately after the deployment finishes. This simplifies your workflow by handling both deployment and source code verification in one single command, rather than requiring you to run a separate manual verification step later.

  2. Confirm the Deployment

    • Terminal will ask you to confirm: Confirm deploy to network routescan_sepolia (11155111)?

    • Type yes and press Enter.

  3. Copy the Contract Address

    • After a moment, the deployment will succeed. Copy the address from the output:

    • CounterModule#Counter - 0x...

    If the automatic verification fails (often due to network latency where the explorer hasn't indexed the new block yet), you can always manually verify it later using below command.

    To Verify the Contract

    • Use the address you just copied.

    • (Replace <YOUR_DEPLOYED_ADDRESS> with the address you copied)

    npx hardhat verify etherscan --network routescan --force <YOUR_DEPLOYED_ADDRESS>

After a successful run, the status on Routescan Contracts Tab will update to Contract Source Code Verified.

Submitted source code for verification on Routescan:    contracts/Counter.sol:Counter   Address: <YOUR_DEPLOYED_ADDRESS>   Waiting for verification result...    Contract verified successfully on Routescan!    contracts/Counter.sol:Counter   Explorer: https://11155111.testnet.routescan.io//address/<YOUR_DEPLOYED_ADDRESS>#cod
Did this answer your question?