CCTPHelper

Git Source

Title: CCTPHelper

Author: Malda Protocol

Helper for building/sending/receiving CCTP v2 messages and encoding/decoding hook payloads.

State Variables

TOKEN_MESSENGER

Circle TokenMessenger (v2) used to burn tokens and attach hook data.

address public immutable TOKEN_MESSENGER

MESSAGE_TRANSMITTER

Circle MessageTransmitter (v2) used to validate and receive messages with attestations.

address public immutable MESSAGE_TRANSMITTER

acceptedTokens

Token allowlist for burns via CCTP.

mapping(address token => bool isAccepted) public acceptedTokens

Functions

constructor

Constructor for the CCTPHelper contract.

constructor(address _tokenMessenger, address _messageTransmitter) ;

Parameters

NameTypeDescription
_tokenMessengeraddressAddress of the TokenMessenger contract.
_messageTransmitteraddressAddress of the MessageTransmitter contract.

createAndBurn

Burns tokens via CCTP v2 and returns the decoded message struct plus its encoded representation.

function createAndBurn(
    address _token,
    uint256 _amount,
    uint32 _dstDomain,
    bytes32 _receiver,
    bytes memory _payload,
    uint32 _srcDomain
) internal returns (CCTPMessage memory msgData, bytes memory encoded);

Parameters

NameTypeDescription
_tokenaddressToken to burn.
_amountuint256Amount to burn.
_dstDomainuint32Destination CCTP domain.
_receiverbytes32Receiver bytes32 (typically the bridge address encoded).
_payloadbytesApp payload to attach as hook data.
_srcDomainuint32Source CCTP domain.

Returns

NameTypeDescription
msgDataCCTPMessageParsed message struct (nonce is 0 for v2).
encodedbytesPacked encoding of msgData produced by _encodeMsg.

handleDestinationMsg

Validates a CCTP message+attestation via Circle and decodes the embedded hook payload into a CCTPMessage.

function handleDestinationMsg(bytes calldata cctpMessage, bytes calldata attestation)
    internal
    returns (CCTPMessage memory msgData);

Parameters

NameTypeDescription
cctpMessagebytesRaw CCTP message bytes.
attestationbytesCircle attestation proving message validity.

Returns

NameTypeDescription
msgDataCCTPMessageDecoded app-level message extracted from the hook payload.

_toBytes32

Converts an address to a left-padded bytes32 representation.

function _toBytes32(address addr) internal pure returns (bytes32);

Parameters

NameTypeDescription
addraddressAddress to convert.

Returns

NameTypeDescription
<none>bytes32Encoded bytes32.

_burnSrc

Burns tokens via CCTP v2 and returns the nonce.

function _burnSrc(address _token, uint256 _amount, uint32 _dstDomain, bytes32 _receiver, bytes memory _payload)
    private
    returns (uint64 nonce);

Parameters

NameTypeDescription
_tokenaddressToken to burn.
_amountuint256Amount to burn.
_dstDomainuint32Destination CCTP domain.
_receiverbytes32Receiver bytes32 (typically the bridge address encoded).
_payloadbytesApp payload to attach as hook data.

Returns

NameTypeDescription
nonceuint64Nonce of the burn.

_encodeMsg

Encodes a CCTPMessage into a compact, packed byte format. Layout (all fields big-endian where applicable):

  • [ 0 .. 0] : uint8 payloadId (fixed = 1)
  • [ 1 .. 32] : bytes32 token (ERC20 address left-padded to 32 bytes)
  • [ 33 .. 64] : uint256 amount
  • [ 65 .. 68] : uint32 srcChain (CCTP domain / chain id)
  • [ 69 .. 72] : uint32 dstChain
  • [ 73 .. 80] : uint64 nonce (0 for CCTP v2; kept for compatibility)
  • [ 81 .. 112] : bytes32 from (sender address left-padded)
  • [113 .. 144] : bytes32 receiver (receiver address or arbitrary 32 bytes)
  • [145 .. 146] : uint16 payloadLen (length of payload below)
  • [147 .. end] : bytes payload (opaque app-level payload) Minimum length with empty payload is therefore 147 bytes.

Encodes a CCTPMessage into a compact, packed byte format.

function _encodeMsg(CCTPMessage memory message) private pure returns (bytes memory);

Parameters

NameTypeDescription
messageCCTPMessageCCTPMessage to encode.

Returns

NameTypeDescription
<none>bytesencoded Encoded packed representation of the message.

_decodeMsg

Decodes bytes produced by _encodeMsg back into a CCTPMessage. Expects exactly the layout documented above:

  • Reverts with CCTPHelper_MsgTooShort if the buffer is shorter than the fixed header (147 bytes).
  • Reverts with CCTPHelper_PayloadMismatch if payloadId != 1.
  • Reverts with CCTPHelper_LengthMismatch if the trailing bytes length does not match the embedded payloadLen. Numeric fields are read as big-endian from the high bits of a 32-byte word:
  • uint32 values are taken from the highest 4 bytes of the word (shr(224, ...)).
  • uint64 values are taken from the highest 8 bytes of the word (shr(192, ...)).
  • uint16 values are taken from the highest 2 bytes of the word (shr(240, ...)). The payload bytes are copied verbatim into a new bytes array.

Decodes bytes produced by _encodeMsg back into a CCTPMessage.

function _decodeMsg(bytes memory encoded) private pure returns (CCTPMessage memory message);

Parameters

NameTypeDescription
encodedbytesEncoded packed representation of the message.

Returns

NameTypeDescription
messageCCTPMessageDecoded CCTPMessage.

Events

BurnInitiated

Emitted after a burn is initiated via TokenMessenger.

event BurnInitiated(
    address indexed token,
    uint256 amount,
    uint32 dstDomain,
    bytes32 indexed recipient,
    uint64 indexed nonce,
    bytes payload
);

Parameters

NameTypeDescription
tokenaddressThe ERC20 token burned.
amountuint256The amount burned.
dstDomainuint32The destination CCTP domain.
recipientbytes32The destination recipient (bytes32).
nonceuint64Always 0 for CCTP v2 (kept for compatibility).
payloadbytesHook payload passed to Circle.

MessageCreated

Emitted when an app-level message payload is constructed and encoded.

event MessageCreated(
    bytes32 indexed token,
    uint256 amount,
    uint32 indexed srcDomain,
    uint32 indexed dstDomain,
    uint64 nonce,
    bytes32 from,
    bytes32 receiver,
    bytes payload,
    bytes encodedMessage
);

Parameters

NameTypeDescription
tokenbytes32Token address (bytes32 encoded).
amountuint256Amount burned.
srcDomainuint32Source CCTP domain.
dstDomainuint32Destination CCTP domain.
nonceuint64Always 0 for CCTP v2 (kept for compatibility).
frombytes32Sender (bytes32 encoded).
receiverbytes32Receiver (bytes32).
payloadbytesApp payload.
encodedMessagebytesEncoded packed representation produced by _encodeMsg.

MessageReceived

Emitted after a message is received/validated by Circle and decoded into the app payload.

event MessageReceived(
    uint64 indexed nonce,
    uint32 indexed srcDomain,
    uint32 indexed dstDomain,
    uint256 amount,
    bytes32 receiver,
    bytes payload
);

Parameters

NameTypeDescription
nonceuint64Always 0 for CCTP v2 (kept for compatibility).
srcDomainuint32Source CCTP domain.
dstDomainuint32Destination CCTP domain.
amountuint256Amount received.
receiverbytes32Receiver (bytes32).
payloadbytesApp payload.

Errors

CCTPHelper_AmountZero

error CCTPHelper_AmountZero();

CCTPHelper_AddressZero

error CCTPHelper_AddressZero();

CCTPHelper_TokenNotAccepted

error CCTPHelper_TokenNotAccepted();

CCTPHelper_ReceiveFailed

error CCTPHelper_ReceiveFailed();

CCTPHelper_LengthMismatch

error CCTPHelper_LengthMismatch();

CCTPHelper_PayloadMismatch

error CCTPHelper_PayloadMismatch();

CCTPHelper_MsgTooShort

error CCTPHelper_MsgTooShort();

Structs

CCTPMessage

Struct used to encode and decode the app-level hook payload carried by CCTP v2.

struct CCTPMessage {
    bytes32 token; // ERC20 token address left-padded to 32 bytes
    uint256 amount;
    uint32 srcChain; // CCTP domain on source
    uint32 dstChain; // CCTP domain on destination
    uint64 nonce; // always 0 for v2; kept for compatibility
    bytes32 from; // msg.sender on source (left-padded)
    bytes32 receiver; // receiver/caller bytes32
    bytes payload; // opaque app payload
}