A production-ready Rust implementation of Circle's Cross-Chain Transfer Protocol (CCTP), enabling seamless USDC transfers across blockchain networks.
- π Type-safe contract interactions using Alloy
- π Multi-chain support for mainnet and testnet networks
- π¦ Builder pattern for intuitive API usage
- Ethereum
- Arbitrum
- Base
- Optimism
- Avalanche
- Polygon
- Unichain
- Sepolia
- Arbitrum Sepolia
- Base Sepolia
- Optimism Sepolia
- Avalanche Fuji
- Polygon Amoy
Add to your Cargo.toml
:
[dependencies]
cctp-rs = "0.3.0"
use cctp_rs::{Cctp, CctpError};
use alloy_chains::NamedChain;
use alloy_primitives::{Address, U256};
use alloy_provider::{Provider, ProviderBuilder};
#[tokio::main]
async fn main() -> Result<(), CctpError> {
// Create providers for source and destination chains
let eth_provider = ProviderBuilder::new()
.on_http("https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY".parse()?);
let arb_provider = ProviderBuilder::new()
.on_http("https://arb-mainnet.g.alchemy.com/v2/YOUR_API_KEY".parse()?);
// Set up the CCTP bridge
let bridge = Cctp::builder()
.source_chain(NamedChain::Mainnet)
.destination_chain(NamedChain::Arbitrum)
.source_provider(eth_provider)
.destination_provider(arb_provider)
.recipient("0xYourRecipientAddress".parse()?)
.build();
// Get contract addresses
let token_messenger = bridge.token_messenger_contract()?;
let destination_domain = bridge.destination_domain_id()?;
println!("Token Messenger: {}", token_messenger);
println!("Destination Domain: {}", destination_domain);
Ok(())
}
use cctp_rs::{Cctp, BridgeParams, CctpError};
use alloy_chains::NamedChain;
use alloy_primitives::{Address, U256};
async fn bridge_usdc(bridge: &Cctp<impl Provider>) -> Result<(), CctpError> {
// Step 1: Prepare bridge parameters
let params = BridgeParams::builder()
.from_address("0xYourAddress".parse()?)
.recipient("0xRecipientAddress".parse()?)
.token_address("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48".parse()?) // USDC on Ethereum
.amount(U256::from(1_000_000)) // 1 USDC (6 decimals)
.build();
// Step 2: Approve USDC spending (implement this based on your provider)
// approve_usdc_spending(¶ms).await?;
// Step 3: Burn USDC on source chain (get tx hash)
let burn_tx_hash = "0x...".parse()?; // From your burn transaction
// Step 4: Get message and attestation
let (message, message_hash) = bridge.get_message_sent_event(burn_tx_hash).await?;
// Step 5: Wait for attestation
let attestation = bridge.get_attestation(&message_hash, None, None).await?;
println!("Bridge successful! Attestation: {:?}", attestation);
// Step 6: Mint on destination chain using the attestation
// mint_on_destination(&message, &attestation).await?;
Ok(())
}
The library is organized into several key modules:
bridge
- Core CCTP bridge implementationchain
- Chain-specific configurations and supportattestation
- Attestation response types from Circle's Iris APIerror
- Comprehensive error types for proper error handlingcontracts
- Type-safe bindings for TokenMessenger and MessageTransmitter
cctp-rs provides detailed error types for different failure scenarios:
use cctp_rs::{CctpError, Cctp};
match bridge.get_attestation(&message_hash, None, None).await {
Ok(attestation) => println!("Success: {:?}", attestation),
Err(CctpError::AttestationTimeout) => println!("Timeout waiting for attestation"),
Err(CctpError::ChainNotSupported { chain }) => println!("Chain {} not supported", chain),
Err(e) => println!("Other error: {}", e),
}
// Wait up to 10 minutes with 30-second intervals
let attestation = bridge.get_attestation(
&message_hash,
Some(20), // max attempts
Some(30), // poll interval in seconds
).await?;
use cctp_rs::CctpV1;
use alloy_chains::NamedChain;
// Get chain-specific information
let chain = NamedChain::Arbitrum;
let confirmation_time = chain.confirmation_average_time_seconds()?;
let domain_id = chain.cctp_domain_id()?;
let token_messenger = chain.token_messenger_address()?;
println!("Arbitrum confirmation time: {} seconds", confirmation_time);
println!("Domain ID: {}", domain_id);
println!("Token Messenger: {}", token_messenger);
Check out the examples/
directory for complete working examples:
basic_bridge.rs
- Simple USDC bridge exampleattestation_monitoring.rs
- Monitor attestation statusmulti_chain.rs
- Bridge across multiple chains
Run examples with:
cargo run --example basic_bridge
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'feat: add some amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
Run the test suite:
cargo test
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.