<!-- tempo-docs-context -->
> Source: [/docs/guide/private-zones/swap-across-zones](https://tempo.xyz/developers/docs/guide/private-zones/swap-across-zones.md)
> Section: [Zones](https://tempo.xyz/developers/docs/zones.md). Connect to a Zone and work with private balances, deposits, and withdrawals. Zones is in limited preview; see the introduction for access. Earlier testnet sandbox guides describe a separate integration.
> Earlier testnet sandbox: use [Zones](https://tempo.xyz/developers/docs/zones.md) for the current limited preview.
> [Documentation index](https://tempo.xyz/developers/llms.txt) · [Docs skill](https://tempo.xyz/developers/SKILL.md)

> Tempo MCP: Use `search`, `find_pages`, `read_page`, and `code` at `https://mcp.tempo.xyz` for Tempo and related documentation.
> If an indexed page is missing or reflects an older site, read this site’s [documentation index](https://tempo.xyz/developers/llms.txt) and Markdown pages directly.

# Swap across zones

Swap `OUSD` in **Zone A** for `betaUSD` in **Zone B**, using test tokens in the [earlier testnet sandbox](https://tempo.xyz/developers/docs/guide/private-zones#testnet-compatibility). The swap settles on the public chain before Zone B credits the balance.

The route uses `swapAndDepositRouter` on the public chain: withdraw from `Zone A`, swap on the Stablecoin DEX, then deposit the output token into `Zone B`.

Zone A withdraws OUSD. The router swaps it for betaUSD on the Stablecoin DEX and deposits into Zone B in one public transaction. Zone B imports the deposit and credits betaUSD later.

<a id="swapping-pathusd-from-zone-a-into-betausd-on-zone-b" />

<span id="swapping-ousd-from-zone-a-into-betausd-on-zone-b" />

## Swap OUSD for betaUSD

1. Withdraws `OUSD` from `Zone A`.
2. Routes it through the public chain and swaps it on the Stablecoin DEX.
3. Deposits the output token into `Zone B` through `ZonePortal`.
4. Confirms the credited `betaUSD` balance in `Zone B`.

**Interactive demo: Swap across zones**

1. Swap across zones

## Code example

This snippet assumes you already have a signed-in `rootClient` on the public chain plus `zoneAClient`, and the shared token, router, and portal constants used throughout the zone guides.

The callback encoding below is specific to the legacy testnet router. Current routers require an encrypted deposit payload and a Tempo refund recipient. See the [testnet compatibility notes](https://tempo.xyz/developers/docs/guide/private-zones#testnet-compatibility) before adapting this route to another deployment.

It shows the core routed swap submission path; use the demo above when you want to watch the output deposit settle into Zone B.

```ts
import { encodeAbiParameters, parseUnits } from 'viem'

const swapAmount = parseUnits('25', 6)

await zoneAClient.zone.signAuthorizationToken({ zoneId: 6 })

const quotedBetaOut = await rootClient.dex.getSellQuote({
  amountIn: swapAmount,
  tokenIn: ousd,
  tokenOut: betaUsd,
})

const minimumBetaOut = quotedBetaOut - quotedBetaOut / 100n

const callbackData = encodeAbiParameters(
  [
    { type: 'bool' },
    { type: 'address' },
    { type: 'address' },
    { type: 'address' },
    { type: 'bytes32' },
    { type: 'uint128' },
  ],
  [false, betaUsd, ZONE_B.portalAddress, rootClient.account.address, zeroBytes32, minimumBetaOut],
)

const { receipt } = await zoneAClient.zone.requestWithdrawalSync({
  account: rootClient.account,
  amount: swapAmount,
  data: callbackData,
  feeToken: ousd,
  fallbackRecipient: rootClient.account.address,
  gas: routerCallbackGasLimit,
  to: swapAndDepositRouter,
  token: ousd,
})

console.log(receipt.blockNumber)
```

<span id="how-routed-zone-swaps-settle" />

## How the swap settles

This guide's swap flow is asynchronous because the trade temporarily leaves the zone.

The source token is withdrawn through `ZoneOutbox`, transferred to `SwapAndDepositRouter` on Tempo, optionally swapped on the Stablecoin DEX, and then deposited back through a `ZonePortal` as the output token. That routed deposit pays the normal portal deposit fee, so the amount that arrives on the zone is the post-fee output.

:::warning
If the routed withdrawal fails on Tempo - for example because the swap fails, the transfer fails, the router callback reverts, or the target deposit cannot be completed—the amount is bounced back to the withdrawal's `fallbackRecipient` inside the source zone. The fee is still paid to the sequencer, so a failed routed swap still results in fees for the sender.
:::
