# Aztec Multiple-Spend Error Bugfix Review

Missing range check on prover-side residual plus limb overflow let attacker claim full output O per claim, enabling multiple-spend to drain ~$5M TVL.

- Payout: $450,000
- Severity: critical
- Program: Aztec Network
- Found by: LonelySloth
- Disclosed: 2023-11-29
- Write-up quality: 7/10
- Original: https://immunefi.com/blog/bug-fix-reviews/aztec-multiple-spend-error-bugfix-review/
- Library page: https://bugbountylibrary.com/r/blog%3Aimmunefi-com-blog-bug-fix-reviews-aztec-multiple-spend-error-bugfix-review
- Tags: area:web3 domain:web3 impact:funds-loss kind:bounty platform:blog platform:immunefi sev:critical tech:solidity technique:source-review vuln:accounting-error vuln:crypto

**Target:** ZK arithmetic circuit / bridge claim verification (Solidity circuit composer)
**Root cause:** The residual R computed in get_residual lacks a range check and is computed prover-side, so an attacker can tamper with it freely without invalidating the proof. Separately, limb decomposition allows a modulus overflow when limbs are combined, letting the attacker instantiate negative residuals.
**Steps:**
1. Observe claim formula oD + R = dO where R is the division residual computed by get_residual as ((b2*a1) % a2).lo via witness_ct.
2. Note the residual witness has no range constraint and is prover-side, so its value can be set arbitrarily without failing proof verification.
3. Exploit the limb decomposition: limbs[0..3] each range-constrained to 68 bits, but combining them can overflow the modulus (MAX_INPUT_BITS), enabling negative residuals.
4. Set R negative so the equation oD + R = dO is satisfied with o = O (full output) for each claim.
5. Submit multiple claims each claiming the entire output O, spending the same tokens repeatedly and draining TVL.
**How found:** Reviewed the get_residual circuit code and noticed the residual witness lacked a range check and was computed prover-side; then examined limb decomposition and found combining limbs could overflow the modulus, enabling negative residuals.
**Exploitation:** Attacker crafts claims with a tampered prover-side residual R (made negative via the limb modulus overflow) so each claim's output o equals the full total output O, then repeats claims to spend the same tokens multiple times, draining the ~$5M TVL.
**Insight:** In ZK circuit code, any witness value computed on the prover side without a range constraint is attacker-controlled; check residual/remainder witnesses and limb-decomposition overflow bounds where modular arithmetic wraps.

