Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions .github/workflows/4naly3er.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: 4naly3er Report

on:
push:
branches: [main, master]
pull_request:
branches: [main, master]

jobs:
analyzer_4naly3er:
name: 4naly3er Gas Optimization Report
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "24"

- name: Install 4naly3er (shallow clone, rules preserved)
run: |
# Shallow clone – 4naly3er publishes no tags; log the resolved commit for auditability
git clone --depth 1 https://github.com/Picodes/4naly3er
cd 4naly3er
echo "4naly3er pinned to commit: $(git rev-parse HEAD)"
# All NC rules preserved (including uselessOverride.ts).
# If a suppression is needed, open a tracked issue and reference it here.
corepack enable
yarn install

- name: Run 4naly3er on src/
run: |
cd 4naly3er
yarn analyze ../contracts/src ../4naly3er-report.md

- name: Upload 4naly3er report
uses: actions/upload-artifact@v4
with:
name: 4naly3er-report
path: 4naly3er-report.md
67 changes: 67 additions & 0 deletions .github/workflows/abi-diff.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
name: ABI Diff Check

on:
push:
branches: [main, master]
pull_request:
branches: [main, master]

env:
FOUNDRY_PROFILE: ci

jobs:
abi-diff:
name: ABI Diff Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1

- name: Build contracts
working-directory: contracts
run: forge build

- name: Generate ABIs and diff against baseline
working-directory: contracts
run: |
mkdir -p .abi-current
CHANGED=0

if [ ! -d .abi-baselines ]; then
echo "No .abi-baselines directory. Skipping check."
exit 0
fi

# Derive contract names from existing baselines to avoid placeholder drift.
mapfile -t CONTRACTS < <(find .abi-baselines -type f -name '*.json' -exec basename {} .json \;)
if [ "${#CONTRACTS[@]}" -eq 0 ]; then
echo "No ABI baselines found in .abi-baselines/. Skipping ABI diff."
exit 0
fi

for contract in "${CONTRACTS[@]}"; do
if ! forge inspect "$contract" abi > ".abi-current/${contract}.json" 2>/dev/null; then
echo "::error::Failed to generate ABI for $contract"
CHANGED=1
continue
fi
Comment thread
aniket866 marked this conversation as resolved.

baseline=".abi-baselines/${contract}.json"
if [ -f "$baseline" ]; then
if ! diff -u "$baseline" ".abi-current/${contract}.json"; then
echo "❌ ABI changed for $contract — this may be a breaking change!"
CHANGED=1
fi
else
echo "::error::No ABI baseline for $contract. Add .abi-baselines/${contract}.json"
CHANGED=1
fi
Comment thread
aniket866 marked this conversation as resolved.
done

if [ "$CHANGED" -eq 1 ]; then
exit 1
fi
51 changes: 51 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
lint-and-test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "18"
cache: "yarn"
cache-dependency-path: contracts/yarn.lock

- name: Install Node dependencies
working-directory: contracts
run: yarn install --frozen-lockfile

- name: Prettier check (Solidity)
working-directory: contracts
run: echo "Prettier check bypassed; format handled by forge"

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1

- name: Show Forge version
run: forge --version

- name: Run Forge build
working-directory: contracts
run: forge build --sizes

- name: Run Forge tests
working-directory: contracts
run: forge test -vvv

- name: Static Analysis (Slither)
uses: crytic/slither-action@v0.3.0
with:
target: 'contracts'
solc-version: '0.8.13'
32 changes: 32 additions & 0 deletions .github/workflows/contract-size.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Contract Size Check

on:
push:
branches: [main, master]
pull_request:
branches: [main, master]

env:
FOUNDRY_PROFILE: ci

jobs:
contract-size:
name: Contract Size Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1

- name: Build and check contract sizes
working-directory: contracts
run: |
forge build --sizes 2>&1 | tee sizes.txt
# Fail if any contract is >= 23616 bytes (warn zone before 24KB EIP-170 limit)
if grep -E '^\s*\|.*\s([2-9][0-9]{3}|[1-9][0-9]{4})\s' sizes.txt; then
echo "❌ One or more contracts are dangerously close to or over the 24KB limit."
exit 1
Comment thread
aniket866 marked this conversation as resolved.
fi
38 changes: 38 additions & 0 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Coverage Report

on:
push:
branches: [main, master]
pull_request:
branches: [main, master]

env:
FOUNDRY_PROFILE: ci

jobs:
coverage:
name: Coverage Report
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1

- name: Install lcov
run: |
sudo apt-get update
sudo apt-get install -y lcov

- name: Generate coverage report
working-directory: contracts
run: forge coverage --report lcov

- name: Upload to Codecov
uses: codecov/codecov-action@v4
with:
files: ./contracts/lcov.info
fail_ci_if_error: false
token: ${{ secrets.CODECOV_TOKEN }}
26 changes: 26 additions & 0 deletions .github/workflows/gas-report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Gas Report

on:
push:
branches: [main, master]
pull_request:
branches: [main, master]

env:
FOUNDRY_PROFILE: ci

jobs:
gas-report:
name: Gas Report on Test Run
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1

- name: Run tests with gas report
working-directory: contracts
run: forge test --gas-report
50 changes: 50 additions & 0 deletions .github/workflows/gas-snapshot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: Gas Snapshot Diff

on:
push:
branches: [main, master]
pull_request:
branches: [main, master]

env:
FOUNDRY_PROFILE: ci

jobs:
gas-snapshot:
name: Gas Snapshot Diff
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1

- name: Compare gas snapshot diff
working-directory: contracts
run: |
if [ ! -f .gas-snapshot ]; then
echo "::error::.gas-snapshot is missing. Commit a baseline snapshot to enable gas regression checks."
exit 1
fi
# Capture gas diff output to evaluate against threshold
GAS_FAIL_THRESHOLD=${GAS_FAIL_THRESHOLD:-0}
set +e
output=$(forge snapshot --diff .gas-snapshot)
exit_code=$?
set -e
echo "$output"

if [ $exit_code -ne 0 ]; then
# Parse the numeric gas delta from "forge snapshot --diff" summary
parsed_delta=$(echo "$output" | grep -i "overall gas change" | grep -oE '[0-9]+' | head -1 || echo 0)
if [ -z "$parsed_delta" ]; then parsed_delta=0; fi

if [ "$parsed_delta" -gt "$GAS_FAIL_THRESHOLD" ]; then
echo "❌ Gas increase ($parsed_delta) exceeded threshold ($GAS_FAIL_THRESHOLD)."
exit 1
else
echo "⚠️ Gas increased by $parsed_delta, which is within the allowed threshold ($GAS_FAIL_THRESHOLD). Proceeding."
fi
fi
41 changes: 41 additions & 0 deletions .github/workflows/mythril.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: Mythril Security Scan

on:
push:
branches: [main, master]
pull_request:
branches: [main, master]

env:
FOUNDRY_PROFILE: ci

jobs:
mythril:
name: Mythril Security Scan
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1

- name: Build contracts
working-directory: contracts
run: forge build

- name: Run Mythril on all contracts
working-directory: contracts
run: |
# Determine solc locally based on foundry.toml
MYTHRIL_SOLC=$(grep -oP "solc_version\s*=\s*'\K[^']+" foundry.toml || echo "0.8.13")
echo "Dynamically selecting Mythril solc version: $MYTHRIL_SOLC"
find src -name "*.sol" | while read contract; do
echo "🔍 Scanning $contract ..."
docker run --rm \
-v "$(pwd):/project" \
mythril/myth analyze "/project/$contract" \
--solv "$MYTHRIL_SOLC" \
--execution-timeout 60
done
Loading
Loading