Skip to content

test: ✅ [Group] fuzz testing across contracts & API #2298

Description

@hermannleboss

Description

Is your feature request related to a problem?
Our tests are example-based: they assert that specific inputs produce specific outputs, so they
never explore the input space. Whole classes of bugs slip through — arithmetic/rounding edge cases
on-chain, and inputs that pass validation but crash a handler in the API.

Describe the solution you'd like
Introduce property-based / fuzz testing on both the on-chain and off-chain surfaces. Instead of
hard-coded cases we assert invariants that must hold for thousands of generated inputs, and let
the tools shrink any counterexample. Two surfaces, two approaches each — the fast/in-toolchain one
first, the deep/black-box one second:

Contracts (contract/, Hardhat + Solidity)

  • fast-check property tests inside the existing Hardhat/Mocha suite — quick, reuses fixtures.
  • Foundry (forge) invariant + testFuzz_* tests — native, coverage-guided, stateful invariants.

API (backend/, Express + zod + supertest)

  • fast-check + supertest in-process — the "never uncontrolled 5xx / auth always enforced / valid
    JSON" invariants, reusing the Prisma-mock harness.
  • Schemathesis driven by the generated OpenAPI spec — black-box contract conformance against the
    real stack.

Alternatives considered

  • Echidna / Medusa for contracts — heavier setup; deferred until Foundry invariants land.
  • zod-fast-check for API schemas — targets zod v3; we are on v4, so arbitraries are hand-written
    or endpoint-level.

Plan / sub-issues

Suggested order: land the two fast-check sub-issues first (quick wins in the existing suites), then
Foundry and Schemathesis as separate CI jobs.

Acceptance Criteria

  • All four sub-issues delivered.
  • Contract fuzz tests run in contract/'s test command / CI.
  • API fuzz tests run in backend/'s test command / CI.
  • The "no uncontrolled 5xx" and "auth always enforced" invariants are covered on the API side.
  • Each approach documents how to run it and how to reproduce a shrunk counterexample.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions