# `Ethers.Multicall`
[🔗](https://github.com/ExWeb3/elixir_ethers/blob/v0.6.12/lib/ethers/multicall.ex#L1)

This module offers convenient utilities and a user-friendly API for interacting with
`Multicall3` (for more information, visit https://www.multicall3.com).

The primary function of this module is to aggregate multiple Ethereum contract calls
into a single operation. This aggregated call can be subsequently submitted using `Ethers.call/2`
or `Ethers.send_transaction/2` (If you know what you are doing!).

Upon receiving the response, it can be decoded using `Ethers.Multicall.decode/2` to interpret the
results returned by the `Multicall3` contract.

## How to use
```elixir
calls = [
  ContractA.foo(),
  {ContractB.foo(), to: "0x..."},
]

calls
|> Ethers.Multicall.aggregate3() # Or `Ethers.Multicall.aggregate2/1`
|> Ethers.call!()
|> Ethers.Multicall.decode(calls)
```

# `aggregate2_option`

```elixir
@type aggregate2_option() :: {:to, Ethers.Types.t_address()}
```

# `aggregate3_option`

```elixir
@type aggregate3_option() ::
  {:to, Ethers.Types.t_address()} | {:allow_failure, boolean()}
```

# `aggregate2`

```elixir
@spec aggregate2([Ethers.TxData.t() | {Ethers.TxData.t(), [aggregate2_option()]}]) ::
  Ethers.TxData.t()
```

Aggregate calls, returning the executed block number and will revert if any
call fails. Returns a `Ethers.TxData` struct which can be passed to `Ethers.call/2`.

For more information refer to https://github.com/mds1/multicall#batch-contract-reads

## Parameters
- data: A list of `TxData` structs or `{%TxData{...}, options}` tuples. The options can include:
  - to: Overrides the `default_address` (if any) for the respective function call.

## Examples
```elixir
Ethers.Multicall.aggregate2([
  ContractA.foo(), # <-- Assumes `default_address` in ContractA is defined.
  { ContractB.bar(), to: "0x..." }, # <-- ContractB.bar() will call `to`.
])
#Ethers.TxData<
  function aggregate(
    (address,bytes)[] calls [...]
  ) payable returns (
    uint256 blockNumber,
    bytes[] returnData
  )
  default_address: "0xcA11bde05977b3631167028862bE2a173976CA11"
>
```

# `aggregate2_decode`

```elixir
@spec aggregate2_decode(
  [integer() | [...]],
  [Ethers.TxData.t() | {Ethers.TxData.t(), [aggregate2_option()]}] | [binary()]
) :: [integer() | [...]]
```

Decodes an `aggregate2/2` response from `Ethers.call/2`.

## Parameters
- resps: The response from `Ethers.call/2`.
- calls: A list of the function calls or signatures passed to `aggregate2/2`.

## Examples
```elixir
calls = [ ContractA.foo(), { ContractB.foo(), to: "0x..." } ]
calls
|> Ethers.Multicall.aggregate2()
|> Ethers.call!()
|> Ethers.Multicall.aggregate2_decode(calls)
[ 1337, [ "bar", "baz" ]]
```

# `aggregate2_encode_data`

```elixir
@spec aggregate2_encode_data(
  Ethers.TxData.t()
  | {Ethers.TxData.t(), [aggregate2_option()]}
) ::
  {Ethers.Types.t_address(), binary()}
```

Encodes a function call with optional options into a solidity compatible (address,bytes).

## Parameters
- data:  A `TxData` structs or `{%TxData{...}, options}` tuple. The options can include:
  - to: Overrides the `default_address` (if any) for the respective function call.

## Examples
```elixir
{ ContractA.foo(), to: "0x1337..." } |> aggregate2_encode_data()
{"0x1337...", false, <<...>>}

ContractB.bar() |> aggregate2_encode_data()
{"0x...", <<...>>}
```

# `aggregate3`

```elixir
@spec aggregate3([Ethers.TxData.t() | {Ethers.TxData.t(), [aggregate3_option()]}]) ::
  Ethers.TxData.t()
```

Aggregates calls, ensuring each returns success if required, and returns a `Ethers.TxData` struct,
which can be passed to `Ethers.call/2`.

For more details, refer to: https://github.com/mds1/multicall#batch-contract-reads

## Parameters
- `data`: A list of `Ethers.TxData` structs or `{%Ethers.TxData{...}, options}` tuples. The options
can include:
  - `allow_failure`: If set to `false`, the execution will revert. Defaults to `true`.
  - `to`: Overrides the `default_address` (if any) for the respective function call.

## Examples
```elixir
Ethers.Multicall.aggregate3([
  ContractA.foo(), # <-- Assumes `default_address` in ContractA is defined.
  { ContractB.bar(), to: "0x..." }, # <-- ContractB.bar() will call `to`.
  { ContractC.baz(), allow_failure: false, to: "0x..." }
  # ^^^ -> ContractC.baz() will call `to` and will revert on failure.
  { ContractD.foo(), allow_failure: false } # <-- ContractD.foo() will revert on failure.
])
#Ethers.TxData<
  function aggregate3(
    (address,bool,bytes)[] calls [...]
  ) payable returns (
    (bool,bytes)[] returnData
  )
  default_address: "0xcA11bde05977b3631167028862bE2a173976CA11"
>
```

# `aggregate3_decode`

```elixir
@spec aggregate3_decode(
  [{boolean(), term()}],
  [Ethers.TxData.t() | {Ethers.TxData.t() | [aggregate3_option()]}] | [binary()]
) :: [{boolean(), term()}]
```

Decodes an `aggregate3/2` response from `Ethers.call/2`.

## Parameters
- resps: The response from `Ethers.call/2`.
- calls: A list of the function calls or signatures passed to `aggregate3/2`.

## Examples
```elixir
calls = [ ContractA.foo(), { ContractB.foo(), to: "0x..." } ]
calls
|> Ethers.Multicall.aggregate3()
|> Ethers.call!()
|> Ethers.Multicall.aggregate3_decode(calls)
[ true: "bar", true: "baz" ]
```

# `aggregate3_encode_data`

```elixir
@spec aggregate3_encode_data(
  Ethers.TxData.t()
  | {Ethers.TxData.t(), [aggregate3_option()]}
) ::
  {Ethers.Types.t_address(), boolean(), binary()}
```

Encodes a function call with optional options into a multicall3 compatible (address,bool,bytes)
tuple.

## Parameters
- data: A `Ethers.TxData` struct or `{%Ethers.TxData{...}, options}`. The options can include:
  - allow_failure: If false the execution will revert. Defaults to true.
  - to: Overrides the `default_address` (if any) for the respective function call.

## Examples
```elixir
{ ContractA.foo(), allow_failure: false } |> aggregate3_encode_data()
{"0x...", false, <<...>>}

ContractB.bar() |> aggregate3_encode_data()
{"0x...", true, <<...>>}
```

# `decode`

```elixir
@spec decode([integer() | {boolean(), binary()}], [
  Ethers.TxData.t() | {Ethers.TxData.t(), Keyword.t()} | binary()
]) :: [integer() | {boolean(), term()}]
```

Decodes a `Multicall3` response from `Ethers.call/2`.

## Parameters
- resps: List of results returned by aggregate call (The response from `Ethers.call/2`).
- calls: List of the function calls or signatures passed to `aggregate3/2` or `aggregate2/2`.
  (used for decoding)

## Examples
```elixir
calls = [ ContractA.foo(), { ContractB.foo(), to: "0x..." } ]
calls |> Ethers.Multicall.aggregate3() |> Ethers.call!() |> Ethers.Multicall.decode(calls)
[ true: "bar", true: "baz" ]

calls = [ ContractA.foo(), { ContractB.foo(), to: "0x..." } ]
calls |> Ethers.Multicall.aggregate2() |> Ethers.call!() |> Ethers.Multicall.decode(calls)
[ 1337, [ "bar", "baz" ]]
```

---

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