Skip to content

feat(confidential): add compliance clawback - #855

Draft
brozorec wants to merge 1 commit into
feat/conf-token-proofless-revokefrom
feat/conf-token-clawback
Draft

feat(confidential): add compliance clawback#855
brozorec wants to merge 1 commit into
feat/conf-token-proofless-revokefrom
feat/conf-token-clawback

Conversation

@brozorec

Copy link
Copy Markdown
Collaborator

Stack 3/3. Base: feat/conf-token-proofless-revoke (#854), which sits on feat/conf-token-auditor-escrow (#853).

Review #853 and #854 first. Merge in order, or GitHub will show their commits here too.

What

Adds ConfidentialClawback: an opt-in, admin- and auditor-gated seizure of a frozen account's confidential claim, plus a forced revoke that pulls escrowed allowances into reach of the seize.

  • circuits/clawback/ (51 ACIR opcodes — the cheapest circuit after Register) + VK
  • CircuitType::Clawback = 5
  • ConfidentialClawback trait, clawback and force_revoke_spender storage fns
  • set_commitments (pub(crate)), pub(crate) promotion of verify / append_*
  • 3 errors (AccountNotFrozen 3604, InvalidClawbackAmount 3605, InvalidClawbackDestination 3606), Clawback event
  • COMPLIANCE.md §5 rewritten from outline to specification; DESIGN §7.13

The mechanism

The circuit proves what the contract cannot check itself, since the balances are committed: knowledge of the Pedersen openings of C_spend (CB1) and C_receive (CB2), and that the seize is bounded by what those openings hold, α ≤ v_s + v_r (CB3).

The witness is producible by anyone holding the openings — the auditor, or the owner — and not by the admin, which holds no blinding. That asymmetry is the two-party separation: the compliance authority decides whether, the auditor decides how much and where to.

Post-verification is the merge rule plus a public debit — C_spend ← C_spend + C_receive − α·G, C_receive ← O — with no fresh randomness. The new opening (v_s + v_r − α, r_s + r_r) is recomputable by both owner and auditor, so the seized account stays spendable. Re-randomizing under an admin-chosen blinding would brick the account permanently.

_dest_f is an unconstrained public input that binds the settlement destination. Dropping it turns a compromised clawback signer from a griefer into a thief.

⚠️ Carried over from #854: discriminant 5

Clawback = 5 reuses the value RevokeSpender vacated in #854. Admissible only against a verifier registry deployed fresh with an all-new key set. Clawback = 6 avoids the hazard at zero cost — recommend changing before merge.

Known gaps

  • The clawback verifier mock does not bind public inputs, so the replay (INV-28) and destination-redirect (INV-31) cases are not covered by the 10 Rust smoke tests. Circuit-side coverage is in circuits/clawback/src/tests.nr (10 tests).
  • ConfidentialClawback: ConfidentialCompliance does not force a gating Hooks impl. A deployment wiring NoHooks gets a freeze that sets the flag while every operation stays ungated — the target can spend out before the seize lands. Documented as a deployment obligation in COMPLIANCE.md §5.3; not enforceable by the trait bound.

Checks

nargo test 144 passed · cargo test -p stellar-tokens 723 passed · cargo +nightly fmt --check clean · cargo clippy --all-targets clean · constraints.baseline regenerated

Adds the ConfidentialClawback trait: an admin- and auditor-gated seizure of a
frozen account's confidential claim, plus a forced revoke that pulls escrowed
allowances back into reach of the seize.

The Clawback circuit proves knowledge of the openings of C_spend and C_receive
and bounds the seize by their sum (CB1-CB3). Post-verification is the merge
rule plus a public debit with no fresh randomness, so the seized account stays
spendable. Settlement is `None` (pool left over-collateralized) or `Some(d)`
(exactly `amount` transferred), with the destination bound into the proof.
@coderabbitai

coderabbitai Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Aug 26, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.27586% with 1 line in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...ages/tokens/src/confidential/compliance/storage.rs 97.91% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant