китаев.tech

Деплой контракта

Как задеплоить Solidity-контракт через ethers v6: скомпилировать bytecode, отправить deploy-транзакцию и проверить адрес.

Что значит задеплоить контракт

Деплой контракта — это транзакция, которая отправляет bytecode в сеть и создаёт новый contract account.

После подтверждения транзакции у контракта появляется адрес. По этому адресу можно читать состояние и вызывать функции.


Деплоим контракт через ethers v6

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

bash
mkdir deploy-contract-example
cd deploy-contract-example

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

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

typescript
import { defineConfig } from "hardhat/config";

export default defineConfig({
  solidity: {
    version: "0.8.20",
  },
});

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

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

contract Counter {
    uint256 public value;

    constructor(uint256 initialValue) {
        value = initialValue;
    }

    function increment() external {
        value += 1;
    }
}

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

typescript
import { ethers } from "ethers";
import solc from "solc";
import { readFileSync } from "node:fs";

const source = readFileSync("contracts/Counter.sol", "utf8");

const input = {
  language: "Solidity",
  sources: {
    "Counter.sol": {
      content: source,
    },
  },
  settings: {
    outputSelection: {
      "*": {
        "*": ["abi", "evm.bytecode.object"],
      },
    },
  },
};

const output = JSON.parse(solc.compile(JSON.stringify(input)));
const contract = output.contracts["Counter.sol"].Counter;

const abi = contract.abi;
const bytecode = `0x${contract.evm.bytecode.object}`;

const provider = new ethers.JsonRpcProvider("http://127.0.0.1:8545");

// Первый тестовый аккаунт Hardhat. Не используйте этот ключ в mainnet.
const signer = new ethers.Wallet(
  "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80",
  provider,
);

const factory = new ethers.ContractFactory(abi, bytecode, signer);

const counter = await factory.deploy(10);

console.log("Deploy transaction:", counter.deploymentTransaction()?.hash);

await counter.waitForDeployment();

const address = await counter.getAddress();
const value = await counter.value();

console.log("Contract address:", address);
console.log("Initial value:", value.toString());

Запустите локальную сеть Hardhat в отдельном терминале:

bash
npx hardhat node

Во втором терминале выполните deploy-скрипт:

bash
npx tsx scripts/deploy-counter.ts

В выводе появится hash deploy-транзакции, адрес нового контракта и стартовое значение 10.


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

solc.compile() — компилирует Solidity-код и возвращает ABI вместе с bytecode.

abi — описание функций контракта. ethers использует ABI, чтобы понимать методы value() и increment().

bytecode — EVM-код, который deploy-транзакция отправляет в сеть.

new ethers.Wallet(privateKey, provider) — создаёт signer. Именно он подписывает deploy-транзакцию и платит gas.

new ethers.ContractFactory(abi, bytecode, signer) — собирает объект, который умеет создавать новые экземпляры контракта.

factory.deploy(10) — отправляет транзакцию деплоя и передаёт 10 в constructor.

waitForDeployment() — ждёт, пока транзакция попадёт в блок и контракт действительно появится в сети.

getAddress() — возвращает адрес созданного контракта.


Что происходит в сети

Deploy-транзакция отличается от обычного вызова тем, что у неё нет поля to.

Вместо адреса получателя транзакция содержит bytecode:

text
to: null
data: 0x6080604052...

Когда валидаторы включают транзакцию в блок, Ethereum создаёт новый contract account. Адрес контракта вычисляется из адреса деплоера и его nonce.


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

Забыли 0x перед bytecode → ethers ожидает hex-строку. Добавьте префикс: `0x${bytecode}`.

Не дождались деплояfactory.deploy() возвращает объект сразу после отправки транзакции. Перед чтением адреса и вызовом функций используйте await counter.waitForDeployment().

Передали не те аргументы конструктора → порядок и типы аргументов в deploy(...) должны совпадать с constructor в Solidity.

Использовали тестовый private key в публичной сети → ключ Hardhat известен всем. Он подходит только для локального примера.


Что дальше

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