Cross-Chain Transfer Protocol (CCTP) on StateSet

Overview

StateSet Commerce Network implements Circle’s Cross-Chain Transfer Protocol (CCTP) as a native Cosmos SDK module, enabling seamless USDC transfers between StateSet and other supported blockchains. This eliminates the need for wrapped tokens or custodial bridges, providing a secure and efficient way to move USDC across chains.

StateSet has implemented CCTP as a native blockchain module rather than smart contracts, providing superior performance and deeper integration with other StateSet features. For technical details, see the StateSet CCTP Module documentation.

How CCTP Works

Key Benefits

  • Native USDC: No wrapped tokens - USDC is burned on source and minted on destination
  • No Bridge Risk: Eliminates custodial bridge vulnerabilities
  • Unified Liquidity: Same USDC across all supported chains
  • Fast Transfers: Typically completes in minutes
  • Low Cost: Only pay standard transaction fees

Supported Chains

ChainDomainStatus
StateSet Commerce Network7✅ Active
Ethereum0✅ Active
Avalanche1✅ Active
Optimism2✅ Active
Arbitrum3✅ Active
Base6✅ Active
Polygon7✅ Active

Module Address

StateSet CCTP Module

  • Mainnet: stateset1cctp7m4ugfz4m6dd73yysz477jszqnfughxvkss5
  • Testnet: stateset1test9x8ugfz4m6dd73yysz477jszqnfughxvkss5

Quick Start

Transfer USDC from StateSet to Ethereum

import { StateSetCCTP } from '@stateset/cctp-sdk';

const cctp = new StateSetCCTP({
  endpoint: 'https://api.stateset.network',
  signer: wallet
});

// Burn USDC on StateSet
const burnTx = await cctp.depositForBurn({
  amount: '1000.00', // 1000 USDC
  destinationDomain: 0, // Ethereum
  mintRecipient: '0x742d35Cc6634C0532925a3b844Bc9e7595f6E321',
  burnToken: 'usdc'
});

// Get attestation from Circle
const attestation = await cctp.getAttestation(burnTx.messageHash);

// Mint on Ethereum (using ethers.js)
const mintTx = await ethereumCCTP.receiveMessage(
  burnTx.message,
  attestation
);

Core Functions

depositForBurn

Burns USDC on StateSet and initiates transfer to another chain.

interface DepositForBurnParams {
  amount: string;              // Amount of USDC to transfer
  destinationDomain: number;   // Target chain domain
  mintRecipient: string;       // Recipient address (32 bytes)
  burnToken: string;          // Token to burn (usually 'usdc')
}

const result = await cctp.depositForBurn({
  amount: '500.00',
  destinationDomain: 3, // Arbitrum
  mintRecipient: ethers.utils.hexZeroPad(recipientAddress, 32),
  burnToken: 'usdc'
});

// Returns
{
  txHash: '0x...',
  messageHash: '0x...',
  message: '0x...',
  nonce: 12345
}

depositForBurnWithCaller

Burns USDC with a specific caller authorized on destination.

interface DepositForBurnWithCallerParams {
  amount: string;
  destinationDomain: number;
  mintRecipient: string;
  burnToken: string;
  destinationCaller: string;  // Authorized caller (32 bytes)
}

// Only specified contract can receive on destination
const result = await cctp.depositForBurnWithCaller({
  amount: '1000.00',
  destinationDomain: 0,
  mintRecipient: ethers.utils.hexZeroPad(recipientAddress, 32),
  burnToken: 'usdc',
  destinationCaller: ethers.utils.hexZeroPad(contractAddress, 32)
});

receiveMessage

Receives and processes a CCTP message to mint USDC.

interface ReceiveMessageParams {
  message: string;        // Message bytes from source chain
  attestation: string;    // Attestation from Circle
}

// Receive USDC from another chain
const result = await cctp.receiveMessage({
  message: '0x...',      // From burn transaction
  attestation: '0x...'   // From Circle API
});

// Returns
{
  txHash: '0x...',
  amount: '1000.00',
  recipient: 'stateset1...'
}

replaceDepositForBurn

Replace a pending burn message (before attestation).

interface ReplaceDepositForBurnParams {
  originalMessage: string;
  originalAttestation: string;
  newMintRecipient?: string;
  newDestinationCaller?: string;
}

// Change recipient before message is processed
const result = await cctp.replaceDepositForBurn({
  originalMessage: '0x...',
  originalAttestation: '0x...',
  newMintRecipient: ethers.utils.hexZeroPad(newRecipient, 32)
});

Message Format

CCTP messages follow a standardized format across all chains:

interface CCTPMessage {
  version: number;           // Message version (currently 0)
  sourceDomain: number;      // Origin chain domain
  destinationDomain: number; // Target chain domain
  nonce: number;            // Unique message identifier
  sender: string;           // Sender address (32 bytes)
  recipient: string;        // Recipient address (32 bytes)
  destinationCaller: string;// Authorized caller (32 bytes)
  messageBody: string;      // Message payload
}

Integration Examples

E-Commerce Cross-Chain Payments

// Accept payment on any chain, settle on StateSet
class CrossChainPaymentProcessor {
  async acceptPayment(
    orderData: Order,
    paymentChain: number,
    customerAddress: string
  ) {
    // Generate payment address on customer's chain
    const paymentAddress = await this.getPaymentAddress(paymentChain);
    
    // Monitor for payment
    const payment = await this.waitForPayment(
      paymentAddress,
      orderData.total
    );
    
    // Transfer to StateSet for settlement
    if (paymentChain !== STATESET_DOMAIN) {
      const burnTx = await this.burnUSDC({
        chain: paymentChain,
        amount: payment.amount,
        destinationDomain: STATESET_DOMAIN,
        mintRecipient: this.settlementAddress
      });
      
      // Get attestation
      const attestation = await this.getAttestation(burnTx.messageHash);
      
      // Receive on StateSet
      await this.stateset.cctp.receiveMessage({
        message: burnTx.message,
        attestation
      });
    }
    
    // Process order
    await this.fulfillOrder(orderData);
  }
}

Multi-Chain Treasury Management

// Optimize treasury across chains
class MultiChainTreasury {
  async rebalance() {
    const balances = await this.getBalancesAllChains();
    const optimal = this.calculateOptimalDistribution(balances);
    
    for (const transfer of optimal.transfers) {
      // Move funds between chains
      await this.cctpTransfer({
        fromChain: transfer.source,
        toChain: transfer.destination,
        amount: transfer.amount
      });
    }
  }
  
  async cctpTransfer({ fromChain, toChain, amount }) {
    // Initiate burn on source chain
    const burnTx = await this.clients[fromChain].depositForBurn({
      amount,
      destinationDomain: this.domains[toChain],
      mintRecipient: this.addresses[toChain]
    });
    
    // Wait for attestation
    const attestation = await this.waitForAttestation(
      burnTx.messageHash
    );
    
    // Complete on destination
    await this.clients[toChain].receiveMessage({
      message: burnTx.message,
      attestation
    });
  }
}

Arbitrage Across Chains

// Execute arbitrage using CCTP for instant settlement
class CrossChainArbitrage {
  async executeArbitrage(opportunity: ArbOpportunity) {
    // Buy on cheap chain
    const buyTx = await this.dexes[opportunity.buyChain].swap({
      from: 'USDC',
      to: opportunity.token,
      amount: opportunity.amount
    });
    
    // Transfer token to expensive chain (if supported)
    // ... token bridge logic ...
    
    // Sell on expensive chain
    const sellTx = await this.dexes[opportunity.sellChain].swap({
      from: opportunity.token,
      to: 'USDC',
      amount: buyTx.output
    });
    
    // Transfer profits back to StateSet
    const profit = sellTx.output - opportunity.amount;
    if (profit > 10) { // Min $10 profit
      await this.transferViaProtocol({
        amount: profit.toString(),
        fromChain: opportunity.sellChain,
        toChain: 'stateset'
      });
    }
  }
}

Attestation Service

Circle provides attestations for CCTP messages. Integration example:

class AttestationService {
  private baseUrl = 'https://iris-api.circle.com/attestations';
  
  async getAttestation(messageHash: string): Promise<string> {
    // Poll for attestation (usually ready in 10-30 seconds)
    for (let i = 0; i < 60; i++) {
      try {
        const response = await fetch(
          `${this.baseUrl}/${messageHash}`
        );
        
        if (response.status === 200) {
          const data = await response.json();
          return data.attestation;
        }
      } catch (error) {
        // Continue polling
      }
      
      await new Promise(resolve => setTimeout(resolve, 2000));
    }
    
    throw new Error('Attestation timeout');
  }
}

Gas Optimization

Batch Transfers

// Batch multiple transfers to save gas
class BatchCCTP {
  async batchTransfer(transfers: Transfer[]) {
    // Group by destination domain
    const grouped = this.groupByDomain(transfers);
    
    for (const [domain, domainTransfers] of grouped) {
      // Create batch message
      const batchMessage = this.encodeBatchTransfer(domainTransfers);
      
      // Single burn for multiple recipients
      await this.cctp.depositForBurnWithCaller({
        amount: this.sumAmounts(domainTransfers),
        destinationDomain: domain,
        mintRecipient: this.batchProcessor[domain],
        destinationCaller: this.batchProcessor[domain],
        burnToken: 'usdc'
      });
    }
  }
}

Security Considerations

Best Practices

  1. Verify Addresses: Always verify recipient addresses are correct format
  2. Check Domains: Ensure destination domain matches intended chain
  3. Monitor Attestations: Implement timeout handling for attestations
  4. Validate Messages: Verify message integrity before processing
  5. Rate Limiting: Implement transfer limits for security

Address Formatting

// Convert addresses to 32-byte format
function formatAddress(address: string, chain: string): string {
  switch(chain) {
    case 'ethereum':
    case 'arbitrum':
    case 'optimism':
    case 'base':
    case 'avalanche':
    case 'polygon':
      // EVM addresses: pad to 32 bytes
      return ethers.utils.hexZeroPad(address, 32);
      
    case 'stateset':
      // Cosmos addresses: convert and pad
      const decoded = bech32.decode(address);
      const bytes = bech32.fromWords(decoded.words);
      return '0x' + Buffer.from(bytes).toString('hex').padStart(64, '0');
      
    default:
      throw new Error(`Unsupported chain: ${chain}`);
  }
}

Error Handling

Common errors and solutions:

ErrorCauseSolution
Invalid domainUnsupported destination chainCheck supported domains list
Insufficient balanceNot enough USDCEnsure adequate balance
Invalid recipientMalformed addressUse proper address formatting
Attestation timeoutCircle service delayImplement retry logic
Nonce already usedDuplicate messageUse unique nonce

Monitoring and Analytics

// Track CCTP transfers
class CCTPMonitor {
  async trackTransfer(transfer: CCTPTransfer) {
    // Log transfer initiation
    await this.log({
      type: 'cctp_burn',
      chain: transfer.sourceChain,
      amount: transfer.amount,
      destination: transfer.destinationChain,
      timestamp: Date.now()
    });
    
    // Monitor attestation
    const attestationTime = await this.measureAttestationTime(
      transfer.messageHash
    );
    
    // Track completion
    const completion = await this.waitForMint(
      transfer.destinationChain,
      transfer.messageHash
    );
    
    // Record metrics
    await this.metrics.record({
      transferTime: completion.timestamp - transfer.timestamp,
      attestationTime,
      gasUsed: transfer.gasUsed + completion.gasUsed,
      success: true
    });
  }
}

Native Module vs Smart Contracts

StateSet implements CCTP as a native Cosmos SDK module, providing several advantages:

Performance

  • 10x faster: Direct blockchain integration vs contract execution
  • Lower fees: No contract overhead, just base transaction costs
  • Atomic operations: Module-level atomicity guarantees

Integration

  • Deep integration: Direct access to other StateSet modules
  • Native CLI: Built-in command-line interface
  • Governance: Integrated with StateSet governance

Security

  • No contract risk: Eliminate smart contract vulnerabilities
  • Chain-level validation: Enhanced security at the consensus layer
  • Upgrade path: Coordinated upgrades via governance

For detailed module documentation, see StateSet CCTP Module.

Resources

Support

For CCTP integration support: