> ## 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.

# Batch operations

> Submit multiple user operations as a batch

Both developer-controlled wallets and modular smart contract accounts (MSCAs)
support batching user operations into a single atomic transaction. These batched
operations have several advantages:

* Users only need to wait for a single batched transaction to execute, instead
  of multiple individual transactions.
* Users pay less in gas fees, as batched transactions cost less than multiple
  individual transactions.
* Transactions are atomic: if any transaction in the batch reverts, the entire
  batch reverts.

You can batch transactions through the
[`contractExecution`](/api-reference/wallets/developer-controlled-wallets/create-developer-transaction-contract-execution)
endpoint.

## Example: Batch transfer

The following example demonstrates how to generate a call to the
`contractExecution` endpoint that batches two USDC transfer transactions. This
example uses an MSCA wallet, on the ETH-SEPOLIA testnet.

This code creates the encoding of the `transfer` function calls that make up the
`abiParameters` data for the call to the `contractExecution` endpoint:

```javascript JavaScript theme={null}
const { ethers } = require("ethers");

const abiEncode = async function () {
  // encode callData for transfers
  const abiTransfer = ["function transfer(address recipient, uint256 amount)"];
  const contractInterfaceTransfer = new ethers.utils.Interface(abiTransfer);
  let data = contractInterfaceTransfer.encodeFunctionData("transfer", [
    "0xa1404d9E7646b0112C49aE0296D6347C956D0867",
    100000000, // 100 usdc
  ]);
  console.log(data);
};

abiEncode()
  .then(() => process.exit(0))
  .catch((error) => {
    console.error(error);
    process.exit(1);
  });
```

Note that the preceding code sample encodes only a single call to the `transfer`
function, the call is then specified twice in the `abiParameters` field of the
call to the `contractExecution` endpoint.

```json JSON theme={null}
{
  "idempotencyKey": "{{$randomUUID}}",
  "walletId": "{{wallet-id}}",
  "feeLevel": "HIGH",
  "refId": "test batch transfer",

  "contractAddress": "0xcd3d4d703f1884313e8f3188a8c60cc6d389ebd1", // sca wallet address

  "abiFunctionSignature": "executeBatch((address, uint256, bytes)[])",
  "abiParameters": [
    [
      [
        "0x1c7d4b196cb0c7b01d743fbc6116a902379c7238",
        "0",
        "0xa9059cbb000000000000000000000000a1404d9e7646b0112c49ae0296d6347c956d08670000000000000000000000000000000000000000000000000000000000000001"
      ],
      [
        "0x1c7d4b196cb0c7b01d743fbc6116a902379c7238",
        "0",
        "0xa9059cbb000000000000000000000000a1404d9e7646b0112c49ae0296d6347c956d08670000000000000000000000000000000000000000000000000000000000000001"
      ]
    ]
  ],

  "entitySecretCiphertext": "{{entity-secret-ciphertext}}"
}
```

The function signature called is
`executeBatch((address address, uint256 amount, bytes func)[])`. The `address`
is the USDC contract address, `amount` is `0` (the amount of native token
transferred), and `func` is the encoded function call generated by the sample
code. The example provides the parameters twice, so the resulting batched
transactions result in 200 USDC transferred (100 for each transaction).

## Example: Batching CCTP approve and depositForBurn

The following example demonstrates how to generate a call to the
`contractExecution` endpoint that batches two related transactions: `approve`,
and `depositForBurn` in the CCTP contract. This example uses an MSCA wallet, on
the ETH-SEPOLIA testnet.

This code creates the encoding of the two calls that make up the `abiParameters`
data for the call to the `contractExecution` endpoint.

```javascript JavaScript theme={null}
const { ethers } = require("ethers");

const abiEncode = async function () {
  const abiDepositForBurn = [
    "function depositForBurn(uint256,uint32,bytes32,address)",
  ];
  const abiApprove = ["function approve(address,uint256)"];
  const contractInterfaceApprove = new ethers.utils.Interface(abiApprove);
  const contractInterfaceDepositForBurn = new ethers.utils.Interface(
    abiDepositForBurn,
  );

  // encode approve
  let dataApprove = contractInterfaceApprove.encodeFunctionData("approve", [
    "0x9f3B8679c73C2Fef8b59B4f3444d4e156fb70AA5",
    100000000, // 100 usdc
  ]);
  console.log(dataApprove);

  // encode sca wallet address
  const abi = ethers.utils.defaultAbiCoder;
  let encodedAddress = abi.encode(
    ["address"],
    ["0xc4b69f1f26c820e7fa18c925da8bf2b2a3357fe0"],
  );
  console.log(encodedAddress);

  // encode depositForBurn
  let dataDepositForBurn = contractInterfaceDepositForBurn.encodeFunctionData(
    "depositForBurn",
    [
      100000000,
      2, // AVAX
      encodedAddress, // encoded sca wallet address
      "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238", // usdc contract
    ],
  );
  console.log(dataDepositForBurn);
};

abiEncode()
  .then(() => process.exit(0))
  .catch((error) => {
    console.error(error);
    process.exit(1);
  });
```

The first transaction in the batch is a call to the function on the USDC
contract: `approve(address spender, uint256 value)`. Calling `approve` allows
the `spender` to spend `value` USDC on your behalf. This is necessary for the
subsequent `depositForBurn` transaction in the batch. In this example, `address`
is the `TokenMessenger` contract address and the `value` is `100000000` (100
USDC). Note that the example code encodes the parameters of the function call,
the subsequent call to the Circle API specifies the contract address to make the
call to.

The second transaction in the batch is a call to the function on the
`TokenMessenger` contract:
`depositForBurn(uint256 amount, uint32 destinationDomain, bytes32 mintRecipient, address burnToken)`.
Calling `depositForBurn` results in the `TokenMessenger` contract transferring
and burning the specified amount of USDC from the wallet on the origin chain.
The parameters to the `depositForBurn` call are:

* `amount`: the amount of USDC to burn. In this example, `100000000` (100 USDC)
* `destinationDomain`: a Circle-issued identifier for a network where Circle
  deploys CCTP contracts. In this example, `2` to specify Avalanche. For a full
  list, see the
  [CCTP domain list](/cctp/cctp-supported-blockchains#cctp-supported-domains).
* `mintRecipient`: the destination address, encoded as a Solidity address.
* `burnToken`: the contract address of the token to burn. In this example, the
  USDC contract on the source chain.

The preceding code results in a request to the `contractExecution` endpoint like
this:

```json JSON theme={null}
{
  "idempotencyKey": "{{$randomUUID}}",
  "walletId": "{{wallet-id}}",
  "feeLevel": "HIGH",
  "refId": "test batch CCTP",
  "contractAddress": "0xcd3d4d703f1884313e8f3188a8c60cc6d389ebd1", // sca wallet address
  "abiFunctionSignature": "executeBatch((address, uint256, bytes)[])",
  "abiParameters": [
    [
      [
        "0x1c7d4b196cb0c7b01d743fbc6116a902379c7238",
        "0",
        "0x095ea7b30000000000000000000000009f3b8679c73c2fef8b59b4f3444d4e156fb70aa500000000000000000000000000000000000000000000000000000000000003e8"
      ],
      [
        "0x9f3B8679c73C2Fef8b59B4f3444d4e156fb70AA5",
        "0",
        "0x6fd3504e00000000000000000000000000000000000000000000000000000000000003e80000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c4b69f1f26c820e7fa18c925da8bf2b2a3357fe00000000000000000000000001c7d4b196cb0c7b01d743fbc6116a902379c7238"
      ]
    ]
  ],
  "entitySecretCiphertext": "{{entity-secret-ciphertext}}"
}
```

The function signature called is
`executeBatch((address address, uint256 amount, bytes func)[])`. The parameters
for each transaction are:

* `approve`
  * `address` is the USDC token contract address
  * `amount` is the amount of native tokens transferred
  * `func` is the encoded function call generated by the sample code

* `depositForBurn`
  * `address` is the `TokenMessenger` contract address
  * `amount` is the amount of native tokens transferred
  * `func` is the encoded function call generated by the sample code
