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

# Multicall3

> Batch multiple contract calls in a single transaction for gas efficiency and atomicity

Multicall3 is a utility contract that enables batching multiple contract calls into a single transaction. This provides gas savings, atomic execution, and simplified interaction patterns for complex multi-step operations.

**Contract Address**: `0xcA11bde05977b3631167028862bE2a173976CA11`
**Deployment Status**: Default preinstall
**Repository**: [github.com/mds1/multicall](https://github.com/mds1/multicall)

## Key Features

* **Gas Efficiency**: Save on base transaction costs by batching calls
* **Atomic Execution**: All calls succeed or all revert together (optional)
* **State Consistency**: Read multiple values from the same block
* **Flexible Error Handling**: Choose between strict or permissive execution
* **Value Forwarding**: Send ETH/native tokens with calls

## Core Methods

### `aggregate`

Execute multiple calls and revert if any fail.

```solidity theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
function aggregate(Call[] calldata calls)
    returns (uint256 blockNumber, bytes[] memory returnData)
```

### `tryAggregate`

Execute multiple calls, returning success status for each.

```solidity theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
function tryAggregate(bool requireSuccess, Call[] calldata calls)
    returns (Result[] memory returnData)
```

### `aggregate3`

Most flexible method with per-call configuration.

```solidity theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
function aggregate3(Call3[] calldata calls)
    returns (Result[] memory returnData)
```

### `aggregate3Value`

Like aggregate3 but allows sending value with each call.

```solidity theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
function aggregate3Value(Call3Value[] calldata calls)
    payable returns (Result[] memory returnData)
```

## Usage Examples

### Basic Batch Calls

<CodeGroup>
  ```javascript "Ethers.js Multiple Token Balance Query" expandable theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
  import { ethers } from "ethers";

  const provider = new ethers.JsonRpcProvider("YOUR_RPC_URL");
  const MULTICALL3 = "0xcA11bde05977b3631167028862bE2a173976CA11";

  // Multicall3 ABI
  const multicallAbi = [
    "function aggregate3(tuple(address target, bool allowFailure, bytes callData)[] calls) returns (tuple(bool success, bytes returnData)[] returnData)"
  ];

  const multicall = new ethers.Contract(MULTICALL3, multicallAbi, provider);

  // Example: Read multiple token balances
  async function getMultipleBalances(tokenAddress, accounts) {
    const erc20Abi = ["function balanceOf(address) view returns (uint256)"];
    const iface = new ethers.Interface(erc20Abi);

    // Prepare calls
    const calls = accounts.map(account => ({
      target: tokenAddress,
      allowFailure: false,
      callData: iface.encodeFunctionData("balanceOf", [account])
    }));

    // Execute multicall
    const results = await multicall.aggregate3(calls);

    // Decode results
    const balances = results.map((result, i) => {
      if (result.success) {
        return {
          account: accounts[i],
          balance: iface.decodeFunctionResult("balanceOf", result.returnData)[0]
        };
      }
      return { account: accounts[i], balance: null };
    });

    return balances;
  }
  ```

  ```solidity "Solidity Multi-Token Balance Reader" expandable theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
  // SPDX-License-Identifier: MIT
  pragma solidity ^0.8.0;

  interface IMulticall3 {
      struct Call3 {
          address target;
          bool allowFailure;
          bytes callData;
      }

      struct Result {
          bool success;
          bytes returnData;
      }

      function aggregate3(Call3[] calldata calls)
          external returns (Result[] memory returnData);
  }

  contract MultiTokenReader {
      IMulticall3 constant multicall = IMulticall3(0xcA11bde05977b3631167028862bE2a173976CA11);

      function getTokenBalances(
          address[] calldata tokens,
          address account
      ) external returns (uint256[] memory balances) {
          IMulticall3.Call3[] memory calls = new IMulticall3.Call3[](tokens.length);

          for (uint i = 0; i < tokens.length; i++) {
              calls[i] = IMulticall3.Call3({
                  target: tokens[i],
                  allowFailure: true,
                  callData: abi.encodeWithSignature("balanceOf(address)", account)
              });
          }

          IMulticall3.Result[] memory results = multicall.aggregate3(calls);
          balances = new uint256[](results.length);

          for (uint i = 0; i < results.length; i++) {
              if (results[i].success) {
                  balances[i] = abi.decode(results[i].returnData, (uint256));
              }
          }
      }
  }
  ```
</CodeGroup>

### Complex DeFi Operations

Combine multiple DeFi operations atomically:

```javascript "Complex DeFi Swap and Stake Operation" expandable theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
// Swap and stake in one transaction
async function swapAndStake(tokenIn, tokenOut, amountIn, poolAddress) {
  const calls = [
    // 1. Approve router
    {
      target: tokenIn,
      allowFailure: false,
      callData: iface.encodeFunctionData("approve", [router, amountIn])
    },
    // 2. Perform swap
    {
      target: router,
      allowFailure: false,
      callData: iface.encodeFunctionData("swap", [tokenIn, tokenOut, amountIn])
    },
    // 3. Approve staking
    {
      target: tokenOut,
      allowFailure: false,
      callData: iface.encodeFunctionData("approve", [poolAddress, amountOut])
    },
    // 4. Stake tokens
    {
      target: poolAddress,
      allowFailure: false,
      callData: iface.encodeFunctionData("stake", [amountOut])
    }
  ];

  return await multicall.aggregate3(calls);
}
```

### Reading Protocol State

Get consistent protocol state in one call:

```javascript theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
async function getProtocolState(protocol) {
  const calls = [
    { target: protocol, callData: "0x18160ddd", allowFailure: false }, // totalSupply()
    { target: protocol, callData: "0x313ce567", allowFailure: false }, // decimals()
    { target: protocol, callData: "0x06fdde03", allowFailure: false }, // name()
    { target: protocol, callData: "0x95d89b41", allowFailure: false }, // symbol()
  ];

  const results = await multicall.aggregate3(calls);
  // All values from the same block
  return decodeResults(results);
}
```

## Advanced Features

### Value Forwarding

Send native tokens with calls using `aggregate3Value`:

```javascript "Native Token Forwarding with Multicall3" expandable theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
const calls = [
  {
    target: weth,
    allowFailure: false,
    value: ethers.parseEther("1.0"),
    callData: iface.encodeFunctionData("deposit")
  },
  {
    target: contract2,
    allowFailure: false,
    value: ethers.parseEther("0.5"),
    callData: iface.encodeFunctionData("buyTokens")
  }
];

await multicall.aggregate3Value(calls, {
  value: ethers.parseEther("1.5") // Total ETH to send
});
```

### Error Handling Strategies

```javascript "Error Handling Strategies" expandable theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
// Strict mode - revert if any call fails
const strictCalls = calls.map(call => ({
  ...call,
  allowFailure: false
}));

// Permissive mode - continue even if some fail
const permissiveCalls = calls.map(call => ({
  ...call,
  allowFailure: true
}));

// Mixed mode - critical calls must succeed
const mixedCalls = [
  { ...criticalCall, allowFailure: false },
  { ...optionalCall, allowFailure: true }
];
```

## Common Use Cases

<AccordionGroup>
  <Accordion title="Token Balance Queries">
    Query multiple token balances for multiple users efficiently.
  </Accordion>

  <Accordion title="DEX Price Aggregation">
    Fetch prices from multiple DEXs in a single call for best execution.
  </Accordion>

  <Accordion title="Governance Voting">
    Cast votes on multiple proposals in one transaction.
  </Accordion>

  <Accordion title="DeFi Position Management">
    Claim rewards, compound, and rebalance positions atomically.
  </Accordion>

  <Accordion title="NFT Batch Operations">
    Mint, transfer, or approve multiple NFTs efficiently.
  </Accordion>
</AccordionGroup>

## Gas Optimization

Multicall3 saves gas through:

1. **Base Fee Savings**: Pay the 21,000 gas base fee only once
2. **Storage Optimization**: Warm storage slots across calls
3. **Reduced State Changes**: Fewer transaction state transitions

Typical savings: 20-40% for batching 5+ calls

## Best Practices

* **Batch Size**: Optimal batch size is 10-50 calls depending on complexity
* **Gas Limits**: Set appropriate gas limits for complex batches
* **Error Handling**: Use `allowFailure` wisely based on criticality
* **Return Data**: Decode return data carefully, checking success flags
* **Reentrancy**: Be aware of potential reentrancy in batched calls

## Comparison with Alternatives

| Feature           | Multicall3       | Multicall2 | Manual Batching |
| ----------------- | ---------------- | ---------- | --------------- |
| Gas Efficiency    | Excellent        | Good       | Poor            |
| Error Handling    | Flexible         | Basic      | N/A             |
| Value Support     | Yes              | No         | Yes             |
| Deployment        | Standard address | Varies     | N/A             |
| Block Consistency | Yes              | Yes        | No              |

## Integration Libraries

Popular libraries with Multicall3 support:

* **ethers-rs**: Rust implementation
* **web3.py**: Python Web3 library
* **viem**: TypeScript alternative to ethers
* **wagmi**: React hooks for Ethereum

## Troubleshooting

| Issue                     | Solution                                                 |
| ------------------------- | -------------------------------------------------------- |
| "Multicall3: call failed" | Check individual call success flags                      |
| Gas estimation failure    | Increase gas limit or reduce batch size                  |
| Unexpected revert         | One of the calls with `allowFailure: false` failed       |
| Value mismatch            | Ensure total value sent matches sum of individual values |

## Further Reading

* [Multicall3 GitHub Repository](https://github.com/mds1/multicall)
* [Multicall3 Deployments](https://www.multicall3.com/)
* [Original Multicall by MakerDAO](https://github.com/makerdao/multicall)
