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 the signer prevents another account from claiming the relationship with 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
SwapOutput.
Token records are created for the 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