Contract derivation
The contract defines one claim-or-swap domain constant and verifies:Poseidon8::hash_to_address_raw over these values in verify_blinded_address.
Including the program address limits cross-program reuse. Including the domain distinguishes this use from unrelated address constructions. Including self.signer means another account cannot claim the same confidential relationship using only a copied factor.
Client-side factor derivation
The TypeScript client derives a blinding factor from:- Program address
- A client-side blinding-factor domain
- Account view-key scalar
- Local counter
Swap sequence
For a single-hop swap:- The wallet selects or derives a private blinding factor.
- The wallet computes the public confidential address using the AMM program address, domain, signer, and factor.
- The wallet submits the token record and private factor.
- The wallet submits the confidential address and market parameters publicly.
- The contract recomputes the expected address and rejects a mismatch.
- The request stores the confidential address as its recipient.
- The swap ID also commits to the confidential address.
- Finalization stores the confidential address as both recipient and caller in
SwapOutput. - Finalization marks the confidential address used.
Claim sequence
The claimant supplies:- Private blinding factor
- Public confidential address
- Public swap ID
- Public token identifiers
- Public output and refund amounts
self.signer. Finalization then requires the supplied confidential address to match both the stored caller and recipient and requires every supplied amount and token ID to match SwapOutput.
Token records are created for self.signer. The claimant cannot provide a different payout recipient. Successful finalization removes the pending output.
One-time enforcement
used_blinded_addresses is a public mapping. A successful swap rejects an address that is already present and then sets it to true.
The entry is not removed after claim. A confidential address is therefore one-use for successful swaps in this program.
One-time enforcement does not replace wallet-side concurrency control. Two transactions prepared with the same factor can race. At most one can finalize successfully, and the other incurs a rejected execution path.
Recovery requirements
The claim depends on the same signer and factor relationship used for the swap. A production wallet needs to preserve enough state to reconstruct or retrieve:- Program ID or program address
- Domain version
- Signer account
- Blinding factor, or its deterministic derivation inputs
- Confidential address
- Swap ID
- Output and refund values read from public state
used_blinded_addresses mapping can help detect reuse, but it is not a wallet state store and cannot reveal the private factor.
Security properties
The construction provides:- A public pseudonym that is bound to the transaction signer
- A private secret required to reproduce the relation
- Claim restriction to the signer that matches the confidential address
- One-use enforcement for successful swaps
- Separation from the program’s other address domains
Limits
The construction does not provide:- Confidential amounts
- Confidential route selection
- Confidential pool or token identifiers
- Confidential claim timing
- Protection from all statistical correlation
- Recovery of lost blinding material
- A legal identity assertion
- A general stealth-address system for mint or collect
Compliance disclosure
The public sees only the confidential address in swap attribution fields. The encrypted compliance record includes:- Confidential address
- Immediate caller
- Top-level signer
- Swap ID and request details