
Mutation testing comes to DAML
Trail of Bits added DAML support to Mewt, their open-source mutation-testing engine, targeting Canton Network smart contracts. Mewt reuses the tree-sitter-haskell grammar to parse DAML and adds two contract-specific mutation operators — controller party swap (CPS) and controller party removal (CPR) — that probe whether test suites actually verify authorization rules (who must sign off on a choice) rather than just executing them. A worked example on a buyer/seller escrow contract shows a mutant that lets a seller release funds alone surviving a 100%-coverage test suite, illustrating how DAML's built-in choice-level coverage reporting can mask missing negative/unhappy-path tests; the team also ran Mewt against OpenZeppelin's canton-stablecoin reference implementation.
What it is
The page is the how-to and rationale companion to the DAML support Mewt gained in mid-2026. Mewt is Trail of Bits' open-source mutation-testing engine; this release makes it read DAML (the Canton Network contract language), generate mutants, and run them against your existing test suite to count survivors.
How it works
Mutation testing grades tests by sabotage, not reach. Each mutant is a copy of the code with one deliberate change — a flipped comparison, a removed branch, a dropped party — run against your suite. A mutant that makes tests fail is caught; one that passes is a survivor, meaning either equivalent/dead code (set aside) or a missing test case, occasionally a real bug. This is aimed at DAML's blind spot: built-in coverage reports whether a choice was exercised, not whether any test asserts the outcome. A choice exercised once with no assertions still reports green.
The two DAML-specific mutations both attack authorization — the rulebook for which party may exercise a choice:
- CPS (controller party swap): replace one party in a controller clause with another party in scope at that site.
- CPR (controller party removal): drop one party from a multi-party controller list.
Happy-path tests supply every required signature and confirm success; they never remove a signature to check the ledger rejects it, so they never verify the signature was required. CPS/CPR surface exactly those missing negative tests.
What to do
No new test harness is needed. Install Mewt from its repository, write a short mewt.toml naming the files to mutate and the test command, then run:
mewt runFor a Daml 3 project the test command in mewt.toml is dpm test. Output flags each mutant as caught or surviving; each survivor is a specific test worth writing.
Caveats
- No real DAML grammar. As of mid-2026 there is no maintained tree-sitter grammar for DAML, so Mewt reuses
tree-sitter-haskell. Ordinary DAML expressions parse fine (operator swaps, Boolean flips, branch removal all work), but the contract constructs —template,choice,controller,signatory— are not Haskell and parse as error-recovered subtrees. The CPS/CPR mutations are engineered to work despite this. - One surface-syntax adjustment: DAML writes
/=where most languages write!=. - CPS/CPR are a "deliberately small starting set" targeting the authorization bug class; more DAML mutations are stated to be in the pipeline.
- Survivor counts require triage — equivalent code and unreachable branches produce survivors that are not test gaps.
Organisations named here
- OpenZeppelin canton-stablecoin
Technologies named here
- Mewt
- DAML
- tree-sitter-haskell
- Canton Network
- Daml 3.4
- dpm
- Daml 2
- daml assistant
- Trailmark
- canton-stablecoin
- mutation-testing skill
Techniques named here
- Mutation testing
- Controller party swap
- Controller party removal
- Coverage-metric blind spot
Related in AppSec
Flowise MCP Security Bypass Enables RCE
Inside an Oracle Database SQL Injection Attack | Huntress
OASIS
