Deposit: EVM to Stellar
The user’s wallet sends two calls in one batch on the source chain:approvethe chain’s USDC for TokenMessengerV2, for the exact amount.depositForBurnWithHook(amount, 27, forwarder, usdc, forwarder, maxFee, minFinality, hookData).
mintRecipient and destinationCaller are Circle’s Stellar CctpForwarder contract. The hook data names the real recipient:
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.Withdraw: Stellar to EVM
The user signs two Stellar transactions:- A USDC
approveof TokenMessengerMinterV2 for the exact amount. The burn moves USDC withtransfer_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. deposit_for_burnto the destination chain’s domain, withmint_recipientset to the user’s EVM address padded to 32 bytes, zerodestination_caller,max_fee0 and finality 2000.
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.