OpenZeppelin / OpenZeppelin/compact-contracts
N-04: Clarify Documentation Around Deterministic Encryption Of Zero And Resulting Metadata Leakage
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 55
- Forks
- 29
- Avg merge
- 5d 7h
- Merged PRs (30d)
- 25
Description
N-02 Clarify Documentation Around Deterministic Encryption Of Zero And Resulting Metadata Leakage
Severity: Note
Source: Midnight Foundation #02 — OpenZeppelin Compact Contracts Audit, Release 0.3.0-alpha.1 (2026-08-18)
The encryption of zero returns a fixed pair of identity points rather than a randomized ciphertext, and that value is persisted into the balance and pending maps at registration and written back to pending on every sweep. An observer can therefore identify by inspection any slot still holding it, which discloses that an account is registered but never credited, or that a pending pool has just been swept. A zero arrived at by spending is not identifiable, because subtraction produces a randomized ciphertext, so what leaks is the provenance of the value rather than the value itself.
The deterministic form cannot be replaced because _refundPriorEscrow adds the stored owner copy onto the balance homomorphically, and only the identity leaves that ciphertext byte-identical on a first approve, so a randomized encryption of zero would re-randomize the owner's balance for no value moved. It would also extend the set of operations that depend on seed freshness and cost additional circuit rows, while offering no privacy gain, since register and sweep are public calls and the same facts are derivable from transaction history regardless. The remedy therefore lies in documentation rather than in the construction.
That property is recorded on encryptZero itself, which describes the value as not hiding and warns that a slot left at it is distinguishable as never written. It is absent, however, from the plaintext-disclosure enumeration in the ConfidentialFungibleToken header, which lists amounts, the supply delta, the approve cap and the counterparty graph. An integrator reasoning about what reaches the public ledger consults that enumeration rather than a primitive's docstring, and would otherwise carry an assumption of indistinguishability into a privacy interface.
Consider recording in the ElGamal module header, and as a further entry in the ConfidentialFungibleToken plaintext-disclosure enumeration, that a slot still holding the deterministic sentinel is publicly identifiable as never written or freshly reset, so that a single authoritative place exists for an integrator to consult.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the ElGamal module header and the plaintext-disclosure enumeration in contracts/src/token/ConfidentialFungibleToken.compact, then compare them with the encryptZero documentation. Document that the deterministic zero sentinel is publicly identifiable as never written or freshly reset, and ensure both authoritative documentation locations state this metadata leakage.
Written by the indexing model from the issue text.
Assessment
- Domain
- cryptography, documentation
- Issue type
- Documentation
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 84/100