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

# Batched Transactions on EVM: Execute Multiple Operations

> Learn how to batch multiple EVM transactions into one. Reduce gas costs, improve UX, and execute atomic multi-step operations with smart contract wallets

# Batched Transactions on EVM: Execute Multiple Operations

<Accordion title="What are batched transactions?">
  **Batched transactions** combine multiple blockchain operations into a single transaction. Instead of submitting separate transactions (each with its own gas cost and confirmation), you execute everything atomically in one go.

  ```
  Without Batching:
  TX 1: Approve USDC    → Wait → Confirm → Pay gas
  TX 2: Deposit to Aave → Wait → Confirm → Pay gas
  TX 3: Claim rewards   → Wait → Confirm → Pay gas
  Total: 3 signatures, 3 gas payments, 3 confirmations

  With Batching:
  TX 1: [Approve + Deposit + Claim] → Single signature → Single gas payment
  Total: 1 signature, 1 gas payment, atomic execution
  ```

  Batching is enabled by smart contract wallets (account abstraction).
</Accordion>

<Accordion title="Why should I batch transactions?">
  | Benefit                  | Description                                  |
  | ------------------------ | -------------------------------------------- |
  | **Lower gas costs**      | One base transaction fee instead of multiple |
  | **Better UX**            | Users sign once instead of multiple times    |
  | **Atomic execution**     | All operations succeed or all fail together  |
  | **Faster completion**    | No waiting between steps                     |
  | **Reduced failure risk** | No partial state from incomplete sequences   |

  **Gas savings example:**

  | Scenario                  | Without Batching | With Batching | Savings |
  | ------------------------- | ---------------- | ------------- | ------- |
  | Approve + Swap            | \~140k gas       | \~95k gas     | 32%     |
  | 3 token transfers         | \~120k gas       | \~75k gas     | 37%     |
  | Approve + Deposit + Claim | \~200k gas       | \~130k gas    | 35%     |
</Accordion>

<Accordion title="How do I batch transactions with Biconomy?">
  **Using AbstractJS SDK with MEE:**

  ```typescript theme={null}
  import { createMeeClient, toMultichainNexusAccount } from "@biconomy/abstractjs";
  import { encodeFunctionData } from "viem";

  const account = await toMultichainNexusAccount({
    signer: userSigner,
    chains: [base]
  });

  const meeClient = await createMeeClient({ account });

  // Batch multiple operations with MEE
  const quote = await meeClient.getQuote({
    instructions: [
      {
        calls: [
          {
            to: usdcAddress,
            data: encodeFunctionData({
              abi: erc20Abi,
              functionName: "approve",
              args: [aavePool, amount]
            })
          },
          {
            to: aavePool,
            data: encodeFunctionData({
              abi: aaveAbi,
              functionName: "deposit",
              args: [usdcAddress, amount, userAddress, 0]
            })
          },
          {
            to: rewardsController,
            data: encodeFunctionData({
              abi: rewardsAbi,
              functionName: "claimAllRewards",
              args: [assets, userAddress]
            })
          }
        ]
      }
    ]
  });

  const { hash } = await meeClient.executeQuote({ quote });
  console.log("All operations completed in one tx:", hash);
  ```

  <Note>
    MEE (Modular Execution Environment) provides all the batching capabilities of ERC-4337 bundlers and paymasters, plus cross-chain orchestration. Use MEE instead of configuring bundlers and paymasters separately.
  </Note>
</Accordion>

<Accordion title="What operations can I batch together?">
  You can batch any combination of EVM operations:

  **Common batching patterns:**

  | Pattern            | Operations                            |
  | ------------------ | ------------------------------------- |
  | **Token + Action** | Approve → Swap/Deposit/Stake          |
  | **Multi-send**     | Multiple token transfers in one tx    |
  | **DeFi combo**     | Claim → Swap → Deposit                |
  | **NFT batch**      | Approve → List multiple NFTs          |
  | **Gaming**         | Equip + Upgrade + Consume items       |
  | **DAO**            | Delegate → Vote on multiple proposals |

  **Example: Multi-token transfer**

  ```typescript theme={null}
  const transfers = recipients.map(({ address, amount }) => ({
    to: tokenAddress,
    data: encodeFunctionData({
      abi: erc20Abi,
      functionName: "transfer",
      args: [address, amount]
    })
  }));

  // Send to 100 recipients in ONE transaction
  await smartAccount.sendTransactions(transfers);
  ```
</Accordion>

<Accordion title="How does atomic execution work?">
  Atomic execution means **all operations succeed or all fail**. There's no partial state.

  **Why this matters:**

  ```
  Scenario: Approve USDC → Swap USDC for ETH

  Non-atomic (separate txs):
  1. Approve succeeds ✅
  2. Swap fails (price changed) ❌
  Result: Approval is stuck, USDC still approved to router 😰

  Atomic (batched):
  1. [Approve + Swap] fails ❌
  Result: Nothing happened, state unchanged 😌
  ```

  **Biconomy ensures atomicity:**

  ```typescript theme={null}
  try {
    const { hash } = await smartAccount.sendTransactions([
      { /* operation 1 */ },
      { /* operation 2 */ },
      { /* operation 3 */ }
    ]);
    // All succeeded
  } catch (error) {
    // ALL operations reverted, no partial state
    console.log("Batch failed atomically");
  }
  ```
</Accordion>

<Accordion title="Can I batch operations that depend on each other?">
  Yes! Use runtime values to reference outputs from earlier operations:

  ```typescript theme={null}
  import { runtime } from "@biconomy/abstractjs";

  const instructions = [
    // Step 1: Swap ETH for USDC (output unknown until execution)
    {
      type: "intent",
      intent: "swap",
      params: {
        from: "ETH",
        to: "USDC",
        amount: "1.0"
      }
    },
    // Step 2: Use EXACT output from step 1
    {
      to: aavePool,
      data: encodeDeposit(
        usdcAddress,
        runtime.outputOf(0), // Dynamic: uses actual swap output
        userAddress
      )
    }
  ];
  ```

  The `runtime.outputOf(0)` is resolved at execution time with the actual value from the first operation.
</Accordion>

<Accordion title="What's the maximum batch size?">
  Batch size is limited by:

  1. **Block gas limit**: Total gas must fit in a block
  2. **Bundler limits**: Typically 5-10M gas per UserOperation
  3. **Practical limits**: More operations = higher failure risk

  **Guidelines:**

  | Chain    | Recommended Max Operations | Max Gas  |
  | -------- | -------------------------- | -------- |
  | Ethereum | 10-20                      | 3-5M gas |
  | Arbitrum | 20-50                      | 10M gas  |
  | Base     | 20-50                      | 10M gas  |
  | Polygon  | 20-50                      | 8M gas   |

  **Best practices:**

  ```typescript theme={null}
  // Split large batches
  const BATCH_SIZE = 20;

  async function batchTransfer(transfers) {
    const results = [];
    
    for (let i = 0; i < transfers.length; i += BATCH_SIZE) {
      const batch = transfers.slice(i, i + BATCH_SIZE);
      const result = await smartAccount.sendTransactions(batch);
      results.push(result);
    }
    
    return results;
  }
  ```
</Accordion>

<Accordion title="How do I estimate gas for batched transactions?">
  ```typescript theme={null}
  // Estimate gas for batch
  const gasEstimate = await smartAccount.estimateGas({
    transactions: [
      { to: contract1, data: data1 },
      { to: contract2, data: data2 },
      { to: contract3, data: data3 }
    ]
  });

  console.log("Total gas estimate:", gasEstimate);

  // Compare with individual estimates
  const individual1 = await publicClient.estimateGas({ to: contract1, data: data1 });
  const individual2 = await publicClient.estimateGas({ to: contract2, data: data2 });
  const individual3 = await publicClient.estimateGas({ to: contract3, data: data3 });

  const totalIndividual = individual1 + individual2 + individual3;
  const savings = totalIndividual - gasEstimate;

  console.log(`Gas savings from batching: ${savings} (${(savings/totalIndividual*100).toFixed(1)}%)`);
  ```
</Accordion>

<Accordion title="How do I handle failures in batches?">
  **Default behavior: Atomic revert**

  ```typescript theme={null}
  try {
    await smartAccount.sendTransactions([op1, op2, op3]);
  } catch (error) {
    // Entire batch reverted
    // Identify which operation failed from error message
    console.log("Batch failed:", error.message);
  }
  ```

  **For non-critical operations, use conditional execution:**

  ```typescript theme={null}
  const { conditions } = require("@biconomy/abstractjs");

  const transactions = [
    // Critical: Always execute
    { to: contract1, data: data1 },
    
    // Optional: Only if balance exists
    {
      to: contract2,
      data: data2,
      condition: conditions.hasBalance(tokenAddress, minAmount)
    },
    
    // Optional: Only if previous succeeded
    {
      to: contract3,
      data: data3,
      condition: conditions.previousSucceeded()
    }
  ];
  ```

  **Pre-validate operations:**

  ```typescript theme={null}
  async function validateBatch(transactions) {
    const simulations = await Promise.all(
      transactions.map(tx => 
        publicClient.simulateContract({
          address: tx.to,
          data: tx.data
        }).catch(e => ({ error: e }))
      )
    );
    
    const failures = simulations.filter(s => s.error);
    if (failures.length > 0) {
      console.log("Operations that would fail:", failures);
      return false;
    }
    return true;
  }
  ```
</Accordion>

<Accordion title="Can I batch across multiple chains?">
  Yes! Cross-chain batching is possible with Biconomy's orchestration:

  ```typescript theme={null}
  const crossChainBatch = {
    instructions: [
      // Chain 1: Ethereum
      {
        chainId: 1,
        to: usdcEthereum,
        data: encodeApprove(bridge, amount)
      },
      // Bridge operation
      {
        type: "intent",
        intent: "bridge",
        params: { token: "USDC", from: 1, to: 8453, amount }
      },
      // Chain 2: Base
      {
        chainId: 8453,
        to: aaveBase,
        data: encodeDeposit(usdcBase, runtime.bridgeOutput, user)
      }
    ]
  };

  // One signature covers all chains
  const result = await meeClient.execute(crossChainBatch);
  ```

  See [Multi-Chain Execution](/faq/multi-chain-execution) for details.
</Accordion>

<Accordion title="What are real-world batching examples?">
  **Example 1: DeFi Yield Optimization**

  ```typescript theme={null}
  // Claim rewards → Swap to stablecoin → Redeposit
  await smartAccount.sendTransactions([
    // Claim pending rewards
    { to: farm, data: encodeClaim() },
    // Approve swap
    { to: rewardToken, data: encodeApprove(router, maxUint256) },
    // Swap rewards to USDC
    { to: router, data: encodeSwap(rewardToken, usdc, rewardAmount) },
    // Deposit USDC back into farm
    { to: farm, data: encodeDeposit(usdc, usdcAmount) }
  ]);
  ```

  **Example 2: NFT Marketplace Listing**

  ```typescript theme={null}
  // Approve collection → List multiple NFTs
  const listings = tokenIds.map(id => ({
    to: marketplace,
    data: encodeList(collection, id, price)
  }));

  await smartAccount.sendTransactions([
    { to: collection, data: encodeSetApprovalForAll(marketplace, true) },
    ...listings
  ]);
  ```

  **Example 3: Payroll Distribution**

  ```typescript theme={null}
  // Approve total → Transfer to all employees
  const totalAmount = employees.reduce((sum, e) => sum + e.amount, 0n);

  const transfers = employees.map(({ address, amount }) => ({
    to: paymentToken,
    data: encodeTransfer(address, amount)
  }));

  await smartAccount.sendTransactions([
    { to: paymentToken, data: encodeApprove(batchContract, totalAmount) },
    ...transfers
  ]);
  ```
</Accordion>

***

## Learn more

<CardGroup cols={2}>
  <Card title="Multi-Chain Execution" icon="link" href="/faq/multi-chain-execution">
    Batch across multiple chains
  </Card>

  <Card title="Onchain Orchestration" icon="diagram-project" href="/faq/onchain-orchestration">
    Coordinate complex workflows
  </Card>
</CardGroup>
