Верификация контракта на Etherscan
Как верифицировать Solidity-контракт на Etherscan через Hardhat 3: настроить verify-плагин, задеплоить контракт и передать constructor args.
Что такое верификация
Верификация связывает bytecode контракта в сети с исходным Solidity-кодом.
После верификации Etherscan показывает код, ABI, constructor arguments и вкладки для чтения и записи функций контракта.
Настраиваем Hardhat verify
Создайте проект:
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:
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:
npx hardhat keystore set SEPOLIA_RPC_URL
npx hardhat keystore set SEPOLIA_PRIVATE_KEY
npx hardhat keystore set ETHERSCAN_API_KEYSEPOLIA_PRIVATE_KEY должен быть ключом аккаунта с Sepolia ETH. ETHERSCAN_API_KEY создаётся в личном кабинете Etherscan.
Контракт с constructor
Создайте файл contracts/Greeting.sol:
// 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;
}
}Скомпилируйте проект:
npx hardhat buildДеплоим в Sepolia
Создайте файл scripts/deploy-greeting.ts:
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:
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 с теми же настройками:
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.
Что дальше
- Деплой контракта — понять, как создаётся contract address
- Вызов view-функций — read — читать verified-контракт через ABI
- Вызов state-changing функций — write — отправлять транзакции во вкладке Write Contract или через ethers