Skip to content

Add Circle CCTP integration#2

Open
JuanMarchetto wants to merge 2 commits into
masterfrom
feat/cctp-integration
Open

Add Circle CCTP integration#2
JuanMarchetto wants to merge 2 commits into
masterfrom
feat/cctp-integration

Conversation

@JuanMarchetto

Copy link
Copy Markdown
Owner

Summary

  • Adds Circle CCTP (Cross-Chain Transfer Protocol) support for local USDC bridge testing
  • 3 new Rust modules: wire format + attestation signing, bidirectional delivery, Solana + EVM watchers
  • EVM mock contract (MessageTransmitterMock.sol) with ECDSA attestation verification and nonce replay protection
  • Relay routes CCTP messages by domain ID (Solana=5, Ethereum=0), independent from LayerZero EID routing
  • Optional [cctp] config section — no breaking changes to existing configs

Details

  • Wire format: CCTP Message (116-byte header) + BurnMessage (132-byte body), all big-endian
  • Mock attestation: Reuses secp256k1 (k256 crate) — same pattern as Wormhole guardian signing
  • Delivery: receiveMessage(bytes message, bytes attestation) ABI encoding for EVM, Anchor instruction building for Solana
  • No new deps beyond k256 and hex (already used by Wormhole NTT branch)

Test plan

  • 14 new CCTP-specific tests (wire format, attestation, config, security)
  • All 114 existing tests pass — no regressions
  • MessageTransmitterMock.sol compiles with Forge
  • Manual: run puente with [cctp] config against local validators

Extend Puente to support Circle's Cross-Chain Transfer Protocol (CCTP)
alongside existing LayerZero V2 OFT support. Enables local testing of
USDC bridge flows with mock attestation signing.

New modules:
- cctp.rs: CCTP message wire format (116-byte header + 132-byte BurnMessage),
  domain IDs, mock attestation signing (secp256k1), PDA helpers
- cctp_watcher.rs: Solana + EVM watchers for MessageSent events
- cctp_delivery.rs: Bidirectional delivery (EVM→Solana, Solana→EVM)
  with ABI-encoded receiveMessage(bytes,bytes) calldata

Mock contract:
- MessageTransmitterMock.sol: sendMessage, receiveMessage with ECDSA
  attestation verification and nonce replay protection

Integration:
- Relay routes CCTP messages by domain ID (Solana=5, Ethereum=0)
- env.rs conditionally deploys CCTP mock and starts watchers
- Optional [cctp] config section (no breaking changes)

Tests: 14 new tests covering wire format, attestation, config, security
All 114 existing tests continue to pass.
Comprehensive security tests organized by attack category:

SEC-1: Attestation Security (6 tests)
  - Forged attestation produces different signer
  - Empty/truncated attestation rejection
  - Message modification invalidates attestation
  - Attestation covers full message, not just body
  - Recovery ID normalization (v ∈ {0,1})

SEC-2: Nonce Replay Protection (5 tests)
  - Identical messages produce identical digests for dedup
  - Nonce isolation across source domains (PDA uniqueness)
  - u64::MAX nonce boundary
  - Bucket boundary correctness (0-63 vs 64-127)
  - Relay watermark dedup for CCTP domain IDs

SEC-3: Amount & Token Security (7 tests)
  - Zero amount transfers nothing
  - uint256 overflow beyond u64 detected
  - u64::MAX roundtrip safety
  - Amount/burn_token/recipient modification changes digest
  - Dust amount boundary testing

SEC-4: Domain & Routing Security (4 tests)
  - Self-transfer (same domain) is parseable but should be rejected on-chain
  - Domain spoofing (swap src/dst) changes digest
  - Invalid domain IDs are parseable (on-chain must validate)
  - CCTP domains never collide with LayerZero EIDs

SEC-5: Message Integrity (6 tests)
  - Truncated header/body rejected at every length
  - Version mismatch parses (on-chain must validate)
  - All 8 header fields contribute to digest independently

SEC-6: Destination Caller (2 tests)
  - Zero caller = unrestricted relay
  - Non-zero caller changes digest (enforced by on-chain)

SEC-7: PDA Security (5 tests)
  - used_nonces PDA unique per domain+bucket
  - token_pair PDA unique per domain and per token
  - custody PDA unique per mint
  - BE vs LE encoding mismatch detection

SEC-8: Mint/Burn Symmetry (3 tests)
  - Amount preserved across serialization for all edge values
  - message_sender vs sender field independence
  - Body offset correctness (starts at byte 116)

SEC-9: Cross-Chain Invariants (4 tests)
  - Deterministic digest across implementations
  - Wire format field offset verification (CctpMessage + BurnMessage)
  - All known domain IDs have names
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant