View Source Ethers.Multicall (Ethers v0.5.5)

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/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

calls = [
  ContractA.foo(),
  {ContractB.foo(), to: "0x..."},
]

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

Summary

Functions

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.

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

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

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

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

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

Decodes a Multicall3 response from Ethers.call/2.

Types

aggregate2_option()

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

aggregate3_option()

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

Functions

aggregate2(data)

@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

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(list, calls)

@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

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

aggregate2_encode_data(data)

@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

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

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

aggregate3(data)

@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

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(resps, calls)

@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

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(data)

@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

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

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

decode(resps, calls)

@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

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" ]]