Skip to content

Contract upgrade verification script#2141

Open
elvijsTDL wants to merge 5 commits intodevfrom
verification-workflow
Open

Contract upgrade verification script#2141
elvijsTDL wants to merge 5 commits intodevfrom
verification-workflow

Conversation

@elvijsTDL
Copy link
Contributor

No description provided.

@github-actions
Copy link

Changelog Reminder

Reminder to update the CHANGELOG.md for any of the modified packages in this PR.

  • CHANGELOG.md modified
  • Double check before merge

Comment on lines +31 to +239
name: Verify ${{ matrix.network }}
runs-on: ubuntu-22.04

env:
RELEASE_VERSION: ${{ github.event.inputs.release_version }}
ADDRESSES_URL: ${{ github.event.inputs.addresses_url }}

strategy:
fail-fast: false
matrix:
network: [eth-mainnet, polygon-mainnet, xdai-mainnet, optimism-mainnet, arbitrum-one, avalanche-c, bsc-mainnet, celo-mainnet, base-mainnet, scroll-mainnet]

defaults:
run:
shell: nix develop .#ci-default -c bash -xe {0}

steps:
- name: Check only_network filter
if: ${{ github.event.inputs.only_network != '' && github.event.inputs.only_network != matrix.network }}
run: echo "DO_SKIP=1" >> "$GITHUB_ENV"
shell: bash

- uses: actions/checkout@v4
if: env.DO_SKIP != 1
with:
ref: ${{ github.event.inputs.release_version }}

- uses: cachix/install-nix-action@v27
if: env.DO_SKIP != 1
with:
github_access_token: ${{ secrets.GITHUB_TOKEN }}

- name: Build contracts
if: env.DO_SKIP != 1
run: |
yarn install --frozen-lockfile
yarn build-for-contracts-dev

- name: Fetch addresses from URL
if: env.DO_SKIP != 1 && github.event.inputs.addresses_url != ''
run: |
cd packages/ethereum-contracts

ADDRESSES_URL="${{ github.event.inputs.addresses_url }}"
NETWORK="${{ matrix.network }}"

# Check if URL is a directory (ends with /) or a file
if [[ "$ADDRESSES_URL" == */ ]]; then
# Directory URL - append network name
FETCH_URL="${ADDRESSES_URL}${NETWORK}"
else
# File URL - use as-is
FETCH_URL="$ADDRESSES_URL"
fi

echo "Fetching addresses from: $FETCH_URL"
curl -fsSL "$FETCH_URL" -o addresses-from-url.vars || {
echo "::warning::Failed to fetch addresses from URL, will fetch from chain"
touch addresses-from-url.vars
}

if [ -s addresses-from-url.vars ]; then
echo "ADDRESSES_FILE=$(pwd)/addresses-from-url.vars" >> "$GITHUB_ENV"
echo "Addresses file contents:"
cat addresses-from-url.vars
fi

- name: Fetch addresses from chain
if: env.DO_SKIP != 1 && env.ADDRESSES_FILE == ''
run: |
cd packages/ethereum-contracts
npx truffle exec --network ${{ matrix.network }} ops-scripts/info-print-contract-addresses.js : addresses.vars
echo "ADDRESSES_FILE=$(pwd)/addresses.vars" >> "$GITHUB_ENV"
env:
PROVIDER_URL: ${{ secrets.PROVIDER_URL_TEMPLATE }}

- name: Fetch pending Safe transaction
if: env.DO_SKIP != 1 && github.event.inputs.verify_safe_pending == 'true'
id: safe_tx
run: |
cd packages/ethereum-contracts

echo "Fetching pending Safe governance transaction..."

# Run the Hardhat script with PROVIDER_URL
OUTPUT_FILE=safe-pending-tx.json \
npx hardhat run scripts/fetch-safe-pending-tx.ts > safe-output.log 2>&1 || {
echo "::warning::Failed to fetch Safe pending transaction"
cat safe-output.log || true
echo "SAFE_TX_FOUND=false" >> "$GITHUB_ENV"
exit 0
}

if [ -f safe-pending-tx.json ] && [ -s safe-pending-tx.json ]; then
echo "SAFE_TX_FOUND=true" >> "$GITHUB_ENV"
echo "Safe pending transaction:"
cat safe-pending-tx.json

# Extract addresses from Safe tx and append to addresses file
EXTRACTED=$(jq -r '.extractedAddresses | to_entries | .[] | "\(.key)=\(.value)"' safe-pending-tx.json 2>/dev/null || true)

if [ -n "$EXTRACTED" ]; then
echo "" >> "${{ env.ADDRESSES_FILE }}"
echo "# Addresses from pending Safe transaction" >> "${{ env.ADDRESSES_FILE }}"
echo "$EXTRACTED" >> "${{ env.ADDRESSES_FILE }}"
echo "Appended extracted addresses to ${{ env.ADDRESSES_FILE }}"
fi
else
echo "SAFE_TX_FOUND=false" >> "$GITHUB_ENV"
fi
env:
PROVIDER_URL: ${{ secrets.PROVIDER_URL_TEMPLATE }}

- name: Verify bytecode
if: env.DO_SKIP != 1
id: bytecode_verify
run: |
cd packages/ethereum-contracts

echo "=== Bytecode Verification ==="
echo "Addresses file: ${{ env.ADDRESSES_FILE }}"

# Run the Hardhat verification script with PROVIDER_URL
ADDRESSES_FILE="${{ env.ADDRESSES_FILE }}" JSON_OUTPUT=true \
npx hardhat run scripts/verify-bytecode.ts > bytecode-report.json 2>&1 || true

# Parse and display results
if [ -f bytecode-report.json ] && [ -s bytecode-report.json ]; then
echo "Bytecode verification results:"
cat bytecode-report.json | jq '.'

# Extract summary
VERIFIED=$(jq -r '.summary.verified // 0' bytecode-report.json)
MISMATCH=$(jq -r '.summary.mismatch // 0' bytecode-report.json)
ERRORS=$(jq -r '.summary.errors // 0' bytecode-report.json)

echo "BYTECODE_VERIFIED=$VERIFIED" >> "$GITHUB_ENV"
echo "BYTECODE_MISMATCH=$MISMATCH" >> "$GITHUB_ENV"
echo "BYTECODE_ERRORS=$ERRORS" >> "$GITHUB_ENV"

if [ "$MISMATCH" -gt 0 ] || [ "$ERRORS" -gt 0 ]; then
echo "::error::Bytecode verification failed: $MISMATCH mismatches, $ERRORS errors"
else
echo "::notice::Bytecode verification passed: $VERIFIED contracts verified"
fi
else
echo "::error::Failed to generate bytecode report"
cat bytecode-report.json || true
echo "BYTECODE_VERIFIED=0" >> "$GITHUB_ENV"
echo "BYTECODE_MISMATCH=0" >> "$GITHUB_ENV"
echo "BYTECODE_ERRORS=1" >> "$GITHUB_ENV"
fi
env:
PROVIDER_URL: ${{ secrets.PROVIDER_URL_TEMPLATE }}

- name: Verify on Etherscan
if: env.DO_SKIP != 1 && github.event.inputs.verify_etherscan == 'true'
run: |
cd packages/ethereum-contracts
tasks/etherscan-verify-framework.sh ${{ matrix.network }} "${{ env.ADDRESSES_FILE }}"
env:
ETHERSCAN_API_KEY: ${{ secrets.ETHERSCAN_API_KEY }}
POLYGONSCAN_API_KEY: ${{ secrets.POLYGONSCAN_API_KEY }}
SNOWTRACE_API_KEY: ${{ secrets.SNOWTRACE_API_KEY }}
OPTIMISTIC_API_KEY: ${{ secrets.OPTIMISTIC_API_KEY }}
ARBISCAN_API_KEY: ${{ secrets.ARBISCAN_API_KEY }}
BSCSCAN_API_KEY: ${{ secrets.BSCSCAN_API_KEY }}
CELOSCAN_API_KEY: ${{ secrets.CELOSCAN_API_KEY }}

- name: Upload verification artifacts
if: env.DO_SKIP != 1 && always()
uses: actions/upload-artifact@v4
with:
name: verification-${{ matrix.network }}
path: |
packages/ethereum-contracts/bytecode-report.json
packages/ethereum-contracts/safe-pending-tx.json
packages/ethereum-contracts/${{ env.ADDRESSES_FILE }}
retention-days: 30
if-no-files-found: ignore

- name: Generate summary
if: env.DO_SKIP != 1 && always()
run: |
echo "## Verification Results for ${{ matrix.network }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY

echo "### Bytecode Verification" >> $GITHUB_STEP_SUMMARY
echo "- Verified: ${{ env.BYTECODE_VERIFIED || 'N/A' }}" >> $GITHUB_STEP_SUMMARY
echo "- Mismatch: ${{ env.BYTECODE_MISMATCH || 'N/A' }}" >> $GITHUB_STEP_SUMMARY
echo "- Errors: ${{ env.BYTECODE_ERRORS || 'N/A' }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY

if [ "${{ github.event.inputs.verify_safe_pending }}" == "true" ]; then
echo "### Safe Pending Transaction" >> $GITHUB_STEP_SUMMARY
if [ "${{ env.SAFE_TX_FOUND }}" == "true" ]; then
echo "Pending governance transaction found and analyzed." >> $GITHUB_STEP_SUMMARY
else
echo "No pending governance transaction found." >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
fi

if [ "${{ github.event.inputs.verify_etherscan }}" == "true" ]; then
echo "### Etherscan Verification" >> $GITHUB_STEP_SUMMARY
echo "Etherscan verification was executed. Check logs for details." >> $GITHUB_STEP_SUMMARY
fi

generate-report:

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}

Copilot Autofix

AI about 1 month ago

In general, to fix this type of issue, you explicitly declare the permissions: for the GITHUB_TOKEN either at the top level of the workflow (applies to all jobs) or per job (applies only to that job). You then set the minimal permissions needed, which for a read-only CI/verification workflow is typically contents: read. Additional scopes (like pull-requests: write) are only added if specific steps require them.

For this specific workflow, none of the shown steps need to write to the repository or PRs. They primarily read repository contents via actions/checkout and interact with external services and artifacts. Therefore, the best fix without changing existing functionality is to add a root-level permissions: block with contents: read. This will apply to both verify-governance-action and generate-report jobs. Concretely, edit .github/workflows/handler.verify-governance-action.yml and insert a permissions: mapping between the name: and on: keys so that the workflow’s token is restricted to read-only repository contents.

Suggested changeset 1
.github/workflows/handler.verify-governance-action.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/handler.verify-governance-action.yml b/.github/workflows/handler.verify-governance-action.yml
--- a/.github/workflows/handler.verify-governance-action.yml
+++ b/.github/workflows/handler.verify-governance-action.yml
@@ -1,5 +1,8 @@
 name: Verify Governance Action
 
+permissions:
+  contents: read
+
 on:
   workflow_dispatch:
     inputs:
EOF
@@ -1,5 +1,8 @@
name: Verify Governance Action

permissions:
contents: read

on:
workflow_dispatch:
inputs:
Copilot is powered by AI and may make mistakes. Always verify output.
Comment on lines +240 to +307
name: Generate Final Report
needs: verify-governance-action
runs-on: ubuntu-22.04
if: always()

steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
continue-on-error: true

- name: Generate consolidated report
run: |
echo "# Governance Action Verification Report" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Release Version:** ${{ github.event.inputs.release_version }}" >> $GITHUB_STEP_SUMMARY
echo "**Addresses URL:** ${{ github.event.inputs.addresses_url || 'N/A (fetched from chain)' }}" >> $GITHUB_STEP_SUMMARY
echo "**Safe Verification:** ${{ github.event.inputs.verify_safe_pending }}" >> $GITHUB_STEP_SUMMARY
echo "**Etherscan Verification:** ${{ github.event.inputs.verify_etherscan }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY

echo "## Network Results" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Network | Verified | Mismatch | Errors | Status |" >> $GITHUB_STEP_SUMMARY
echo "|---------|----------|----------|--------|--------|" >> $GITHUB_STEP_SUMMARY

if [ -d "artifacts" ]; then
for dir in artifacts/verification-*/; do
if [ -d "$dir" ]; then
NETWORK=$(basename "$dir" | sed 's/verification-//')

if [ -f "$dir/bytecode-report.json" ]; then
VERIFIED=$(jq -r '.summary.verified // 0' "$dir/bytecode-report.json" 2>/dev/null || echo "0")
MISMATCH=$(jq -r '.summary.mismatch // 0' "$dir/bytecode-report.json" 2>/dev/null || echo "0")
ERRORS=$(jq -r '.summary.errors // 0' "$dir/bytecode-report.json" 2>/dev/null || echo "0")

if [ "$MISMATCH" -gt 0 ] || [ "$ERRORS" -gt 0 ]; then
STATUS="Failed"
else
STATUS="Passed"
fi
else
VERIFIED="N/A"
MISMATCH="N/A"
ERRORS="N/A"
STATUS="No report"
fi

echo "| $NETWORK | $VERIFIED | $MISMATCH | $ERRORS | $STATUS |" >> $GITHUB_STEP_SUMMARY
fi
done
else
echo "| (no artifacts found) | - | - | - | - |" >> $GITHUB_STEP_SUMMARY
fi

echo "" >> $GITHUB_STEP_SUMMARY
echo "---" >> $GITHUB_STEP_SUMMARY
echo "*Generated at $(date -u)*" >> $GITHUB_STEP_SUMMARY

- name: Upload consolidated report
if: always()
uses: actions/upload-artifact@v4
with:
name: verification-report
path: artifacts/
retention-days: 90
if-no-files-found: ignore

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {}

Copilot Autofix

AI about 1 month ago

In general, the fix is to add an explicit permissions block that grants only the minimal access the jobs need. Since this workflow only reads repository contents (to run code) and uses artifacts and the step summary, contents: read is sufficient; no write permissions are required.

The best single fix with minimal functional change is to add a top-level permissions block so it applies to all jobs. Place it after the name: and before on: (or right after on:), for example:

name: Verify Governance Action

permissions:
  contents: read

on:
  workflow_dispatch:
  ...

This ensures both verify-governance-action and generate-report run with a GITHUB_TOKEN that can read repository contents but cannot modify them. No other files or imports are needed; this change stays entirely within .github/workflows/handler.verify-governance-action.yml.

Suggested changeset 1
.github/workflows/handler.verify-governance-action.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/handler.verify-governance-action.yml b/.github/workflows/handler.verify-governance-action.yml
--- a/.github/workflows/handler.verify-governance-action.yml
+++ b/.github/workflows/handler.verify-governance-action.yml
@@ -1,5 +1,8 @@
 name: Verify Governance Action
 
+permissions:
+  contents: read
+
 on:
   workflow_dispatch:
     inputs:
EOF
@@ -1,5 +1,8 @@
name: Verify Governance Action

permissions:
contents: read

on:
workflow_dispatch:
inputs:
Copilot is powered by AI and may make mistakes. Always verify output.
@hellwolf hellwolf changed the title WIP verification script Contract upgrade verification script Jan 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants