китаев.tech

Верификация контракта на Etherscan

Как верифицировать Solidity-контракт на Etherscan через Hardhat 3: настроить verify-плагин, задеплоить контракт и передать constructor args.

Что такое верификация

Верификация связывает bytecode контракта в сети с исходным Solidity-кодом.

После верификации Etherscan показывает код, ABI, constructor arguments и вкладки для чтения и записи функций контракта.


Настраиваем Hardhat verify

Создайте проект:

bash
mkdir verify-etherscan-example
cd verify-etherscan-example

npm init -y
npm pkg set type="module"
npm install --save-dev hardhat typescript tsx @types/node @nomicfoundation/hardhat-toolbox-mocha-ethers @nomicfoundation/hardhat-verify @nomicfoundation/hardhat-keystore
mkdir contracts scripts

Создайте файл hardhat.config.ts:

typescript
import hardhatKeystore from "@nomicfoundation/hardhat-keystore";
import hardhatToolboxMochaEthers from "@nomicfoundation/hardhat-toolbox-mocha-ethers";
import hardhatVerify from "@nomicfoundation/hardhat-verify";
import { configVariable, defineConfig } from "hardhat/config";

export default defineConfig({
  plugins: [hardhatToolboxMochaEthers, hardhatVerify, hardhatKeystore],
  solidity: {
    version: "0.8.28",
  },
  networks: {
    sepolia: {
      type: "http",
      chainType: "l1",
      url: configVariable("SEPOLIA_RPC_URL"),
      accounts: [configVariable("SEPOLIA_PRIVATE_KEY")],
    },
  },
  verify: {
    etherscan: {
      apiKey: configVariable("ETHERSCAN_API_KEY"),
    },
  },
});

Сохраните секреты в Hardhat keystore:

bash
npx hardhat keystore set SEPOLIA_RPC_URL
npx hardhat keystore set SEPOLIA_PRIVATE_KEY
npx hardhat keystore set ETHERSCAN_API_KEY

SEPOLIA_PRIVATE_KEY должен быть ключом аккаунта с Sepolia ETH. ETHERSCAN_API_KEY создаётся в личном кабинете Etherscan.


Контракт с constructor

Создайте файл contracts/Greeting.sol:

solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

contract Greeting {
    string public message;
    address public owner;

    constructor(string memory initialMessage) {
        message = initialMessage;
        owner = msg.sender;
    }

    function setMessage(string calldata newMessage) external {
        require(msg.sender == owner, "Only owner");
        message = newMessage;
    }
}

Скомпилируйте проект:

bash
npx hardhat build

Деплоим в Sepolia

Создайте файл scripts/deploy-greeting.ts:

typescript
import { network } from "hardhat";

const { ethers } = await network.create();
const initialMessage = "Привет из Sepolia";

const greeting = await ethers.deployContract("Greeting", [initialMessage]);

await greeting.waitForDeployment();

const address = await greeting.getAddress();
const message = await greeting.message();
const owner = await greeting.owner();

console.log("Greeting address:", address);
console.log("Message:", message);
console.log("Owner:", owner);
console.log(
  `Verify command: npx hardhat verify --network sepolia ${address} "${initialMessage}"`,
);

Запустите deploy:

bash
npx hardhat run scripts/deploy-greeting.ts --network sepolia

Скрипт напечатает адрес контракта и готовую verify-команду.


Верифицируем контракт

Запустите команду из строки Verify command.

Она уже содержит адрес задеплоенного контракта и тот же constructor argument, который использовался в deployContract(...).

Если всё совпало, Hardhat отправит исходники и metadata на Etherscan. Через несколько секунд на странице контракта появится статус Contract Source Code Verified.


Как это работает

@nomicfoundation/hardhat-verify — добавляет команду npx hardhat verify.

verify.etherscan.apiKey — даёт Hardhat доступ к Etherscan API.

--network sepolia — говорит Hardhat, в какой сети искать контракт.

Адрес контракта — указывает, какой bytecode нужно сопоставить с исходниками.

"Привет из Sepolia" — constructor argument. Если передать другое значение, bytecode не совпадёт и Etherscan отклонит верификацию.

Hardhat берёт артефакты из artifacts, compiler settings из hardhat.config.ts и metadata компилятора. Поэтому контракт нужно верифицировать из того же проекта, из которого он был собран.


Что проверяет Etherscan

Etherscan не доверяет вашему исходному коду напрямую.

Он заново компилирует Solidity с теми же настройками:

text
Solidity version
optimizer settings
source files
constructor arguments
library addresses

Если получившийся bytecode совпадает с bytecode по адресу контракта, контракт считается verified.


Частые ошибки

Передали неправильные constructor arguments → используйте ровно те значения, которые были переданы в deployContract(...).

Верифицируете не из того проекта → исходники, версия Solidity и настройки optimizer должны совпадать с деплоем.

Контракт ещё не проиндексирован Etherscan → подождите 30-60 секунд после деплоя и повторите verify.

Секреты лежат в коде → не вставляйте private key и Etherscan API key в hardhat.config.ts. Используйте configVariable(...) и keystore.


Что дальше

Материалы китаev.tech публикуются в образовательных целях и не являются инвестиционной рекомендацией. Примеры кода и описания протоколов — для обучения; использование в продакшне на ваш собственный риск. Дисклеймер и политика конфиденциальности.