# `Onchain.Multicall`
[🔗](https://github.com/ZenHive/onchain/blob/v0.5.4/lib/onchain/multicall.ex#L1)

Multicall3 batched contract reads.

Batches N arbitrary contract calls into a single RPC round-trip using the
Multicall3 contract (`0xcA11bde05977b3631167028862bE2a173976CA11`), deployed
identically on every EVM chain.

## Functions

| Function | Purpose |
|----------|---------|
| `aggregate3/2` | Low-level: raw calldata tuples → raw results |
| `aggregate3!/2` | Same, raises on error |
| `call_many/2` | High-level: signature-based calls → decoded results |
| `call_many!/2` | Same, raises on error |

## Error Format

- Input validation: `{:error, {:invalid_address, input}}`
- RPC/ABI errors pass through from `Contract.call/5`
- Individual call failures in `call_many`: `{:error, raw_hex}` per failed call

## API Functions
| Function | Arity | Description | Param Kinds |
| --- | --- | --- | --- |
| `call_many!` | 2 | Batch contract calls with encoding/decoding. Raises on error. | `calls: value`, `opts: value` |
| `call_many` | 2 | Batch contract calls with automatic ABI encoding/decoding. | `calls: value`, `opts: value` |
| `aggregate3!` | 2 | Batch raw contract calls. Raises on error. | `calls: value`, `opts: value` |
| `aggregate3` | 2 | Batch raw contract calls via Multicall3 aggregate3. | `calls: value`, `opts: value` |

# `aggregate3`

```elixir
@spec aggregate3(
  [{String.t(), boolean(), String.t()}],
  keyword()
) :: {:ok, [{boolean(), binary()}]} | {:error, term()}
```

Batch raw contract calls via Multicall3 aggregate3.

## Parameters

  * `calls` - List of \{address_hex, allow_failure_bool, calldata_hex\} tuples (value)
  * `opts` - Options: :rpc_url, :timeout, :block (default: `[]`, value)

## Returns

List of \{success, return_data\} tuples (`{:ok, [{boolean(), binary()}]} | {:error, term()}`)

```elixir
# descripex:contract
%{
  params: %{
    opts: %{
      default: [],
      description: "Options: :rpc_url, :timeout, :block",
      kind: :value
    },
    calls: %{
      description: "List of {address_hex, allow_failure_bool, calldata_hex} tuples",
      kind: :value
    }
  },
  returns: %{
    type: "{:ok, [{boolean(), binary()}]} | {:error, term()}",
    description: "List of {success, return_data} tuples"
  }
}
```

# `aggregate3!`

```elixir
@spec aggregate3!(
  [{String.t(), boolean(), String.t()}],
  keyword()
) :: [{boolean(), binary()}]
```

Batch raw contract calls. Raises on error.

## Parameters

  * `calls` - List of \{address, allow_failure, calldata\} tuples (value)
  * `opts` - Options: :rpc_url, :timeout, :block (default: `[]`, value)

## Returns

List of \{success, return_data\} (`[{boolean(), binary()}]`)

```elixir
# descripex:contract
%{
  params: %{
    opts: %{
      default: [],
      description: "Options: :rpc_url, :timeout, :block",
      kind: :value
    },
    calls: %{
      description: "List of {address, allow_failure, calldata} tuples",
      kind: :value
    }
  },
  returns: %{
    type: "[{boolean(), binary()}]",
    description: "List of {success, return_data}"
  }
}
```

# `call_many`

```elixir
@spec call_many(
  [{String.t() | binary(), String.t(), list(), String.t()}],
  keyword()
) :: {:ok, ok: list(), error: String.t()} | {:error, term()}
```

Batch contract calls with automatic ABI encoding/decoding.

## Parameters

  * `calls` - List of (address, signature, params, return_type) tuples (value)
  * `opts` - Options: :rpc_url, :timeout, :block (default: `[]`, value)

## Returns

List where each result is \{:ok, decoded_values\} or \{:error, return_data_hex\} (`{:ok, [result]} | {:error, term()}`)

```elixir
# descripex:contract
%{
  params: %{
    opts: %{
      default: [],
      description: "Options: :rpc_url, :timeout, :block",
      kind: :value
    },
    calls: %{
      description: "List of (address, signature, params, return_type) tuples",
      kind: :value
    }
  },
  returns: %{
    type: "{:ok, [result]} | {:error, term()}",
    description: "List where each result is {:ok, decoded_values} or {:error, return_data_hex}"
  }
}
```

# `call_many!`

```elixir
@spec call_many!(
  [{String.t() | binary(), String.t(), list(), String.t()}],
  keyword()
) :: [ok: list(), error: String.t()]
```

Batch contract calls with encoding/decoding. Raises on error.

## Parameters

  * `calls` - List of \{address, signature, params, return_type\} tuples (value)
  * `opts` - Options: :rpc_url, :timeout, :block (default: `[]`, value)

## Returns

List of \{:ok, values\} or \{:error, data\} (`[result]`)

```elixir
# descripex:contract
%{
  params: %{
    opts: %{
      default: [],
      description: "Options: :rpc_url, :timeout, :block",
      kind: :value
    },
    calls: %{
      description: "List of {address, signature, params, return_type} tuples",
      kind: :value
    }
  },
  returns: %{
    type: "[result]",
    description: "List of {:ok, values} or {:error, data}"
  }
}
```

---

*Consult [api-reference.md](api-reference.md) for complete listing*
