Skip to main content

Contract responsibilities

  • TokenMessengerV2: Entrypoint for cross-chain USDC transfer. Routes messages to burn USDC on a source chain, and mint USDC on a destination chain.
  • MessageTransmitterV2: Generic message passing. Sends all messages on the source chain, and receives all messages on the destination chain.
  • TokenMinterV2: Responsible for minting and burning USDC. Contains chain-specific settings used by burners and minters.
  • MessageV2: Provides helper functions for cross-chain transfers, such as bytes32ToAddress and addressToBytes32, which are commonly used when bridging between EVM and non-EVM chains. These conversions are simple: prepend 12 zero bytes to an EVM address, or strip them to convert back.
Note: If you’re writing your own integration, it’s more gas-efficient to include this logic directly in your contract rather than calling an external one.
Full contract source code is available on GitHub.

Mainnet contract addresses

TokenMessengerV2: Mainnet

ChainDomainAddress
Ethereum00x28b5a0e9C621a5BadaA536219b3a228C8168cf5d
Avalanche10x28b5a0e9C621a5BadaA536219b3a228C8168cf5d
OP Mainnet20x28b5a0e9C621a5BadaA536219b3a228C8168cf5d
Arbitrum30x28b5a0e9C621a5BadaA536219b3a228C8168cf5d
Base60x28b5a0e9C621a5BadaA536219b3a228C8168cf5d
Polygon PoS70x28b5a0e9C621a5BadaA536219b3a228C8168cf5d
Unichain100x28b5a0e9C621a5BadaA536219b3a228C8168cf5d
Linea110x28b5a0e9C621a5BadaA536219b3a228C8168cf5d
Codex120x28b5a0e9C621a5BadaA536219b3a228C8168cf5d
Sonic130x28b5a0e9C621a5BadaA536219b3a228C8168cf5d
World Chain140x28b5a0e9C621a5BadaA536219b3a228C8168cf5d
Sei160x28b5a0e9C621a5BadaA536219b3a228C8168cf5d
XDC180x28b5a0e9C621a5BadaA536219b3a228C8168cf5d
HyperEVM190x28b5a0e9C621a5BadaA536219b3a228C8168cf5d
Ink210x28b5a0e9C621a5BadaA536219b3a228C8168cf5d
Plume220x28b5a0e9C621a5BadaA536219b3a228C8168cf5d

MessageTransmitterV2: Mainnet

ChainDomainAddress
Ethereum00x81D40F21F12A8F0E3252Bccb954D722d4c464B64
Avalanche10x81D40F21F12A8F0E3252Bccb954D722d4c464B64
OP Mainnet20x81D40F21F12A8F0E3252Bccb954D722d4c464B64
Arbitrum30x81D40F21F12A8F0E3252Bccb954D722d4c464B64
Base60x81D40F21F12A8F0E3252Bccb954D722d4c464B64
Polygon PoS70x81D40F21F12A8F0E3252Bccb954D722d4c464B64
Unichain100x81D40F21F12A8F0E3252Bccb954D722d4c464B64
Linea110x81D40F21F12A8F0E3252Bccb954D722d4c464B64
Codex120x81D40F21F12A8F0E3252Bccb954D722d4c464B64
Sonic130x81D40F21F12A8F0E3252Bccb954D722d4c464B64
World Chain140x81D40F21F12A8F0E3252Bccb954D722d4c464B64
Sei160x81D40F21F12A8F0E3252Bccb954D722d4c464B64
XDC180x81D40F21F12A8F0E3252Bccb954D722d4c464B64
HyperEVM190x81D40F21F12A8F0E3252Bccb954D722d4c464B64
Ink210x81D40F21F12A8F0E3252Bccb954D722d4c464B64
Plume220x81D40F21F12A8F0E3252Bccb954D722d4c464B64

TokenMinterV2: Mainnet

ChainDomainAddress
Ethereum00xfd78EE919681417d192449715b2594ab58f5D002
Avalanche10xfd78EE919681417d192449715b2594ab58f5D002
OP Mainnet20xfd78EE919681417d192449715b2594ab58f5D002
Arbitrum30xfd78EE919681417d192449715b2594ab58f5D002
Base60xfd78EE919681417d192449715b2594ab58f5D002
Polygon PoS70xfd78EE919681417d192449715b2594ab58f5D002
Unichain100xfd78EE919681417d192449715b2594ab58f5D002
Linea110xfd78EE919681417d192449715b2594ab58f5D002
Codex120xfd78EE919681417d192449715b2594ab58f5D002
Sonic130xfd78EE919681417d192449715b2594ab58f5D002
World Chain140xfd78EE919681417d192449715b2594ab58f5D002
Sei160xfd78EE919681417d192449715b2594ab58f5D002
XDC180xfd78EE919681417d192449715b2594ab58f5D002
HyperEVM190xfd78EE919681417d192449715b2594ab58f5D002
Ink210xfd78EE919681417d192449715b2594ab58f5D002
Plume220xfd78EE919681417d192449715b2594ab58f5D002

MessageV2: Mainnet

ChainDomainAddress
Ethereum00xec546b6B005471ECf012e5aF77FBeC07e0FD8f78
Avalanche10xec546b6B005471ECf012e5aF77FBeC07e0FD8f78
OP Mainnet20xec546b6B005471ECf012e5aF77FBeC07e0FD8f78
Arbitrum30xec546b6B005471ECf012e5aF77FBeC07e0FD8f78
Base60xec546b6B005471ECf012e5aF77FBeC07e0FD8f78
Polygon PoS70xec546b6B005471ECf012e5aF77FBeC07e0FD8f78
Unichain100xec546b6B005471ECf012e5aF77FBeC07e0FD8f78
Linea110xec546b6B005471ECf012e5aF77FBeC07e0FD8f78
Codex120xec546b6B005471ECf012e5aF77FBeC07e0FD8f78
Sonic130xec546b6B005471ECf012e5aF77FBeC07e0FD8f78
World Chain140xec546b6B005471ECf012e5aF77FBeC07e0FD8f78
Sei160xec546b6B005471ECf012e5aF77FBeC07e0FD8f78
XDC180xec546b6B005471ECf012e5aF77FBeC07e0FD8f78
HyperEVM190xec546b6B005471ECf012e5aF77FBeC07e0FD8f78
Ink210xec546b6B005471ECf012e5aF77FBeC07e0FD8f78
Plume220xec546b6B005471ECf012e5aF77FBeC07e0FD8f78

Testnet contract addresses

TokenMessengerV2: Testnet

ChainDomainAddress
Ethereum Sepolia00x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA
Avalanche Fuji10x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA
OP Sepolia20x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA
Arbitrum Sepolia30x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA
Base Sepolia60x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA
Polygon PoS Amoy70x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA
Unichain Sepolia100x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA
Linea Sepolia110x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA
Codex Testnet120x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA
Sonic Testnet130x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA
World Chain Sepolia140x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA
Sei Testnet160x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA
XDC Apothem180x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA
HyperEVM Testnet190x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA
Ink Testnet210x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA
Plume Testnet220x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA

MessageTransmitterV2: Testnet

ChainDomainAddress
Ethereum Sepolia00xE737e5cEBEEBa77EFE34D4aa090756590b1CE275
Avalanche Fuji10xE737e5cEBEEBa77EFE34D4aa090756590b1CE275
OP Sepolia20xE737e5cEBEEBa77EFE34D4aa090756590b1CE275
Arbitrum Sepolia30xE737e5cEBEEBa77EFE34D4aa090756590b1CE275
Base Sepolia60xE737e5cEBEEBa77EFE34D4aa090756590b1CE275
Polygon PoS Amoy70xE737e5cEBEEBa77EFE34D4aa090756590b1CE275
Unichain Sepolia100xE737e5cEBEEBa77EFE34D4aa090756590b1CE275
Linea Sepolia110xE737e5cEBEEBa77EFE34D4aa090756590b1CE275
Codex Testnet120xE737e5cEBEEBa77EFE34D4aa090756590b1CE275
Sonic Testnet130xE737e5cEBEEBa77EFE34D4aa090756590b1CE275
World Chain Sepolia140xE737e5cEBEEBa77EFE34D4aa090756590b1CE275
Sei Testnet160xE737e5cEBEEBa77EFE34D4aa090756590b1CE275
XDC Apothem180xE737e5cEBEEBa77EFE34D4aa090756590b1CE275
HyperEVM Testnet190xE737e5cEBEEBa77EFE34D4aa090756590b1CE275
Ink Testnet210xE737e5cEBEEBa77EFE34D4aa090756590b1CE275
Plume Testnet220xE737e5cEBEEBa77EFE34D4aa090756590b1CE275

TokenMinterV2: Testnet

ChainDomainAddress
Ethereum Sepolia00xb43db544E2c27092c107639Ad201b3dEfAbcF192
Avalanche Fuji10xb43db544E2c27092c107639Ad201b3dEfAbcF192
OP Sepolia20xb43db544E2c27092c107639Ad201b3dEfAbcF192
Arbitrum Sepolia30xb43db544E2c27092c107639Ad201b3dEfAbcF192
Base Sepolia60xb43db544E2c27092c107639Ad201b3dEfAbcF192
Polygon PoS Amoy70xb43db544E2c27092c107639Ad201b3dEfAbcF192
Unichain Sepolia100xb43db544E2c27092c107639Ad201b3dEfAbcF192
Linea Sepolia110xb43db544E2c27092c107639Ad201b3dEfAbcF192
Codex Testnet120xb43db544E2c27092c107639Ad201b3dEfAbcF192
Sonic Testnet130xb43db544E2c27092c107639Ad201b3dEfAbcF192
World Chain Sepolia140xb43db544E2c27092c107639Ad201b3dEfAbcF192
Sei Testnet160xb43db544E2c27092c107639Ad201b3dEfAbcF192
XDC Apothem180xb43db544E2c27092c107639Ad201b3dEfAbcF192
HyperEVM Testnet190xb43db544E2c27092c107639Ad201b3dEfAbcF192
Ink Testnet210xb43db544E2c27092c107639Ad201b3dEfAbcF192
Plume Testnet220xb43db544E2c27092c107639Ad201b3dEfAbcF192

MessageV2: Testnet

ChainDomainAddress
Ethereum Sepolia00xbaC0179bB358A8936169a63408C8481D582390C4
Avalanche Fuji10xbaC0179bB358A8936169a63408C8481D582390C4
OP Sepolia20xbac0179bb358a8936169a63408c8481d582390c4
Arbitrum Sepolia30xbaC0179bB358A8936169a63408C8481D582390C4
Base Sepolia60xbaC0179bB358A8936169a63408C8481D582390C4
Polygon PoS Amoy70xbac0179bb358a8936169a63408c8481d582390c4
Unichain Sepolia100xbaC0179bB358A8936169a63408C8481D582390C4
Linea Sepolia110xbaC0179bB358A8936169a63408C8481D582390C4
Codex Testnet120xbac0179bb358a8936169a63408c8481d582390c4
Sonic Testnet130xbaC0179bB358A8936169a63408C8481D582390C4
World Chain Sepolia140xbaC0179bB358A8936169a63408C8481D582390C4
Sei Testnet160xbaC0179bB358A8936169a63408C8481D582390C4
XDC Apothem180xbaC0179bB358A8936169a63408C8481D582390C4
HyperEVM Testnet190xbaC0179bB358A8936169a63408C8481D582390C4
Ink Testnet210xbaC0179bB358A8936169a63408C8481D582390C4
Plume Testnet220xbaC0179bB358A8936169a63408C8481D582390C4

CCTP V2 Interface

This section provides the Smart Contract Interface exposed by CCTP V2, outlining the available functions, and their parameters. The interface below serves as a reference for permissionless messaging functions exposed by the TokenMessengerV2 and MessageTransmitterV2 functions.

Changes from CCTP V1

New functions

  • TokenMessengerV2#depositForBurnWithHook (extends depositForBurn by adding hook data)
  • TokenMessengerV2#handleReceiveUnfinalizedMessage (replaces handleReceiveMessage)
  • TokenMessengerV2#handleReceiveFinalizedMessage (replaces handleReceiveMessage)

Modified functions

  • TokenMessengerV2#depositForBurn
  • MessageTransmitterV2#sendMessage
  • MessageTransmitterV2#receiveMessage

Removed functions

  • TokenMessengerV2#handleReceiveMessage
  • TokenMessengerV2#replaceDepositForBurn
  • TokenMessengerV2#depositForBurnWithCaller
  • MessageTransmitterV2#replaceMessage
  • MessageTransmitterV2#sendMessageWithCaller

TokenMessengerV2

depositForBurn

Deposits and burns tokens from sender to be minted on destination domain, and emits a cross-chain message by calling MessageTransmitter’s sendMessage function. Minted tokens will be transferred to mintRecipient. Parameters
FieldTypeDescription
amountuint256Amount of tokens to deposit and burn
destinationDomainuint32Destination domain ID to send the message to
mintRecipientbytes32Address of mint recipient on destination domain (must be converted to 32 byte array, that is, prefix with zeros if needed)
burnTokenaddressAddress of contract to burn deposited tokens on local domain
destinationCallerbytes32Address as bytes32 which can call receiveMessage on destination domain. If set to bytes32(0), any address can call receiveMessage
maxFeeuint256Max fee paid for fast burn, specified in units of burnToken
minFinalityThresholduint32Minimum finality threshold at which burn will be attested

depositForBurnWithHook

Deposits and burns tokens from sender to be minted on destination domain, and emits a cross-chain message with additional hook data appended. In addition to the standard depositForBurn parameters, depositForBurnWithHook accepts a dynamic-length hookData parameter, allowing the caller to include additional metadata to the attested message, which can be used to trigger custom logic on the destination chain. Parameters
FieldTypeDescription
amountuint256Amount of tokens to burn
destinationDomainuint32Destination domain to send the message to
mintRecipientbytes32Address of mint recipient on destination domain (must be converted to 32 byte array, that is, prefix with zeros if needed)
burnTokenaddressAddress of contract to burn deposited tokens on local domain
destinationCallerbytes32Address as bytes32 which can call receiveMessage on destination domain. If set to bytes32(0), any address can call receiveMessage
maxFeeuint256Max fee paid for fast burn, specified in units of burnToken
minFinalityThresholduint32Minimum finality threshold at which burn will be attested
hookDatabytesAdditional metadata attached to the attested message, which can be used to trigger custom logic on the destination chain

getMinFeeAmount

Calculates and returns the minimum fee required for a given amount in a Standard Transfer. If the minFee (per unit of burnToken) is non-zero, the specified maxFee must be at least the returned minimum fee. Otherwise, the burn will revert onchain. Parameters
FieldTypeDescription
amountuint256The amount used to compute the minimum fee. Must be greater than 1 if standard fee is applied

handleReceiveFinalizedMessage

Handles incoming message received by the local MessageTransmitter, and takes the appropriate action. For a burn message, mints the associated token to the requested recipient on the local domain. Validates the function sender is the local MessageTransmitter, and the remote sender is a registered remote TokenMessenger for remoteDomain. Parameters
FieldTypeDescription
remoteDomainuint32The domain where the message originated from
senderbytes32The sender of the message (remote TokenMessenger)
finalityThresholdExecuteduint32Specifies the level of finality Iris signed the message with
messageBodybytes (dynamic length)The message body bytes

handleReceiveUnfinalizedMessage

Handles incoming message received by the local MessageTransmitter, and takes the appropriate action. For a burn message, mints the associated token to the requested recipient on the local domain. Validates the function sender is the local MessageTransmitter, and the remote sender is a registered remote TokenMessenger for remoteDomain. Similar to handleReceiveFinalizedMessage, but is called for messages which are not finalized (finalityThresholdExecuted < 2000). Unlike handleReceiveFinalizedMessage, handleReceiveUnfinalizedMessage has the following messageBody parameters:
  • expirationBlock. If expirationBlockblockNumber on the destination domain, the message will revert and must be re-signed without the expiration block.
  • feeExecuted. If nonzero, the feeExecuted is minted to the feeRecipient.
Parameters
FieldTypeDescription
remoteDomainuint32The domain where the message originated from
senderbytes32The sender of the message (remote TokenMessenger)
finalityThresholdExecuteduint32Specifies the level of finality Iris signed the message with
messageBodybytes (dynamic length)The message body bytes (see Message format)

MessageTransmitterV2

receiveMessage

Receive message on destination chain by passing message and attestation. Emits MessageReceived event. Messages with a given nonce can only be broadcast successfully once for a pair of domains. The message body of a valid message is passed to the specified recipient for further processing. Parameters
FieldTypeDescription
messagebytesEncoded message (see Message format)
attestationbytesSigned attestation received from attestation service (Iris)

sendMessage

Sends a message to the recipient on the destination domain. Emits a MessageSent event which will be attested by Circle’s attestation service. Parameters
FieldTypeDescription
destinationDomainuint32Destination domain ID to send the message to
recipientbytes32Address of recipient on destination domain
destinationCallerbytes32Address as bytes32 which can call receiveMessage on destination domain. If set to bytes32(0), any address can call receiveMessage
minFinalityThresholduint32Minimum finality threshold requested.

Initially, supported values for minFinalityThreshold are [1, 2000]. A value outside of the support values range will be interpreted as 2000 (finalized) by the attestation service (Iris).

For a value within the supported range, the attestation service (Iris) will attest the message with a finalityThresholdExecuted >= minFinalityThreshold.

Initial thresholds supported:

1000: Confirmed
2000: Finalized
messageBodybytesApp-specific message to be handled by recipient

CCTP V2 Workflow vs. CCTP V1

This table highlights the key workflow improvements of CCTP V2 over CCTP V1 in terms of enhanced cross-chain messaging, fewer manual steps, and greater control over message acceptance:
CCTP V2CCTP V1
Burn USDC via depositForBurnWithHook

You can call depositForBurnWithHook on TokenMessengerV2, which supports hooks and finality thresholds. New parameters include destinationCaller, maxFee, and minFinalityThreshold, allowing you to choose Fast Transfer (1000) or Standard Transfer (2000).
Burn USDC via depositForBurn

In CCTP V1, you call depositForBurn on TokenMessenger.
Retrieve, Hash, and Wait for Attestation

Iris automates message retrieval and hashing, allowing you to just poll for attestation via GET /v2/messages. The attestation includes both the hashed message and the attestation signature.
Retrieve and Hash Message explicitly

In CCTP V1, you need to manually extract and hash the messageBytes data from the MessageSent event logs using Keccak256.
Wait for Attestation via Iris

The attestation request is merged with message retrieval and hashing from the previous step. You simply wait for the polling to complete and retrieve the attestation.
Request Attestation from Circle’s Attestation Service

In CCTP V1, you poll for attestation via GET /v1/attestations.
Send Messages via MessageTransmitterV2#sendMessage

The recipient must implement message handling methods based on finality thresholds:
handleReceiveFinalizedMessage for messages with finalityThresholdExecuted ≥ 2000 (fully finalized).
handleReceiveUnfinalizedMessage for messages with finalityThresholdExecuted < 2000 (pre-finalized).

This allows recipients to enforce specific finality requirements before accepting a message.
Send Messages via MessageTransmitter#sendMessage

In CCTP V1, you send an arbitrary message via sendMessage on MessageTransmitter. The recipient must implement IMessageHandler#handleReceiveMessage to process the message.

WHAT’S NEXT
I