Rule
zero-amount-complementary-send-review
Review exact same-color complementary sends with two zero-inclusive amount envelopes.
Specimen 76 of 96 · Other active opt-ins / Token, coin and value transfers
- Severity
- info
- Confidence
- varies
- Maturity
- experimental
- Selection
- Opt-in
- Policy intent
- not required
- Release
- v0.1.1
- Engine facts used
canonical-send-operandscomplete-original-successful-historiesimmutable-unsigned-subtraction
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.
./.nightshade/node_modules/.bin/nightshade ./contracts --detectors zero-amount-complementary-send-review
./.nightshade/node_modules/.bin/nightshade detector show zero-amount-complementary-send-reviewThe 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 |
|---|---|---|---|---|
| 4/4 | 2/2 | 3/4 | 7/8 | 1 |
Deviations recorded for this rule:
| Case | Kind | Expected to observed lines | Issue |
|---|---|---|---|
| manifest.json / complementarySendReview47/drafts/complementary47/boundaries/intentional-same-executable-as-positive.compact | lookalike | [9] to [9] | control hit |
| manifest.json / complementarySendReview47/drafts/complementary47/boundaries/persistent-map-lost-lineage-refusal.compact | negative | [] to [] | incomplete or unvalidated |
These are behavior checks on synthetic fixtures, not a precision or recall estimate. See evaluation.
Rule documentation#
From docs/detectors/zero-amount-complementary-send-review.md at v0.1.1.
Availability: opt-in; severity info. Select it with --detectors zero-amount-complementary-send-review.
The rule reports one complementary pair of canonical CompactStandardLibrary.sendUnshielded calls on a complete original successful invocation history. The calls use the same exact immutable token-color operand and send unsigned scalar snapshots P and T-P. Aliases and value-preserving casts retain the relationship. The exact total T must have a proven positive modeled lower bound, and both actual sent amount envelopes must have lower bound zero after all modeled mandatory checks, including late checks.
assert(disclose(total) > 0 as Uint<128>, "positive total");
const remainder = total - part;
sendUnshielded(disclose(color), disclose(part), disclose(recipient));
sendUnshielded(disclose(color), disclose(remainder), disclose(recipient));Review whether the application's allocation policy should conditionally skip exact zero endpoint sends. Intentional zero/full endpoint allocations may match. A guard that makes either sent amount positive quiets this rule. A literal-zero part with a positive total is quiet because its remainder is strictly positive. Independent fee amounts, different color snapshots, mutually exclusive calls, and Field subtraction do not establish the selected relationship.
Supported profiles are Compact 0.31.1/ZKIR2 and 0.34.0/ZKIR2 or ZKIR3. Admission counts possible canonical calls through helpers and callbacks, including zero-iteration callbacks. Closures without an unsigned subtraction or two possible canonical sends can establish structural absence without requesting a numeric profile. Original histories remain separate; cached and uncached transfers preserve the same operands and evaluation order. Exact read/storage summaries remain available; fresh computed scalar occurrences are interpreted rather than reused from cached results.
Preparation, execution, immutable-key traversal, numeric bounds, pair matching, and emission share the existing 40,000 steps per entry, 256 paths per entry, and 50,000 cumulative values per rule. Unsupported applicable profiles, checkpoints, lost arithmetic lineage, inconsistent or missing history carriers, unfinished baseline analysis, and exhausted allowances produce rule-scoped incomplete diagnostics. Experimental Counter-query histories do not supply this rule's exact observation evidence.
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:
// nightshade-disable-next-line zero-amount-complementary-send-review -- Reason this match is intentionalDiagnostics cannot be suppressed, and an unmatched directive for a selected rule makes analysis incomplete. See configuration for fingerprint suppressions and baselines.