# ============================================================ # 合约安全 CI — Foundry Tests + Slither + Mythril # ============================================================ name: Contract Security on: push: paths: - 'blockchain/genex-contracts/**' pull_request: paths: - 'blockchain/genex-contracts/**' env: FOUNDRY_PROFILE: ci jobs: # ─── Foundry 编译 & 测试 ──────────────────────────────── foundry-tests: name: Foundry Tests runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: submodules: recursive - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 with: version: nightly - name: Build contracts working-directory: blockchain/genex-contracts run: forge build --sizes - name: Run tests working-directory: blockchain/genex-contracts run: forge test -vvv --gas-report - name: Check contract sizes working-directory: blockchain/genex-contracts run: | forge build --sizes 2>&1 | tee sizes.txt if grep -q "exceeds" sizes.txt; then echo "::error::Contract size exceeds 24KB limit" exit 1 fi # ─── Slither 静态分析 ─────────────────────────────────── slither: name: Slither Analysis runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: submodules: recursive - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 with: version: nightly - name: Run Slither uses: crytic/slither-action@v0.4.0 with: target: blockchain/genex-contracts/ slither-args: >- --filter-paths "lib|test|script" --exclude naming-convention,solc-version fail-on: medium sarif: results/slither.sarif - name: Upload Slither SARIF uses: github/codeql-action/upload-sarif@v3 if: always() with: sarif_file: results/slither.sarif # ─── Mythril 符号执行 ─────────────────────────────────── mythril: name: Mythril Scan runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: submodules: recursive - name: Setup Python uses: actions/setup-python@v5 with: python-version: '3.11' - name: Install Mythril run: pip install mythril - name: Install solc 0.8.20 run: | pip install solc-select solc-select install 0.8.20 solc-select use 0.8.20 - name: Run Mythril on core contracts working-directory: blockchain/genex-contracts run: | CONTRACTS=( "src/CouponFactory.sol" "src/Coupon.sol" "src/Settlement.sol" "src/Redemption.sol" "src/Compliance.sol" "src/Treasury.sol" ) EXIT_CODE=0 for contract in "${CONTRACTS[@]}"; do echo "=== Analyzing $contract ===" myth analyze "$contract" \ --solv 0.8.20 \ --execution-timeout 300 \ --max-depth 24 \ -o json \ --remappings "@openzeppelin/=lib/openzeppelin-contracts/" \ 2>&1 | tee "mythril-$(basename $contract .sol).json" || EXIT_CODE=1 done exit $EXIT_CODE - name: Upload Mythril results uses: actions/upload-artifact@v4 if: always() with: name: mythril-results path: blockchain/genex-contracts/mythril-*.json # ─── Foundry 合约验证 (Blockscout) ───────────────────── verify: name: Contract Verification runs-on: ubuntu-latest needs: [foundry-tests] if: github.ref == 'refs/heads/main' steps: - uses: actions/checkout@v4 with: submodules: recursive - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 with: version: nightly - name: Verify contracts on Blockscout working-directory: blockchain/genex-contracts env: BLOCKSCOUT_URL: ${{ secrets.BLOCKSCOUT_API_URL }} run: | if [ -z "$BLOCKSCOUT_URL" ]; then echo "::warning::BLOCKSCOUT_API_URL not set, skipping verification" exit 0 fi forge verify-contract \ --verifier blockscout \ --verifier-url "$BLOCKSCOUT_URL/api" \ --watch \ --compiler-version v0.8.20 \ ${{ secrets.COUPON_FACTORY_ADDRESS }} \ src/CouponFactory.sol:CouponFactory