# No cumulative floating-point errors in multi-step transactions

- **Pattern:** `ab-001442` (`finserv-form-validation.currency-amount.no-float-accumulation`)
- **Severity:** high
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001442
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001442)

## Why it matters

Floating-point errors in a single step are small; across a multi-step chain they compound unpredictably. A refund pipeline that subtracts a fee, applies a discount, and then taxes the result in float arithmetic will produce a different final amount depending on the order of operations — a determinism failure that makes reconciliation impossible. CWE-682 covers incorrect calculation; ISO 25010 functional-correctness requires financial outputs to be exact. Even a one-cent error per transaction becomes a material accounting discrepancy at tens of thousands of monthly transactions.

## Severity rationale

High because floating-point intermediates in chained calculations produce non-deterministic results that break financial reconciliation and audit trails.

## Remediation

Refactor all multi-step calculation chains to operate in integer cents from start to finish. Convert to cents once at the entry point and convert back to decimal only at display time.

```ts
// src/lib/finance.ts — integer arithmetic throughout
export function calculateRefund(
  originalCents: number,
  feeCents: number,
  discountCents: number
): number {
  // All intermediates remain integers
  const afterFee = originalCents - feeCents;
  const afterDiscount = afterFee - discountCents;
  return Math.max(0, afterDiscount); // never negative
}
```

Search `src/` for any pattern matching `balance +=` or `total -=` where the variable is initialized as a float and replace with integer cent equivalents.

## Detection

- **ID:** `no-float-accumulation`
- **Severity:** `high`
- **What to look for:** Enumerate all multi-step financial calculation chains (transfers with fees, interest accrual loops, tax + subtotal sums, refund deductions). For each chain, count the number of arithmetic steps and classify whether intermediate values are integers (cents) or floats. Quote the accumulation pattern found (e.g., `balance += interest` where `balance` is a float). Report: "X of Y multi-step chains use integer arithmetic throughout."
- **Pass criteria:** At least 100% of multi-step financial chains use integer (cents) arithmetic for all intermediate and final values. No more than 0 chains accumulate floating-point intermediates. Report even on pass: "X multi-step chains found, all using integer cents."
- **Fail criteria:** Any multi-step chain uses float intermediates that are accumulated across at least 2 steps.
- **Do not pass when:** A chain converts to cents at the end but performs intermediate calculations in floats — the accumulation damage occurs before the final conversion.
- **Skip (N/A) when:** The project has no multi-step financial transactions (0 arithmetic chains with at least 2 steps found).
- **Detail on fail:** Provide an example. Example: `"In refund processing, fee is subtracted from amount using floats: amount (22.50) - fee (2.50) = result (20.00). After 100s of such operations, rounding errors accumulate."` or `"Interest accrual loop: for each month, interest is added to balance as float and accumulated"`
- **Cross-reference:** The integer-cents-storage check in this same category verifies the storage layer; this check verifies the computation layer stays in integer space.
- **Remediation:** Always work with integers throughout the chain. In `src/lib/finance.ts` or the relevant calculation module:

  **Bad (float accumulation) — do NOT use:**
  ```ts
  let balance = 100.50; // float
  balance -= 2.30; // fee
  balance += 1.05; // interest
  balance -= 5.00; // withdrawal
  // balance = 94.25, but floating-point errors compound
  ```

  **Good (integer arithmetic) in `src/lib/finance.ts`:**
  ```ts
  let balanceCents = 10050; // integer
  balanceCents -= 230; // fee (integer cents)
  balanceCents += 105; // interest (integer cents)
  balanceCents -= 500; // withdrawal (integer cents)
  // balanceCents = 9425 (exact)
  ```

---

## External references

- cwe CWE-682
- iso-25010 functional-correctness

Taxons: data-integrity

HTML version: https://auditbuffet.com/patterns/ab-001442
