Настройка автоматического деплоя смарт-контрактов через Hardhat multi-deploy

Проектируем и разрабатываем блокчейн-решения полного цикла: от архитектуры смарт-контрактов до запуска DeFi-протоколов, NFT-маркетплейсов и криптобирж. Аудит безопасности, токеномика, интеграция с существующей инфраструктурой.
Показано 1 из 1 услугВсе 1306 услуг
Настройка автоматического деплоя смарт-контрактов через Hardhat multi-deploy
Простая
от 1 рабочего дня до 3 рабочих дней
Часто задаваемые вопросы
Направления блокчейн-разработки
Этапы блокчейн-разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1221
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1163
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    855
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1056
  • image_logo-advance_0.png
    Разработка логотипа компании B2B Advance
    561
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    828

Настройка автоматического деплоя смарт-контрактов через Hardhat multi-deploy

Деплой на одну сеть — несколько команд. Деплой на 8 сетей одновременно с сохранением адресов, верификацией исходников и обновлением конфигов фронтенда — это уже инфраструктурная задача. hardhat-deploy плагин решает её декларативно.

Почему стандартный Hardhat deploy недостаточен

Базовый подход npx hardhat run scripts/deploy.ts — это императивный скрипт без состояния. Нет отслеживания, что уже задеплоено. Нет идемпотентности. Запустить повторно — задеплоит снова, получишь второй экземпляр контракта. Адреса нигде не сохраняются автоматически.

hardhat-deploy добавляет:

  • Отслеживание деплоев — JSON-файлы в deployments/<network>/ с адресом, ABI, bytecode, transaction hash
  • Идемпотентность — повторный запуск не деплоит если контракт уже есть и не изменился
  • Именованные аккаунтыnamedAccounts в конфиге для читаемости
  • Fixtures для тестовdeployments доступны в тестах через getNamedAccounts

Конфигурация multi-chain

// hardhat.config.ts
import { HardhatUserConfig } from "hardhat/config";
import "@nomicfoundation/hardhat-toolbox";
import "hardhat-deploy";

const config: HardhatUserConfig = {
  solidity: {
    version: "0.8.24",
    settings: {
      optimizer: { enabled: true, runs: 200 },
      viaIR: false, // включаем только если нужно
    },
  },
  
  namedAccounts: {
    deployer: {
      default: 0,         // первый аккаунт
      mainnet: "0x...",   // конкретный адрес для mainnet
    },
    treasury: {
      default: 1,
      mainnet: "0x...",
    },
  },
  
  networks: {
    mainnet:  { url: process.env.MAINNET_RPC,  accounts: [process.env.DEPLOYER_KEY!], chainId: 1 },
    polygon:  { url: process.env.POLYGON_RPC,  accounts: [process.env.DEPLOYER_KEY!], chainId: 137 },
    arbitrum: { url: process.env.ARBITRUM_RPC, accounts: [process.env.DEPLOYER_KEY!], chainId: 42161 },
    optimism: { url: process.env.OPTIMISM_RPC, accounts: [process.env.DEPLOYER_KEY!], chainId: 10 },
    base:     { url: process.env.BASE_RPC,     accounts: [process.env.DEPLOYER_KEY!], chainId: 8453 },
  },
  
  etherscan: {
    apiKey: {
      mainnet:        process.env.ETHERSCAN_KEY!,
      polygon:        process.env.POLYGONSCAN_KEY!,
      arbitrumOne:    process.env.ARBISCAN_KEY!,
      optimisticEthereum: process.env.OPTIMISM_KEY!,
      base:           process.env.BASESCAN_KEY!,
    },
  },
};

Deploy скрипты с hardhat-deploy

// deploy/001_deploy_token.ts
import { HardhatRuntimeEnvironment } from "hardhat/types";
import { DeployFunction } from "hardhat-deploy/types";

const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => {
  const { deployments, getNamedAccounts, network } = hre;
  const { deploy } = deployments;
  const { deployer, treasury } = await getNamedAccounts();

  const token = await deploy("MyToken", {
    from: deployer,
    args: [treasury, "1000000000000000000000000"], // 1M tokens
    log: true,          // логирует адрес и tx hash
    autoMine: true,     // автоматический майнинг на локальной сети
    waitConfirmations: network.name === "mainnet" ? 5 : 1,
  });

  // Верификация сразу после деплоя
  if (network.name !== "hardhat" && network.name !== "localhost") {
    await hre.run("verify:verify", {
      address: token.address,
      constructorArguments: [treasury, "1000000000000000000000000"],
    });
  }
};

func.tags = ["Token", "all"];
func.dependencies = []; // этот скрипт без зависимостей
export default func;
// deploy/002_deploy_staking.ts
const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => {
  const { deployments, getNamedAccounts } = hre;
  const { deploy, get } = deployments;
  const { deployer } = await getNamedAccounts();

  const token = await get("MyToken"); // получаем адрес уже задеплоенного токена

  await deploy("StakingContract", {
    from: deployer,
    args: [token.address],
    log: true,
  });
};

func.tags = ["Staking", "all"];
func.dependencies = ["Token"]; // деплоится только после Token
export default func;

Порядок выполнения управляется через tags и dependencies. Hardhat-deploy строит граф зависимостей и деплоит в правильном порядке.

Деплой на несколько сетей

# Одна сеть
npx hardhat deploy --network polygon

# Несколько сетей через скрипт
for network in mainnet polygon arbitrum optimism base; do
  npx hardhat deploy --network $network --tags all
done

Для параллельного деплоя на несколько сетей одновременно — небольшой bash скрипт:

#!/bin/bash
networks=("polygon" "arbitrum" "optimism" "base")
pids=()

for network in "${networks[@]}"; do
  npx hardhat deploy --network $network --tags all &
  pids+=($!)
done

for pid in "${pids[@]}"; do
  wait $pid || exit 1
done

echo "All deployments complete"

Mainnet деплоим отдельно, вручную, после проверки всех тестовых сетей.

Хранение и экспорт адресов

После деплоя hardhat-deploy создаёт файлы в deployments/polygon/MyToken.json с адресом и ABI. Для фронтенда — экспортируем в единый конфиг:

// scripts/export-addresses.ts
import { deployments } from "hardhat";

const networks = ["mainnet", "polygon", "arbitrum", "optimism", "base"];
const contracts = ["MyToken", "StakingContract"];

const config: Record<string, Record<string, string>> = {};

for (const network of networks) {
  config[network] = {};
  for (const contract of contracts) {
    try {
      const deployment = await deployments.get(contract);
      config[network][contract] = deployment.address;
    } catch {
      // контракт не задеплоен на эту сеть
    }
  }
}

fs.writeFileSync("src/contracts/addresses.json", JSON.stringify(config, null, 2));

CI/CD интеграция

GitHub Actions для автоматического деплоя при merge в main:

# .github/workflows/deploy.yml
name: Deploy Contracts

on:
  push:
    branches: [main]
    paths: ["contracts/**", "deploy/**"]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - uses: actions/setup-node@v4
        with:
          node-version: "20"
          cache: "npm"
      
      - run: npm ci
      
      - name: Deploy to testnets
        env:
          DEPLOYER_KEY: ${{ secrets.DEPLOYER_KEY }}
          POLYGON_RPC: ${{ secrets.POLYGON_MUMBAI_RPC }}
        run: npx hardhat deploy --network polygonMumbai --tags all
      
      - name: Commit updated deployments
        run: |
          git config user.name "GitHub Actions"
          git config user.email "[email protected]"
          git add deployments/
          git commit -m "chore: update deployment artifacts" || echo "No changes"
          git push

Деплой артефактов коммитятся обратно в репозиторий — адреса всегда актуальны и версионированы.

Срок настройки полноценного multi-chain деплой pipeline — 1-3 дня в зависимости от количества сетей и требований к CI/CD.