1685 Commits
Author SHA1 Message Date
Gustavo Grieco 5adfc83986 Update hevm with arithmetic abstraction and execution optimizations (#1639)
* Update hevm and enable arithmetic abstraction internally

* Test arithmetic abstraction on multiplication monotonicity

* Optimize hevm while preserving symbolic Keccak preimages

Integrate the optimization settings and conditional preimage recording from PR #1621. Keep recording throughout symbolic campaigns and verify that both solvers recover earlier transaction inputs after replaying a symbolic counterexample.
2026-10-08 21:31:16 +02:00
dependabot[bot] 272e2f59f4 build(deps): bump msys2/setup-msys2 (#1638)
Bumps the gh-actions group with 1 update: [msys2/setup-msys2](https://github.com/msys2/setup-msys2).


Updates `msys2/setup-msys2` from 2.32.0 to 2.33.0
- [Release notes](https://github.com/msys2/setup-msys2/releases)
- [Changelog](https://github.com/msys2/setup-msys2/blob/main/CHANGELOG.md)
- [Commits](https://github.com/msys2/setup-msys2/compare/66cd2cce69caa17b53920067426061ca1de3a884...ec48f7c5447b3140e2b088413ae3a55687bccb6e)

---
updated-dependencies:
- dependency-name: msys2/setup-msys2
  dependency-version: 2.33.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gh-actions
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-08 13:40:40 -03:00
Gustavo Grieco f7881f6785 Reject fixed seeds with campaign timeouts (#1637) 2026-10-08 15:26:48 +02:00
Martin MonperrusandClaude Sonnet 5.5 2a5137074d JSON output: encode string/bytes/array/tuple call arguments as structured JSON (#1636)
transactions[].arguments used ppAbiValue for every argument, so bytes,
bytesN and string were the Haskell `show` rendering (\NUL, \DEL, decimal
escapes, \&) and arrays/tuples were stringified. Encode bytes/bytesN as
0x-hex, string as a JSON string (hex if not UTF-8), arrays/tuples as JSON
arrays. Scalars are unchanged.

Co-authored-by: Claude Sonnet 5.5 <[email protected]>
2026-10-05 16:04:37 +02:00
dependabot[bot] b0348b68bc build(deps): bump the gh-actions group with 2 updates (#1635)
Bumps the gh-actions group with 2 updates: [haskell-actions/setup](https://github.com/haskell-actions/setup) and [DeterminateSystems/nix-installer-action](https://github.com/determinatesystems/nix-installer-action).


Updates `haskell-actions/setup` from 2.12.0 to 2.12.1
- [Release notes](https://github.com/haskell-actions/setup/releases)
- [Commits](https://github.com/haskell-actions/setup/compare/6037f33647c3f17758a2356c80fc4a53d7e0685d...0f8e8c99d88aeb3fbfd523f1ef2c6f762d10d64d)

Updates `DeterminateSystems/nix-installer-action` from 22 to 23
- [Release notes](https://github.com/determinatesystems/nix-installer-action/releases)
- [Commits](https://github.com/determinatesystems/nix-installer-action/compare/v22...3138316df39ed29be04236d7ffc686fa525866aa)

---
updated-dependencies:
- dependency-name: haskell-actions/setup
  dependency-version: 2.12.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gh-actions
- dependency-name: DeterminateSystems/nix-installer-action
  dependency-version: '23'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: gh-actions
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-05 09:22:45 -03:00
5403657dbf test: drive the MCP server the way its clients do (#1608)
The MCP server is the one part of Echidna that another program talks to,
and the Haskell suite cannot say whether that conversation works: it runs
in process, while what matters here is what goes over the wire and what
the tools answer about a campaign that is actually fuzzing.

So this suite starts one. conftest.py launches a real echidna against a
fixture contract and waits for the server to accept an MCP initialize
rather than merely for the socket to open, then hands the same campaign
to every module. Four layers ride on it:

test_mcp.py covers the nine tools -- what each one reports about a live
campaign, and what it says when it cannot answer. status while the
campaign fuzzes, coverage marked up line by line, an LCOV file that is
really on disk, an injected sequence that the workers keep fuzzing
through, a replayed sequence reported call by call including the revert
reason, a sampled function whose counts show up in status a few seconds
later. Anything that steers the campaign is undone afterwards, so no test
depends on the order it ran in.

test_mcp_conformance.py is the regression guard for "real clients can
still connect". A notification gets 202 with no body; a GET asking for a
server stream gets 405 rather than the JSON blob a strict client tries to
read as SSE; initialize negotiates a version and names the server. These
are exactly the two behaviours mcp-server 0.2.0.1 fixed, and the reason
that version is the floor.

test_mcp_codex.py replays Codex's rmcp handshake step by step, and
test_mcp_claude.py drives the server with the reference `mcp` SDK through
a real session. Both are transport-level and need no API key, so both run
in CI; a live-model run is the LangGraph example instead.

That example is here too. It reads status, and when the campaign has gone
a minute without finding coverage it hands Claude the ABI and the coverage
report and injects the sequences that come back -- a demonstration that
those tools are enough to close the loop, not a tuned strategy.

Some notes on what differs from the version this is adapted from:

The tool tests are written against the server as it is rather than the
prototype: status answers JSON, show_coverage takes a contract, and a tool
that cannot do what it was asked answers with an MCP error result. They
assert on all three, where the originals asserted that some substring
appeared somewhere in the text. They also go through the shared wire
helpers after a handshake, rather than a second raw client that posted
tools/call with no handshake and no headers -- asserting leniency next to
a suite that asserts strictness said two different things about what the
server promises.

The `mcp` SDK's 2.0 renamed its transport helper, dropped the third stream
it used to yield, and moved its result models to snake_case. Rather than
straddle both majors, requirements-test.txt follows the current one and
the test skips itself on an older SDK. The other pins are bounded by major
version only, since a compatibility suite should be running against what
clients actually ship.

The fixture contracts lost their spec-kit headers, two properties that
could not fail (one returned a literal `true`), and the `test` prefix on
their entry points, which means something else in Foundry mode. What is
left is a contract that gives the tools something to report on: calls that
succeed, calls that revert with a reason, and properties that hold so the
campaign keeps running for as long as the session needs it.

The workflow now triggers on master and on pull requests against it, like
every other workflow here, and only for paths that can change what the
server answers -- it builds the whole closure and then fuzzes, which is
not something to do on every push to every branch. Its Cachix token is
unavailable to pull requests from forks, so those runs read the public
cache and push nothing; that is noted where it will be read.

tests/mcp/requirements.txt is gone: nothing referenced it, and it
contradicted both its sibling and the example's README on what to install.
So is pytest.ini, which was only read when pytest was given the directory
as an argument -- the one async test carries an explicit marker instead,
which works either way.

Co-authored-by: Dani Tradito <[email protected]>
Co-authored-by: gustavo-grieco <[email protected]>
2026-09-29 17:10:51 -03:00
Emilio Lópezandgustavo-grieco e6baf93926 Replace the Server-Sent Events server with an MCP server (#1607)
* feat: add a call-sequence syntax for MCP clients

Something driving a campaign from outside it needs a way to name a
sequence of calls, and the natural one is how the calls would be written
in Solidity, with a hole wherever the fuzzer should choose:

    approve(0x10, ?); transferFrom(?, ?, 100)

Echidna.MCP.Parse reads that into the list of SolCallPrototypes the
preceding commits taught the fuzzer to generate from. Parsing stops at an
argument's shape rather than its type -- an integer becomes a uint256, an
0x-prefixed literal an address -- because an argument left open carries no
type to compare against anyway, so a prototype is resolved against the
ABI by name and arity either way.

It is a module of its own rather than part of the server that will use
it. This is the one piece of the interface with a set of edge cases worth
enumerating, and Tests.MCPParse enumerates them without needing a
campaign to run against.

Three things differ from the version this is adapted from. `foo(1` no
longer parses as a call with no arguments: the closing parenthesis is
checked rather than assumed, which is what that silently relied on. An
empty sequence is rejected instead of accepted as a sequence of no calls.
And splitting on `;` is Data.List.Split's job rather than a hand-rolled
splitter's -- the bracket-aware split of an argument list still needs its
own, since a comma inside `[1,2]` does not separate arguments.

Nothing parses a sequence yet; the MCP server that does arrives next.

Co-authored-by: gustavo-grieco <[email protected]>

* feat: replace the events server with an MCP server

--server PORT has run a Server-Sent Events server: a one-way stream of
campaign events, enough to watch a campaign with but not to ask it
anything. Replace it with a Model Context Protocol server on the same
flag and the same port, so what is on the other end can both read the
campaign and steer it.

Nine tools. Four report: status (corpus size, iterations, coverage,
tests, optimization values, how long since the last coverage, the
functions that found it, and whatever is being sampled), target,
show_coverage and dump_lcov. Five act: inject_fuzz_transactions and
clear_fuzz_priorities aim the fuzzer at an ordering, sample starts and
stops recording what a function does, execute_sequence replays a concrete
sequence without disturbing the campaign, and reload_corpus picks up
whatever was written to the corpus directory since it started.

The five that act do so over the inter-worker bus, which is why this
comes last: the commands they send, the sampling they switch on and the
replay they ask for all landed in the preceding commits with nothing to
send them. AgentId gains ServerId to say where they come from.

Retiring SSE is the point of the commit rather than a side effect of it.
Echidna.Server had no other caller, so it goes, and wai-extra with it.
The "Waiting until all SSE are received..." drain at the end of a
non-interactive run goes too, and with no reader left the MVar the SIGINT
handler filled goes as well. --server and the `server` config key keep
their names and their meaning -- a port to serve the campaign on -- so
there is no point at which the flag does nothing.

On the dependency: mcp-server comes from Hackage at 0.2.0.1, not from the
personal fork this was prototyped against. Upstream has since released
the two fixes that fork existed for (202 with no body for a notification,
405 for a server-stream GET), so there is no reason to carry a fork of a
library in the closure of a security tool. It needs http-types >= 0.12.6,
which nixpkgs and lts-23.24 both predate: only that version re-exports
`hOrigin` from the umbrella Network.HTTP.Types module that mcp-server
imports unqualified, and http-types has to move for the whole package set
rather than for mcp-server alone, since wai and warp exchange its Status
type with it. Everything in the closure builds against 0.12.6.

Some notes on the shape of it:

The server runs mcpApplication under Warp directly instead of
runMcpServerHttpWithConfig, which announces itself with a bare putStrLn.
Going through a ServerLog event instead keeps the line timestamped and
prefixed like every other one, and leaves Warp's settings to us -- which
matters for binding to loopback.

Origin validation is on with an empty allow-list. The campaign is
reachable from a browser on the same machine, and a page must not be able
to drive a fuzzer through DNS rebinding; a client that sends no Origin at
all, which is every CLI agent, is unaffected.

A tool that cannot do what it was asked answers with an MCP error result
rather than with a report whose text begins "Error:", so a model does not
have to read prose to notice. That is what the Either in ToolRun is.

reload_corpus reads the same two directories the campaign read at
startup, through loadInitialCorpus, rather than the corpus directory
itself -- what is directly in there is those directories, and reading one
as a file is an exception. It decides what is new and adds it inside a
single atomicModifyIORef', because workers are adding to the corpus while
it runs and a read followed by a write would drop whatever arrived in
between. Sequences from disk take the weight of the best entry already
there, never zero, which selectFromCorpus would never draw.

The upstream version's Env.sourceCache is not here: DappInfo already
carries the source cache, so env.dapp.sources is the same thing without a
second copy in Env. Its DumpLcov bus command is not here either -- the
tool calls saveLcovSnapshot directly, and a command with no sender is
what the earlier commits have been leaving out. Its markLines change is
not here: dropping the line number and column separator to save an
agent's tokens would have regressed every text and HTML coverage report
Echidna writes, and an agent that cannot cite a line number is worse off
than one reading a few more tokens.

The recently-covered functions are kept with takeStrict, not take. They
are appended to on every coverage event and read only when a client asks,
so a lazy tail would retain every sequence the campaign ever found
coverage with -- the same trap the sampling state was written around.

One limitation worth knowing: execute_sequence sends every call to the
contract under test, so a sequence naming a function of some other
deployed contract goes to the wrong address. The sequence syntax has no
way to spell an address, so there is nothing to fix it with yet.

Co-authored-by: gustavo-grieco <[email protected]>

* fix: coerce concrete MCP arguments to ABI parameter types

Resolve concrete replay calls against the ABI before constructing SolCall values, and coerce fixed arguments in fuzz prototypes. Preserve signed and full-width literals, validate bounds and array lengths, and reject ambiguous replay overloads.

Add parser, coercion, mixed-prototype and Solidity replay regressions. The focused 63-test suite and live MCP probe pass; restoring the original call construction fails all four call-site regression tests.

* test: cover bytes32 literals in mixed MCP calls

Exercise asymmetric 32-byte words through generic mixed-parameter replay and injected prototypes. Check leading-zero padding, the zero word, and oversized literal rejection for G3, whose implementation is covered by the B1 coercion fix.

Validation: targeted HLint and git diff --check pass. Execution testing is deferred to GitHub CI.

* fix: start MCP only after workers are ready

---------

Co-authored-by: gustavo-grieco <[email protected]>
2026-09-29 18:27:59 +02:00
Emilio Lópezandgustavo-grieco 0a6ec5bdfc Concrete sequence replay with a JSON report (#1606)
* feat: replay a concrete sequence and report on it

Add ExecuteSequence, the command that answers "what does this sequence
of calls actually do?". A caller hands a worker a concrete sequence and
gets back a JSON report: what each call was, whether it completed,
reverted or failed an assertion, the gas it burned and the events it
emitted, then the block number and timestamp the sequence ended on and,
if asked for, the EVM trace.

The replay goes through execTx rather than callseq, so the campaign is
left exactly as it was: no coverage recorded, nothing added to the
corpus, no test falsified. Answering a question about the contract must
not change what the campaign does next, and a test pins that down.

The report summarises the sequence by its worst transaction rather than
its first failure. An assertion failure anywhere outranks a revert, even
one that happened earlier -- reverts are common enough in a random
sequence that reporting one would bury the thing the caller was looking
for. Assertion failures are recognised with checkAssertionEvent and
checkPanicEvent, the same pair an assertion test uses, so both the
emit-AssertionFailed convention and solc's Panic(1) are covered; the
tests exercise one path each.

The command is addressed to a single worker, which answers through a
one-shot Reply channel. The replay runs on that worker's own thread, so
it stops fuzzing for as long as the caller is waiting on it.

Nothing sends this command yet; the MCP server that does arrives next.

Co-authored-by: gustavo-grieco <[email protected]>

* fix: drop a partial head from the replay tests

GHC 9.8 turned head into a -Wall warning, and CI builds the test suite
with -Werror, so the single-transaction assertion in the Panic(1) test
failed the Windows and Linux builds.

Match on the list instead. The test replays exactly one transaction, so
pinning that down says what the assertion already assumed and reports a
useful failure if it ever stops holding.

---------

Co-authored-by: gustavo-grieco <[email protected]>
2026-09-29 16:23:24 +02:00
dependabot[bot] 3fdf4a2c20 build(deps): bump the gh-actions group across 1 directory with 3 updates (#1634)
Bumps the gh-actions group with 3 updates in the / directory: [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action), [docker/build-push-action](https://github.com/docker/build-push-action) and [DeterminateSystems/nix-installer-action](https://github.com/determinatesystems/nix-installer-action).


Updates `docker/setup-buildx-action` from 4.3.0 to 4.4.1
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/37fe631027851001ddb9b187196cc803df7f5f0e...f87e5991a6d7451dcb8d9637bfbc97413f497069)

Updates `docker/build-push-action` from 7.3.0 to 7.4.0
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/53b7df96c91f9c12dcc8a07bcb9ccacbed38856a...c3c9e263c25d99ce0380d002d59b67737d91b0dc)

Updates `DeterminateSystems/nix-installer-action` from 22 to 23
- [Release notes](https://github.com/determinatesystems/nix-installer-action/releases)
- [Commits](https://github.com/determinatesystems/nix-installer-action/compare/ef8a148080ab6020fd15196c2084a2eea5ff2d25...3138316df39ed29be04236d7ffc686fa525866aa)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  dependency-version: 4.4.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gh-actions
- dependency-name: docker/build-push-action
  dependency-version: 7.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gh-actions
- dependency-name: DeterminateSystems/nix-installer-action
  dependency-version: '23'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: gh-actions
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-27 15:44:17 -03:00
dependabot[bot] ddb680b574 build(deps): bump the gh-actions group across 1 directory with 2 updates (#1628)
Bumps the gh-actions group with 2 updates in the / directory: [cachix/cachix-action](https://github.com/cachix/cachix-action) and [softprops/action-gh-release](https://github.com/softprops/action-gh-release).


Updates `cachix/cachix-action` from 5f2d7c5294214f71b873db4b969586b980625e71 to 38b082610b782e7e93e209c35fd730d399dee866
- [Release notes](https://github.com/cachix/cachix-action/releases)
- [Changelog](https://github.com/cachix/cachix-action/blob/master/RELEASE.md)
- [Commits](https://github.com/cachix/cachix-action/compare/5f2d7c5294214f71b873db4b969586b980625e71...38b082610b782e7e93e209c35fd730d399dee866)

Updates `softprops/action-gh-release` from 3.0.2 to 3.0.3
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](https://github.com/softprops/action-gh-release/compare/3d0d9888cb7fd7b750713d6e236d1fcb99157228...efb35369e0ad2afab669f228072c1b0d510eae64)

---
updated-dependencies:
- dependency-name: cachix/cachix-action
  dependency-version: 38b082610b782e7e93e209c35fd730d399dee866
  dependency-type: direct:production
  dependency-group: gh-actions
- dependency-name: softprops/action-gh-release
  dependency-version: 3.0.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gh-actions
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-10 11:51:22 -03:00
Emilio Lópezandgustavo-grieco 3a084a4111 Prioritized and injected transaction sequences (#1605)
* refactor: factor the shared tail out of genTx

genTx does three things in sequence: resolve the deployed contracts to
the ABIs Echidna knows how to call, pick one of them and generate a call
to it, then wrap that call in a transaction with a random sender, value
and delay. Only the middle step is about choosing what to call; the two
ends are the same for any generator that has already decided.

Split them into callableContracts, genRandomCall and toTx, leaving genTx
as the composition of the three. No behaviour changes -- this is the
groundwork for a generator that picks its own call and reuses both ends
rather than repeating them.

Co-authored-by: gustavo-grieco <[email protected]>

* feat: generate a transaction from a call prototype

A prototype is a SolCall with holes: a function name and an argument
list where Nothing marks an argument left for the fuzzer to fill in. It
is how something outside the campaign says "call transfer, I don't care
with what", or "call transfer with this recipient and any amount".

genTxFromPrototype resolves one against the deployed contracts and hands
the result to the same tail genTx uses. Matching is on name and arity
only: an argument left open carries no type to compare against, so
same-arity overloads all qualify and one is picked at random.
matchingContracts cuts each contract down to just the signatures that
match, which keeps the subsequent pick total -- there is no filtered
list that can turn out to be empty after a contract was already chosen.

When nothing deployed exposes such a function it falls back to a fully
random transaction, so a prototype naming a function that isn't there
costs diversity rather than stalling the worker.

Nothing produces prototypes yet; the command that injects them follows.

Co-authored-by: gustavo-grieco <[email protected]>

* feat: prioritize injected call sequences during fuzzing

Add the other half of prototypes: a worker can be handed a sequence of
them together with a probability, and will fuzz that sequence instead of
a corpus-mutated one that often. This is what lets something outside the
campaign spend part of a worker's budget on a specific ordering -- an
ordering it has reason to believe is interesting, but that the corpus
mutators are unlikely to stumble into.

FuzzSequence and ClearPrioritization join the commands a fuzzing worker
accepts over the bus, and what they inject accumulates in
WorkerState.prioritizedSequences. randseq now chooses between the
prioritized path and the standard one; its previous body moves to
genStandardSeq unchanged.

genPrioritizedSeq turns a sequence of prototypes into a real one. The
calls are generated in order with up to maxInterleavedTxs random
transactions between consecutive ones, so what gets pinned is the
ordering rather than the whole sequence. It is then prefixed with the
start of a corpus entry, so the ordering also runs from a state the
campaign has already reached -- except on worker 0, which always takes
the empty prefix so the initial state stays covered. The result is
padded with random transactions, or truncated, to respect seqLen.

Nothing sends these commands yet; the client that does arrives with the
MCP server.

Co-authored-by: gustavo-grieco <[email protected]>

---------

Co-authored-by: gustavo-grieco <[email protected]>
2026-09-10 15:33:57 +02:00
Emilio López 0ea96cb952 Sequence generation fixes (#1620) 2026-09-04 22:32:41 +02:00
dependabot[bot] cff8760d4b build(deps): bump the gh-actions group with 2 updates (#1611)
Bumps the gh-actions group with 2 updates: [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) and [cachix/install-nix-action](https://github.com/cachix/install-nix-action).


Updates `docker/setup-buildx-action` from 4.2.0 to 4.3.0
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/bb05f3f5519dd87d3ba754cc423b652a5edd6d2c...37fe631027851001ddb9b187196cc803df7f5f0e)

Updates `cachix/install-nix-action` from 31.11.0 to 31.11.1
- [Release notes](https://github.com/cachix/install-nix-action/releases)
- [Changelog](https://github.com/cachix/install-nix-action/blob/master/RELEASE.md)
- [Commits](https://github.com/cachix/install-nix-action/compare/630ae543ea3a38a9a4166f03376c02c50f408342...13d8dd58da0234aa297dedd986986ccb8e7f3e24)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  dependency-version: 4.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gh-actions
- dependency-name: cachix/install-nix-action
  dependency-version: 31.11.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gh-actions
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-01 15:39:42 -03:00
Emilio López e53ab731e2 fix: deflake values/rconstants.sol test (#1613)
Slither classifies seed() as a constant function (no state reads or
writes), so Echidna demotes it to the low-priority signature map, which
genTx samples with probability 1/1001. The test can only be solved by
harvesting seed()'s return value (1337 + 13337) into the dictionary and
then generating find(14674), so a campaign capped at 10000 transactions
failed whenever the RNG drew seed() too late or never (~0.8% of runs).

Add a dummy state write to seed() so it stays in the high-priority map
and is sampled like any other function. The value 14674 still exists
only as a runtime return value, so the test still exercises return
value harvesting. Modeled failure rate drops from ~1/120 to ~1/90000.

Same workaround precedent: values/contract.sol ("writes state to make
it non-pure and more likely for echidna to call").
2026-09-01 15:29:58 -03:00
Emilio Lópezandgustavo-grieco 620fcdb414 Inter-worker message bus and per-function call sampling (#1604)
* feat: sample per-function call statistics

A worker can now be asked to watch a handful of functions and keep, for
each of them, how often it was called, how often the call did not return
successfully, the range its return value spanned, and a short tail of
revert summaries. This is what an outside observer needs to answer "is
this function reachable, and what does it do when it is" without reading
the corpus.

The state hangs off WorkerState.sampledFunctions, keyed by canonical
signature. Nothing populates that map yet -- the command that enables
sampling arrives with the inter-worker bus -- so callseq's cost is a
Map.null check per sequence, and the per-call work only happens for
functions someone asked about.

The interesting part is the per-event algebra, so it is factored out of
the worker: applySampleEvent folds one call result into a SampleStats,
abiCompare gives the partial ordering the range tracking needs, and
mergeSampleStats combines two workers' views. All three are pure and
covered by Tests.Sample; updateSampleStats in Worker/Sequence.hs is left
with just the decode-and-dispatch.

Every SampleStats field is strict, and the revert list is built with a
take that forces its spine and elements. These are updated on the fuzzing
hot path and only read when a client asks, so a lazy field would quietly
retain the entire call history: a plain `take n (new : old)` keeps `old`
alive through its unevaluated tail, and `old` keeps the one before it.

Co-authored-by: gustavo-grieco <[email protected]>

* feat: add an inter-worker message bus

Workers have so far been able to communicate in exactly one direction:
each pushes events onto the campaign's event queue, which the UI and the
listener read. Nothing can talk back to a running worker, and a worker
cannot tell another one what it just learned.

Add a bus to Env alongside the event queue: a broadcast STM channel, so
readers take their own dupTChan of it and every reader sees every
message rather than racing for it. Echidna.Types.InterWorker holds the
protocol -- a message, its sender, and the commands a fuzzing worker
accepts.

Two things use it. callseq broadcasts NewCoverageInfo whenever a
sequence finds coverage, carrying the sequence and whether it came from
replaying the corpus, which is the new argument threaded through
callseq's callers. And a fuzzing worker checks the bus once per loop
iteration for commands addressed to it, which is how sampling gets
turned on and off.

The two commands land here rather than with a sender because they are
what makes the bus worth having; the client that issues them, and the
listener for NewCoverageInfo, arrive with the MCP server. Everything
else in the upstream protocol -- symbolic commands, request/response,
the other broadcasts -- has neither a sender nor a reader, so it is left
out until it has both.

The command handler lives in its own module rather than in another
where-block inside runFuzzWorker, which is the shape the preceding
decomposition was aiming for and the natural home for the handlers that
follow.

Two details worth calling out:

checkMessages drains its queue rather than taking one message per
iteration. Every broadcast is copied to every worker's duplicate, so
with N workers finding coverage a worker receives roughly N messages per
iteration; consuming one would let the queue grow without bound during
the early phase of a campaign, when almost every sequence is new
coverage. Commands come from outside the campaign at human pace, so
there is nothing to starve fuzzing with.

The broadcast's sender is resolved through workerIDToType, the same way
pushWorkerEvent decides which worker type to attribute an event to. The
symbolic worker calls callseq too, and it is not a fuzzer.

Co-authored-by: gustavo-grieco <[email protected]>

---------

Co-authored-by: gustavo-grieco <[email protected]>
2026-08-31 12:29:51 +02:00
DefiAudit 3521b37a88 test(coverage): make boolean corpus count deterministic (#1610) 2026-08-27 15:12:52 +02:00
Emilio López c195ffe97c Use broadcast TChan for campaign events (#1576)
* Revert "Drain campaign event queue to fix root-cursor memory leak (#1587)"

This reverts commit 58d7fc5860.

* Use broadcast TChan for campaign events

Replace the campaign event queue with an STM broadcast TChan so subscribers
keep the existing events-after-subscribe behavior without the Chan root
cursor retention issue. Producers now write through STM, and campaign/UI/SSE
listeners subscribe with dupTChan/readTChan.

Avoid retaining full VM snapshots in queued TestFalsified/TestOptimized
events by publishing VM-free EchidnaTest copies. The canonical testRefs
state still keeps the VM so shrinking, reports, traces, and final JSON
continue to work.
2026-08-25 08:19:23 +02:00
Emilio López a2c0a92a6f Library auto-linking support through crytic-compile (#1389) 2026-08-24 23:11:26 +02:00
Emilio Lópezandgustavo-grieco 3e02a8af92 refactor: replace runWorker dispatch with an Agent sum type (#1603)
* refactor: replace runWorker dispatch with an Agent typeclass

runWorker dispatched on WorkerType and threaded eight positional
arguments down to runFuzzWorker/runSymWorker, so every caller had to
supply arguments the other worker discards: testLimit for the symbolic
worker, the selected contract name for the fuzzer.

Replace it with Echidna.Types.Agent:

  class Agent a where
    runAgent :: a -> Env -> IO WorkerStopReason

FuzzerAgent and SymbolicAgent each carry exactly the parameters their
worker needs plus the IORef WorkerState they publish through, and
Echidna.Campaign shrinks to isSuccessful.

runAgent returns the stop reason rather than pushing a WorkerStopped
event: an agent killed by the campaign timeout never reaches its own
last line, so only spawnWorker knows the real reason, and it has to
emit that event exactly once per worker -- listeners count those events
to decide when the campaign is over.

Two details come along with the move:

The agents announce themselves through the generic Log event, so
"Starting FuzzerAgent N" shows up in the same stream as the rest of the
worker output.

runAgent publishes the final worker state to stateRef before returning.
The callback publishes as the worker goes but not from every exit path
-- verification mode never runs it -- and src/test/Common.hs now reads
the state back from that ref instead of from runWorker's return value,
so the ref has to be authoritative.

Co-authored-by: gustavo-grieco <[email protected]>

* refactor: retire Echidna.Campaign, move isSuccessful to Types.Test

With runWorker gone, Echidna.Campaign held a single pure predicate over a
list of tests and had a single caller. The name no longer described the
contents: nothing about a campaign was left in it.

Echidna.Types.Test already collects the EchidnaTest state predicates --
isOpen, isPassed, isVerified, didFail, isConclusiveFailure,
needsShrinking -- and isSuccessful is the same kind of thing, one level
up on a list. It needs no import that module does not already have, so
move it there and drop Echidna.Campaign.

Echidna.Test.State was the other candidate and is the wrong fit: it is
about reading and updating Env.testRefs in a monad, while isSuccessful
is pure and takes the list directly.

The function is moved verbatim. It does not treat Unsolvable as a
success, so a fully verified run exits non-zero; that is a separate
behaviour change and gets its own commit.

Co-authored-by: gustavo-grieco <[email protected]>

* fix: count verified tests as a success in the exit code

In verification mode a run where every test was formally verified still
exited 1. isSuccessful accepted only Passed and Open, and Unsolvable --
the state symbolic execution sets once it proves an assertion cannot be
reached -- fell through to False. The better verification did, the more
likely the run was to "fail": a test that could not be verified stays
Open and counted as a success, while one that was verified did not.

Every other consumer of the state already treats Unsolvable as a
success: ppTS prints "verified", tsWidget shows VERIFIED!, and the JSON
encoder maps it to Verified. Only the exit code disagreed, which made it
useless for gating CI on a verification run.

Say it with the sibling predicates it now sits next to, so the three
accepted states are visible in one line.

Fixes #1602

* refactor: make Agent a sum type instead of a typeclass

The class had two instances and nothing ever abstracted over it: both
call sites matched on WorkerType and then named a concrete instance, so
it bought a shared method name and no polymorphism.

A closed set of two worker kinds with per-kind behaviour at several
sites is what a sum type is for. Echidna.Types.Agent now holds one
Agent with a constructor per worker, and Echidna.Agent holds runAgent,
sitting above both worker modules exactly where runWorker used to.

That is the real shape of the original problem: runWorker took a tag
plus the union of both workers' parameters. The fix was never a class,
it was a sum of records, one per worker, each carrying only its own
arguments.

Falls out of it:

WorkerType is now derived from the agent via workerTypeOf rather than
carried alongside it, so spawnWorker picks the constructor once and
everything else follows.

The corpus split moves into that choice. "if workerType ==
SymbolicWorker then initialCorpus else corpusChunk" is gone; each
constructor is simply built with the corpus its worker wants.

Adding a third worker kind is now a compile error at every site that
has to care, which the class would not have given us.

* refactor: stop passing the symbolic worker a corpus it discards

runSymWorker has bound its initialCorpus parameter to _ since #1394
(c2671049), which removed the "void $ replayCorpus vm initialCorpus"
call but left the parameter and every caller feeding it. replayCorpus
now has exactly one caller, in Worker/Fuzz.hs.

So the argument was threaded from UI.hs, through the agent, into a
function that dropped it. Worse, UI.hs had a branch specifically to hand
the symbolic worker the *whole* corpus instead of a chunk, and a comment
claiming "the symbolic worker always replays the full corpus", which has
not been true for a year.

Drop the parameter, the SymbolicAgent field, and the special case, and
correct the comment. Behaviour cannot change: the value was already
being discarded.

This also restores the premise of the Agent constructors, that each one
carries only what its own worker needs.

---------

Co-authored-by: gustavo-grieco <[email protected]>
2026-08-14 15:36:23 -03:00
Emilio Lópezandgustavo-grieco d87e720342 Small standalone fixes: coverage attribution, generic log events (#1599)
* feat: name the function that found new coverage

ppWorkerEvent already receives the transaction sequence behind a
NewCoverage event but only reported the aggregate counters. Append the
last transaction's call to the log line so it is visible which function
is making progress.

Co-authored-by: gustavo-grieco <[email protected]>

* feat: add generic log events

Add a WorkerEvent Log constructor for free-form worker messages and a
CampaignEvent ServerLog for messages that are not attributable to any
worker, reported with a [Server] prefix in the text UI and as a
server_log SSE event.

All four exhaustive matches over these types (the ToJSON instances, the
pretty printers and the SSE event names) land together so the compiler
stays happy.

Co-authored-by: gustavo-grieco <[email protected]>

* fix(tests): return the flag from flags.sol set0/set1

Both functions are declared 'returns (bool)' but fall off the end, so
solc warns and they silently return false.

Co-authored-by: gustavo-grieco <[email protected]>

* chore: gitignore Python artifacts

Co-authored-by: gustavo-grieco <[email protected]>

* fix(worker): avoid hlint false positive on record-dot access

CI runs bare `hlint lib src`, which does not read echidna.cabal and so
does not know OverloadedRecordDot is on. It parsed `(last txs).call` as
function composition and flagged the parens as a redundant bracket.

Taking that suggestion would have broken the build: under
OverloadedRecordDot, `last txs.call` parses as `last (txs.call)`.

Bind the last transaction first so the expression needs no parens and
reads identically to hlint and to GHC.

---------

Co-authored-by: gustavo-grieco <[email protected]>
2026-08-14 19:54:20 +02:00
Gustavo GriecoandEmilio López 07282dac29 refactor: decompose campaign execution by worker (#1596)
* feat: add explicit verification test mode

* fix: respect sequence length in Foundry filtering

* test: use explicit verification mode for symbolic assertions

* refactor: decompose campaign execution

* refactor: narrow exports of decomposed campaign modules

* refactor: move listenerLoop to Echidna.Worker

listenerLoop is event-bus plumbing, not transaction execution: it reads
CampaignEvents off a Chan and counts WorkerStopped events. Echidna.Worker
already owns the write side of that bus (pushWorkerEvent,
pushCampaignEvent) and the worker accounting it depends on (getNWorkers,
workerIDToType), so the reader belongs there too.

This also drops Echidna.Execution from Campaign's imports, and narrows
Agent.Symbolic's dependency on Execution to the three call-sequence
functions it actually uses.

Pure move: the function body is unchanged.

* refactor: move MonadThrow (RandT) orphan to its own module

Both worker bodies run in RandT g (StateT WorkerState m) and call
callseq/replayCorpus, which carry a MonadThrow constraint, so they need
this instance. exceptions covers the standard transformers, but
MonadRandom's RandT is a newtype over StateT that derives nothing from
exceptions, so the instance is missing and we have to supply it.

It lived in Echidna.Execution, which has no use for it: that module only
mentions MonadThrow as a polymorphic constraint and compiles fine without
the instance. Meanwhile the two modules that do need it never named it --
they resolved it transitively through their Echidna.Execution import, and
-fno-warn-orphans kept GHC quiet about the arrangement. Narrowing or
dropping that import would have produced a "Could not deduce MonadThrow
(RandT ...)" error pointing at callseq, far from the cause.

Echidna.Orphans.Rand now holds it, alongside Echidna.Orphans.JSON, and
Agent.Fuzzer and Agent.Symbolic import it explicitly so the dependency is
visible where it is relied upon. Named for the type rather than the class,
following the same rule as Orphans.JSON: name the axis that stays fixed
while the other varies. JSON fixes the class family and accumulates types;
this module fixes RandT and would accumulate classes (MonadCatch or
MonadMask, should a worker ever need bracket).

Verified by deleting the instance outright: the only two failures were
Agent/Fuzzer.hs (replayCorpus) and Agent/Symbolic.hs (callseq).

* refactor: extract worker-agnostic test-set ops into Echidna.Test.State

updateTests and findFailedTests both declared MonadState WorkerState but
never touched it -- they only read Env.testRefs. Move them to a module that
says so, dropping the vestigial constraint.

updateOpenTest stays private next to its only caller evalSeq: it is genuinely
worker-scoped (stamps test.workerId, emits worker events).

Also replaces the symbolic worker's two inline "mark the assertion test for
this method signature" blocks with setAssertionTestState, which skips the
IORef write for non-matching tests instead of rewriting them unchanged.

* refactor: move the worker modules under Echidna.Worker

Echidna.Execution sat next to Echidna.Exec with a name that did not
distinguish them. Its remaining contents are worker-scoped call-sequence
machinery, so they move to Echidna.Worker.Sequence, alongside the two worker
strategies -- which also drop the "Agent" spelling for the "Worker" vocabulary
the rest of the codebase uses.

  Echidna.Execution      -> Echidna.Worker.Sequence
  Echidna.Agent.Fuzzer   -> Echidna.Worker.Fuzz
  Echidna.Agent.Symbolic -> Echidna.Worker.Symbolic

* refactor: put spawnListener next to listenerLoop, share the shrink loop

spawnListener was in Echidna.Campaign calling listenerLoop in Echidna.Worker;
they are one mechanism, so both now live in Echidna.Worker. Echidna.Campaign is
left as what it is: the worker dispatcher. It has to stay above Worker.Fuzz and
Worker.Symbolic -- folding runWorker into Echidna.Worker would cycle, since both
workers import it for pushWorkerEvent.

The two workers also had byte-identical copies of "shrink the tests this worker
falsified", which is now Echidna.Shrink.shrinkWorkerTests.

* refactor: reuse initialWorkerState, name the stopOnFail predicate

Both workers hand-rolled the WorkerState record that Echidna.Types.Campaign
already provides as initialWorkerState, and both carried an identical local
'final' predicate whose name did not explain why a falsified test still being
shrunk (Large) must not trip stopOnFail. That is now isConclusiveFailure,
next to the other test-state predicates.

* refactor: share one shrinkable predicate between the workers

The two workers disagreed: the fuzzer bounded shrinking with n < shrinkLimit,
the symbolic worker returned True for any Large test on this worker. Only the
fuzzer's version is safe on its own terms. shrinkTest never moves an
optimization test to Solved -- it keeps reporting Large (i + 1) -- so without
the bound a loop over shrinkable tests cannot terminate. The symbolic worker
gets away with it because its shrink branch of shrinkAndRandomlyExplore
recurses on the same n and would spin, but an optimization test never carries
the symbolic worker's id: updateOpenTest only stamps workerId on BoolValue
False, and optimization tests get theirs from the fuzzer's
closeOptimizationTest.

So the two predicates agree on every reachable state today, and the bounded
one is strictly more conservative. Sharing it as Echidna.Shrink.isShrinkable
keeps the divergence from silently reappearing now that the workers live in
separate modules.

---------

Co-authored-by: Emilio López <[email protected]>
2026-08-14 13:02:21 -03:00
dependabot[bot]andEmilio López 3afcb8b795 build(deps): bump haskell-actions/setup from 2.11.0 to 2.12.0 in the gh-actions group (#1598)
* build(deps): bump haskell-actions/setup in the gh-actions group

Bumps the gh-actions group with 1 update: [haskell-actions/setup](https://github.com/haskell-actions/setup).


Updates `haskell-actions/setup` from 2.11.0 to 2.12.0
- [Release notes](https://github.com/haskell-actions/setup/releases)
- [Commits](https://github.com/haskell-actions/setup/compare/cd0d9bdd65b20557f41bea4dbe43d0b5fbbfe553...6037f33647c3f17758a2356c80fc4a53d7e0685d)

---
updated-dependencies:
- dependency-name: haskell-actions/setup
  dependency-version: 2.12.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gh-actions
...

Signed-off-by: dependabot[bot] <[email protected]>

* Update version comment tag

---------

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Emilio López <[email protected]>
2026-08-12 19:56:51 -03:00
Gustavo GriecoandClaude Opus 5 2bfa64ef6c fix: handle verification and Foundry campaign modes (#1595)
* feat: add explicit verification test mode

* fix: respect sequence length in Foundry filtering

* test: use explicit verification mode for symbolic assertions

* foundry fixes

* test: add missing testFail regression test files

The contract and config used by the "foundry/TestFail.sol" test case were
left out of the previous commit, making the test fail on CI with a missing
config file.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01GWXznupnma5sEUJ7NrLDvi

* fix: fuzz check and prove functions in Foundry mode

"check" and "prove" functions are symbolic entry points, but a Foundry mode
campaign is a fuzzing campaign: symbolic execution is only used when it is
enabled, so these functions must be fuzzed like any other test function.

Before this, a stateless Foundry campaign (seqLen == 1) would neither call
nor check them, silently testing nothing for contracts whose properties all
use those prefixes.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01GWXznupnma5sEUJ7NrLDvi

* test: cover stateful and reverting check/prove functions

The stateless case was the only one covered: add a stateful campaign, where
parameterless "check" and "prove" functions are checked after each
transaction, and a "check" function that reverts, which is a failure like it
is for any other test function.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01GWXznupnma5sEUJ7NrLDvi

---------

Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
2026-08-11 23:24:34 +02:00
Emilio López 5fd668155c Merge pull request #1597 from crytic/dependabot/github_actions/gh-actions-e57353e2b8
build(deps): bump the gh-actions group across 1 directory with 5 updates
2026-08-10 16:33:00 -03:00
dependabot[bot] c0eff0589c build(deps): bump the gh-actions group across 1 directory with 5 updates
Bumps the gh-actions group with 5 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [actions/checkout](https://github.com/actions/checkout) | `7.0.0` | `7.0.1` |
| [actions/setup-python](https://github.com/actions/setup-python) | `6.3.0` | `7.0.0` |
| [foundry-rs/foundry-toolchain](https://github.com/foundry-rs/foundry-toolchain) | `1.9.0` | `1.9.1` |
| [docker/login-action](https://github.com/docker/login-action) | `4.4.0` | `4.6.0` |
| [sigstore/gh-action-sigstore-python](https://github.com/sigstore/gh-action-sigstore-python) | `3.4.0` | `3.5.0` |



Updates `actions/checkout` from 7.0.0 to 7.0.1
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0...3d3c42e5aac5ba805825da76410c181273ba90b1)

Updates `actions/setup-python` from 6.3.0 to 7.0.0
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/ece7cb06caefa5fff74198d8649806c4678c61a1...5fda3b95a4ea91299a34e894583c3862153e4b97)

Updates `foundry-rs/foundry-toolchain` from 1.9.0 to 1.9.1
- [Release notes](https://github.com/foundry-rs/foundry-toolchain/releases)
- [Changelog](https://github.com/foundry-rs/foundry-toolchain/blob/master/RELEASE.md)
- [Commits](https://github.com/foundry-rs/foundry-toolchain/compare/b00af27efadbc7b4ca8b82abbd903b17cc874d2a...908c540300062bd5a7e473851cdb4282204cee09)

Updates `docker/login-action` from 4.4.0 to 4.6.0
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/af1e73f918a031802d376d3c8bbc3fe56130a9b0...dbcb813823bdd20940b903addbd779551569679f)

Updates `sigstore/gh-action-sigstore-python` from 3.4.0 to 3.5.0
- [Release notes](https://github.com/sigstore/gh-action-sigstore-python/releases)
- [Changelog](https://github.com/sigstore/gh-action-sigstore-python/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sigstore/gh-action-sigstore-python/compare/5b79a39c381910c090341a2c9b0bf022c8b387e1...790bc6befb9d733738f18d8f895854b453640ec9)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gh-actions
- dependency-name: actions/setup-python
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: gh-actions
- dependency-name: foundry-rs/foundry-toolchain
  dependency-version: 1.9.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gh-actions
- dependency-name: docker/login-action
  dependency-version: 4.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gh-actions
- dependency-name: sigstore/gh-action-sigstore-python
  dependency-version: 3.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gh-actions
...

Signed-off-by: dependabot[bot] <[email protected]>
2026-08-05 21:35:31 +00:00
Emilio López 4454f3a337 Merge pull request #1591 from crytic/release-2.3.3
Echidna 2.3.3
v2.3.3
2026-07-24 14:44:13 -03:00
dependabot[bot]andEmilio López 355f1bbb96 build(deps): bump the gh-actions group across 1 directory with 9 updates (#1589)
* build(deps): bump the gh-actions group across 1 directory with 9 updates

Bumps the gh-actions group with 9 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [actions/cache](https://github.com/actions/cache) | `5.0.5` | `6.1.0` |
| [actions/setup-python](https://github.com/actions/setup-python) | `6.2.0` | `6.3.0` |
| [foundry-rs/foundry-toolchain](https://github.com/foundry-rs/foundry-toolchain) | `1.8.0` | `1.9.0` |
| [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) | `4.1.0` | `4.2.0` |
| [docker/metadata-action](https://github.com/docker/metadata-action) | `6.1.0` | `6.2.0` |
| [docker/login-action](https://github.com/docker/login-action) | `4.2.0` | `4.4.0` |
| [docker/build-push-action](https://github.com/docker/build-push-action) | `7.2.0` | `7.3.0` |
| [cachix/install-nix-action](https://github.com/cachix/install-nix-action) | `31.10.6` | `31.11.0` |
| [softprops/action-gh-release](https://github.com/softprops/action-gh-release) | `3.0.0` | `3.0.2` |



Updates `actions/cache` from 5.0.5 to 6.1.0
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/27d5ce7f107fe9357f9df03efb73ab90386fccae...55cc8345863c7cc4c66a329aec7e433d2d1c52a9)

Updates `actions/setup-python` from 6.2.0 to 6.3.0
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/a309ff8b426b58ec0e2a45f0f869d46889d02405...ece7cb06caefa5fff74198d8649806c4678c61a1)

Updates `foundry-rs/foundry-toolchain` from 1.8.0 to 1.9.0
- [Release notes](https://github.com/foundry-rs/foundry-toolchain/releases)
- [Changelog](https://github.com/foundry-rs/foundry-toolchain/blob/master/RELEASE.md)
- [Commits](https://github.com/foundry-rs/foundry-toolchain/compare/c7450ba673e133f5ee30098b3b54f444d3a2ca2d...b00af27efadbc7b4ca8b82abbd903b17cc874d2a)

Updates `docker/setup-buildx-action` from 4.1.0 to 4.2.0
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5...bb05f3f5519dd87d3ba754cc423b652a5edd6d2c)

Updates `docker/metadata-action` from 6.1.0 to 6.2.0
- [Release notes](https://github.com/docker/metadata-action/releases)
- [Commits](https://github.com/docker/metadata-action/compare/80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9...dc802804100637a589fabce1cb79ff13a1411302)

Updates `docker/login-action` from 4.2.0 to 4.4.0
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/650006c6eb7dba73a995cc03b0b2d7f5ca915bee...af1e73f918a031802d376d3c8bbc3fe56130a9b0)

Updates `docker/build-push-action` from 7.2.0 to 7.3.0
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/f9f3042f7e2789586610d6e8b85c8f03e5195baf...53b7df96c91f9c12dcc8a07bcb9ccacbed38856a)

Updates `cachix/install-nix-action` from 31.10.6 to 31.11.0
- [Release notes](https://github.com/cachix/install-nix-action/releases)
- [Changelog](https://github.com/cachix/install-nix-action/blob/master/RELEASE.md)
- [Commits](https://github.com/cachix/install-nix-action/compare/8aa03977d8d733052d78f4e008a241fd1dbf36b3...630ae543ea3a38a9a4166f03376c02c50f408342)

Updates `softprops/action-gh-release` from 3.0.0 to 3.0.2
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](https://github.com/softprops/action-gh-release/compare/b4309332981a82ec1c5618f44dd2e27cc8bfbfda...3d0d9888cb7fd7b750713d6e236d1fcb99157228)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-version: 6.1.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: gh-actions
- dependency-name: actions/setup-python
  dependency-version: 6.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gh-actions
- dependency-name: foundry-rs/foundry-toolchain
  dependency-version: 1.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gh-actions
- dependency-name: docker/setup-buildx-action
  dependency-version: 4.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gh-actions
- dependency-name: docker/metadata-action
  dependency-version: 6.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gh-actions
- dependency-name: docker/login-action
  dependency-version: 4.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gh-actions
- dependency-name: docker/build-push-action
  dependency-version: 7.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gh-actions
- dependency-name: cachix/install-nix-action
  dependency-version: 31.11.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gh-actions
- dependency-name: softprops/action-gh-release
  dependency-version: 3.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gh-actions
...

Signed-off-by: dependabot[bot] <[email protected]>

* Adjust version tags in comments

Co-authored-by: Emilio López <[email protected]>

---------

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Emilio López <[email protected]>
2026-07-24 13:24:19 -03:00
gustavo-griecoandClaude Fable 5 07ad0e75eb Update hevm to 4ca42fd (0.58.0)
Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-24 15:42:45 +02:00
gustavo-griecoandClaude Fable 5 9694c2a121 Echidna 2.3.3
Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-24 15:42:45 +02:00
Emilio López 1e1d7a2e2b Bump tls to 2.2.2 in flake and stack (#1581)
* Bump tls to 2.2.2 in flake and stack

tls < 2.2.2 is affected by https://github.com/haskell-tls/hs-tls/pull/515.

tls 2.2.2 needs the crypton-x509 1.8 line, which still builds against
crypton 1.0.x (the 1.9 line would force crypton >= 1.1 and a much wider
cascade). No crypton-connection release targets tls 2.2 (0.4.5 caps < 2.2,
0.4.6 needs >= 2.3), so its tls < 2.2 bound is relaxed, along with
warp-tls and tls-session-manager (pulled in by Hoogle in the dev shell);
all compile fine against 2.2.2.

In flake.nix the codegen cabal2nix is pinned to the un-overridden base
set, otherwise regenerating tls via callHackageDirect loops (cabal2nix
transitively depends on tls). stack.yaml additionally pins the
crypton-asn1-*/crypton-pem/time-hourglass/hpke/ech-config packages that
lts-23.24 lacks; nixpkgs-unstable already carries compatible versions.

* Add crypton-socks-0.6.2 extra-dep for stack

crypton-connection 0.4.5 needs crypton-socks >= 0.6, which lts-23.24 does
not provide. Matches the version the flake already resolves.
2026-07-24 15:41:49 +02:00
Gustavo GriecoandClaude Fable 5 f583f214b6 Allow to disable testing of view/pure function, except prefix ones in property mode (#1552)
* allow to disable testing of view/pure function, except prefix ones in property mode

* removed unused import

* test/config: fix remaining CI failures for excludeViewPure

- default.yaml: add excludeViewPure (the config test requires every option be
  listed; it was failing with 'unset options: fromList ["excludeViewPure"]')
- Tests/Integration: pin basic/excludeviewpure.sol to solc >= 0.8.0 (pragma
  ^0.8.0), so it is skipped on the <0.8 solc CI matrix instead of failing to
  compile.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>

* test: prove view/pure functions are excluded, using notPresent

Addresses review feedback: excludeviewpure.sol gains a view function with
a planted assert(false), and a new assertion-mode run checks that no
assertion test is created for any view/pure function (via the previously
unused notPresent helper), so the planted assert can never fire. A control
run without excludeViewPure proves the assert IS found otherwise and pins
the test names the notPresent checks look up.

Co-Authored-By: Claude Fable 5 <[email protected]>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
2026-07-20 21:12:53 +02:00
Emilio López 58d7fc5860 Drain campaign event queue to fix root-cursor memory leak (#1587)
Every consumer reads campaign events from its own dupChan, so the
original Chan's read end is never advanced and pins every event ever
written, keeping the whole campaign's event history (including full VM
snapshots) alive. Drain the original queue from a dedicated thread so
the GC can reclaim delivered events, and publish VM-free, strictly
forced copies of falsified/optimized tests so queued events can't
retain a VM through a lazy thunk.
2026-07-20 09:38:01 +02:00
Emilio López 9680bb1ef8 Fix divide-by-zero distributing corpus with workers: 0 (#1583)
The corpus distribution introduced in 92b90d4a uses integer divMod by
nFuzzWorkers, which throws on workers: 0 (symbolic-only mode, where the
sym worker is the only worker and forces the corpus chunks). Guard the
nFuzzWorkers == 0 case explicitly: there are no fuzz workers to
distribute to, and the symbolic worker replays the full corpus anyway.
2026-07-11 16:23:13 +02:00
Samy a23d1d993d Reject precompile deployment addresses (#1585) 2026-07-05 20:14:42 +02:00
dependabot[bot]andEmilio López 74274d420b build(deps): bump the gh-actions group across 1 directory with 3 updates (#1582)
* build(deps): bump the gh-actions group across 1 directory with 3 updates

Bumps the gh-actions group with 3 updates in the / directory: [actions/checkout](https://github.com/actions/checkout), [msys2/setup-msys2](https://github.com/msys2/setup-msys2) and [sigstore/gh-action-sigstore-python](https://github.com/sigstore/gh-action-sigstore-python).


Updates `actions/checkout` from 6.0.2 to 7.0.0
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/de0fac2e4500dabe0009e67214ff5f5447ce83dd...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0)

Updates `msys2/setup-msys2` from 2.31.1 to 2.32.0
- [Release notes](https://github.com/msys2/setup-msys2/releases)
- [Changelog](https://github.com/msys2/setup-msys2/blob/main/CHANGELOG.md)
- [Commits](https://github.com/msys2/setup-msys2/compare/e9898307ac31d1a803454791be09ab9973336e1c...66cd2cce69caa17b53920067426061ca1de3a884)

Updates `sigstore/gh-action-sigstore-python` from 3.3.0 to 3.4.0
- [Release notes](https://github.com/sigstore/gh-action-sigstore-python/releases)
- [Changelog](https://github.com/sigstore/gh-action-sigstore-python/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sigstore/gh-action-sigstore-python/compare/04cffa1d795717b140764e8b640de88853c92acc...5b79a39c381910c090341a2c9b0bf022c8b387e1)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: gh-actions
- dependency-name: msys2/setup-msys2
  dependency-version: 2.32.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gh-actions
- dependency-name: sigstore/gh-action-sigstore-python
  dependency-version: 3.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gh-actions
...

Signed-off-by: dependabot[bot] <[email protected]>

* Fix version number comments

Co-authored-by: Emilio López <[email protected]>

---------

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Emilio López <[email protected]>
2026-06-25 11:26:22 -03:00
Emilio Lópezandgustavo-grieco 636ef293f9 Update hevm to support dynamic argument inputs in symbolic mode (#1580)
* Fix suitableForSymExec precedence inversion

`not $ null m.inputs && ...` parsed as `not (null m.inputs && ...)`,
negating the whole conjunction: the dynamic-argument guard never fired
(so bytes/string/dynamic-array methods were handed to the symbolic
encoder, which throws).
Bind `not` to the emptiness check alone so the filter means what it
says: explore methods that have arguments, none dynamic, not opted out.

* updated to new hevm

* dynamic array handling

* Update hevm in flake.nix

---------

Co-authored-by: gustavo-grieco <[email protected]>
2026-06-25 16:23:22 +02:00
Emilio LópezandClaude 6d856e07fd Fix unbounded thunk accumulation in GenDict constants update (#1577)
Every call sequence updates the constants dictionary with the lazy
Data.Map's `unionWith Set.union`, which allocates a suspended
`Set.union old new` per colliding key. Such a suspension is only forced
when the generator samples that key's AbiType (genWithDict), and only
the argument types of fuzzed functions are ever sampled. Since callseq
unconditionally inserts an AbiAddressType entry into the additions map
(even when no contract was created), any target ABI without an
`address`-typed parameter accumulates a never-forced chain of union
thunks: one per call sequence per worker, for the campaign lifetime.

On a minimal one-function contract this leaks ~0.4 B/call (~31 kB/s at
~75k calls/s), 100% of live-heap growth: the heap census shows a
single monotonically growing THUNK band, info-table profiling points at
the Map.unionWith specialization's collision branch, and retainer
profiling roots it at callseq's WorkerState.genDict. Note this is
distinct from the dictionary's known value growth -- it happens even
when no new constants are harvested at all.

Use Data.Map.Strict.unionWith so per-key sets are forced as they are
unioned. Measured on the reproducer: live-heap slope drops from
~31,010 B/s to ~3 B/s over 93M calls, with identical coverage and
corpus behavior.

Co-authored-by: Claude <[email protected]>
2026-06-16 22:02:38 +02:00
Emilio López 1b444b6c9b Update hevm to 8b2cb6266413f7f964e49053a278a895a21dc507 (#1575) 2026-06-06 11:20:52 +02:00
90d465955b Fix shrinking desync between reproducer and vm traces (#1554)
* Fix shrinking desync between reproducer and vm traces

* Root cause fix

* Proper fix by Emilio

* Add regression test for time-advance-on-revert

A reverting transaction must still advance the block clock; only EVM
state rolls back on a revert, not time. This test exercises that: f()
reverts at og+1 and asserts at og+2, so the assertion is reachable only
if the reverting step still advanced time. With maxTimeDelay=1 and
seqLen=2, the assert is solved iff the fix is present (found in 15/15
seeds at testLimit 500 with the fix, 0/5 at testLimit 10000 without it).

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>

* removed txDelay variable

---------

Co-authored-by: gustavo-grieco <[email protected]>
Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-04 16:33:38 +02:00
Gustavo GriecoandEmilio López 9fb9fe06d7 Allow foundry unit test generation to handle assertion failure with events (#1550)
* allow foundry unit test generation to handle assertion failure with events

* fix

---------

Co-authored-by: Emilio López <[email protected]>
2026-06-04 08:41:48 +02:00
Gustavo Grieco a48b303746 make sure failure reason is consistent across outputs (#1572) 2026-06-04 08:40:55 +02:00
dependabot[bot] 7b500f45e5 build(deps): bump the gh-actions group across 1 directory with 7 updates (#1574)
Bumps the gh-actions group with 7 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [foundry-rs/foundry-toolchain](https://github.com/foundry-rs/foundry-toolchain) | `1.7.0` | `1.8.0` |
| [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) | `4.0.0` | `4.1.0` |
| [docker/metadata-action](https://github.com/docker/metadata-action) | `6.0.0` | `6.1.0` |
| [docker/login-action](https://github.com/docker/login-action) | `4.1.0` | `4.2.0` |
| [docker/build-push-action](https://github.com/docker/build-push-action) | `7.1.0` | `7.2.0` |
| [cachix/install-nix-action](https://github.com/cachix/install-nix-action) | `31.10.5` | `31.10.6` |
| [cachix/cachix-action](https://github.com/cachix/cachix-action) | `1eb2ef646ac0255473d23a5907ad7b04ce94065c` | `5f2d7c5294214f71b873db4b969586b980625e71` |



Updates `foundry-rs/foundry-toolchain` from 1.7.0 to 1.8.0
- [Release notes](https://github.com/foundry-rs/foundry-toolchain/releases)
- [Changelog](https://github.com/foundry-rs/foundry-toolchain/blob/master/RELEASE.md)
- [Commits](https://github.com/foundry-rs/foundry-toolchain/compare/8789b3e21e6c11b2697f5eb56eddae542f746c10...c7450ba673e133f5ee30098b3b54f444d3a2ca2d)

Updates `docker/setup-buildx-action` from 4.0.0 to 4.1.0
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd...d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5)

Updates `docker/metadata-action` from 6.0.0 to 6.1.0
- [Release notes](https://github.com/docker/metadata-action/releases)
- [Commits](https://github.com/docker/metadata-action/compare/030e881283bb7a6894de51c315a6bfe6a94e05cf...80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9)

Updates `docker/login-action` from 4.1.0 to 4.2.0
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/4907a6ddec9925e35a0a9e82d7399ccc52663121...650006c6eb7dba73a995cc03b0b2d7f5ca915bee)

Updates `docker/build-push-action` from 7.1.0 to 7.2.0
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/bcafcacb16a39f128d818304e6c9c0c18556b85f...f9f3042f7e2789586610d6e8b85c8f03e5195baf)

Updates `cachix/install-nix-action` from 31.10.5 to 31.10.6
- [Release notes](https://github.com/cachix/install-nix-action/releases)
- [Changelog](https://github.com/cachix/install-nix-action/blob/master/RELEASE.md)
- [Commits](https://github.com/cachix/install-nix-action/compare/ab739621df7a23f52766f9ccc97f38da6b7af14f...8aa03977d8d733052d78f4e008a241fd1dbf36b3)

Updates `cachix/cachix-action` from 1eb2ef646ac0255473d23a5907ad7b04ce94065c to 5f2d7c5294214f71b873db4b969586b980625e71
- [Release notes](https://github.com/cachix/cachix-action/releases)
- [Changelog](https://github.com/cachix/cachix-action/blob/master/RELEASE.md)
- [Commits](https://github.com/cachix/cachix-action/compare/1eb2ef646ac0255473d23a5907ad7b04ce94065c...5f2d7c5294214f71b873db4b969586b980625e71)

---
updated-dependencies:
- dependency-name: foundry-rs/foundry-toolchain
  dependency-version: 1.8.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gh-actions
- dependency-name: docker/setup-buildx-action
  dependency-version: 4.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gh-actions
- dependency-name: docker/metadata-action
  dependency-version: 6.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gh-actions
- dependency-name: docker/login-action
  dependency-version: 4.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gh-actions
- dependency-name: docker/build-push-action
  dependency-version: 7.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gh-actions
- dependency-name: cachix/install-nix-action
  dependency-version: 31.10.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gh-actions
- dependency-name: cachix/cachix-action
  dependency-version: 5f2d7c5294214f71b873db4b969586b980625e71
  dependency-type: direct:production
  dependency-group: gh-actions
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-03 17:07:01 +02:00
Emilio López 42f4b0a741 libff: fix header installation with CMake 4.3+ (#1573) 2026-06-03 16:04:04 +02:00
Gustavo Grieco 70160eecaf Disable ANSI escape codes when echidna output is not executed on TTY (#1567)
* disable ANSI escape codes when echidna output is not executed on TTY

* added missing dependency
2026-05-22 07:43:48 +02:00
Rappie 55e1303f10 Start event listener before workers 2026-04-30 18:24:46 -03:00
dependabot[bot] 4f0f364cfa build(deps): bump the gh-actions group across 1 directory with 10 updates
Bumps the gh-actions group with 10 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [msys2/setup-msys2](https://github.com/msys2/setup-msys2) | `2.31.0` | `2.31.1` |
| [haskell-actions/setup](https://github.com/haskell-actions/setup) | `2.10.3` | `2.11.0` |
| [actions/cache](https://github.com/actions/cache) | `5.0.4` | `5.0.5` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `7.0.0` | `7.0.1` |
| [docker/login-action](https://github.com/docker/login-action) | `4.0.0` | `4.1.0` |
| [docker/build-push-action](https://github.com/docker/build-push-action) | `7.0.0` | `7.1.0` |
| [cachix/install-nix-action](https://github.com/cachix/install-nix-action) | `31.10.2` | `31.10.5` |
| [DeterminateSystems/nix-installer-action](https://github.com/determinatesystems/nix-installer-action) | `21` | `22` |
| [sigstore/gh-action-sigstore-python](https://github.com/sigstore/gh-action-sigstore-python) | `3.2.0` | `3.3.0` |
| [softprops/action-gh-release](https://github.com/softprops/action-gh-release) | `2.6.1` | `3.0.0` |



Updates `msys2/setup-msys2` from 2.31.0 to 2.31.1
- [Release notes](https://github.com/msys2/setup-msys2/releases)
- [Changelog](https://github.com/msys2/setup-msys2/blob/main/CHANGELOG.md)
- [Commits](https://github.com/msys2/setup-msys2/compare/cafece8e6baf9247cf9b1bf95097b0b983cc558d...e9898307ac31d1a803454791be09ab9973336e1c)

Updates `haskell-actions/setup` from 2.10.3 to 2.11.0
- [Release notes](https://github.com/haskell-actions/setup/releases)
- [Commits](https://github.com/haskell-actions/setup/compare/f9150cb1d140e9a9271700670baa38991e6fa25c...cd0d9bdd65b20557f41bea4dbe43d0b5fbbfe553)

Updates `actions/cache` from 5.0.4 to 5.0.5
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/668228422ae6a00e4ad889ee87cd7109ec5666a7...27d5ce7f107fe9357f9df03efb73ab90386fccae)

Updates `actions/upload-artifact` from 7.0.0 to 7.0.1
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/bbbca2ddaa5d8feaa63e36b76fdaad77386f024f...043fb46d1a93c77aae656e7c1c64a875d1fc6a0a)

Updates `docker/login-action` from 4.0.0 to 4.1.0
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/b45d80f862d83dbcd57f89517bcf500b2ab88fb2...4907a6ddec9925e35a0a9e82d7399ccc52663121)

Updates `docker/build-push-action` from 7.0.0 to 7.1.0
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/d08e5c354a6adb9ed34480a06d141179aa583294...bcafcacb16a39f128d818304e6c9c0c18556b85f)

Updates `cachix/install-nix-action` from 31.10.2 to 31.10.5
- [Release notes](https://github.com/cachix/install-nix-action/releases)
- [Changelog](https://github.com/cachix/install-nix-action/blob/master/RELEASE.md)
- [Commits](https://github.com/cachix/install-nix-action/compare/51f3067b56fe8ae331890c77d4e454f6d60615ff...ab739621df7a23f52766f9ccc97f38da6b7af14f)

Updates `DeterminateSystems/nix-installer-action` from 21 to 22
- [Release notes](https://github.com/determinatesystems/nix-installer-action/releases)
- [Commits](https://github.com/determinatesystems/nix-installer-action/compare/c5a866b6ab867e88becbed4467b93592bce69f8a...ef8a148080ab6020fd15196c2084a2eea5ff2d25)

Updates `sigstore/gh-action-sigstore-python` from 3.2.0 to 3.3.0
- [Release notes](https://github.com/sigstore/gh-action-sigstore-python/releases)
- [Changelog](https://github.com/sigstore/gh-action-sigstore-python/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sigstore/gh-action-sigstore-python/compare/a5caf349bc536fbef3668a10ed7f5cd309a4b53d...04cffa1d795717b140764e8b640de88853c92acc)

Updates `softprops/action-gh-release` from 2.6.1 to 3.0.0
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](https://github.com/softprops/action-gh-release/compare/153bb8e04406b158c6c84fc1615b65b24149a1fe...b4309332981a82ec1c5618f44dd2e27cc8bfbfda)

---
updated-dependencies:
- dependency-name: msys2/setup-msys2
  dependency-version: 2.31.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gh-actions
- dependency-name: haskell-actions/setup
  dependency-version: 2.11.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gh-actions
- dependency-name: actions/cache
  dependency-version: 5.0.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gh-actions
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gh-actions
- dependency-name: docker/login-action
  dependency-version: 4.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gh-actions
- dependency-name: docker/build-push-action
  dependency-version: 7.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gh-actions
- dependency-name: cachix/install-nix-action
  dependency-version: 31.10.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gh-actions
- dependency-name: DeterminateSystems/nix-installer-action
  dependency-version: '22'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: gh-actions
- dependency-name: sigstore/gh-action-sigstore-python
  dependency-version: 3.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gh-actions
- dependency-name: softprops/action-gh-release
  dependency-version: 3.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: gh-actions
...

Signed-off-by: dependabot[bot] <[email protected]>
2026-04-30 18:22:38 -03:00
Rappie 92b90d4a0c Distribute replay corpus across all fuzz workers 2026-04-30 18:20:31 -03:00
Gustavo Grieco cdedbca838 Add giveth.io url as a custom field in FUNDING.json (#1553) 2026-04-06 18:45:29 +02:00
Gustavo Grieco 7cbb32f3ff Remove PropertyRepro.sol pragma v2.3.2 2026-03-27 10:36:59 -03:00
Emilio López e021daad4c Echidna 2.3.2 2026-03-27 10:05:57 -03:00