# Attacker May Disable Identical Spend Aggregation in Statutes

User-controlled mutation arg in statutes.clsp lets attacker pass (() 2 entropy) to trigger announce path with entropy, breaking identical spend aggregation and DoSing the statutes singleton.

- Payout: Contest reward
- Severity: medium
- Program: Circuit Puzzles
- Credited: yakuhito
- Disclosed: 2025-08-21
- Write-up quality: 7/10
- Original: https://cdn.cantina.xyz/reports/cantina_competition_circuit_puzzles.pdf#3.3.8
- Library page: https://bugbountylibrary.com/r/cantina%3Acircuit_puzzles%3A3.3.8
- Tags: domain:web3 impact:dos impact:funds-loss kind:contest platform:cantina sev:medium tech:solidity technique:source-review vuln:business-logic vuln:dos

**Target:** Chialisp statutes singleton puzzle (statutes.clsp)
**Root cause:** The mutation argument is user-controlled and only checked for truthiness; a non-empty list like (() 2 entropy) evaluates truthy but yields operation=(), so operation_mod_hash is false while the announce path still runs, and the entropy value makes the spend ineligible for identical spend aggregation.
**Steps:**
1. Read statutes.clsp L70: (assign (operation mutation_index mutation_value) (if mutation mutation (() () ())))
2. Note announce path triggers in else branch of (if mutation ...), i.e. when mutation is falsy
3. Craft mutation = (() 2 "yakuhito") so mutation is truthy but operation = ()
4. Verify with brun: '(mod (mutation) (if mutation (f mutation) ()))' on '((() 2 "yakuhito"))' returns ()
5. Submit spend with this mutation; announce path emits (list ASSERT_HEIGHT_RELATIVE 0) so it runs once per block
6. Repeat each block spending statutes singleton + fee coin to block all other users
**How found:** Code review of the mutation deconstruction in statutes.clsp; noticed mutation is only truthiness-checked and that a list whose first element is () yields operation=() while still being truthy, then confirmed behavior with minimal brun simulations.
**Exploitation:** Attacker spends the statutes singleton each block with mutation (() 2 entropy), triggering the announce path (which asserts height-relative 0, once per block) while the entropy value breaks identical spend aggregation with legitimate () mutations. This DoSes the singleton used by all protocol functionality, preventing users from interacting (e.g. repaying debt before liquidation), potentially causing fund loss; under 0-fee conditions the attack is free, otherwise only modest tx fees per block.
**Escalation:** Combined with XCH price decrease, blocked liquidations/governance could force vaults into undercollateralization and major depeg.
**Insight:** In Chialisp, (if x ...) tests truthiness not emptiness — a list like (() 2 entropy) is truthy but its head is (), so any code branching on truthiness of a user-supplied list can be steered into the 'empty' branch while smuggling extra data that breaks aggregation/hashing assumptions.
