# Reshield

> Change a shielded asset without leaving the pool: withdraw, swap through an aggregator, and redeposit as a fresh note in one transaction, on this chain or another.

A reshield turns a shielded position in one asset into a shielded position in another. On-chain it is a [withdraw-and-swap](/operations/withdraw-and-swap) whose aggregator route ends not at a recipient but at a `contractCalls` step that deposits the swapped output back into the [Entrypoint](/protocol/contracts/entrypoint). The result is a new note with no on-chain link to the one you spent, and the funds never sit in a wallet in between.

Reshielding is honest about one thing the shorthand hides: the funds do leave the pool. They exit, trade, and return within one transaction. The privacy claim is about what an observer can link, not about the funds staying shielded throughout.

## Same-chain reshield

1.  **Estimate.** `estimateReshieldAmount` queries the relayer fee and the aggregator, reads the output token's `vettingFeeBPS` from the Entrypoint, and returns the note value the deposit will carry plus `totalDepositCost` (the deposit value and its vetting fee).
2.  **Prove the deposit.** Build a standard deposit proof for the *output* token with `prepareDeposit({ tokenId: outputToken, value: estimate.noteValue })`. This is the note you will hold afterwards.
3.  **Quote.** `prepareReshieldQuote` fetches the aggregator's `contractCalls` quote (swap, then a call to `Entrypoint.deposit` with your deposit proof and note data), and commits the routing with the relayer. Because the deposit calldata is inside the aggregator calldata, and that is inside the proof-bound routing, the deposit is as fixed as the swap.
4.  **Relay.** `relayReshield` proves the withdrawal and submits. RelaySwaps executes the swap; the aggregator's post-swap call deposits; the pool inserts your new commitment.

```ts
const estimate = await session.estimateReshieldAmount({
    relayerInfo,
    amount: spendAmount,           // Hex, in the input token
    tokenId: usdcAddress,
    outputToken: usdtAddress,
});

const depositResult = await session.prepareDeposit({
    tokenId: usdtAddress,
    value: estimate.noteValue,
});

const quote = await session.prepareReshieldQuote({
    relayerInfo,
    amount: spendAmount,
    tokenId: usdcAddress,
    outputToken: usdtAddress,
    depositResult,
    totalDepositCost: estimate.totalDepositCost,
});

const receipt = await session.relayReshield({
    inputCommitments: [noteToSpend.commitment],
    amount: spendAmount,
    tokenId: usdcAddress,
    outputToken: usdtAddress,
    swapCalldata: quote.swapCalldata,
    selectedQuote: quote.selectedQuote,
    swapTarget: quote.swapTarget,
    approvalAddress: quote.approvalAddress,
    dustRecipient: quote.dustRecipient,
    depositNote: quote.depositNote,     // persisted as PENDING once mined
});
```

When `outputToken` is a [yield share](/concepts/yield-shares), the embedded call is [`PPRouter`](/protocol/contracts/pp-router)`.depositExactShares` (or `depositExactSharesNative` for a native-mode router) instead of `Entrypoint.deposit`: the swap buys the wrapper's underlying, and the aggregator approves the router. Configure the session's yield deployments so the SDK can resolve the router.

## Cross-chain reshield

The same three calls with a destination: `estimateReshieldCrosschainAmount`, `prepareReshieldCrosschainQuote`, and `relayReshieldCrosschain`, each taking `toChainId`. The withdrawal happens on the source chain, the aggregator bridges and swaps, and the deposit lands in the destination chain's Entrypoint. Two things change:

-   **The deposit proof is destination-scoped.** Build `depositResult` against the destination chain's pool and Entrypoint (a second session, or the destination interactors), because that is where the commitment will be inserted. Share deposits on the destination reserve a larger rate headroom (`CROSS_CHAIN_DEPOSIT_RATE_HEADROOM_PPM`), since a bridge leg takes minutes rather than seconds.
-   **Dust can be rescued to a stealth address.** A bridge delivers slightly more or less than quoted. Opt in with `dustRescue: { recipientIdentifier }` and the leftover on the destination is deposited for a one-time [stealth address](/concepts/stealth-addresses) derived from your meta-address, with the discovery material packed into the deposit's own `noteData` rather than a public announcement. The identifier rides in the routing's `dustRescue` field, so it is proof-bound even though `RelaySwaps` never reads it.

Cross-chain is not a single moment. The source transaction confirms, then the bridge leg completes on its own schedule; the SDK's swap status provider tracks it.

## Constraints

-   **Two providers.** Reshield needs `withSwapAndDepositQuoteProvider(...)` for the `contractCalls` quote in addition to `withSwapQuoteProvider(...)`. `LiFiSwapQuoteProvider` implements both.
-   **The vetting fee is read on-chain.** It is whatever `Entrypoint.assets(outputToken).vettingFeeBPS` says at quote time and is not caller-supplied, because `Entrypoint.deposit` accepts nothing else.
-   **No recipient, no floor.** The routing carries a zero `recipient`, so the on-chain output check does not run; a failed or short delivery makes the embedded `Entrypoint.deposit` revert, which fails the whole transaction. The contract also rejects any `nativeGas` or `minOutputAmount` on such a routing, so those fields cannot be set by mistake.
-   **The new note is `PENDING`.** Like any deposit it awaits [ASP attestation](/concepts/asp-attestation) before it is spendable; the ASP sees a fresh deposit from RelaySwaps' aggregator leg, not from you.
-   **Cross-chain needs both chains.** Source-chain relayer with swaps enabled, destination-chain Entrypoint interactor, and matching yield targets on the destination if you are landing as a share.

## Behind the scenes

SDK calls `estimateReshieldAmount`, `prepareReshieldQuote`, `relayReshield`; or the `...Crosschain` trio. Plus `prepareDeposit` for the output note.
Contract method [`RelaySwaps`](/protocol/contracts/relay-swaps)`.execute` (or `.executeUnwrapped` when spending a yield share), whose aggregator call ends in `Entrypoint.deposit` or `PPRouter.depositExactShares` on the destination.
Relayer routes `POST /v1/quote/evm/{chainId}/swap` and `POST /v1/relay/evm/{chainId}/relay-swap`, as for a plain withdraw-and-swap.
Circuits A [`transact_NxM`](/protocol/circuits/transact) proof for the spend and a [`deposit`](/protocol/circuits/deposit) proof for the new note, the second embedded in the aggregator calldata the first commits to.

## What's next

-   [Withdraw and swap](withdraw-and-swap): the same route delivered to a public address.
-   [Swap and deposit](swap-and-deposit): enter the pool from any wallet token.
-   [Stealth addresses](/concepts/stealth-addresses): where cross-chain dust lands.
