# merkle-insert-without-dedupe

> Review sequential bounded Merkle insertion without exact surviving duplicate prevention.

Canonical: https://nightshade.dicksonwu.xyz/rules/merkle-insert-without-dedupe.html
Release: Nightshade 0.1.1 (v0.1.1)

| Field | Value |
| --- | --- |
| Rule ID | `merkle-insert-without-dedupe` |
| Severity | info |
| Confidence | medium |
| Maturity | experimental |
| Selection | Opt-in |
| Policy intent | not required |
| Default enabled | no |
| Category | Other active opt-ins / Source structure and validation |
| Engine facts used | canonical-insertion-snapshots, collection-observations, all-predicates, completed-entries |
| Release | v0.1.1 |

## Selection and scope

Not selected by default. Select it with `--detectors` or the `detectors` list in nightshade.json. Either one replaces profile selection, so list every rule you want.

```sh
./.nightshade/node_modules/.bin/nightshade ./contracts --detectors merkle-insert-without-dedupe
./.nightshade/node_modules/.bin/nightshade detector show merkle-insert-without-dedupe
```

The first command runs only this rule; `--detectors` takes a comma-separated list. The second prints the rule's metadata from your installed version.

Severity is review priority. It does not express exploitability or impact. Confidence is detector metadata, not a probability. All built-in rules are experimental.

Compiler scope: the engine supports the pinned profiles 0.28.0, 0.29.0, 0.30.0, 0.31.1, 0.33.0-rc.2, 0.34.0, 0.35.0-rc.1 and 0.35.0, with ZKIR2 by default. Support for this rule can be narrower; the rule documentation below states any narrower scope.

## Corpus checks

Synthetic corpus checks for this rule in the 0.1.1 proof run. A check counts only with compiler acceptance and complete analysis.

| Positive detected | Corrected quiet | Lookalike quiet | Other negative quiet | Incomplete |
| ---: | ---: | ---: | ---: | ---: |
| 2/2 | 2/2 | 1/2 | 0/0 | 0 |

Deviations recorded for this rule:

| Case | Kind | Expected to observed lines | Issue |
| --- | --- | --- | --- |
| synthetic-regressions.json / merkle-insert-without-dedupe-39 | lookalike | [11] to [11] | control hit |

These are behavior checks on synthetic fixtures, not a precision or recall estimate. See [evaluation](https://nightshade.dicksonwu.xyz/evaluation.md#synthetic-corpus).

## Rule documentation

From https://github.com/DicksonWu654/nightshade/blob/v0.1.1/docs/detectors/merkle-insert-without-dedupe.md at v0.1.1.

Availability: **opt-in**; severity **info**, confidence **medium**.

This rule reviews sequential native `MerkleTree` and `HistoricMerkleTree`
`insert`/`insertHash` calls without exact duplicate-prevention evidence. A bounded
tree has a finite number of slots; review whether repeated values should consume
more than one. Indexed replacement and constructor setup are outside this rule.

```compact
assert(!seen.member(value), "already inserted");
tree.insert(value);
seen.insert(value);
```

The analyzer requires an enforced preceding absence check on the actual inserted
value, plus a matching insertion into that same persistent collection which
survives completion. Remembering before the tree insert is also supported.
Required immutable equality can connect aliases and nested receiver keys.
Ignored or unrelated checks, erased records and checks borrowed from an exclusive
history do not suppress review. Reusing one check for another potentially aliasing
tree insertion remains a review candidate.

If duplicates are invalid, use a persistent dedupe collection and retain its
record. If repeated leaves are intentional, document that contract and optionally disable
this informational review. External uniqueness invariants, alternate dedupe schemes,
or independent tree operations can also produce review candidates. This rule
does not establish repeated-insert feasibility, capacity exhaustion, denial of
service, replay or deployed impact.

## Suppress a match

If a match is intentional, suppress it on the line before with the exact rule ID and a reason of at least eight characters:

```compact
// nightshade-disable-next-line merkle-insert-without-dedupe -- Reason this match is intentional
```

Diagnostics cannot be suppressed, and an unmatched directive for a selected rule makes analysis incomplete. See [configuration](https://nightshade.dicksonwu.xyz/configuration.md#suppress-an-intentional-match) for fingerprint suppressions and baselines.

## References

- [Rule source document at v0.1.1](https://github.com/DicksonWu654/nightshade/blob/v0.1.1/docs/detectors/merkle-insert-without-dedupe.md)
- [Catalog entry in rules.json](https://nightshade.dicksonwu.xyz/rules.json)
- [All rules](https://nightshade.dicksonwu.xyz/rules.md#source-structure-and-validation)
- [Limitations](https://nightshade.dicksonwu.xyz/limitations.md)
