The pattern
Conservation across layers.
The conservation class, broadly, asserts that units entering a system must be consistently accounted for. Every deposit must appear in the total. Every debit that gets processed must reduce the right balance. No unit slips between the layers unaccounted. Within a single contract, this fails when the accounting logic misses a credit or debit somewhere in the call graph. Across layers, it fails when the accounting view at one layer diverges from what the other layer actually processed.
The numRealTxs boundary is the cross-layer shape.
The ZK proof layer and the L1 settlement layer are supposed to
agree on which transactions have been finalized. The proof said
“all 32 are valid.” Settlement said “I
processed the first N.” Transactions at position N+1
through 32 existed in one accounting view and not the other.
Conservation broke at the boundary.
The invariant that should hold is: for every transaction slot in
a proof-validated batch, the L1 settlement loop processes exactly
that slot, or the batch is invalid. Equivalently: the set of
transactions the proof considers finalized must equal the set the
settlement considers finalized. A test that carries a batch with
numRealTxs < batch_size and checks that the
accounting across both layers matches after settlement would have
flagged this shape.
CI-verified coverage
What we cover, and where we stop.
For the conservation class, we ship reference artifacts on two runtimes: Cairo on Starknet and HyperEVM. Both carry the class with clean and planted-bug twins running in CI. The EVM-L1-ZK-settlement surface that Aztec used is not one of them.
cf-invariants, Cairo / Starknet (same-layer
conservation). The 12-class reference suite includes
two conservation-class references: erc4626_ref and
staking_ref. The erc4626 conservation invariant
(cf_invariant_share_asset_conservation) tracks the
vault’s total_assets against an
externally-maintained cumulative net-deposit count across every
deposit and withdraw transition. The planted bug:
withdraw decrements total_shares but
not total_assets, so the vault’s reported
total drifts from the real one after the first withdrawal. The
invariant fires as soon as the two counts diverge. The staking
conservation invariant
(cf_invariant_stake_slash_conservation) asserts the
same shape across a staking vault with a slashing path: every
unit that enters as stake must appear either in
total_staked or in slashed_pool or in
completed withdrawals. The planted bug omits the
slashed_pool credit on a slash, and the conservation
assertion fails the moment a non-zero slash lands.
Both are single-layer conservation: the invariant lives inside one contract and the assertion compares internal accounting fields. They teach the conservation class shape. They are not the Aztec shape, which is a cross-layer divergence.
CI evidence for cf-invariants: PR #2 squash-merged 2026-06-07,
commit 003e33c, CI run 27075213962
26/26 green. All 12 references source-verified on Starknet
Sepolia. Repo:
github.com/caliperforge/cf-invariants.
Developer cookbook:
github.com/caliperforge/cf-invariants/tree/main/docs/cookbook.
hyperevm-safety, HyperEVM / Solidity (cross-layer
conservation window). D-5
(CoreWriterSolvencyWindow) is the cross-layer
variant in our artifact set. The bug class it covers: a lending
protocol on HyperEVM pre-credits a pending CoreWriter action on
the EVM side before HyperCore has confirmed the settlement. The
EVM-side solvency view shows inflated collateral that has not
cleared the HyperCore layer yet. If HyperCore rejects the action,
the borrower holds debt against collateral that never arrived.
The CoreWriterSolvency library’s
assertSettlementWindowInvariant reverts if the
EVM-reported solvency would only hold because of unsettled
credits. A protocol that calls this from every
position-mutating entry point cannot be exploited via the
pre-credit path.
The structural resemblance to the Aztec shape: in both cases, one layer’s accounting runs ahead of the other layer’s confirmed state. In Aztec, the proof layer validates transactions the settlement layer never processes. In D-5, the EVM layer counts collateral the HyperCore layer has not confirmed. The class identity is a cross-layer conservation window: two layers that should agree on settled state temporarily diverge, and the divergence window is exploitable.
CI evidence for hyperevm-safety: v0.1, commit
540464e, CI run 27379686747 6/6 jobs
green. D-5 planted twin
(CoreWriterSolvencyWindow.planted.t.sol) fires the
INVARIANT VIOLATED CoreWriterSolvencyWindow marker
and stays silent on the clean variant. Repo:
github.com/caliperforge/hyperevm-safety.
What is not in our set. The
EVM-L1-ZK-settlement surface, which is the Aztec attack surface,
does not appear in our artifact set. We do not have a planted
twin at the numRealTxs boundary or on any
ZK-rollup-to-L1-settlement pair. A test that caught the Aztec
shape directly would harness the
RollupProcessor’s settlement loop, construct
a batch with numRealTxs < batch_size, invoke
settlement, and assert that the post-settlement accounting
matches the full batch. That test does not exist in our CI today.
The teach
Why the class identity is the useful thing to say here.
The conservation class is not a single implementation pattern. It surfaces wherever there is a summary that two separate accounting views must agree. Single-layer conservation (erc4626, staking) fails when a contract’s internal bookkeeping has a gap. Cross-layer conservation (D-5, Aztec) fails when two systems that share a settlement boundary disagree on what has settled.
The useful output from an incident like Aztec’s is the
class name, the invariant formulation, and the question: does
anything in our harness already carry this shape? For teams
building on Cairo or Starknet, the cf-invariants
conservation references are the closest runnable starting point,
with the caveat that they are single-layer. For teams building
on HyperEVM or any EVM chain with a cross-layer settlement path,
D-5 is the structural analog. For teams building the actual
EVM-L1-ZK-settlement harness that the Aztec incident calls for,
neither artifact covers it yet.
That is what the class-identity teach is doing: the method generalizes across runtimes; our coverage of this specific surface does not.
Sources
Primary analysis and CaliperForge artifacts.
- SlowMist root-cause analysis: slowmist.medium.com/analysis-of-the-2-19-million-asset-theft-from-aztec-connect-d867c59b1fc6
- Aztec Connect incident, widely reported (KuCoin, NewsBTC, CryptoTimes, others).
CaliperForge artifacts cited:
-
cf-invariants
, Cairo / Starknet, 12-class matrix including two
conservation-class references, CI-verified
003e33c, run27075213962. -
cf-invariants developer cookbook
, public since 2026-06-11,
7f94b08. -
hyperevm-safety
, HyperEVM / Solidity, D-5 cross-layer conservation
window, CI-verified
540464e, run27379686747.