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

# Circle Forwarding Service for Gateway

> Forward destination chain mints to simplify crosschain transfers

The Circle Forwarding Service is a service for Gateway that simplifies
integration by removing the need for you to run multichain infrastructure. This
can improve user experience for crosschain transfers by ensuring reliability and
eliminating the need to handle destination chain gas fees.

## How it works

A Gateway transfer without the Forwarding Service is a three-step process
(assuming funds already deposited):

1. Create burn intents to burn USDC on the source chain.
2. Use the burn intents to request an attestation from the Circle API.
3. Submit the attestation to the destination minter contract to mint USDC.

This process requires you to have a wallet that can sign transactions on the
source and destination chains, and native tokens for paying the transaction gas
fee on both chains.

By enabling the forwarding service, you can pay for all the costs (base fee,
transfer fee, forwarding fee) when the funds are burned on the source chain.

## Enabling the Forwarding Service

To enable the Forwarding Service, add the `enableForwarder=true` query parameter
to the [`/transfer`](/api-reference/gateway/all/create-transfer-attestation)
endpoint:

```bash theme={null}
POST /v1/transfer?enableForwarder=true
```

When this parameter is set to `true`, Gateway will handle the destination chain
minting automatically. Because forwarding submits the destination mint for you,
the `POST /v1/transfer?enableForwarder=true` response may omit top-level
`attestation` and `signature` fields. Use
[`GET /v1/transfer/{id}`](/api-reference/gateway/all/get-transfer-by-id) for the
full transfer record, including nested attestation details.

## Fees and execution

The Forwarding Fee includes two parts:

* Forwarding Service fee
* Forwarding Gas Fee

The *Forwarding Service fee* for each transfer:

| Destination chain | Service fee (USDC) |
| ----------------- | ------------------ |
| All chains        | \$0.20             |

The *Forwarding Gas fee* is the amount needed to execute the mint attestation.
This cost is roughly the same gas costs as the
[burn fees](/gateway/references/fees#gas-fees).

The burn intent max fee must account for the forwarding fee.

```text theme={null}
maxFee ≥ gas fee + forwarding fee + (transfer amount * 0.00005)
```

For example, transferring 1,000 USDC from Base:

* Gas fee: \$0.01
* forwarding fee: \$0.21 (forwarding service and gas fee)
* Transfer fee: 1,000 \* 0.00005 = \$0.05
* Minimum `maxFee`: \$0.27 (270,000 in USDC subunits)

## Estimate forwarding fee

The [`/estimation`](/api-reference/gateway/all/estimate-transfer) endpoint can
be utilized by passing in the query parameter `enableForwarder=true`

```bash theme={null}
POST /v1/estimate?enableForwarder=true
```

Note that the `forwardingFee` includes the forwarding service and gas fees. If
the `maxFee` specified in the first burn intent is not enough to satisfy the
forwarding fee, the estimate endpoint will automatically bump up the max fee.

## Fee collection

Similar to the gas fee and transfer fee, forwarding fees will also be collected
when funds are burned on the source chain.

The forwarding fee collection process works as follows:

1. The forwarding fee is deducted from the `maxFee` of the burn intents in the
   order they were passed to the transfer endpoint.
2. The system will take up to the `maxFee` amount from the first burn intent to
   satisfy the forwarding fee.

**Example:**

If the forwarding fee is \$0.25 and the request contains three burn intents with
the following parameters:

* Burn intent 1: `maxFee` = \$0.30
  * Gas and transfer fees: \$0.08
  * Available for forwarding: \$0.22
* Burn intent 2: `maxFee` = \$0.15
  * Gas and transfer fees: \$0.05
  * Available for forwarding: \$0.10
* Burn intent 3: `maxFee` = \$0.25
  * Gas and transfer fees: \$0.06
  * Available for forwarding: \$0.19

The forwarding fee collection would work as follows:

1. \$0.22 is collected from burn intent 1's available `maxFee` after gas and
   transfer fees
2. \$0.03 is collected from burn intent 2's available `maxFee` to satisfy the
   remaining forwarding fee, totaling \$0.25
3. No forwarding fee is collected from burn intent 3 since the full forwarding
   fee has already been satisfied

Note that each burn intent's `maxFee` must first cover the gas and transfer fees
before any remaining amount can be applied to the forwarding fee.

## Automatic ATA creation for Solana

When the destination chain is Solana, the transfer `destinationRecipient` must
be an initialized USDC token account. If the recipient does not already have a
USDC token account, the Forwarding Service can create an Associated Token
Account (ATA) automatically as part of the mint transaction.

To enable automatic ATA creation, include `recipientSetupOptions` in each burn
intent that requires ATA creation in the
[`/transfer`](/api-reference/gateway/all/create-transfer-attestation) and
[`/estimate`](/api-reference/gateway/all/estimate-transfer) request bodies:

| Field                   | Type      | Description                                                 |
| :---------------------- | :-------- | :---------------------------------------------------------- |
| `includeRecipientSetup` | `boolean` | Set to `true` to request ATA creation                       |
| `recipientOwnerAddress` | `bytes32` | Recipient owner address for the ATA (hex-encoded, 32 bytes) |

The following example shows how to derive the ATA address, construct
`recipientSetupOptions`, and include it in the `/estimate` and `/transfer`
requests.

```typescript theme={null}
import { PublicKey } from "@solana/web3.js";
import { getAssociatedTokenAddressSync } from "@solana/spl-token";

const recipientOwner = new PublicKey("RecipientOwnerAddress");
const USDC_MINT = new PublicKey("4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU");

// Derive the ATA address — use this as destinationRecipient in the transfer spec
const recipientAta = getAssociatedTokenAddressSync(
  USDC_MINT,
  recipientOwner,
  true,
);
const destinationRecipient =
  "0x" + Buffer.from(recipientAta.toBytes()).toString("hex");
const recipientOwnerHex =
  "0x" + Buffer.from(recipientOwner.toBytes()).toString("hex");

// In the /estimate request body
const estimateRequest = [
  {
    spec: {
      // ... rest of the transfer spec
      destinationRecipient: destinationRecipient,
    },
    recipientSetupOptions: {
      includeRecipientSetup: true,
      recipientOwnerAddress: recipientOwnerHex,
    },
  },
];

// In the /transfer request body
const transferRequest = [
  {
    burnIntent: {
      // ... rest of the burn intent
      spec: {
        // ... rest of the transfer spec
        destinationRecipient: destinationRecipient,
      },
      recipientSetupOptions: {
        includeRecipientSetup: true,
        recipientOwnerAddress: recipientOwnerHex,
      },
    },
    signature,
  },
];
```

For a complete walkthrough, see
[Forward to a Solana destination with ATA creation](/gateway/howtos/forwarding-service#forward-to-a-solana-destination-with-ata-creation).

### Constraints

* `recipientSetupOptions` is only valid for requests using the Forwarding
  Service.
* The `destinationRecipient` must equal the ATA derived from the
  `recipientOwnerAddress` and the USDC token mint.
* The `recipientOwnerAddress` can be an on-curve public key controlled by a
  keypair, such as a wallet public key, or an off-curve Program Derived Address
  (PDA) controlled by a Solana program. If you derive the ATA with SPL Token
  helpers and the owner might be off-curve, pass `true` for the
  `allowOwnerOffCurve` parameter in `getAssociatedTokenAddressSync`.

### ATA creation fees

When automatic ATA creation is enabled, the forwarding fee includes the Solana
rent cost for creating the token account. The
[`/estimate`](/api-reference/gateway/all/estimate-transfer) endpoint factors
this cost in automatically when `recipientSetupOptions` is provided. If multiple
burn intents reference the same `recipientOwnerAddress`, the ATA creation fee is
charged only once.
