Skip to main content
Circle’s Cross-Chain Transfer Protocol (CCTP) burns USDC on one chain and mints the same amount on another, after Circle’s attestation service (Iris) signs the burn. No wrapped token and no liquidity pool sit in between. Stellar is CCTP domain 27.

Deposit: EVM to Stellar

The user’s wallet sends two calls in one batch on the source chain:
  1. approve the chain’s USDC for TokenMessengerV2, for the exact amount.
  2. depositForBurnWithHook(amount, 27, forwarder, usdc, forwarder, maxFee, minFinality, hookData).
Both mintRecipient and destinationCaller are Circle’s Stellar CctpForwarder contract. The hook data names the real recipient:
Then:
1

Iris attests

Pesa’s worker polls GET /v2/messages/{sourceDomain}?transactionHash=... until Circle returns the message and its attestation.
2

Pesa's relay mints

The relay checks that the nonce is unused, then submits mint_and_forward(message, attestation) on Stellar. The forwarder mints and pays the recipient in one atomic call. The function is public, so anyone may submit it; the nonce check makes a second submit a no-op.
3

The arrival is credited

The transfer becomes CREDITED only after the USDC transfer to the user’s wallet is observed on Stellar.
If mintRecipient or destinationCaller is not the forwarder, or the hook data names the wrong account, the USDC is lost for good. The SDK’s verifyCctpCalls refuses any such call before the wallet prompt.

Withdraw: Stellar to EVM

The user signs two Stellar transactions:
  1. A USDC approve of TokenMessengerMinterV2 for the exact amount. The burn moves USDC with transfer_from, so it needs this allowance. The allowance lives 17,280 ledgers (about a day). If it already covers the amount, this prompt is skipped.
  2. deposit_for_burn to the destination chain’s domain, with mint_recipient set to the user’s EVM address padded to 32 bytes, zero destination_caller, max_fee 0 and finality 2000.
Iris attests the burn (source domain 27). Pesa’s relayer on the destination chain calls receiveMessage(message, attestation). It mints to the address in the message, so the relayer cannot redirect funds. If a third party relays first, the nonce check skips Pesa’s submit and the delivery is still observed.

Units

CCTP amounts have 6 decimals. Stellar USDC has 7.

Speed

Pesa uses CCTP Standard Transfer (maxFee = 0, minFinality = 2000). The wait is the source chain’s finality: seconds on Avalanche, about 15 to 19 minutes on Base, Arbitrum and Ethereum. Fast Transfer is turned on per source chain once a canary shows Stellar accepts it.