Skip to main content

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.

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.

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 (TransferParams in common.rs) and prepends cctp_version so the backend cannot replay a v1 quote through the v2 entrypoint.
  • Aptos (TransferParams in sources/transfer.move) and Sui (TransferParams in sources/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 invoking transfer 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’s transfer 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 the recipient 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 CashmereTransfer with 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_native signs the same payload for Solana/Aptos/Sui.
  • Responses include the relayer fee (6-dec USDC or native units), an expiry deadline (now + 100s), and the signature bytes expected by each chain.
  • Example workflow:
    1. Query the Gas API with localDomain / destinationDomain / isNative.
    2. Populate Transfer(V2)Params.fee, gasDropAmount, and PermitParams.value using the quoted amounts.
    3. Forward the returned signature to the contract call (or inject it into the Ed25519 helper instruction on Solana).
  • 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 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:
Align maxFee and minFinalityThreshold with these values before submitting transferV2* transactions.

TransferV2WithPermit (Native Fee Example)

  • recipient is zero-padded to 32 bytes because Circle expects fixed-length addresses on every chain.
  • solanaOwner stays 0x00…00 when the destination is EVM/Sui/Aptos; set it to the Solana wallet address (ATA owner) only when destinationDomain = 5.
  • fee is denominated in native token units when isNative = true; include fee + gasDropAmount in the transaction value so 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’s amount and the ERC-20 permit value.
  • maxFee – Upper bound you are willing to pay in USDC; compare against Circle IRIS guidance for the chosen minFinalityThreshold.
  • fee – Relayer fee; denominated in USDC when isNative=false, native token units when isNative=true.
  • deadline – Unix timestamp from the quote; protect against replay by rejecting stale values.
  • gasDropAmount – Native gas to forward on destination; leave 0 for 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) when destinationDomain=5, otherwise 0x00…00.
  • isNative – When true, send fee + gasDropAmount as msg.value; when false, ensure those amounts are funded with USDC approvals.
  • hookData – ABI-encoded payload for downstream hooks; 0x when 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 same amount/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: 5

Instructions

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.
  1. Borsh-encode the signature payload.
  2. Add an ed25519 program instruction with the backend public key and message bytes.
  3. 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 but cctpVersion = 2.
  • Two extra arguments are enforced: max_fee (relayer cap in USDC) and min_finality_threshold (Circle’s notarisation target).
  • Circle currently defines two thresholds: 1000 for Fast transfers and 2000 for Normal transfers. Use the value that matches the quote returned by your backend/UI.
  • Additional accounts such as denylist_account and the CCTP v2 program IDs must be supplied; Anchor types in transfer_v2_ix.rs show the full list.

Aptos Implementation

Module Addresses: See Contract Addresses for Aptos module addresses. Domain ID: 9

Entry Functions

Signature Payload (BCS)

The relayer signs the BCS bytes of 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

  • recipientHex should be a 0x-prefixed 32-byte address encoded for the destination chain (Circle expects 32 bytes).
  • Set solanaOwnerHex when sending into Solana; otherwise pass 0x0.
  • signatureBytes is the byte array returned by the Cashmere quote API.

Sui Implementation

Module Addresses: See Contract Addresses for Sui module addresses. Domain ID: 8

Entry 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_ticket call; no signature is needed when finalising.
  • native_fee_coin must contain fee + gas_drop_amount SUI when fee_is_native = true; otherwise supply an empty SUI coin object.
  • signatureBytes is 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 amount
  • TransferFailed() - USDC transfer failed
  • DeadlineExpired() - Signature has expired
  • InvalidSignature() - Signature verification failed
  • GasDropLimitExceeded() - Gas drop exceeds maximum limit
  • ReentrancyError() - Reentrancy attempt detected
  • Paused() - Contract is paused

Solana Errors

  • NotSigVerified (6000) - Signature not verified
  • InvalidSignatureData (6001) - Invalid signature data
  • InvalidDataFormat (6002) - Invalid data format
  • EpochTooLarge (6004) - Epoch too large
  • InvalidSignature (6006) - Invalid signer

Events

CashmereTransfer Event

Emitted on all successful transfers:

Chain IDs

EVM chain IDs for RPC configuration:

Testing

Unit Tests

Best Practices

  1. Always validate signatures before submitting transactions
  2. Use deadline parameters to prevent replay attacks
  3. Approve sufficient USDC before transfers
  4. Handle revert reasons for better UX
  5. Monitor events for transfer status
  6. Use transferV2 for max fee protection
  7. Leverage permits for gas-efficient approvals

View Source Code

Browse the contract repository