Verifying smart contracts
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.
In this guide, you’ll learn how to verify your contracts using the hardhat-verify plugin.
If you initialized your project using hardhat --init, 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:
-
Install the plugin:
Terminal window npm add --save-dev @nomicfoundation/hardhat-verifyTerminal window pnpm add --save-dev @nomicfoundation/hardhat-verifyTerminal window yarn add --save-dev @nomicfoundation/hardhat-verify -
Add it to the list of plugins in your Hardhat configuration:
import hardhatVerify from "@nomicfoundation/hardhat-verify";const config: HardhatUserConfig = {plugins: [hardhatVerify,// ...other plugins...],// ...other config...};export default config;
Configuration
Section titled “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:
const config: HardhatUserConfig = { // ... verify: { etherscan: { apiKey: "YOUR_ETHERSCAN_API_KEY", }, },};You can get an Etherscan API key by following this guide.
To verify contracts on Blockscout, 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:
const config: HardhatUserConfig = { // ... verify: { blockscout: { enabled: false, }, },};Verifying a contract
Section titled “Verifying a contract”To verify a contract, run the verify task with the contract’s address and the network you deployed it to:
npx hardhat verify --network sepolia 0x1234567890...pnpm hardhat verify --network sepolia 0x1234567890...yarn 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:
npx hardhat verify --network sepolia 0x1234567890... "Hello" 1000pnpm hardhat verify --network sepolia 0x1234567890... "Hello" 1000yarn hardhat verify --network sepolia 0x1234567890... "Hello" 1000If 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:
const constructorArgs = ["Hello", [1000, 2000]];
export default constructorArgs;and then pass it with the --constructor-args-path flag:
npx hardhat verify --network sepolia --constructor-args-path constructor-args.ts 0x1234567890...pnpm hardhat verify --network sepolia --constructor-args-path constructor-args.ts 0x1234567890...yarn hardhat verify --network sepolia --constructor-args-path constructor-args.ts 0x1234567890...Using different build profiles
Section titled “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:
npx hardhat verify --network sepolia --build-profile default 0x1234567890...pnpm hardhat verify --network sepolia --build-profile default 0x1234567890...yarn hardhat verify --network sepolia --build-profile default 0x1234567890...Verifying contracts on different block explorers
Section titled “Verifying contracts on different block explorers”The plugin currently supports Etherscan and Blockscout. You can use subtasks to verify on each of the block explorers:
npx hardhat verify etherscan ...pnpm hardhat verify etherscan ...yarn hardhat verify etherscan ...They have the same interface, but verify on a different block explorer.
Running verify without any subtask will verify on both Etherscan and Blockscout.
Verifying on a block explorer of a different network
Section titled “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:
const config: HardhatUserConfig = { // ... chainDescriptors: { // Example chain 123456: { name: "ExampleChain", blockExplorers: { etherscan: { name: "ExampleScan", url: "https://example.scan", apiUrl: "https://example.scan/api", }, // other explorers... }, }, },};Troubleshooting
Section titled “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-profilewith other profiles to verify your contract, beginning withdefault. You may also need to runhardhat buildwith the same build profile to generate the correct artifacts.