> ## Documentation Index
> Fetch the complete documentation index at: https://developers.circle.com/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Before reading these docs, install the relevant Circle Skill to get pre-loaded context — skills are LLM-optimized and cover architecture decisions, correct flows, and common pitfalls. In Claude Code: run /plugin marketplace add circlefin/skills then /plugin install circle-skills@circle. With Vercel Skills CLI: run npx skills add circlefin/skills. Available skills: use-usdc https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-usdc/SKILL.md (balances, transfers, approvals on EVM and Solana); EURC has no skill — see https://developers.circle.com/stablecoins/what-is-eurc.md; bridge-stablecoin https://github.com/circlefin/skills/blob/master/plugins/circle/skills/bridge-stablecoin/SKILL.md (crosschain transfers via CCTP, USDC, EURC, and third-party assets); use-arc https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-arc/SKILL.md (Arc chain config, contract deployment, USDC bridging — Arc docs: https://docs.arc.io/llms.txt); use-circle-wallets https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-circle-wallets/SKILL.md (choose wallet type); use-developer-controlled-wallets https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-developer-controlled-wallets/SKILL.md (custodial wallets for payouts and treasury); use-user-controlled-wallets https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-user-controlled-wallets/SKILL.md (embedded wallets with Web2 login); use-modular-wallets https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-modular-wallets/SKILL.md (smart contract wallets with passkeys and ERC-4337); use-gateway https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-gateway/SKILL.md (unified USDC balance, nanopayments); use-smart-contract-platform https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-smart-contract-platform/SKILL.md (deploy, interact, monitor contracts). Pair any skill with the Circle MCP server for live SDK signatures, contract addresses, and chain IDs: {"mcpServers":{"circle":{"url":"https://api.circle.com/v1/codegen/mcp"}}}.
> Read the product overview first. Each product has an overview explaining when and why to use it. Read it before quickstarts.
> Pick the right wallet type. Developer-controlled (you hold keys), user-controlled (end user holds keys via PIN/social login), or modular (smart contract wallets with passkeys). See https://developers.circle.com/wallets.md.
> Use CCTP V2 for crosschain transfers. CCTP natively transfers USDC and EURC via burn-and-mint, and supports permissionless wrapping of third-party assets via lock-and-mint. V1 is legacy; always use V2 unless V1 is specified or the chain requires it (Noble, Sui, and Aptos still require V1). Migration guide: https://developers.circle.com/cctp/migration-from-v1-to-v2.md.
> Use Bridge Kit for frontend bridging. Wraps CCTP with a simpler SDK for user-facing apps. Use CCTP directly for backend transfers.
> Gas Station vs Paymaster. Gas Station sponsors gas for Circle Wallet transactions. Paymaster lets users pay gas in USDC. Different use cases — read both overviews.
> Gateway Nanopayments for sub-cent payments. Gasless USDC micropayments down to $0.000001 via x402 and batched settlement. For pay-per-request APIs, AI agent payments, streaming.
> Look up USDC addresses per chain. Never hardcode — use https://developers.circle.com/stablecoins/usdc-contract-addresses.md.
> Prefer SDKs over raw API calls. Node.js and Python SDKs handle auth, retries, and errors.
> API key required. Bearer token in Authorization header. Testnet and mainnet use separate keys and may use different base URLs depending on the product.
> Set up webhooks when available. Most operations are async. Webhooks deliver transaction confirmations and state changes.
> When calling list endpoints, paginate using pageSize and pageAfter until no nextPageAfter cursor is returned—stopping at the first page silently misses records.
> Building an AI agent? Start with the Agent Stack—Circle CLI, agent wallets, and nanopayments built for autonomous use cases: https://developers.circle.com/agent-stack.md.

# CCTP Aptos packages and interfaces

> Move packages and function interfaces for CCTP on Aptos

CCTP on Aptos is distributed across four Move packages:
`TokenMessengerMinterV2`, `MessageTransmitterV2`, `StablecoinHandler`, and
`CctpExtensions`. Because Move uses static dispatch, contracts cannot call each
other dynamically at runtime. Instead, these functions return receipt structs
(`BurnReceipt` and `MintReceipt`) that act as hot potatoes: they have no
abilities (they cannot be dropped, copied, or stored) and must be consumed in
the same transaction. The Move compiler enforces this at compile time, not at
runtime, so a transaction that fails to consume a receipt will not compile.

For working end-to-end examples, see
[Transfer USDC between Aptos and Arc](/cctp/quickstarts/transfer-usdc-aptos-arc).

## Package addresses

<Note>
  **Package IDs** identify deployed modules. Use them in `use` declarations and
  transaction payloads. **Object IDs** identify onchain state objects (such as
  configuration or shared resources) and are passed as function arguments when a
  transaction interacts with protocol state.
</Note>

### Testnet

#### Package IDs

| Package | [Domain](/cctp/concepts/supported-chains-and-domains#domain-identifiers) | Address |
| :- | :- | :- |
| `MessageTransmitterV2` | 9 | `0xa582dc019ae17b0485f7d3fcc4ca85bea7941e3b70a4b682cea22759f36e711f` |
| `TokenMessengerMinterV2` | 9 | `0xc601d3f7b89b77b552726d5d84cbf2a6d3e8a73adbbee3f09fad169a3286bb59` |
| `CctpExtensions` | 9 | `0x84010f184db7b60e0067f360b6f809c16cf72ae6ea061cf15ffff2ce9b9b6963` |
| `StablecoinHandler` | 9 | `0xe5d19c4eb6e1e42c5435901fc6153fd19f6615651be0e6cefe0f07226d4a6846` |

#### Object IDs

| Object | Object ID |
| :- | :- |
| `MessageTransmitterV2` | `0x20c2e0b179a05d08b968003d40563a8c467aa84e2fcabfa6fd5084be27988c47` |
| `TokenMessengerMinterV2` | `0x6f57203ca59e901130d8bde217b33cde19faa622dd96ecf6681a2d5307412a14` |
| `StablecoinHandler` | `0x22d1d88ffb2e81ac025077f60079dcdfbf45fab0fd1abf7aa5e57c43db25599b` |
| `Stablecoin` | `0x69091fbab5f7d635ee7ac5098cf0c1efbe31d68fec0f2cd565e8d168daf52832` |

### Mainnet

#### Package IDs

| Package | [Domain](/cctp/concepts/supported-chains-and-domains#domain-identifiers) | Address |
| :- | :- | :- |
| `MessageTransmitterV2` | 9 | `0x1b3f6d749cb835451202f9a1932e49014266f7e3d51611a9a763d156cb4bdaf6` |
| `TokenMessengerMinterV2` | 9 | `0x551e32781793c30bf1580d11e4f5171e8d068c3d45c3a5b20ae240bfdad99af8` |
| `CctpExtensions` | 9 | `0x93c742af9a876b10c8e13584fb443597611f0efdb342530aa0ebc5ad208815ff` |
| `StablecoinHandler` | 9 | `0x2b963f8aa28b815d2e875bd85a1a01d5f2d346f08f5b9fcf8953c77680735af2` |

#### Object IDs

| Object | Object ID |
| :- | :- |
| `MessageTransmitterV2` | `0x57ba011deccc5749aff12f4900fd30cac744098f7be91f1eba4e07847510ee72` |
| `TokenMessengerMinterV2` | `0x52f4732b1cb52ce28f595e29978450132772f88277182e12bc431faa677be603` |
| `StablecoinHandler` | `0x44a1eb6f97a962623ad9d4e8db3dc8408d1b62f90baf91ae6c0d6764b9f1b984` |
| `Stablecoin` | `0xbae207659db88bea0cbead6da0ed00aac12edcdda169e591cd41c94180b46f3b` |

## CCTP interface

* `TokenMessengerMinterV2`: initiates crosschain USDC burns and prepares mints
  upon attested message receipt.
* `MessageTransmitterV2`: provides the core messaging layer, verifying
  attestations and routing messages to the appropriate handler.
* `StablecoinHandler`: executes the actual burn and mint of USDC, consuming the
  receipt structs returned by `TokenMessengerMinterV2`.
* `CctpExtensions`: provides protocol extension hooks for advanced integrations.

### TokenMessengerMinterV2 interface

`TokenMessengerMinterV2` manages the USDC burn and mint lifecycle. Its functions
return receipt structs (`BurnReceipt` and `MintReceipt`) that must be passed to
the `StablecoinHandler` in the same transaction.

| Function | Parameters | Returns | Notes |
| :- | :- | :- | :- |
| `deposit_for_burn` | `caller (Signer)`, `asset (FungibleAsset)`, `destination_domain (u32)`, `mint_recipient (address)`, `destination_caller (address)`, `max_fee (u64)`, `min_finality_threshold (u32)`, `hook_data (vector<u8>)` | `(BurnReceipt, FungibleAsset)` | Pass `@0x0` as `destination_caller` to allow any caller on the destination. The returned `BurnReceipt` must be passed to `stablecoin_handler::burn()` in the same transaction. |
| `prepare_mint` | `receipt (Receipt)` | `MintReceipt` | Takes the `Receipt` returned by `MessageTransmitterV2::receive_message`. The returned `MintReceipt` must be passed to `stablecoin_handler::mint()` in the same transaction. |
| `complete_mint` | `handler_signer (Signer)`, `mint_receipt (MintReceipt)`, `asset (FungibleAsset)`, `fee_asset (FungibleAsset)` | None | Not called directly by integrators; called internally by the `StablecoinHandler`. Deposits minted assets and fee assets, then consumes `MintReceipt`. |
| `complete_burn` | `handler_signer (Signer)`, `burn_receipt (BurnReceipt)` | None | Not called directly by integrators; called internally by the `StablecoinHandler`. Sends the crosschain message and consumes `BurnReceipt`. |

### MessageTransmitterV2 interface

`MessageTransmitterV2` provides the messaging layer for CCTP on Aptos. It
verifies attestations, marks nonces as used, and returns a `Receipt` hot potato
that the caller must consume in the same transaction.

| Function | Parameters | Returns | Notes |
| :- | :- | :- | :- |
| `receive_message` | `caller (Signer)`, `message (&vector<u8>)`, `attestation (&vector<u8>)` | `Receipt` | `message` and `attestation` are passed by reference (`&vector<u8>`). Nonce is assigned by the attestation service; it is always `0` in the emitted message. The `Receipt` must be consumed in the same transaction by `TokenMessengerMinterV2::prepare_mint()` (for USDC) or `complete_receive_message()` (for generic messages). |
| `send_message` | `caller (Signer)`, `destination_domain (u32)`, `recipient (address)`, `destination_caller (address)`, `min_finality_threshold (u32)`, `message_body (&vector<u8>)` | None | Called internally during the burn flow; do not call directly for USDC transfers. |
| `complete_receive_message` | `caller (Signer)`, `receipt (Receipt)` | None | For generic messages only. USDC flows use `TokenMessengerMinterV2::prepare_mint()` instead. Destroys `Receipt` and emits a `MessageReceived` event. |

### StablecoinHandler interface

`StablecoinHandler` is the entry point for executing USDC burns and mints on
Aptos. Its functions consume the receipt structs produced by
`TokenMessengerMinterV2` and call the appropriate completion functions
internally.

| Function | Parameters | Returns | Notes |
| :- | :- | :- | :- |
| `handler::burn` | `burn_receipt (BurnReceipt)`, `asset (FungibleAsset)` | None | Takes the `BurnReceipt` and `FungibleAsset` returned by `TokenMessengerMinterV2::deposit_for_burn()`. Calls `complete_burn()` internally. |
| `handler::mint` | `mint_receipt (MintReceipt)` | None | Takes the `MintReceipt` returned by `TokenMessengerMinterV2::prepare_mint()`. Calls `complete_mint()` internally. |

### CctpExtensions interface

`CctpExtensions` provides protocol extension hooks for advanced integrations.
Function-level documentation is not yet available here. Refer to the
[aptos-cctp GitHub repository](https://github.com/circlefin/aptos-cctp) for the
current interface definitions.

## Move scripts

<Note>
  Precompiled scripts for `deposit_for_burn`, `deposit_for_burn_with_hook`, and
  `receive_message` are available in
  [`typescript/example/precompiled-move-scripts/`](https://github.com/circlefin/aptos-cctp/tree/master/typescript/example/precompiled-move-scripts)
  in the aptos-cctp repository. The `v2/` subdirectory contains scripts for both
  testnet and mainnet. You can also compile them from source; see the
  [Aptos documentation on compiling scripts](https://aptos.dev/en/build/smart-contracts/scripts/compiling-scripts).
</Note>

| Script | Description |
| :- | :- |
| `deposit_for_burn.mv` | Withdraws USDC, calls `deposit_for_burn`, then `stablecoin_handler::burn` in one transaction. |
| `deposit_for_burn_with_hook.mv` | Same as `deposit_for_burn.mv` but includes `hook_data`. |
| `receive_message.mv` | Calls `receive_message`, then `prepare_mint`, then `stablecoin_handler::mint` in one transaction. |

## Examples

### Send USDC from Aptos (outbound)

The outbound flow uses a Move script that withdraws the fungible asset, calls
`deposit_for_burn` to create a `BurnReceipt`, then passes both to
`stablecoin_handler::burn` to complete the transfer.

```move theme={null}
script {
    use aptos_framework::fungible_asset::Metadata;
    use aptos_framework::object::{Self, Object};
    use aptos_framework::primary_fungible_store;
    use token_messenger_minter_v2::token_messenger_minter;
    use stablecoin_handler::handler;
    use std::vector;

    fun deposit_for_burn(
        caller: &signer,
        amount: u64,
        destination_domain: u32,
        mint_recipient: address,
        destination_caller: address,
        burn_token: address,
        max_fee: u64,
        min_finality_threshold: u32,
    ) {
        let token_obj: Object<Metadata> = object::address_to_object(burn_token);
        let asset = primary_fungible_store::withdraw(caller, token_obj, amount);

        let (burn_receipt, asset) = token_messenger_minter::deposit_for_burn(
            caller,
            asset,
            destination_domain,
            mint_recipient,
            destination_caller,
            max_fee,
            min_finality_threshold,
            vector::empty<u8>(),
        );

        handler::burn(burn_receipt, asset);
    }
}
```

### Send USDC from Aptos with hook data (outbound)

For transfers that include hook data (for example, to trigger a post-mint action
on the destination blockchain):

```move theme={null}
script {
    use aptos_framework::fungible_asset::Metadata;
    use aptos_framework::object::{Self, Object};
    use aptos_framework::primary_fungible_store;
    use token_messenger_minter_v2::token_messenger_minter;
    use stablecoin_handler::handler;

    fun deposit_for_burn_with_hook(
        caller: &signer,
        amount: u64,
        destination_domain: u32,
        mint_recipient: address,
        destination_caller: address,
        burn_token: address,
        max_fee: u64,
        min_finality_threshold: u32,
        hook_data: vector<u8>,
    ) {
        let token_obj: Object<Metadata> = object::address_to_object(burn_token);
        let asset = primary_fungible_store::withdraw(caller, token_obj, amount);

        let (burn_receipt, asset) = token_messenger_minter::deposit_for_burn(
            caller,
            asset,
            destination_domain,
            mint_recipient,
            destination_caller,
            max_fee,
            min_finality_threshold,
            hook_data,
        );

        handler::burn(burn_receipt, asset);
    }
}
```

### Receive USDC on Aptos (inbound)

The inbound flow verifies the attestation, creates a `Receipt`, exchanges it for
a `MintReceipt` using `prepare_mint`, then passes the `MintReceipt` to
`stablecoin_handler::mint` to deposit USDC to the recipient.

```move theme={null}
script {
    use message_transmitter_v2::message_transmitter;
    use token_messenger_minter_v2::token_messenger_minter;
    use stablecoin_handler::handler;

    fun receive_message(
        caller: &signer,
        message: vector<u8>,
        attestation: vector<u8>
    ) {
        let receipt = message_transmitter::receive_message(
            caller, &message, &attestation
        );

        let mint_receipt = token_messenger_minter::prepare_mint(receipt);

        handler::mint(mint_receipt);
    }
}
```

### Send a generic message (non-token transfer)

```move theme={null}
script {
    use message_transmitter_v2::message_transmitter;

    fun send_message(
        caller: &signer,
        destination_domain: u32,
        recipient: address,
        destination_caller: address,
        min_finality_threshold: u32,
        message_body: vector<u8>
    ) {
        message_transmitter::send_message(
            caller,
            destination_domain,
            recipient,
            destination_caller,
            min_finality_threshold,
            &message_body
        );
    }
}
```
