Struct MulticallBuilder

Source
pub struct MulticallBuilder<T: CallTuple, P: Provider<N>, N: Network> { /* private fields */ }
Expand description

A Multicall3 builder

This builder implements a simple API interface to build and execute multicalls using the IMultiCall3 contract which is available on 270+ chains.

§Example

use alloy_primitives::address;
use alloy_provider::{MulticallBuilder, Provider, ProviderBuilder};
use alloy_sol_types::sol;

sol! {
   #[sol(rpc)]
   #[derive(Debug, PartialEq)]
   interface ERC20 {
       function totalSupply() external view returns (uint256 totalSupply);
       function balanceOf(address owner) external view returns (uint256 balance);
   }
}

#[tokio::main]
async fn main() {
    let weth = address!("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2");
    let provider = ProviderBuilder::new().on_http("https://eth.merkle.io".parse().unwrap());
    let erc20 = ERC20::new(weth, &provider);

    let ts_call = erc20.totalSupply();
    let balance_call = erc20.balanceOf(address!("d8dA6BF26964aF9D7eEd9e03E53415D37aA96045"));

    let multicall = provider.multicall().add(ts_call).add(balance_call);

    let (total_supply, balance) = multicall.aggregate().await.unwrap();

    println!("Total Supply: {:?}, Balance: {:?}", total_supply, balance);
}

Implementations§

Source§

impl<P, N> MulticallBuilder<Empty, P, N>
where P: Provider<N>, N: Network,

Source

pub fn new(provider: P) -> Self

Instantiate a new MulticallBuilder

Source§

impl<D: SolCall + 'static, P, N> MulticallBuilder<Dynamic<D>, P, N>
where P: Provider<N>, N: Network,

Source

pub fn new_dynamic(provider: P) -> Self

Instantiate a new MulticallBuilder that restricts the calls to a specific call type.

Multicalls made using this builder return a vector of the decoded return values.

An example would be trying to fetch multiple ERC20 balances of an address.

§Example
use alloy_primitives::address;
use alloy_provider::{MulticallBuilder, Provider, ProviderBuilder};
use alloy_sol_types::sol;

sol! {
  #[sol(rpc)]
  #[derive(Debug, PartialEq)]
  interface ERC20 {
    function balanceOf(address owner) external view returns (uint256 balance);
  }
}

#[tokio::main]
async fn main() {
   let weth = address!("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2");
   let usdc = address!("A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48");
     
   let provider = ProviderBuilder::new().on_http("https://eth.merkle.io".parse().unwrap());
   let weth = ERC20::new(weth, &provider);
   let usdc = ERC20::new(usdc, &provider);

   let owner = address!("0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045");

   let mut erc20_balances = MulticallBuilder::new_dynamic(provider);

   for token in &[weth, usdc] {
       erc20_balances = erc20_balances.add_dynamic(token.balanceOf(owner));
   }

   let balances: Vec<ERC20::balanceOfReturn> = erc20_balances.aggregate().await.unwrap();

   let weth_bal = &balances[0];
   let usdc_bal = &balances[1];
   println!("WETH Balance: {:?}, USDC Balance: {:?}", weth_bal, usdc_bal);
}
Source

pub fn add_dynamic(self, item: impl MulticallItem<Decoder = D>) -> Self

Add a dynamic call to the builder

Source

pub fn extend( self, items: impl IntoIterator<Item = impl MulticallItem<Decoder = D>>, ) -> Self

Extend the builder with a sequence of calls

Source§

impl<T, P, N> MulticallBuilder<T, &P, N>
where T: CallTuple, P: Provider<N> + Clone, N: Network,

Source

pub fn with_cloned_provider(&self) -> MulticallBuilder<Empty, P, N>

Clones the underlying provider and returns a new MulticallBuilder.

Source§

impl<T, P, N> MulticallBuilder<T, P, N>
where T: CallTuple, P: Provider<N>, N: Network,

Source

pub fn address(self, address: Address) -> Self

Set the address of the multicall3 contract

Default is MULTICALL3_ADDRESS.

Source

pub fn block(self, block: BlockId) -> Self

Sets the block to be used for the call.

Source

pub fn overrides(self, state_override: impl Into<StateOverride>) -> Self

Set the state overrides for the call.

Source

pub fn add<Item: MulticallItem>( self, item: Item, ) -> MulticallBuilder<T::Pushed, P, N>
where Item::Decoder: 'static, T: TuplePush<Item::Decoder>, <T as TuplePush<Item::Decoder>>::Pushed: CallTuple,

Appends a SolCall to the stack.

Source

pub fn add_call<D>(self, call: CallItem<D>) -> MulticallBuilder<T::Pushed, P, N>
where D: SolCall + 'static, T: TuplePush<D>, <T as TuplePush<D>>::Pushed: CallTuple,

Appends a CallItem to the stack.

Source

pub async fn aggregate(&self) -> Result<T::SuccessReturns>

Calls the aggregate function

Requires that all calls succeed, else reverts.

§Solidity Function Signature
sol! {
    function aggregate(Call[] memory calls) external returns (uint256 blockNumber, bytes[] memory returnData);
}
§Returns
  • returnData: A tuple of the decoded return values for the calls

One can obtain the block context such as block number and block hash by using the MulticallBuilder::block_and_aggregate function.

§Example
use alloy_primitives::address;
use alloy_provider::{MulticallBuilder, Provider, ProviderBuilder};
use alloy_sol_types::sol;

sol! {
   #[sol(rpc)]
   #[derive(Debug, PartialEq)]
   interface ERC20 {
       function totalSupply() external view returns (uint256 totalSupply);
       function balanceOf(address owner) external view returns (uint256 balance);
   }
}

#[tokio::main]
async fn main() {
    let weth = address!("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2");
    let provider = ProviderBuilder::new().on_http("https://eth.merkle.io".parse().unwrap());
    let erc20 = ERC20::new(weth, &provider);

    let ts_call = erc20.totalSupply();
    let balance_call = erc20.balanceOf(address!("d8dA6BF26964aF9D7eEd9e03E53415D37aA96045"));

    let multicall = provider.multicall().add(ts_call).add(balance_call);

    let (total_supply, balance) = multicall.aggregate().await.unwrap();

    println!("Total Supply: {:?}, Balance: {:?}", total_supply, balance);
}
Source

pub async fn try_aggregate(&self, require_success: bool) -> Result<T::Returns>

Call the tryAggregate function

Allows for calls to fail by setting require_success to false.

§Solidity Function Signature
sol! {
    function tryAggregate(bool requireSuccess, Call[] calldata calls) external payable returns (Result[] memory returnData);
}
§Returns
  • A tuple of the decoded return values for the calls.
  • Each return value is wrapped in a Result struct.
  • The Result::Ok variant contains the decoded return value.
  • The Result::Err variant contains the Failure struct which holds the index(-position) of the call and the returned data as Bytes.
§Example
use alloy_primitives::address;
use alloy_provider::{MulticallBuilder, Provider, ProviderBuilder};
use alloy_sol_types::sol;

sol! {
   #[sol(rpc)]
   #[derive(Debug, PartialEq)]
   interface ERC20 {
       function totalSupply() external view returns (uint256 totalSupply);
       function balanceOf(address owner) external view returns (uint256 balance);
   }
}

#[tokio::main]
async fn main() {
    let weth = address!("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2");
    let provider = ProviderBuilder::new().on_http("https://eth.merkle.io".parse().unwrap());
    let erc20 = ERC20::new(weth, &provider);

    let ts_call = erc20.totalSupply();
    let balance_call = erc20.balanceOf(address!("d8dA6BF26964aF9D7eEd9e03E53415D37aA96045"));

    let multicall = provider.multicall().add(ts_call).add(balance_call);

    let (total_supply, balance) = multicall.try_aggregate(true).await.unwrap();

    assert!(total_supply.is_ok());
    assert!(balance.is_ok());
}
Source

pub async fn aggregate3(&self) -> Result<T::Returns>

Call the aggregate3 function

Doesn’t require that all calls succeed, reverts only if a call with allowFailure set to false, fails.

By default, adding a call via MulticallBuilder::add sets allow_failure to false.

You can add a call that allows failure by using MulticallBuilder::add_call, and setting allow_failure to true in CallItem.

§Solidity Function Signature
sol! {
    function aggregate3(Call3[] calldata calls) external payable returns (Result[] memory returnData);
}
§Returns
  • A tuple of the decoded return values for the calls.
  • Each return value is wrapped in a Result struct.
  • The Result::Ok variant contains the decoded return value.
  • The Result::Err variant contains the Failure struct which holds the index(-position) of the call and the returned data as Bytes.
Source

pub async fn aggregate3_value(&self) -> Result<T::Returns>

Call the aggregate3Value function

Similar to aggregate3 allows for calls to fail. Moreover, it allows for calling into payable functions with the value parameter.

One can set the value field in the CallItem struct and use MulticallBuilder::add_call to add it to the stack.

It is important to note the aggregate3Value only succeeds when msg.value is strictly equal to the sum of the values of all calls. Summing up the values of all calls and setting it in the transaction request is handled internally by the builder.

§Solidity Function Signature
sol! {
   function aggregate3Value(Call3Value[] calldata calls) external payable returns (Result[] memory returnData);
}
§Returns
  • A tuple of the decoded return values for the calls.
  • Each return value is wrapped in a Result struct.
  • The Result::Ok variant contains the decoded return value.
  • The Result::Err variant contains the Failure struct which holds the index(-position) of the call and the returned data as Bytes.
Source

pub async fn block_and_aggregate( &self, ) -> Result<(u64, B256, T::SuccessReturns)>

Call the blockAndAggregate function

Source

pub async fn try_block_and_aggregate( &self, require_success: bool, ) -> Result<(u64, B256, T::Returns)>

Call the tryBlockAndAggregate function

Source

pub fn get_block_hash( self, number: BlockNumber, ) -> MulticallBuilder<T::Pushed, P, N>
where T: TuplePush<getBlockHashCall>, T::Pushed: CallTuple,

Add a call to get the block hash from a block number

Source

pub fn get_current_block_coinbase(self) -> MulticallBuilder<T::Pushed, P, N>
where T: TuplePush<getCurrentBlockCoinbaseCall>, T::Pushed: CallTuple,

Add a call to get the coinbase of the current block

Source

pub fn get_block_number(self) -> MulticallBuilder<T::Pushed, P, N>
where T: TuplePush<getBlockNumberCall>, T::Pushed: CallTuple,

Add a call to get the current block number

Source

pub fn get_current_block_difficulty(self) -> MulticallBuilder<T::Pushed, P, N>
where T: TuplePush<getCurrentBlockDifficultyCall>, T::Pushed: CallTuple,

Add a call to get the current block difficulty

Source

pub fn get_current_block_gas_limit(self) -> MulticallBuilder<T::Pushed, P, N>
where T: TuplePush<getCurrentBlockGasLimitCall>, T::Pushed: CallTuple,

Add a call to get the current block gas limit

Source

pub fn get_current_block_timestamp(self) -> MulticallBuilder<T::Pushed, P, N>
where T: TuplePush<getCurrentBlockTimestampCall>, T::Pushed: CallTuple,

Add a call to get the current block timestamp

Source

pub fn get_chain_id(self) -> MulticallBuilder<T::Pushed, P, N>
where T: TuplePush<getChainIdCall>, T::Pushed: CallTuple,

Add a call to get the chain id

Source

pub fn get_base_fee(self) -> MulticallBuilder<T::Pushed, P, N>
where T: TuplePush<getBasefeeCall>, T::Pushed: CallTuple,

Add a call to get the base fee

Source

pub fn get_eth_balance( self, address: Address, ) -> MulticallBuilder<T::Pushed, P, N>
where T: TuplePush<getEthBalanceCall>, T::Pushed: CallTuple,

Add a call to get the eth balance of an address

Source

pub fn get_last_block_hash(self) -> MulticallBuilder<T::Pushed, P, N>
where T: TuplePush<getLastBlockHashCall>, T::Pushed: CallTuple,

Add a call to get the last block hash

Source

pub fn clear(self) -> MulticallBuilder<Empty, P, N>

Returns an Empty builder

Retains previously set provider, address, block and state_override settings.

Source

pub fn len(&self) -> usize

Get the number of calls in the builder

Source

pub fn is_empty(&self) -> bool

Check if the builder is empty

Trait Implementations§

Source§

impl<T: Debug + CallTuple, P: Debug + Provider<N>, N: Debug + Network> Debug for MulticallBuilder<T, P, N>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<T, P, N> Freeze for MulticallBuilder<T, P, N>
where P: Freeze,

§

impl<T, P, N> RefUnwindSafe for MulticallBuilder<T, P, N>

§

impl<T, P, N> Send for MulticallBuilder<T, P, N>
where T: Send,

§

impl<T, P, N> Sync for MulticallBuilder<T, P, N>
where T: Sync,

§

impl<T, P, N> Unpin for MulticallBuilder<T, P, N>
where P: Unpin, T: Unpin, N: Unpin,

§

impl<T, P, N> UnwindSafe for MulticallBuilder<T, P, N>
where P: UnwindSafe, T: UnwindSafe, N: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> ErasedDestructor for T
where T: 'static,

Source§

impl<T> MaybeSendSync for T

Layout§

Note: Unable to compute type layout, possibly due to this type having generic parameters. Layout can only be computed for concrete, fully-instantiated types.