Перейти к основному содержимому
БлокчейнMar 28, 2026

Deep EVM #20: CI/CD для смарт-контрактов — тесты, газ-регрессия и безопасность

OS
Open Soft Team

Engineering Team

Почему CI/CD критичен для смарт-контрактов

Смарт-контракты неизменяемы после деплоя. Ошибка в продакшене — это не «откатим и пофиксим», а потенциальная потеря миллионов долларов. CI/CD-пайплайн для блокчейн-проектов должен быть строже, чем для обычного софта, потому что цена ошибки несоизмеримо выше.

В этой статье мы построим полноценный пайплайн, который включает компиляцию, юнит-тесты, фазз-тесты, газ-регрессию, статический анализ безопасности и безопасный деплой.

Архитектура пайплайна

Оптимальный CI/CD-пайплайн для смарт-контрактов состоит из пяти этапов:

  1. Lint & Format — проверка стиля кода
  2. Compile — компиляция контрактов
  3. Test — юнит-тесты, фаззинг, инварианты
  4. Security — статический анализ, проверка зависимостей
  5. Deploy — контролируемый деплой с верификацией

Этап 1: Lint и форматирование

lint:
  stage: lint
  script:
    - forge fmt --check
    - solhint 'src/**/*.sol'
    - forge build --sizes  # Проверка размера контрактов
  rules:
    - if: $CI_MERGE_REQUEST_ID

Форматирование с forge fmt должно быть единообразным. Solhint проверяет паттерны безопасности: правильное использование external vs public, наличие NatSpec-документации, запрет tx.origin.

Этап 2: Компиляция и размер контрактов

EVM ограничивает размер контракта 24 576 байтами (EIP-170). Проверяйте это в CI:

forge build --sizes 2>&1 | while IFS= read -r line; do
  size=$(echo "$line" | grep -oP '\d+\.\d+')
  if [ "$(echo "$size > 24" | bc)" -eq 1 ]; then
    echo "ERROR: Contract exceeds size limit: $line"
    exit 1
  fi
done

Этап 3: Многоуровневое тестирование

Юнит-тесты с покрытием

forge test --match-test "test_" -vvv
forge coverage --report lcov

Фаззинг

forge test --match-test "testFuzz_" --fuzz-runs 50000

Инвариантное тестирование

forge test --match-test "invariant_" --fuzz-runs 1000

Этап 4: Газ-регрессия

Газ-снепшоты позволяют отслеживать потребление газа между коммитами:

forge snapshot --check .gas-snapshot --tolerance 5

Толеранс 5% допускает незначительные колебания из-за оптимизаций компилятора, но поймает значительные регрессии. Если порог превышен — MR блокируется.

Для автоматического обновления базового уровня на main:

update-gas-snapshot:
  stage: post-merge
  script:
    - forge snapshot
    - git add .gas-snapshot
    - git commit -m "chore: Update gas snapshot"
    - git push
  rules:
    - if: $CI_COMMIT_BRANCH == "main"

Этап 5: Статический анализ безопасности

Slither

slither . --filter-paths "test/|script/" \
  --exclude-dependencies \
  --sarif results.sarif

Slither обнаруживает reentrancy, неконтролируемые делегат-коллы, некорректное использование tx.origin и десятки других паттернов уязвимостей.

Mythril

myth analyze src/Contract.sol --solc-json mythril.config.json

Mythril использует символическое выполнение для обнаружения уязвимостей, которые пропускает статический анализ.

Aderyn

aderyn . --src src/

Aderyn — новый инструмент от Cyfrin, специализирующийся на Foundry-проектах.

Безопасный деплой

Деплой смарт-контрактов должен быть контролируемым:

# Деплой с верификацией на Etherscan
forge script script/Deploy.s.sol:DeployScript \
  --rpc-url $RPC_URL \
  --broadcast \
  --verify \
  --etherscan-api-key $ETHERSCAN_KEY \
  --slow  # Ожидание подтверждения каждой транзакции

Важные принципы:

  • Dry run перед деплоем: --broadcast без --verify сначала
  • Мультисиг для критичных операций: используйте Safe (бывший Gnosis Safe)
  • Timelock: задержка между предложением и исполнением
  • Мониторинг после деплоя: подписка на события через Tenderly

Пример полного пайплайна GitLab CI

stages:
  - lint
  - build
  - test
  - security
  - deploy

variables:
  FOUNDRY_PROFILE: ci

lint:
  stage: lint
  script:
    - forge fmt --check
    - solhint 'src/**/*.sol'

build:
  stage: build
  script:
    - forge build --sizes
  artifacts:
    paths: [out/]

test-unit:
  stage: test
  script:
    - forge test --match-test "test_" -vvv
    - forge coverage --report summary

test-fuzz:
  stage: test
  script:
    - forge test --match-test "testFuzz_|invariant_" --fuzz-runs 50000
  timeout: 30m

gas-check:
  stage: test
  script:
    - forge snapshot --check .gas-snapshot --tolerance 5
  allow_failure: false

security:
  stage: security
  script:
    - slither . --filter-paths "test/|script/"
    - aderyn . --src src/

deploy-testnet:
  stage: deploy
  script:
    - forge script script/Deploy.s.sol --rpc-url $SEPOLIA_RPC --broadcast --verify
  when: manual
  environment: staging

Заключение

CI/CD для смарт-контрактов — это не роскошь, а необходимость. Автоматизированный пайплайн с многоуровневым тестированием, газ-регрессией и статическим анализом безопасности — единственный надёжный способ обеспечить качество неизменяемого кода. Инвестируйте в инфраструктуру CI/CD сейчас — это окупится при первом же предотвращённом инциденте.