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>
impl<P, N> MulticallBuilder<Empty, P, N>
Sourcepub fn new(provider: P) -> Self
pub fn new(provider: P) -> Self
Instantiate a new MulticallBuilder
Source§impl<D: SolCall + 'static, P, N> MulticallBuilder<Dynamic<D>, P, N>
impl<D: SolCall + 'static, P, N> MulticallBuilder<Dynamic<D>, P, N>
Sourcepub fn new_dynamic(provider: P) -> Self
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);
}
Sourcepub fn add_dynamic(self, item: impl MulticallItem<Decoder = D>) -> Self
pub fn add_dynamic(self, item: impl MulticallItem<Decoder = D>) -> Self
Add a dynamic call to the builder
Sourcepub fn extend(
self,
items: impl IntoIterator<Item = impl MulticallItem<Decoder = D>>,
) -> Self
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>
impl<T, P, N> MulticallBuilder<T, &P, N>
Sourcepub fn with_cloned_provider(&self) -> MulticallBuilder<Empty, P, N>
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>
impl<T, P, N> MulticallBuilder<T, P, N>
Sourcepub fn address(self, address: Address) -> Self
pub fn address(self, address: Address) -> Self
Set the address of the multicall3 contract
Default is MULTICALL3_ADDRESS
.
Sourcepub fn overrides(self, state_override: impl Into<StateOverride>) -> Self
pub fn overrides(self, state_override: impl Into<StateOverride>) -> Self
Set the state overrides for the call.
Sourcepub fn add<Item: MulticallItem>(
self,
item: Item,
) -> MulticallBuilder<T::Pushed, P, N>
pub fn add<Item: MulticallItem>( self, item: Item, ) -> MulticallBuilder<T::Pushed, P, N>
Appends a SolCall
to the stack.
Sourcepub 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,
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.
Sourcepub async fn aggregate(&self) -> Result<T::SuccessReturns>
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);
}
Sourcepub async fn try_aggregate(&self, require_success: bool) -> Result<T::Returns>
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 theFailure
struct which holds the index(-position) of the call and the returned data asBytes
.
§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());
}
Sourcepub async fn aggregate3(&self) -> Result<T::Returns>
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 theFailure
struct which holds the index(-position) of the call and the returned data asBytes
.
Sourcepub async fn aggregate3_value(&self) -> Result<T::Returns>
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 theFailure
struct which holds the index(-position) of the call and the returned data asBytes
.
Sourcepub async fn block_and_aggregate(
&self,
) -> Result<(u64, B256, T::SuccessReturns)>
pub async fn block_and_aggregate( &self, ) -> Result<(u64, B256, T::SuccessReturns)>
Call the blockAndAggregate
function
Sourcepub async fn try_block_and_aggregate(
&self,
require_success: bool,
) -> Result<(u64, B256, T::Returns)>
pub async fn try_block_and_aggregate( &self, require_success: bool, ) -> Result<(u64, B256, T::Returns)>
Call the tryBlockAndAggregate
function
Sourcepub fn get_block_hash(
self,
number: BlockNumber,
) -> MulticallBuilder<T::Pushed, P, N>where
T: TuplePush<getBlockHashCall>,
T::Pushed: CallTuple,
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
Sourcepub fn get_current_block_coinbase(self) -> MulticallBuilder<T::Pushed, P, N>where
T: TuplePush<getCurrentBlockCoinbaseCall>,
T::Pushed: CallTuple,
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
Sourcepub fn get_block_number(self) -> MulticallBuilder<T::Pushed, P, N>where
T: TuplePush<getBlockNumberCall>,
T::Pushed: CallTuple,
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
Sourcepub fn get_current_block_difficulty(self) -> MulticallBuilder<T::Pushed, P, N>where
T: TuplePush<getCurrentBlockDifficultyCall>,
T::Pushed: CallTuple,
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
Sourcepub fn get_current_block_gas_limit(self) -> MulticallBuilder<T::Pushed, P, N>where
T: TuplePush<getCurrentBlockGasLimitCall>,
T::Pushed: CallTuple,
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
Sourcepub fn get_current_block_timestamp(self) -> MulticallBuilder<T::Pushed, P, N>where
T: TuplePush<getCurrentBlockTimestampCall>,
T::Pushed: CallTuple,
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
Sourcepub fn get_chain_id(self) -> MulticallBuilder<T::Pushed, P, N>where
T: TuplePush<getChainIdCall>,
T::Pushed: CallTuple,
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
Sourcepub fn get_base_fee(self) -> MulticallBuilder<T::Pushed, P, N>where
T: TuplePush<getBasefeeCall>,
T::Pushed: CallTuple,
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
Sourcepub fn get_eth_balance(
self,
address: Address,
) -> MulticallBuilder<T::Pushed, P, N>where
T: TuplePush<getEthBalanceCall>,
T::Pushed: CallTuple,
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
Sourcepub fn get_last_block_hash(self) -> MulticallBuilder<T::Pushed, P, N>where
T: TuplePush<getLastBlockHashCall>,
T::Pushed: CallTuple,
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
Sourcepub fn clear(self) -> MulticallBuilder<Empty, P, N>
pub fn clear(self) -> MulticallBuilder<Empty, P, N>
Returns an Empty
builder
Retains previously set provider, address, block and state_override settings.
Trait Implementations§
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>
impl<T, P, N> UnwindSafe for MulticallBuilder<T, P, N>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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 moreSource§impl<T> WithSubscriber for T
impl<T> WithSubscriber for T
Source§fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
Source§fn with_current_subscriber(self) -> WithDispatch<Self>
fn with_current_subscriber(self) -> WithDispatch<Self>
impl<T> ErasedDestructor for Twhere
T: 'static,
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.