# Nonce and hash identity desync

Nonce or hash compared against a value built differently, or advanced on paths the checker never sees

_Area: Smart contract access control and control flow. Seen in 5 disclosed reports; latest 2026-02-18. Updated 2026-10-23._

## How it works
A nonce or hash is the identity of a one-time action. The assumption that breaks is that the value the caller computes equals the value the contract or verifier stores, and that both advance in step. Two distinct failure modes: (1) **layout mismatch** — the stored value carries extra bytes (a packed nonce suffix, a trailing flag) that the comparison omits or mis-sizes, so a valid action never matches; (2) **mutation/clobber** — the stored value is advanced or overwritten by a frame the checker does not observe: a revert rolls back an increment, a host protocol advances its own counter on skipped actions, or a merge writes a default over a populated field.

## Where it shows up
- Off-chain code re-implementing an on-chain hash/seed check (TypeScript, Rust, SDK helpers) [E3](https://bugbountylibrary.com/r/cantina%3Agenius_jul2025%3A3.1.3.md)
- `keccak256(...)` compared against `bytes16(hash) | bytes16(nonce)` [E3](https://bugbountylibrary.com/r/cantina%3Agenius_jul2025%3A3.1.3.md)
- Storage keyed by `abi.encode(...)` where one site omits a trailing constant (bool flag) [E5](https://bugbountylibrary.com/r/c4%3A2021-10-ambire%3AH-02.md)
- Counters (nonce, salt, id) incremented inside a revertible frame rather than before the snapshot [E1](https://bugbountylibrary.com/r/c4%3A2023-10-zksync%3AM-21.md)
- Strict equality against a host protocol's counter that advances on skipped/failed orders [E2](https://bugbountylibrary.com/r/c4%3A2023-09-delegate%3AM-02.md)
- Structs merged or split where a default-initialized field (`[0;4]`) overwrites a populated one [E4](https://bugbountylibrary.com/r/c4%3A2025-09-succinct%3AM-06.md)

## How to review
For every nonce/hash comparison, write down the exact byte layout on both sides: length, truncation, packed suffix, endianness, argument list. Confirm the comparison uses the same layout as the producer and check against test vectors, not intuition [E3](https://bugbountylibrary.com/r/cantina%3Agenius_jul2025%3A3.1.3.md)[E5](https://bugbountylibrary.com/r/c4%3A2021-10-ambire%3AH-02.md). For counters, trace where the increment happens relative to any revert boundary; the invariant is that the nonce advances exactly once per attempted action regardless of downstream failure, matching the reference chain — diff against GETH line-by-line for EVM-equivalent L2s [E1](https://bugbountylibrary.com/r/c4%3A2023-10-zksync%3AM-21.md). For integrations, do not mirror a host's internal counter with strict equality; the host may advance state on paths your callback never sees [E2](https://bugbountylibrary.com/r/c4%3A2023-09-delegate%3AM-02.md). For merges, verify every field at the merge site against the verifier's invariant (e.g. all shards share one `proof_nonce`); a default must never overwrite a populated value [E4](https://bugbountylibrary.com/r/c4%3A2025-09-succinct%3AM-06.md).

## Variants seen
- Reverted child constructor rolls back the factory deployment nonce, desynchronizing CREATE addresses from the EVM [E1](https://bugbountylibrary.com/r/c4%3A2023-10-zksync%3AM-21.md)
- Host increments its nonce for skipped orders, permanently desyncing a strict-equality mirror [E2](https://bugbountylibrary.com/r/c4%3A2023-09-delegate%3AM-02.md)
- Full 32-byte hash compared to a 16-byte hash plus 16-byte nonce, so no order ever matches [E3](https://bugbountylibrary.com/r/cantina%3Agenius_jul2025%3A3.1.3.md)
- Deferred accumulator's default nonce clobbering the last shard's real nonce during split [E4](https://bugbountylibrary.com/r/c4%3A2025-09-succinct%3AM-06.md)
- `cancel()` hash omits the trailing bool used at scheduling, so the lookup key never matches [E5](https://bugbountylibrary.com/r/c4%3A2021-10-ambire%3AH-02.md)

## Why fixes fail
Fixing one comparison site leaves other re-implementations of the same hash/seed check inconsistent; the layout must be fixed everywhere it is recomputed, ideally via a shared helper both sides call [E3](https://bugbountylibrary.com/r/cantina%3Agenius_jul2025%3A3.1.3.md).

## Impact and severity
In the evidence this blocked valid orders, broke proof verification, and made scheduled transactions uncancellable (functional denial of service), and desynchronized cross-chain addresses. Severity rises when the mismatch is silent: callers cannot tell why valid input fails, and cross-chain identity drift can misroute funds or break replay assumptions.

## Evidence
- E1: https://bugbountylibrary.com/r/c4%3A2023-10-zksync%3AM-21.md
- E2: https://bugbountylibrary.com/r/c4%3A2023-09-delegate%3AM-02.md
- E3: https://bugbountylibrary.com/r/cantina%3Agenius_jul2025%3A3.1.3.md
- E4: https://bugbountylibrary.com/r/c4%3A2025-09-succinct%3AM-06.md
- E5: https://bugbountylibrary.com/r/c4%3A2021-10-ambire%3AH-02.md
