Первый контракт — написать и задеплоить
Как написать простой Solidity-контракт, скомпилировать его в Hardhat и задеплоить в локальную Ethereum-сеть.
Что будем деплоить
Первый контракт должен быть маленьким: одно состояние, одна функция чтения, одна транзакция записи.
В этом примере контракт MessageBoard хранит строку message. Скрипт деплоит контракт в локальную сеть Hardhat, читает стартовое значение и меняет его транзакцией.
Создаём проект
mkdir first-ethereum-contract
cd first-ethereum-contract
npm init -y
npm pkg set type="module"
npm install --save-dev hardhat typescript tsx @types/node @nomicfoundation/hardhat-toolbox-mocha-ethers
mkdir contracts scriptsСоздайте файл hardhat.config.ts:
import { defineConfig } from "hardhat/config";
import hardhatToolboxMochaEthers from "@nomicfoundation/hardhat-toolbox-mocha-ethers";
export default defineConfig({
plugins: [hardhatToolboxMochaEthers],
solidity: {
version: "0.8.28",
},
});Пишем контракт
Создайте файл contracts/MessageBoard.sol:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
contract MessageBoard {
string private message;
event MessageChanged(address indexed author, string newMessage);
constructor(string memory initialMessage) {
message = initialMessage;
}
function readMessage() external view returns (string memory) {
return message;
}
function changeMessage(string calldata newMessage) external {
message = newMessage;
emit MessageChanged(msg.sender, newMessage);
}
}Проверьте компиляцию:
npx hardhat buildКонтракт готов к деплою, если Hardhat создал артефакты без ошибок компилятора Solidity.
Деплоим контракт
Создайте файл scripts/deploy-message-board.ts:
import { network } from "hardhat";
const { ethers } = await network.create();
const messageBoard = await ethers.deployContract("MessageBoard", [
"Первое сообщение из конструктора",
]);
await messageBoard.waitForDeployment();
const contractAddress = await messageBoard.getAddress();
const initialMessage = await messageBoard.readMessage();
console.log("Адрес MessageBoard:", contractAddress);
console.log("Стартовое сообщение:", initialMessage);
const tx = await messageBoard.changeMessage("Сообщение изменено транзакцией");
await tx.wait();
const updatedMessage = await messageBoard.readMessage();
console.log("Новое сообщение:", updatedMessage);В первом терминале запустите локальную сеть:
npx hardhat nodeВо втором терминале выполните deploy-скрипт:
npx hardhat run scripts/deploy-message-board.ts --network localhostВ выводе появится адрес контракта, стартовое сообщение и новое сообщение после транзакции.
Как это работает
constructor() — выполняется один раз при деплое и записывает первое сообщение в storage.
string private message — хранит строку в состоянии контракта. Это данные внутри Ethereum, а не переменная в JavaScript.
readMessage() — view-функция. Она читает состояние и не тратит gas при локальном RPC-вызове.
changeMessage() — меняет состояние, поэтому Hardhat отправляет транзакцию.
event MessageChanged — пишет лог в receipt транзакции. Так frontend или backend могут отслеживать изменения.
ethers.deployContract("MessageBoard", [...]) — деплоит контракт и передаёт аргументы в constructor.
tx.wait() — ждёт, пока транзакция попадёт в блок локальной сети.
Что происходит при деплое
Деплой — это обычная Ethereum-транзакция без адреса получателя. Вместо вызова существующего контракта она отправляет bytecode нового контракта в сеть.
После включения транзакции в блок сеть создаёт новый адрес. По этому адресу теперь лежит код MessageBoard и его состояние.
Частые ошибки
Забыли аргументы конструктора → передайте массив аргументов вторым параметром в ethers.deployContract().
Hardhat не находит контракт → проверьте имя файла, имя контракта и результат npx hardhat build.
Транзакция отправлена, но значение не изменилось в выводе → убедитесь, что вы вызвали await tx.wait() перед повторным чтением.
Что дальше
- Подключение к сети — Infura и Alchemy — понять, как перейти от локальной сети к внешнему RPC
- Как работает транзакция изнутри — разобрать путь транзакции от подписи до блока
- Деплой контракта — вынести деплой в более гибкий production-скрипт