Hydrozoa is a lightweight multi-party state channel implementation for Cardano, written in Scala 3.
Hydrozoa is a multi-party state channel protocol that decouples execution from custody.
-
L2 state channel. A small set of head peers run a fast off-chain ledger, rapidly sequencing user transactions while the L1 holds the funds. The channel admits continuous deposits and withdrawals while open; if consensus stalls, a pre-signed dead-man's-switch transaction matures and shifts custody into a rules-based regime where every participant can individually evacuate against the last KZG-committed state.
-
Pluggable L2 ledger, EUTXO built in. Hydrozoa treats the L2 ledger as a black-box state machine. An EUTXO-based L2 ledger is provided out of the box (transactions are CBOR-serialized Cardano txs; outputs are either L2-bound or L1-bound via settlement / rollout effects), and application-specific ledgers can be slotted in — for example, Sugar Rush, a privacy-enhancing CLOB DEX, runs as its own domain-specific L2.
-
Cardano-first, multi-L1 by design. Cardano is the initial and currently the only supported L1. The architecture is intentionally agnostic about the custody chain; multi-L1 custody (one head holding funds from several L1s) and inter-head transactions are planned future work.
This repository contains the L1 interface, the consensus actors (fast and slow), the rules-based fallback regime, and the EUTXO L2 ledger — i.e. the operational substrate of a Hydrozoa head.
- Read the Gummiworm whitepaper (the protocol spec), or browse the in-repo design specs — see Specification below.
- Deploy a multi-party head —
DEPLOYMENT.mdis an end-to-end runbook: fleet configuration, node image, head initialization on a Cardano testnet, and running the peers. - Join the discussion => goto discussions
- Start hacking by picking up an issue => goto issues: help wanted
The authoritative protocol description is the Gummiworm whitepaper: https://gummiworm.net/whitepaper/introduction.
In-repo documentation complements it:
docs/ documents the system as built —
docs/user-guide/ task-oriented how-tos and
docs/spec/ design/reference.
The top-level design/ directory is a scratchpad for in-flight
feature specs, which graduate into docs/spec/ once built.
The preferred and supported setup is Nix.
Install a recent Nix and run nix develop to drop into a dev shell with every
dependency pinned (JDK, sbt, just, nixfmt);
formatting and linting run through sbt.
If you use direnv,
.envrc already runs use flake . so the shell loads automatically.
Without Nix you'll need a Java JDK (21+; the Nix shell pins JDK 25) and sbt. The project targets Scala 3.3.6 (LTS).
File -> New -> Project from Existing Sources ->
select the project directory -> Import project from external model -> BSP
-> Sbt
Launch IDEA from within the Nix shell so sbt and the other tools are on
PATH.
Enter the sbt shell with sbt:
sbt
> compile
> testFormatting and linting are exposed as sbt aliases:
sbt fmtAll # scalafmt — format all sources
sbt fmtCheckAll # scalafmt — check only
sbt lintAll # scalafix — apply fixes
sbt lintCheckAll # scalafix — check onlyAlways run linting and formatting before committing.
The integration subproject contains model-based test suites built on
ScalaCheck commands-inspired modified ModelBasedSuite harness.
"Stages" here refer to levels of testing —
each stage exercises the system at a different layer of abstraction:
-
stage1— single-peer head, low-level commands. Drives the node with primitives likeStartBlock/CompleteBlockand checks that the produced block briefs match the model and that timing rules are satisfied. Useful for pinning down block-production and scheduling invariants in isolation. The same suite runs against three L1 backends: an in-process mock L1, a local Yaci DevKit, and a public Cardano testnet (Preview, via Blockfrost). -
stage4— multi-peer head, real user commands. Runs several peers in a single suite, communicating either in-process or over the WebSocket transport, and drives them with user-level commands — L2 transactions and deposits — exercising the full consensus path end-to-end.
Run the full integration suite (mock + public Preview):
sbt "integration/test"Or run a single stage1 backend in isolation:
sbt "integration/testOnly hydrozoa.integration.stage1.Stage1PropertiesL1Mock" # mock L1 (default)
sbt "integration/testOnly hydrozoa.integration.stage1.Stage1PropertiesYaci" # local Yaci DevKit
sbt "integration/testOnly hydrozoa.integration.stage1.Stage1PropertiesPublic" # public Preview testnetThe Yaci suite requires a running Yaci DevKit instance and is excluded from the default integration run. The public-testnet suite runs by default and needs network access.
Code is licensed under
Apache-2.0;
documentation and the specification under
CC BY-SA 4.0.
See LICENSE and NOTICE for details.