Skip to content

Instantly share code, notes, and snippets.

@Nickforall
Created January 8, 2022 11:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Nickforall/bdfd94ff47b2cddb8c1ece9e87374963 to your computer and use it in GitHub Desktop.
Save Nickforall/bdfd94ff47b2cddb8c1ece9e87374963 to your computer and use it in GitHub Desktop.
Call multicall contract with ExAbi in Elixir
defmodule MyProject.Ethereum.Multicall do
@multicall_addr "0xeefBa1e63905eF1D7ACbA5a8513c70307C1cE441"
@doc """
Takes a list of {address, call} tuples, returns an ok tuple with block number and data in same order as list of calls
iex> MyProject.Ethereum.Multicall.multicall({"0x000", ABI.encode("tokenURI(uint256)", [token_id])})
{:ok, 0x000}
"""
def multicall(list) do
abi_data =
list
|> Enum.map(&encode_call/1)
|> encode_aggregate_call()
Ethereumex.HttpClient.eth_call(%{
data: "0x" <> abi_data,
to: @multicall_addr
})
|> case do
{:ok, data} ->
data
|> String.slice(2..-1)
|> Base.decode16!(case: :lower)
|> ABI.TypeDecoder.decode_raw([{:uint, 256}, {:array, :bytes}])
|> case do
[block_number, answers] -> {:ok, block_number, answers}
_ -> {:error, "Incorrectly formatted response from aggregate function"}
end
{:error, error} ->
{:error, error}
end
end
defp encode_call({"0x" <> address, data}) do
{Base.decode16!(address, case: :mixed), data}
end
defp encode_aggregate_call(calls) do
ABI.encode("aggregate((address,bytes)[])", [calls])
|> Base.encode16(case: :lower)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment