Overview
CashmereCCTP is a comprehensive multi-chain implementation supporting zero-slippage native USDC transfers across EVM and non-EVM chains. All contracts follow Circle’s CCTP standard for secure cross-chain messaging.Contract Repository: GitHub - cashmere-prod/contracts-prod
Architecture
All CashmereCCTP contracts implement the same core functionality across different chain environments:Core Transfer Surface
Transfer Methods
transfer
Base burn + mint flow. Supported on all chains (EVM, Solana, Aptos, Sui).
transferV2
Circle CCTP v2 flow with
maxFee and minFinalityThreshold. Implemented on EVM and Solana.transferWithPermit
EIP-2612 approval helper. Available on EVM only.
transferV2WithPermit
Combines permit + CCTP v2. Available on EVM only.
| Chain | Entrypoints | Notes |
|---|---|---|
| EVM | transfer, transferV2, transferWithPermit, transferV2WithPermit | transferV2* routes through tokenMessengerV2.depositForBurnWithHook, hookData forwards to the remote router. |
| Solana | transfer, transfer_v2 | Anchor contexts mirror the EVM structs. transfer_v2 targets the CCTP v2 program and enforces denylist + finality threshold. |
| Aptos | transfer_outer, transfer | transfer_outer withdraws coins for you, transfer expects pre-withdrawn USDC/native coins. Only CCTP v1 is implemented today. |
| Sui | prepare_deposit_for_burn_ticket, post_deposit_for_burn | Two-phase flow: create the burn ticket then emit Cashmere event when Circle finalizes the burn. |
Signature Payload
Every quote produced by the Cashmere API signs the same logical fields: local domain, remote domain, relayer fee, deadline, and whether native gas is requested. The on-chain encoding differs per VM.- Solana serialises the same fields with Borsh (
TransferParamsincommon.rs) and prependscctp_versionso the backend cannot replay a v1 quote through the v2 entrypoint. - Aptos (
TransferParamsinsources/transfer.move) and Sui (TransferParamsinsources/transfer.move) encode with BCS and currently only expose the v1 path, so the version byte is omitted.
gasDropAmount is never part of the signature. Instead, each contract enforces max_native_gas_drop / max_usdc_gas_drop caps to protect user funds.Recipient Encoding
CashmereCCTP.transfer* surfaces two address parameters: recipient (bytes32) and solanaOwner (bytes32). Correctly formatting these fields is critical for routes that involve Solana.
Solana as Destination
When invokingtransfer or transferV2 on any non-Solana chain with destinationDomain = 5, set the recipient field to the hex-encoded Solana USDC token account that should receive funds. Populate solanaOwner with the Solana wallet address (ATA owner) encoded as 32-byte hex. If that token account does not exist when the relayer executes receive_message on Solana, Cashmere relayers bootstrap it automatically. The helper below converts a Base58 token account into the required hex string for the Solidity call.
Solana as Source
When calling the Solana program’stransfer or transfer_v2 instructions with a non-Solana destination, provide recipient as the Base58 representation of the 32-byte hex address expected by the remote chain. The snippet below mirrors the Solana quickstart tutorial and produces a PublicKey that can be passed directly into Anchor account serializers.
EVM, Sui, and Aptos Destinations
For transfers targeting EVM, Sui, or Aptos, ensure therecipient field is the 32-byte hex form of the destination account (padded with leading zeros, 64 hex characters after the 0x prefix). In these routes set solanaOwner to an all-zero 32-byte value (0x0000000000000000000000000000000000000000000000000000000000000000).
Fees, Gas Drops, and Events
- Protocol fee: capped at 100 bp (
MAX_FEE_BP) on every chain for security and collected in USDC. Using 0 bp now. - Relayer fee + gas drop: charged in native tokens when
isNative=true, otherwise deducted from the USDC that is being burnt. - All implementations emit
CashmereTransferwith matching fields so downstream indexers can treat transfers uniformly.
Obtaining Quotes & Signatures
- Use the Gas API at
https://gas.cashmere.exchange/getEcdsaSig_native(isV2=true) for EVM TransferV2/permit flows;/getEd25519Sig_nativesigns the same payload for Solana/Aptos/Sui. - Responses include the relayer
fee(6-dec USDC or native units), an expirydeadline(now + 100s), and the signature bytes expected by each chain. - Example workflow:
- Query the Gas API with
localDomain/destinationDomain/isNative. - Populate
Transfer(V2)Params.fee,gasDropAmount, andPermitParams.valueusing the quoted amounts. - Forward the returned signature to the contract call (or inject it into the Ed25519 helper instruction on Solana).
- Query the Gas API with
- Full endpoint docs live at Backend APIs.
EVM Implementation
Contract Addresses: For all Cashmere CCTP contracts, USDC/USDT token addresses, and domain IDs across all chains, see Contract Addresses.
Interface
Usage Examples
Basic Transfer
Transfer with Permit
TransferV2 with Max Fee Protection
Circle publishes recommended Align
maxFee values per route via the IRIS API. Query https://iris-api.circle.com/v2/burn/USDC/fees/{sourceDomainId}/{destDomainId} to receive the current minimumFee for each finalityThreshold. Example response:maxFee and minFinalityThreshold with these values before submitting transferV2* transactions.TransferV2WithPermit (Native Fee Example)
recipientis zero-padded to 32 bytes because Circle expects fixed-length addresses on every chain.solanaOwnerstays0x00…00when the destination is EVM/Sui/Aptos; set it to the Solana wallet address (ATA owner) only whendestinationDomain = 5.feeis denominated in native token units whenisNative = true; includefee + gasDropAmountin the transactionvalueso the contract can forward native gas on the caller’s behalf.
Quote-to-Param Checklist
amount– USDC to burn (6 decimals); should match the quote’samountand the ERC-20 permitvalue.maxFee– Upper bound you are willing to pay in USDC; compare against Circle IRIS guidance for the chosenminFinalityThreshold.fee– Relayer fee; denominated in USDC whenisNative=false, native token units whenisNative=true.deadline– Unix timestamp from the quote; protect against replay by rejecting stale values.gasDropAmount– Native gas to forward on destination; leave0for pure USDC routes.destinationDomain– Circle domain ID (see table below); ensure UI selection matches this ID.minFinalityThreshold– 1,000 (Fast) or 2,000 (Normal) for CCTP v2 routes.recipient– Always a 32-byte value; pad EVM addresses, convert Solana token accounts to hex, or encode Move addresses as 32-byte hex.solanaOwner– Solana ATA owner (32-byte hex) whendestinationDomain=5, otherwise0x00…00.isNative– Whentrue, sendfee + gasDropAmountasmsg.value; whenfalse, ensure those amounts are funded with USDC approvals.hookData– ABI-encoded payload for downstream hooks;0xwhen unused.signature– Raw bytes from the Gas API quote (ECDSA for EVM, Ed25519 for Solana/Move chains).PermitParams– Tie the EIP-2612 approval to the sameamount/deadline; reject mismatched values client-side.
Security Features
- Reentrancy Protection (EVM): Transfer functions on EVM chains use OpenZeppelin’s ReentrancyGuard
- Deadline Validation: Prevents replay attacks with time-limited signatures
- Fee Limits: Maximum 1% protocol fee (100 basis points)
- Gas Drop Limits: Configurable maximum gas drop amounts
- Signature Verification: ECDSA signature validation for relayer quotes
- Pause Mechanism: Emergency pause functionality
Solana Implementation
Program Addresses: See Contract Addresses for Solana program IDs and USDC mint address. Domain ID:
5Instructions
Ed25519 Verification
The program does not accept the relayer signature as an argument. Instead, it inspects the previous instruction in the transaction and replays the Ed25519 verifier proof.- Borsh-encode the signature payload.
- Add an ed25519 program instruction with the backend public key and message bytes.
- Include
Sysvar1nstructions11111111111111111111111111111111(system constant) so the program can read the verifier instruction.
Usage Example
transfer_v2 Details
- Call
program.methods.transferV2(...)with the same signature payload butcctpVersion = 2. - Two extra arguments are enforced:
max_fee(relayer cap in USDC) andmin_finality_threshold(Circle’s notarisation target). - Circle currently defines two thresholds:
1000for Fast transfers and2000for Normal transfers. Use the value that matches the quote returned by your backend/UI. - Additional accounts such as
denylist_accountand the CCTP v2 program IDs must be supplied; Anchor types intransfer_v2_ix.rsshow the full list.
Aptos Implementation
Module Addresses: See Contract Addresses for Aptos module addresses. Domain ID:
9Entry Functions
Signature Payload (BCS)
TransferParams. Pass that signature to either transfer_outer or transfer. When fee_is_native is false, the module automatically withdraws usdc_amount + gas_drop_amount from the caller and burns usdc_amount.
native_amount should equal fee + gas_drop_amount when fee_is_native = true; otherwise pass 0.Usage Example
recipientHexshould be a 0x-prefixed 32-byte address encoded for the destination chain (Circle expects 32 bytes).- Set
solanaOwnerHexwhen sending into Solana; otherwise pass0x0. signatureBytesis the byte array returned by the Cashmere quote API.
Sui Implementation
Module Addresses: See Contract Addresses for Sui module addresses. Domain ID:
8Entry Functions
Signature Payload (BCS)
prepare_deposit_for_burn_ticket enforces the signature above and moves protocol + relayer fees before returning a DepositForBurnTicket. The ticket must then be consumed by Circle’s deposit_for_burn Move call; afterwards call post_deposit_for_burn to emit the Cashmere event and bump the nonce.
Usage Example
- The same signature is reused for the
prepare_deposit_for_burn_ticketcall; no signature is needed when finalising. native_fee_coinmust containfee + gas_drop_amountSUI whenfee_is_native = true; otherwise supply an empty SUI coin object.signatureBytesis the Ed25519 quote returned by Cashmere; pass it as raw bytes, not hex.
Domain IDs
Complete list of Circle CCTP domain IDs for all supported chains. These values are immutable and differ from chain IDs—use them in every Gas API request and contract call.Admin Functions
All contracts support administrative functions via role-based access control:EVM
Solana
Error Codes
EVM Errors
FeeExceedsAmount()- Fee is greater than transfer amountTransferFailed()- USDC transfer failedDeadlineExpired()- Signature has expiredInvalidSignature()- Signature verification failedGasDropLimitExceeded()- Gas drop exceeds maximum limitReentrancyError()- Reentrancy attempt detectedPaused()- Contract is paused
Solana Errors
NotSigVerified(6000) - Signature not verifiedInvalidSignatureData(6001) - Invalid signature dataInvalidDataFormat(6002) - Invalid data formatEpochTooLarge(6004) - Epoch too largeInvalidSignature(6006) - Invalid signer
Events
CashmereTransfer Event
Emitted on all successful transfers:Chain IDs
EVM chain IDs for RPC configuration:Testing
Unit Tests
Best Practices
- Always validate signatures before submitting transactions
- Use deadline parameters to prevent replay attacks
- Approve sufficient USDC before transfers
- Handle revert reasons for better UX
- Monitor events for transfer status
- Use transferV2 for max fee protection
- Leverage permits for gas-efficient approvals
View Source Code
Browse the contract repository