From 665713163c62d97bebb49bd68069c83c51793205 Mon Sep 17 00:00:00 2001 From: nisedo <73041332+nisedo@users.noreply.github.com> Date: Mon, 9 Mar 2026 17:59:53 +0100 Subject: [PATCH 1/4] Add CI workflow for compilation checks Lightweight build workflow that verifies Foundry and Hardhat compilation succeeds for both root contracts and all test harnesses (ERC20, ERC721, ERC4626). Catches remapping, config, and dependency issues early. Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/build.yaml | 91 ++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 .github/workflows/build.yaml diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml new file mode 100644 index 0000000..6df1bc8 --- /dev/null +++ b/.github/workflows/build.yaml @@ -0,0 +1,91 @@ +name: Build + +on: + push: + branches: + - main + pull_request: + branches: + - "*" + +jobs: + foundry-root: + name: Compile root contracts (Foundry) + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + submodules: recursive + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + + - name: Run forge build + run: forge build + + foundry-tests: + name: Compile ${{ matrix.standard }} test harness (Foundry) + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + standard: [ERC20, ERC721, ERC4626] + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + submodules: recursive + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + + - name: Run forge build + working-directory: tests/${{ matrix.standard }}/foundry + run: forge build + + hardhat-root: + name: Compile root contracts (Hardhat) + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + submodules: recursive + + - name: Set up Node.js + uses: actions/setup-node@v6 + with: + node-version: 22 + + - name: Install dependencies + run: npm install + + - name: Run hardhat compile + run: npx hardhat compile + + hardhat-tests: + name: Compile ${{ matrix.standard }} test harness (Hardhat) + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + standard: [ERC20, ERC721, ERC4626] + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + submodules: recursive + + - name: Set up Node.js + uses: actions/setup-node@v6 + with: + node-version: 22 + + - name: Install dependencies + working-directory: tests/${{ matrix.standard }}/hardhat + run: npm install + + - name: Run hardhat compile + working-directory: tests/${{ matrix.standard }}/hardhat + run: npx hardhat compile From 25390c50c6262b1402c62855d87e6e4059e037d4 Mon Sep 17 00:00:00 2001 From: nisedo <73041332+nisedo@users.noreply.github.com> Date: Mon, 9 Mar 2026 18:16:36 +0100 Subject: [PATCH 2/4] Add remappings validation to build CI Validates that all remapping targets in every remappings.txt actually exist on disk, resolving paths through Foundry's libs config. Catches broken remappings early (like the issue in PR#82/#90). Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/build.yaml | 39 ++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 6df1bc8..0002f49 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -9,6 +9,45 @@ on: - "*" jobs: + validate-remappings: + name: Validate remappings + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + submodules: recursive + + - name: Check all remapping targets exist + run: | + rc=0 + for file in $(find . -name remappings.txt -not -path './lib/*' -not -path './node_modules/*'); do + dir=$(dirname "$file") + # Collect search bases: the remappings dir + libs from foundry.toml + bases="$dir" + if [ -f "$dir/foundry.toml" ]; then + for lib in $(grep "^libs" "$dir/foundry.toml" | sed "s/.*\[//;s/\].*//;s/'//g;s/\"//g;s/,/ /g"); do + bases="$bases $dir/$lib" + done + fi + while IFS= read -r line; do + [ -z "$line" ] && continue + target=$(echo "$line" | sed 's/.*=//') + found=false + for base in $bases; do + if [ -d "$base/$target" ]; then + found=true + break + fi + done + if [ "$found" = false ]; then + echo "::error file=$file::Broken remapping: $line (target '$target' not found)" + rc=1 + fi + done < "$file" + done + exit $rc + foundry-root: name: Compile root contracts (Foundry) runs-on: ubuntu-latest From 17c853cb04d8cf2acbdd3caa6bdcc6dd2e3816cc Mon Sep 17 00:00:00 2001 From: nisedo <73041332+nisedo@users.noreply.github.com> Date: Mon, 9 Mar 2026 18:17:57 +0100 Subject: [PATCH 3/4] Add ERC721 Medusa fuzzing configs and CI jobs The Medusa CI workflow covered ERC20 and ERC4626 but was missing ERC721. Add internal and external Medusa configs for ERC721 (modeled after ERC20) and wire them into the medusa.yaml workflow. Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/medusa.yaml | 14 ++++ tests/ERC721/foundry/medusa-config-ext.json | 80 +++++++++++++++++++++ tests/ERC721/foundry/medusa-config.json | 80 +++++++++++++++++++++ 3 files changed, 174 insertions(+) create mode 100644 tests/ERC721/foundry/medusa-config-ext.json create mode 100644 tests/ERC721/foundry/medusa-config.json diff --git a/.github/workflows/medusa.yaml b/.github/workflows/medusa.yaml index 5635b32..8623a6c 100644 --- a/.github/workflows/medusa.yaml +++ b/.github/workflows/medusa.yaml @@ -52,6 +52,20 @@ jobs: run: | medusa fuzz --target-contracts CryticERC20ExternalHarness --config medusa-config-ext.json + - name: Compile ERC721 Foundry example + working-directory: tests/ERC721/foundry + run: forge build --build-info + + - name: Run Medusa for Internal ERC721 tests + working-directory: tests/ERC721/foundry + run: | + medusa fuzz --target-contracts CryticERC721InternalHarness --config medusa-config.json + + - name: Run Medusa for External ERC721 tests + working-directory: tests/ERC721/foundry + run: | + medusa fuzz --target-contracts CryticERC721ExternalHarness --config medusa-config-ext.json + - name: Compile ERC4626 Foundry example working-directory: tests/ERC4626/foundry run: forge build --build-info diff --git a/tests/ERC721/foundry/medusa-config-ext.json b/tests/ERC721/foundry/medusa-config-ext.json new file mode 100644 index 0000000..0acd176 --- /dev/null +++ b/tests/ERC721/foundry/medusa-config-ext.json @@ -0,0 +1,80 @@ +{ + "fuzzing": { + "workers": 10, + "workerResetLimit": 50, + "timeout": 0, + "testLimit": 500000, + "callSequenceLength": 100, + "corpusDirectory": "tests/medusa-corpus-ext", + "coverageEnabled": true, + "targetContracts": [], + "targetContractsBalances": [], + "constructorArgs": {}, + "deployerAddress": "0x10000", + "senderAddresses": [ + "0x10000", + "0x20000", + "0x30000" + ], + "blockNumberDelayMax": 60480, + "blockTimestampDelayMax": 604800, + "blockGasLimit": 125000000, + "transactionGasLimit": 12500000, + "testing": { + "stopOnFailedTest": true, + "stopOnFailedContractMatching": false, + "stopOnNoTests": true, + "testAllContracts": true, + "traceAll": false, + "assertionTesting": { + "enabled": true, + "testViewMethods": false, + "panicCodeConfig": { + "failOnCompilerInsertedPanic": false, + "failOnAssertion": true, + "failOnArithmeticUnderflow": false, + "failOnDivideByZero": false, + "failOnEnumTypeConversionOutOfBounds": false, + "failOnIncorrectStorageAccess": false, + "failOnPopEmptyArray": false, + "failOnOutOfBoundsArrayAccess": false, + "failOnAllocateTooMuchMemory": false, + "failOnCallUninitializedVariable": false + } + }, + "propertyTesting": { + "enabled": false, + "testPrefixes": [ + "property_" + ] + }, + "optimizationTesting": { + "enabled": false, + "testPrefixes": [ + "optimize_" + ] + } + }, + "chainConfig": { + "codeSizeCheckDisabled": true, + "cheatCodes": { + "cheatCodesEnabled": true, + "enableFFI": false + } + } + }, + "compilation": { + "platform": "crytic-compile", + "platformConfig": { + "target": ".", + "solcVersion": "", + "exportDirectory": "", + "args": ["--foundry-compile-all"] + } + }, + "logging": { + "level": "info", + "logDirectory": "", + "noColor": false + } +} diff --git a/tests/ERC721/foundry/medusa-config.json b/tests/ERC721/foundry/medusa-config.json new file mode 100644 index 0000000..d5a8b5b --- /dev/null +++ b/tests/ERC721/foundry/medusa-config.json @@ -0,0 +1,80 @@ +{ + "fuzzing": { + "workers": 10, + "workerResetLimit": 50, + "timeout": 0, + "testLimit": 500000, + "callSequenceLength": 100, + "corpusDirectory": "tests/medusa-corpus", + "coverageEnabled": true, + "targetContracts": [], + "targetContractsBalances": [], + "constructorArgs": {}, + "deployerAddress": "0x10000", + "senderAddresses": [ + "0x10000", + "0x20000", + "0x30000" + ], + "blockNumberDelayMax": 60480, + "blockTimestampDelayMax": 604800, + "blockGasLimit": 125000000, + "transactionGasLimit": 12500000, + "testing": { + "stopOnFailedTest": true, + "stopOnFailedContractMatching": true, + "stopOnNoTests": true, + "testAllContracts": false, + "traceAll": false, + "assertionTesting": { + "enabled": true, + "testViewMethods": false, + "panicCodeConfig": { + "failOnCompilerInsertedPanic": false, + "failOnAssertion": true, + "failOnArithmeticUnderflow": false, + "failOnDivideByZero": false, + "failOnEnumTypeConversionOutOfBounds": false, + "failOnIncorrectStorageAccess": false, + "failOnPopEmptyArray": false, + "failOnOutOfBoundsArrayAccess": false, + "failOnAllocateTooMuchMemory": false, + "failOnCallUninitializedVariable": false + } + }, + "propertyTesting": { + "enabled": false, + "testPrefixes": [ + "property_" + ] + }, + "optimizationTesting": { + "enabled": false, + "testPrefixes": [ + "optimize_" + ] + } + }, + "chainConfig": { + "codeSizeCheckDisabled": true, + "cheatCodes": { + "cheatCodesEnabled": true, + "enableFFI": false + } + } + }, + "compilation": { + "platform": "crytic-compile", + "platformConfig": { + "target": ".", + "solcVersion": "", + "exportDirectory": "", + "args": ["--foundry-compile-all"] + } + }, + "logging": { + "level": "info", + "logDirectory": "", + "noColor": false + } +} From 4667091e4539fc69ebe4419a34e30b9e68e8794f Mon Sep 17 00:00:00 2001 From: nisedo <73041332+nisedo@users.noreply.github.com> Date: Mon, 9 Mar 2026 18:36:54 +0100 Subject: [PATCH 4/4] Remove nonexistent FOUNDRY_PROFILE=ci from Medusa and Echidna workflows No foundry.toml defines a [profile.ci] section. Newer Foundry nightly versions error on missing profiles instead of silently falling back to the default, causing CI failures. Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/echidna.yaml | 3 --- .github/workflows/medusa.yaml | 3 --- 2 files changed, 6 deletions(-) diff --git a/.github/workflows/echidna.yaml b/.github/workflows/echidna.yaml index 6839438..25db973 100644 --- a/.github/workflows/echidna.yaml +++ b/.github/workflows/echidna.yaml @@ -8,9 +8,6 @@ on: branches: - "*" -env: - FOUNDRY_PROFILE: ci - jobs: foundry: name: Test Foundry examples diff --git a/.github/workflows/medusa.yaml b/.github/workflows/medusa.yaml index 8623a6c..97f9c89 100644 --- a/.github/workflows/medusa.yaml +++ b/.github/workflows/medusa.yaml @@ -8,9 +8,6 @@ on: branches: - "*" -env: - FOUNDRY_PROFILE: ci - jobs: foundry: name: Test Foundry examples