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

# CCTP split transfer

> The cctp-split and plain-transfer programs shipped in @eco-incorp/sauce: move a USDC amount in CCTP depositForBurn calls capped per message, atomically in one cook, and the no-bridge baseline. Built into intents by buildCctpSplitTransfer and buildPlainTransfer.

Two programs ship together in `@eco-incorp/sauce/recipes`. Their values arrive as compile-time `defines`: the consts are declared with placeholder defaults so each file reads and compiles standalone, and the builders (`buildCctpSplitTransfer`, `buildPlainTransfer`) override them per intent. A define replaces the module's own `const` of that name and is constant-folded, so a given set of values yields fixed bytecode. This is the opposite design from [settle](/cookbook/sauce/settle), whose values are runtime arguments so its bytecode stays hash-pinnable.

Both programs are DSL-native with no ABI and no address in the source: `USDC` resolves to the source chain's USDC from the token registry, and `Cctp.TokenMessenger` resolves interface and address from the CCTP protocol descriptor, in call position and in value position (as the approve spender). Declarations are unannotated because the accessor rewrite that resolves them parses plain JavaScript.

## Prerequisites

Complete [Sauce setup](/programmable-transactions/sauce/getting-started) and use the documented SDK and compiler versions. For execution, confirm the target deployment, Pot ownership, balances and Kitchen fee. Simulate the complete transaction and estimate its gas before submitting it.

## cctp-split

Move `CCTP_AMOUNT` in burns capped at `CCTP_CHUNK_SIZE`: `count = amount / chunkSize` full-cap burns, then one final burn of the remainder when it is not zero. `$2.50` at a `$1` cap becomes `$1 + $1 + $0.50`. One approval for the whole amount; if any burn reverts, the entire source-chain transaction reverts.

```typescript cctp-split.sauce.ts theme={null}
const CCTP_RECIPIENT = 0n;
const CCTP_AMOUNT = 0n;
const CCTP_CHUNK_SIZE = 1n;
const CCTP_DEST_DOMAIN = 0n;
const CCTP_MAX_FEE = 0n;

function main() {
  USDC.approve(Cctp.TokenMessenger, CCTP_AMOUNT);
  let count = CCTP_AMOUNT / CCTP_CHUNK_SIZE;
  for (let i = 0n; i < count; i++) {
    Cctp.TokenMessenger.depositForBurn(
      CCTP_CHUNK_SIZE,
      CCTP_DEST_DOMAIN,
      CCTP_RECIPIENT,
      USDC,
      0n,
      CCTP_MAX_FEE,
      0n,
    );
  }
  let remainder = CCTP_AMOUNT % CCTP_CHUNK_SIZE;
  if (remainder > 0n) {
    Cctp.TokenMessenger.depositForBurn(
      remainder,
      CCTP_DEST_DOMAIN,
      CCTP_RECIPIENT,
      USDC,
      0n,
      CCTP_MAX_FEE,
      0n,
    );
  }
  return 0n;
}
```

## plain-transfer

The no-bridge baseline: move `XFER_AMOUNT` USDC to `XFER_RECIPIENT` in one call. The solver delivers the amount on the destination chain through the normal Eco flow.

```typescript plain-transfer.sauce.ts theme={null}
const XFER_RECIPIENT = 0n;
const XFER_AMOUNT = 0n;

function main() {
  USDC.transfer(XFER_RECIPIENT, XFER_AMOUNT);
  return 0n;
}
```

## Build them into intents

```typescript theme={null}
import { buildCctpSplitTransfer, buildPlainTransfer } from "@eco-incorp/sauce/recipes";
```

Both take a `CctpTransferParams` (`from`, `to`, `amount`, `perMessageLimit`, `recipient`, optional `maxFeePerChunk`, `pot`, `engine`, `portal`, and the remaining fields listed in the reference) and return a `BuiltIntent`. The CCTP variant is fulfilled locally on the source chain, so the intent's destination is its source. Reference: [recipes](/sdk-reference/sauce/recipes/cctp-transfer), [`routes.BuiltIntent`](/sdk-reference/sauce/routes/open-route#routes-builtintent).

In SDK 0.99.4, these convenience builders do not set a nonzero cook fee or request the token delivery and Executor-to-Pot transfer needed by the program. Their output is not ready to submit to a paid Kitchen. To integrate these programs, load `cctpSplitSource()` or `plainTransferSource()` and build the route with explicit `execution.value`, `nativeAmount`, `tokens` and `precalls`, following [Programs as intents](/programmable-transactions/sauce/programs-as-intents).

CCTP burns occur on the source chain. Destination minting is a separate process and is not part of the source transaction's atomicity.

## Troubleshooting

The CCTP builder rejects a nonpositive amount or chunk size and destinations without a registered CCTP domain. Check the current per-message limit and fee configuration for your source chain, and simulate using the actual recipient and amounts.

## Next steps

[Build an intent with explicit funding and execution fees](/programmable-transactions/sauce/getting-started).
