How it works
A CCTP transfer without the Forwarding Service is a three-step process:- Create a transaction to burn USDC on the source chain and wait for Circle to sign an attestation.
- Request an attestation from the Circle API.
- Create a transaction to mint USDC on the destination chain.
Hook format
The hook data for Forwarding Service begins with the reserved magic bytescctp-forward followed by versioning and payload fields. You can append your
own custom hook data after Circle’s reserved space. Forwarding Service doesn’t
support forwarding to wrapper contracts (for example, when destinationCaller
is set).
If no additional integrator hook data is required, a static hex string can be
used for the forwarding hook data:
Solana mintRecipient
When the destination blockchain is Solana, the mintRecipient parameter in
depositForBurnWithHook must be the recipient’s USDC
Associated Token Account (ATA)
address, not the recipient’s wallet address. Unlike EVM destinations where
mintRecipient is the wallet address, Solana requires the address of the SPL
token account that will hold the minted USDC.
You can derive the ATA address from the recipient owner address and the USDC
mint address using the
getAssociatedTokenAddressSync
function from the @solana/spl-token library. In Solana terms, the recipient
owner 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 the owner might be off-curve, pass true for allowOwnerOffCurve:
Solana hook data for ATA creation
If the recipient does not have an existing USDC ATA, you can request the Forwarding Service to create it by encoding additional fields in the hook data. The extended hook data format is:
When using this format,
mintRecipient must be the ATA derived from the
recipient owner address in bytes 33-64 and the USDC mint. The recipient owner
can be an on-curve public key controlled by a keypair or an off-curve PDA.
Forwarding Service validates that these values match before creating the
account.
The following example shows how to construct the extended hook data for Solana
with ATA creation:
Fees and execution
The Forwarding Service charges a fee for each transfer, in addition to the CCTP protocol fee. The Forwarding Service fee charged is to cover gas costs on the destination chain and a small service fee. The Forwarding Service prioritizes fast execution and quotes gas dynamically. If gas used is less than gas needed for execution, the remainder is spent as an additional priority fee where they are supported. On all chains, a higher fee provides a safety buffer for successful transaction delivery on the destination chain. Circle does not refund for excess gas and does not keep the excess gas, except in cases where excess priority fees are rejected. ThedepositForBurnWithHook
transaction includes a maxFee parameter. When using the Forwarding Service,
this parameter should be set to a value that is large enough to cover the CCTP
protocol fee and the Forwarding Service fee. Because the gas budget for the
destination chain comes from a USDC fee on the source chain, choosing a lower
maxFee results in a lower priority fee on the destination chain. A higher
maxFee results in a higher priority fee on the destination chain and can
result in faster confirmation.
The Forwarding Service charges a service fee for each transfer:
Solana fees
When forwarding to Solana, the Forwarding Service fee includes both a gas component and a rent component. Rent covers the cost of creating onchain accounts required by each transfer. The fee estimate API returnsforwardFee
values that already include rent, so no additional calculation is needed on your
part.
If the recipient does not already have a USDC
Associated Token Account (ATA)
on Solana, the transfer will fail. To have the Forwarding Service create the
ATA, you must:
- Pass
includeRecipientSetup=truewhen calling the fee estimate API so the returnedforwardFeecovers the ATA creation cost. - Encode the ATA creation fields in the hook data of the burn transaction.
GET /v2/burn/USDC/fees API reference.
includeRecipientSetup only applies when the destination blockchain is Solana.
It has no effect for EVM destination blockchains.