Medusa Fuzzing Campaign
Relevant source files
The following files were used as context for generating this wiki page:
The Medusa Fuzzing Campaign is a critical security component of the Canon Guard ecosystem, designed to perform high-coverage invariant testing on the project's multisig and transaction management smart contracts. By utilizing the Medusa fuzzer, the project automates the discovery of edge cases and security vulnerabilities that might not be caught by standard unit tests, specifically targeting the logic governing Actions contracts and dynamic timelocks.
Sources: README.md:1-10, CLAUDE.md:10-20, test/invariants/PROPERTIES.md:3-10
The campaign is integrated into the project's development lifecycle via the yarn test:fuzz command, which executes the Medusa binary using the configuration defined in medusa.json. It targets specific invariant properties related to cap accounting, transaction timing, and queue consistency to ensure the "Safe" remains in a secure, non-frozen state even under adversarial transaction sequences.
Sources: package.json:15-30, medusa.json:1-10, test/invariants/PROPERTIES.md:12-15
Fuzzing Architecture and Execution Flow
The fuzzing campaign operates by deploying a set of target contracts and handlers that interact with the core Canon Guard system. The execution flow involves a specialized fuzzer that generates sequences of transactions to test defined invariants.
The diagram shows the lifecycle of a Medusa fuzzing run from command execution to invariant validation.
Sources: package.json:28, medusa.json:71-78, test/invariants/PROPERTIES.md:52-58
Core Components
- Target Contract: The primary entry point for the fuzzer is
FuzzTest.t.sol. - Handlers: Dedicated contracts for each Action Builder and Hub (e.g.,
SimpleActions,SimpleTransfers) that manage the queueing and execution logic during the fuzzing session. - ActionTarget: A mock contract used as a target for all Action Hubs to simulate interactions with arbitrary external contracts.
Sources: medusa.json:73, test/invariants/PROPERTIES.md:52-60
Configuration Parameters
The fuzzing environment is highly tuned through medusa.json to maximize coverage and performance.
| Parameter | Value | Description |
|---|---|---|
workers | 10 | Number of concurrent fuzzing threads. |
callSequenceLength | 100 | Length of the transaction sequence in a single fuzzing run. |
timeout | 0 | No time limit for the campaign (until completion). |
testLimit | 0 | No limit on the number of tests executed. |
shrinkLimit | 5000 | The maximum number of attempts to simplify a failing test case. |
blockNumberDelayMax | 60480 | Maximum block delay simulated (approx. 1 week). |
blockTimestampDelayMax | 604800 | Maximum timestamp delay (604,800 seconds). |
Sources: medusa.json:3-23
Invariant Categories
The campaign focuses on four primary categories of invariants to ensure the integrity of the multisig solution.
1. Cap & Accounting Invariants
Ensures that defined limits are strictly enforced across different hubs, particularly during epoch boundaries.
invariant_capNeverExceeded: Validates that cap limits in any hub are never surpassed.
Sources: test/invariants/PROPERTIES.md:16-21
2. Approval & Timing Invariants
The core logic of Canon Guard relies on precise timing and valid signatures.
invariant_queuedTransactionsHaveValidApprovals: Ensures transactions in the queue are backed by valid approvals.invariant_transactionTimingIsCorrect: Asserts thatexpiresAt > executableAtandexecutableAt >= queuedAt.invariant_preApprovedTransactionsUsedShortDelay: Confirms that pre-approved actions correctly utilize theSHORT_TX_EXECUTION_DELAY.
Sources: test/invariants/PROPERTIES.md:28-36
3. Queue Consistency
Maintains the integrity of the internal transaction queue data structures.
invariant_queueHasNoDuplicates: Prevents the same action builder address from appearing twice in the queue.invariant_queueMappingConsistency: Ensures the queue array andtransactionsInfomapping remain synchronized.
Sources: test/invariants/PROPERTIES.md:43-48
Integration with Foundry
The Medusa campaign leverages the Foundry environment for compilation and basic testing parameters, though it uses its own execution engine.
The relationship between Medusa and Foundry configuration profiles.
Sources: foundry.toml:14-20, medusa.json:2-10, test/invariants/PROPERTIES.md:12-40
Key Execution Commands
- Standard Fuzzing:
yarn test:fuzzexecutesmedusa fuzz. - Deep Fuzzing (Foundry):
yarn test:unit:deepruns standard Foundry fuzzing with 5,000 runs instead of 1,000. - Coverage:
yarn coveragegenerates LCOV reports to identify untested branches.
Sources: package.json:28-32, foundry.toml:35-37
Testing Constraints and Assumptions
The campaign operates under specific architectural assumptions to prevent false positives and handle complex logic:
- Assertion Testing: Medusa is configured to fail on compiler-inserted panics and manual assertions (
failOnAssertion: true), but ignores arithmetic underflows/overflows if they are expected behaviors of the fuzzer's random input. - Delay Fixes: Previous versions required explicit constraints on
SHORT_TX_EXECUTION_DELAYandLONG_TX_EXECUTION_DELAYto prevent overflows in_queueTransaction, which have since been integrated into the core logic. - Cheat Codes: Medusa has
cheatCodesEnabled: truebutenableFFI: falseto maintain a secure and deterministic testing environment.
Sources: medusa.json:37-55, medusa.json:62-66, test/invariants/PROPERTIES.md:62-72
The Medusa Fuzzing Campaign provides an automated, adversarial testing layer that ensures the safety of the Canon Guard multisig. By targeting complex timing and accounting invariants, it guarantees that transaction execution remains predictable and secure under all possible on-chain states.