# Verifying smart contracts

Description: How to verify a smart contract

Note: This document was authored using MDX

  Source: https://github.com/NomicFoundation/hardhat-website/tree/main/src/content/docs/docs/guides/smart-contract-verification.mdx

  Components used in this page:
    - <Run cmd="..."/>: Runs a command in the terminal with npm/pnpm/yarn.
    - <Install pkg="..."/>: Installs a package in the terminal with npm/pnpm/yarn.
    - <Steps>: Wraps an ordered list to render as numbered steps. No props.
    - :::danger: A critical warning callout block. Supports custom title `:::danger[Title]` and icon `:::danger{icon="name"}` syntax.

import { Steps } from "@astrojs/starlight/components";
import Install from "@hh/Install.astro";
import Run from "@hh/Run.astro";

Smart contract verification is used to prove that a deployed contract's bytecode comes from a specific source code. This allows users and tools to inspect the original source on block explorers, like Etherscan and Blockscout, and verification services, like Sourcify.

In this guide, you'll learn how to verify your contracts using the `hardhat-verify` plugin.

## Setup

If you initialized your project using `hardhat --init` and chose anything but the minimal project, you don't need to do anything: `hardhat-verify` is already included as part of the template project.

If you want to add the plugin manually:

<Steps>

1. Install the plugin:

   <Install packages="@nomicfoundation/hardhat-verify" />

2. Add it to the list of plugins in your Hardhat configuration:

   ```ts
   // hardhat.config.ts
   import { defineConfig } from "hardhat/config";
   import hardhatVerify from "@nomicfoundation/hardhat-verify";

   export default defineConfig({
     plugins: [
       hardhatVerify,
       // ...other plugins...
     ],
     // ...other config...
   });
   ```

</Steps>

## Configuration

The `hardhat-verify` plugin adds a `verify` object to the Hardhat configuration. With it, you can configure the different block explorers to verify your contracts on.

To verify contracts on Etherscan, you need to set an API key in your Hardhat configuration:

```ts
// hardhat.config.ts
import { defineConfig } from "hardhat/config";

export default defineConfig({
  // ...
  verify: {
    etherscan: {
      apiKey: "YOUR_ETHERSCAN_API_KEY",
    },
  },
});
```

:::danger

In the example above we wrote the API key in a config file for learning purposes. This is a security risk, and you should avoid it.

Take a look at [this guide](/docs/guides/configuration-variables) to handle sensitive information in your config safely.

:::

You can get an Etherscan API key by following [this guide](https://etherscan.io/apidashboard). This plugin uses Etherscan's API v2, so it only requires a single API key, which works with every supported chain.

To verify contracts on Blockscout and Sourcify, you don't need to set an API key, nor any config.

You can also disable a block explorer by setting its `enabled` property to `false`. For example, you can disable Blockscout verification like this:

```ts
// hardhat.config.ts
import { defineConfig } from "hardhat/config";

export default defineConfig({
  // ...
  verify: {
    blockscout: {
      enabled: false,
    },
  },
});
```

## Verifying a contract

To verify a contract, run the `verify` task with the contract's address and the network you deployed it to:

<Run command="hardhat verify --network sepolia 0x1234567890..." />

If your contract has constructor arguments, you have to also pass the values that were used during deployment. For example, if the contract received a `string` and a `uint` as constructor parameters:

<Run command='hardhat verify --network sepolia 0x1234567890... "Hello" 1000' />

If the arguments are too complex to pass directly in the shell, for example an array of numbers, you can define them in a TypeScript or JavaScript file:

```ts
// constructor-args.ts
const constructorArgs = ["Hello", [1000, 2000]];

export default constructorArgs;
```

and then pass it with the `--constructor-args-path` flag:

<Run command="hardhat verify --network sepolia --constructor-args-path constructor-args.ts 0x1234567890..." />

## Using different build profiles

By default, the `verify` task uses the `production` build profile, as this is the recommended build profile to build your contracts before deploying them. If you deploy your contracts with Hardhat Ignition, you automatically use the `production` build profile.

If you want to use a different build profile, you can pass the `--build-profile` flag:

<Run command="hardhat verify --network sepolia --build-profile default 0x1234567890..." />

## Verifying contracts on different block explorers

The plugin currently supports Etherscan, Blockscout, and Sourcify. You can use subtasks to verify on each of the block explorers:

<Run command="hardhat verify etherscan ..." />

These subtasks have the same interface, but verify on different services.

Running `verify` without any subtask will verify on Etherscan, Blockscout, and Sourcify.

## Verifying on a block explorer of a different network

If you want to verify a contract on a block explorer of a network that isn't natively supported by the plugin, you can set a chain descriptor in your Hardhat configuration to add support for that network.

Adding a chain descriptor for a network called "ExampleChain", with chain id `123456`, would look like this:

```ts
// hardhat.config.ts
import { defineConfig } from "hardhat/config";

export default defineConfig({
  // ...
  chainDescriptors: {
    // Example chain
    123456: {
      name: "ExampleChain",
      blockExplorers: {
        etherscan: {
          name: "ExampleScan",
          url: "https://example.scan",
          apiUrl: "https://example.scan/api",
        },
        // other explorers...
      },
    },
  },
});
```

## Troubleshooting

Your verification might fail for a variety of reasons. Here are some common issues and how to fix them:

- **Verifying immediately after deploying**: Your contracts may not have been indexed by the block explorer yet, causing the verification to fail. Normally, waiting a minute is enough for it to work
- **Wrong constructor arguments**: Double-check that your constructor arguments are correct
- **Using code that is different from the one used for deployment**: If you are trying to verify a contract that you have deployed weeks ago, then chances are that the code has changed in the meantime. Double-check that you are using the correct code
- **Using a different build profile**: If you are using a different build profile than the one used for deployment, then the bytecode will be different, causing the verification to fail. Try using `--build-profile` with other profiles to verify your contract, beginning with `default`. You may also need to run `hardhat build` with the same build profile to generate the correct artifacts
