Skip to content

Conversation

@gustavo-grieco
Copy link
Collaborator

@gustavo-grieco gustavo-grieco commented Dec 18, 2025

This branch contains a rewrite of some core features of Echidna to transform workers into agents, which can receive commands and collaborate with each other. It also allows to easily add MCP commands to query and guide the fuzzing campaign.

image

Commands

This code is still a work in progress but it can already tested with the few command implemented:

  • status(): Show fuzzing campaign status
  • target(): Show the name and the ABI of the target contract
  • reload_corpus(): Reload the transactions from the corpus, but without replay them
  • dump_lcov(): Dump coverage in LCOV format"
  • inject_fuzz_transactions(string): Inject a sequence of transaction to fuzz with optional concrete arguments (e.g. f(1, ?, 3) ; g(?, -1))
  • inject_symb_transaction(string): Inject a single of transaction to explore using symbolic execution with optional concrete arguments (e.g. f(1, ?, 3))
  • clear_fuzz_priorities(): Clear the function prioritization list used in fuzzing
  • read_logs(): Read the last 100 log messages [disabled in the current code, perhaps not necessary]
  • show_coverage(string): Show coverage report for a particular contract
  • avoid_function(string): Exclude a transaction from the list of randomly generated transactions

All these commands are subject to change, and there will be an experimentation phase where we will challenge the agents to increase the coverage (or break properties) using different commands

There are some additional changes in the logs to convey useful information for the agent, in particular, when new coverage is found:

[2025-12-18 11:45:22.26] [Worker 2] New coverage: 15176 instr, 7 contracts, 19 seqs in corpus (mintAndApprove)

How to test this PR

  1. Open your echidna-compatible fuzzing project in Visual Studio Code, make sure you have Github Copilot installed.
  2. Compile this branch or download the echidna executable from our CI tests.
  3. Start/resume an Echidna campaign for the agent to guide. Very recommended to use text mode (--format text) for this test. Append the --server 3000 to your command line to start the MCP server in the port 3000.
  4. Create the .vscode/mcp.json file with the following content:
{
  "servers": {
    "Echidna fuzzing campaign": {
      "type": "http",
      "url": "http://localhost:3000/mcp"
    }
  }
}

Once you save the file, you will be able to click on the "Run" button next the server name to make sure the it is detected by Copilot. It should list the number of commands available (currently 7).
5. Everything should be ready to go, open the Chat window (Cmd + Shift + P and write /chat) and start prompting. My recommended option to quickly start:

An Echidna fuzzing campaign is currently running and has already achieved baseline coverage using the default strategy, meaning trivial execution paths are mostly explored.

Using the available MCP interface **only** (do not modify any code or functions):

1. **Identify the campaign context**
   - Determine the fuzzing target and current campaign status using the appropriate MCP commands.

2. **Analyze coverage**
   - Inspect coverage for the relevant contracts using `show_coverage`.
   - Identify execution paths or code regions with **low coverage** that are *theoretically reachable* from the target logic.

3. **Design targeted fuzzing sequences**
   - Once you understand the contract behavior, use `inject_fuzz_transactions` to prioritize one or more transaction sequences.
   - Separate multiple calls with `;` (e.g., `f(1,?,?) ; g(?,2,5)`).
   - Combine **concrete values and random parameters** strategically.
   - **Do not use `?` for all parameters**, as those cases are already well-covered by the existing campaign.
   - **Avoid making all parameters concrete when possible**. As a *recommendation* (not a strict requirement), leave at least one parameter as `?` per call to allow the fuzzer to continue exploring the input space rather than repeatedly replaying a single fixed execution. Fully concrete calls may still be used when they intentionally target a very specific path or invariant.
   - **Injection semantics:** the prioritized sequence is **not executed in isolation**. Echidna starts from an existing transaction sequence in the current corpus and **inserts the injected sequence at a random position within it**, not necessarily at the beginning. Design injected calls assuming relevant state may already exist.

4. **Evaluate results**
   - After injecting transactions, run `sleep 20` to allow fuzzing to progress.
   - Then call `status` to check whether additional coverage was discovered or any invariant (e.g., `assert`) failed.

5. **Reset priorities**
   - Clear prioritized calls using `clear_fuzz_priorities` to return the fuzzer to its default random sampling strategy.

Focus on crafting transaction sequences that are most likely to exercise uncovered logic or trigger invariant violations, while still allowing the fuzzer enough freedom to explore variations.

@CLAassistant
Copy link

CLAassistant commented Dec 18, 2025

CLA assistant check
All committers have signed the CLA.

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.

3 participants