본문으로 건너뛰기
블록체인Mar 28, 2026

Deep EVM #20: 스마트 컨트랙트를 위한 CI/CD — 테스트, 가스 회귀, 안전성

OS
Open Soft Team

Engineering Team

스마트 컨트랙트에 전용 CI/CD가 필요한 이유

스마트 컨트랙트는 일반 소프트웨어와 다릅니다. 배포 후에는 불변입니다. 웹 앱의 버그는 핫픽스와 재배포를 의미합니다. 스마트 컨트랙트의 버그는 자금 손실, 영구적 상태 손상, 또는 비용이 많이 드는 프록시 업그레이드를 의미합니다. 이것이 전체 CI/CD 철학을 바꿉니다: 파이프라인은 단순한 회귀 감지가 아니라 되돌릴 수 없는 배포 전 최후의 방어선입니다.

프로덕션급 스마트 컨트랙트 CI/CD 파이프라인에는 다음이 포함되어야 합니다: 컴파일과 타입 검사, 포괄적 테스트 스위트(유닛, 퍼즈, 불변성), 가스 회귀 추적, 취약점 패턴을 위한 정적 분석, 배포 시뮬레이션, 자동 컨트랙트 검증.

파이프라인 아키텍처

Foundry 기반 스마트 컨트랙트 프로젝트를 위한 완전한 GitHub Actions 워크플로입니다:

# .github/workflows/ci.yml
name: Smart Contract CI

on:
  push:
    branches: [main]
  pull_request:

env:
  FOUNDRY_PROFILE: ci

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          submodules: recursive
      - uses: foundry-rs/foundry-toolchain@v1
        with:
          version: nightly
      - name: Install Huff
        run: |
          curl -L get.huff.sh | bash
          echo "$HOME/.huff/bin" >> $GITHUB_PATH
      - name: Build
        run: forge build --sizes
      - name: Check contract sizes
        run: |
          forge build --sizes 2>&1 | while read line; do
            size=$(echo "$line" | grep -oP '\d+\.\d+' | head -1)
            if [ ! -z "$size" ] && (( $(echo "$size > 24.0" | bc -l) )); then
              echo "::error::Contract exceeds 24KB limit: $line"
              exit 1
            fi
          done

  test:
    runs-on: ubuntu-latest
    needs: build
    steps:
      - uses: actions/checkout@v4
        with:
          submodules: recursive
      - uses: foundry-rs/foundry-toolchain@v1
      - name: Unit tests
        run: forge test --match-path "test/unit/*" -vvv
      - name: Fuzz tests
        run: |
          forge test --match-path "test/fuzz/*" \
            --fuzz-runs 50000 -vv
      - name: Invariant tests
        run: |
          forge test --match-path "test/invariant/*" \
            --invariant-runs 512 \
            --invariant-depth 256 -vv

forge snapshot으로 가스 회귀 추적

가스 회귀는 스마트 컨트랙트의 중요한 지표입니다. DEX 라우터의 스왑 함수에서 5% 가스 증가는 대규모에서 실제 비용이 됩니다. 체계적으로 추적합니다:

# 기준선 생성 (리포지토리에 커밋)
forge snapshot > .gas-snapshot
git add .gas-snapshot
git commit -m "chore: update gas snapshot"

# CI에서 기준선과 비교
forge snapshot --check .gas-snapshot --tolerance 2

--tolerance 2 플래그는 최대 2%의 가스 증가를 실패 없이 허용합니다. MEV 봇 운영과 같은 핫 경로에서는 허용치를 0%로 설정합니다.

정적 분석: Slither와 Aderyn

Slither

Slither는 Solidity의 업계 표준 정적 분석기입니다. 재진입, 검사되지 않은 외부 호출, 접근 제어 문제 등의 취약점 패턴을 감지합니다:

slither . --filter-paths "test/|script/|lib/" \
  --exclude naming-convention,solc-version \
  --fail-on medium

일반적인 발견과 처리 방법:

발견심각도조치
재진입높음즉시 수정, CEI 패턴 사용
미확인 반환중간반환값 검사 추가
명명 규칙정보--exclude로 억제
미사용 상태 변수낮음제거 또는 억제

Aderyn

Aderyn은 Slither를 보완하는 Rust 기반 정적 분석기입니다:

aderyn . --output report.json --format json

Aderyn은 가스 최적화 기회 감지와 중앙화 리스크 탐지에 특히 뛰어납니다.

배포 체크리스트

배포 전 검사를 스크립트로 자동화합니다:

// script/DeployChecklist.s.sol
contract DeployChecklist is Script {
    function run() external view {
        require(block.chainid == 1, "Wrong chain!");
        address expectedOwner = vm.envAddress("OWNER");
        require(expectedOwner != address(0), "Owner not set");
        require(
            IWETH(WETH).totalSupply() > 0,
            "WETH not deployed"
        );
        console.log("All checks passed");
    }
}

배포 시뮬레이션

메인넷 배포 전에 포크에 대해 전체 배포를 시뮬레이션합니다:

# 배포 시뮬레이션
forge script script/Deploy.s.sol \
  --fork-url $ETH_RPC_URL \
  --sender $DEPLOYER \
  -vvvv

# 시뮬레이션 통과 시 브로드캐스트
forge script script/Deploy.s.sol \
  --rpc-url $ETH_RPC_URL \
  --broadcast \
  --slow \
  --verify

--slow 플래그는 트랜잭션을 하나씩 제출하고 확인을 기다리며, 다단계 배포에 더 안전합니다.

보안 도구 요약

도구유형적합한 용도
Slither정적 분석취약점 패턴, Solidity
Aderyn정적 분석가스, 중앙화 리스크
Foundry Fuzz동적 테스트엣지 케이스, 경계값
Foundry Invariant상태 기반 퍼징상태 의존적 버그
Echidna퍼저속성 테스트(대안)
Mythril기호 실행경로 탐색
Certora형식 검증수학적 증명

결론

프로덕션급 스마트 컨트랙트 CI/CD 파이프라인은 전통적 소프트웨어 CI와 근본적으로 다릅니다. 모든 단계는 되돌릴 수 없는 배포 전 안전 게이트 역할을 합니다. 가스 스냅샷은 성능 회귀를 잡고, 정적 분석기는 취약점 패턴을 표시하며, 퍼저는 엣지 케이스를 탐색하고, 배포 시뮬레이션은 실제 상태에 대한 동작을 검증합니다. 파이프라인의 임무는 간단합니다: 버그를 잡는 것보다 버그를 배포하는 것을 더 어렵게 만드는 것.