diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml new file mode 100644 index 0000000..0002f49 --- /dev/null +++ b/.github/workflows/build.yaml @@ -0,0 +1,130 @@ +name: Build + +on: + push: + branches: + - main + pull_request: + branches: + - "*" + +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 + 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 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 5635b32..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 @@ -52,6 +49,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 + } +}