> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polygon.technology/llms.txt
> Use this file to discover all available pages before exploring further.

# Private Send

> Send funds privately from a non-custodial wallet, with the sender's identity shielded and the transaction integrity cryptographically verified end to end.

**Private Send lets your users transfer funds from their non-custodial wallet without exposing the link between their wallet and the public delivery transaction.**

The privacy option is opt-in per transaction. Users choose to enable it on a specific send and keep custody of their funds throughout: keys never leave the wallet, and every transaction is signed by the user.

What is hidden depends on the privacy mode. Sender privacy is always provided; recipient and amount visibility depend on whether the user picks sender-private or fully-shielded. See [Privacy modes](#privacy-modes) for the per-mode breakdown.

## How it works

A Private Send moves funds in two on-chain steps separated by a shielded pool. The wallet first deposits the user's funds into the pool; the privacy layer then withdraws to the recipient from the pool. The deposit and the withdrawal are not publicly linked.

When the user enables privacy on a send and chooses a token, amount, and recipient, the wallet requests a prepared order from the privacy enclave. The enclave returns a signed order that includes the privacy fee and the deposit calldata. The wallet verifies the response signature, the request nonce, the deposit destination against an allowlist of known privacy-layer contracts, and reconciles the amount before asking the user to sign.

For ERC-20 tokens, the user signs an approval transaction before the deposit. Native-token sends skip this step. The user then signs the deposit, which moves the funds from their wallet into the shielded pool. Inside the pool the funds are represented as private notes; the deposit and the later withdrawal are not publicly linked. The privacy layer then issues a private withdrawal that delivers the funds to the recipient.

The amount debited from the user's wallet equals the requested send amount plus the privacy fee. The fee is disclosed before the user confirms.

Once the deposit has been submitted, the wallet polls the order for delivery status. A top-level failure reported by the privacy layer surfaces immediately as a failed send rather than waiting for the polling window to time out.

```mermaid theme={null}
sequenceDiagram
    autonumber
    participant U as User wallet
    participant W as Wallet app
    participant E as Privacy enclave (TEE)
    participant P as Shielded pool
    participant R as Recipient

    U->>W: Enable privacy, choose token / amount / recipient
    W->>E: Request prepared order (with nonce)
    E-->>W: Signed order (fee, deposit calldata)
    Note over W: Verify response signature + nonce<br/>Verify destination allowlist + amount reconciliation
    opt ERC-20 only
        U->>P: Approve
    end
    U->>P: Deposit (funds enter pool)
    E->>P: Private withdrawal to recipient
    P-->>R: Funds delivered
    Note over E,P: The enclave orchestrates but does not custody funds.
    Note over P,R: The deposit and the delivery are not publicly linked.
```

The send lifecycle includes an explicit verification gate before the deposit. If any verification step fails, Private Send is disabled for that transaction and the wallet falls back to the normal transfer path.

```mermaid theme={null}
flowchart TD
    A[Idle] --> B[Privacy enabled]
    B --> C[Order prepared]
    C --> D{Verification gate}
    D -- Fails --> X[Privacy disabled / fall back]
    D -- Passes --> E[Deposit submitted]
    E --> F{Delivery}
    F -- Succeeds --> G[Complete]
    F -- Fails --> H[Funds held in shielded pool<br/>recoverable]
    H --> I[Recovery]
    I --> J[Returned to user wallet]
```

## Privacy modes

The wallet exposes two modes. Both break the link between the sender's wallet and the public delivery; they differ in whether the recipient and amount are also shielded.

**Sender-private.** The default mode described in [How it works](#how-it-works). The sender's wallet is unlinkable from the delivery transaction. The recipient address and amount remain visible on the delivering transaction.

**Fully-shielded transfers.** The recipient receives funds at a one-time stealth address derived from their viewing key, and the delivering transaction does not expose the final recipient or the amount. The only divergence from the sender-private flow is the final delivery leg: the private withdrawal targets a stealth address rather than a plain recipient address. Anonymity-set considerations are stronger in this mode because no recipient or amount metadata is exposed on chain.

```mermaid theme={null}
sequenceDiagram
    participant E as Privacy enclave (TEE)
    participant P as Shielded pool
    participant R as Recipient (stealth address)

    E->>P: Private withdrawal (stealth address derivation, amount shielded)
    P-->>R: Funds delivered
    Note over P,R: Recipient and amount are not exposed on the delivering transaction.
```

## What is and isn't private

| Property                            | Sender-private        | Fully-shielded             |
| ----------------------------------- | --------------------- | -------------------------- |
| Link from sender wallet to delivery | Broken (shielded)     | Broken (shielded)          |
| Recipient address                   | Visible on delivery   | Shielded (stealth address) |
| Amount                              | Visible on delivery   | Shielded                   |
| User custody of funds               | Retained              | Retained                   |
| Anonymity set                       | Grows with pool usage | Grows with pool usage      |

Unlinkability strengthens as more transactions flow through the shielded pool: a larger anonymity set makes statistical linkage harder.

## Security and verification model

Private Send's integrity rests on a layered trust chain. Four cryptographic layers establish what code is running, that it is the code we reviewed, and that requests and responses are bound to that code. Two client-side controls layer defense in depth on top.

**Enclave attestation** establishes what code is running. The privacy provider's API runs inside a hardware-backed Trusted Execution Environment (TEE). The enclave exposes an attestation endpoint that returns a token signed by the cloud provider's Confidential Computing attestation service. The token cryptographically commits to the exact container image digest running in the enclave: any change to the server code changes the digest and invalidates the attestation. The wallet requests this token with a fresh nonce, so the attestation cannot be replayed.

Attestation validation is complete before the wallet trusts the token: the wallet checks the token issuer, that the token has not expired, that the workload identifies as the expected Confidential Space software, and that the workload runs in the stable (not debug or preview) support profile. Attestation and JWKS fetches are bounded by the wallet's shared request timeout so a stalled dependency cannot hang verification.

**Source-to-digest provenance** establishes that the running code is the code we reviewed. The enclave's source is published, and every production build is signed via a transparency-log-backed supply-chain attestation (Sigstore and cosign, with a Rekor transparency-log entry per build). Our backend independently verifies that the attested image digest was built from the published source by the expected CI pipeline, and maintains a signed allowlist of approved image digests. The wallet only trusts attestations whose digest is on that allowlist.

**Response signing** establishes that an API response actually came from the enclave and was not tampered with. On attestation, the enclave generates an ephemeral signing keypair and binds its public key into the attestation token as the token audience, proving the key was generated inside the enclave. Every API response carries a signature over the response body in a response-signature header, which the wallet verifies against that attested key. The enclave also echoes the request's per-request nonce inside the signed response, so a previously captured response cannot be replayed.

Response-signature verification applies uniformly: failure responses and non-2xx error bodies must also be signature-verified and nonce-matched before the wallet trusts or surfaces their contents, so an unverified error payload cannot leak into the UI. When the enclave's response-signing key legitimately rotates, the wallet retries verification once against a freshly attested key and a reloaded allowlist so a cached key does not cause a valid response to be rejected. If both attempts fail, the response is rejected.

**Request signing and EIP-712 binding** establish that the enclave acts only on what the user authorized. At session creation the wallet generates a session-scoped signing keypair (separate from the wallet key), registers its public key with the enclave, and signs every subsequent request payload with it in a request-signature header. The enclave rejects any request whose signature does not match. For sensitive transactions, the wallet additionally signs an [EIP-712](https://eips.ethereum.org/EIPS/eip-712) typed-data struct that binds the exact parameters: destination address, token, chain, and a single-use nonce. If any field is altered in transit, the reconstructed struct does not match and the enclave rejects the request. This turns request tampering into a prevented failure rather than a detected-after-the-fact one.

When the connected wallet is an OMS smart wallet rather than an externally owned account, the wallet validates the session and typed-data signatures through smart-wallet signature validation (ERC-1271 style) instead of skipping the check. Order-status requests are additionally bound to the specific `orderId` they poll, so a signed status request cannot be replayed against a different order.

**Destination allowlisting and amount reconciliation** are client-side controls. Before submitting any transaction, the wallet validates that the deposit destination and any approval target match a known privacy-layer contract, and reconciles the amount it is about to move against what the user requested plus the disclosed fee. A response that tried to redirect funds or inflate the amount is rejected client-side before the user signs.

Value-integrity checks run unconditionally, independent of the per-chain address allowlist. A native-token deposit must carry a `value` equal to the signed `amountIn`; an ERC-20 deposit must carry no native value and must declare a usable approval target. The signed deposit amount returned by the privacy layer must match the amount the user signed plus the quoted fee, or the send is aborted before the wallet requests wallet approval or submits the deposit. The relayer preflight is bound to the specific order it was prepared for, and the wallet refuses to submit a preflight whose order identifier does not match the verified order at submit time, so a stale preflight cannot deposit against a different order than the one the user authorized.

**Fail-closed gating** is the final client-side control. If any verification step fails (bad attestation, an image digest not on the allowlist, a signature mismatch, or the verification service being unreachable), Private Send is disabled for that transaction and the wallet falls back to the normal (non-private) transfer path or surfaces the privacy option as unavailable. If the trusted image-digest allowlist is temporarily unreachable, the privacy toggle is disabled rather than opened against an unknown allowlist. There is no "unverified privacy" mode. The feature can also be remotely disabled if a concern is identified.

```mermaid theme={null}
flowchart TD
    A[Reviewed source<br/>published]
    B[Approved image digest<br/>verified by digest allowlist]
    C[Running enclave TEE<br/>ephemeral signing key bound to attestation]
    D[API response<br/>verified by wallet against attested key]
    E[Wallet client controls<br/>request signing · EIP-712 binding · contract allowlist · amount reconciliation · fail-closed gate]
    F[User signs / funds move<br/>only if every layer passes]

    A -->|built by expected CI, signed Sigstore/cosign, logged in transparency log| B
    B -->|attested by Confidential Computing token, nonce-bound| C
    C -->|signs every response, per-request nonce echoed| D
    D --> E
    E --> F
```

| Layer               | Guarantees                                                           | Mechanism                                                                                                    |
| ------------------- | -------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| Enclave attestation | The privacy service runs unmodified, known code                      | Confidential Computing attestation token (nonce-bound) over the image digest                                 |
| Source provenance   | That code is the build we reviewed                                   | Transparency-log-backed (Sigstore and cosign) signature; verified digest allowlist                           |
| Response signing    | Responses are genuinely from the enclave, untampered, non-replayable | Enclave-attested ephemeral key signs each response; per-request nonce echoed                                 |
| Request signing     | Requests reach the enclave unaltered                                 | Session-scoped key signs each request payload                                                                |
| Transaction binding | The enclave acts only on user-authorized parameters                  | [EIP-712](https://eips.ethereum.org/EIPS/eip-712) typed-data struct binding destination, token, chain, nonce |
| Client controls     | Funds cannot be redirected or inflated even on a provider flaw       | Contract allowlist, amount reconciliation, fail-closed gating                                                |

[Sigstore](https://www.sigstore.dev/) is the supply-chain signing project; [EIP-712](https://eips.ethereum.org/EIPS/eip-712) is the typed-data signing standard. No partner-specific links are used in this section.

## Recovery

Because a Private Send is a two-step deposit-then-deliver flow, an interrupted or failed delivery can leave funds resting in the shielded pool. The wallet provides a recovery flow that returns those funds to the user's own wallet. Funds in this state are never lost: they remain in the pool, associated with the user, and recoverable.

Recovery is non-custodial. The destination is the user's own connected wallet, and it is bound into the [EIP-712](https://eips.ethereum.org/EIPS/eip-712) typed-data struct that authorizes the recovery, so the destination cannot be redirected. Recovery requires a connected wallet: it is a signed operation, not a read.

The wallet validates that the recovery session and withdrawal signatures were produced by the expected recovery wallet before submitting a recovery API call, so a mismatched signer cannot initiate recovery. Recovery sessions are scoped by chain and wallet address, and switching between wallets in the app resets Private Send recovery state so recoverable balances belonging to one wallet are not shown under another. A recovery submission that hits the client timeout is treated as a failed submission and surfaced as such rather than left hanging.

## Supported networks and tokens

Private Send is available on Ethereum, Polygon, Base, Arbitrum, and Optimism. The wallet surfaces availability dynamically based on the selected token and chain: the privacy option only appears when the chosen combination is supported. See [Supported networks](/wallets/supported-networks) for the canonical wallet-wide list of chains.

## Related

<CardGroup cols={2}>
  <Card title="Security" icon="lock" href="/wallets/security">
    Key security, enclave-bound authentication, and the non-custodial guarantee.
  </Card>

  <Card title="Smart sessions" icon="shield-check" href="/wallets/smart-sessions">
    Scoped transaction permissions so users approve once.
  </Card>

  <Card title="Wallet operations" icon="arrow-right-arrow-left" href="/wallets/wallet-operations">
    Send transactions, sign messages, and check balances.
  </Card>

  <Card title="Recovery" icon="rotate-left" href="/wallets/recovery">
    Multi-auth linking and timed recovery for user wallet access.
  </Card>
</CardGroup>
