From e789d1a0d4eda6c2bce2419c2557a842503f33b2 Mon Sep 17 00:00:00 2001 From: Ayushdubey86 Date: Mon, 5 May 2025 14:09:43 +0530 Subject: [PATCH 01/11] Raising Draft pr CallBatchLayer single request --- crates/provider/src/layers/batch.rs | 145 +++++++++++++++++++--------- 1 file changed, 99 insertions(+), 46 deletions(-) diff --git a/crates/provider/src/layers/batch.rs b/crates/provider/src/layers/batch.rs index f21aac7fd94..0d1a61529b6 100644 --- a/crates/provider/src/layers/batch.rs +++ b/crates/provider/src/layers/batch.rs @@ -123,15 +123,38 @@ where type CallBatchMsgTx = TransportResult; -struct CallBatchMsg { - call: IMulticall3::Call3, +struct CallBatchMsg { + kind: CallBatchMsgKind, tx: oneshot::Sender, } -impl fmt::Debug for CallBatchMsg { +impl Clone for CallBatchMsgKind +where + N::TransactionRequest: Clone, +{ + fn clone(&self) -> Self { + match self { + Self::Call(tx) => Self::Call(tx.clone()), + Self::BlockNumber => Self::BlockNumber, + Self::ChainId => Self::ChainId, + Self::Balance(addr) => Self::Balance(*addr), + } + } +} + +// impl Clone for CallBatchMsg +// where +// CallBatchMsgKind: Clone, +// { +// fn clone(&self) -> Self { +// panic!("CallBatchMsg cannot be cloned because oneshot::Sender is not cloneable"); +// } +// } + +impl fmt::Debug for CallBatchMsg{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("BatchProviderMessage(")?; - self.call.fmt(f)?; + self.kind.fmt(f)?; f.write_str(")") } } @@ -144,13 +167,13 @@ enum CallBatchMsgKind { Balance(Address), } -impl CallBatchMsg { - fn new( +impl CallBatchMsg { + fn new( kind: CallBatchMsgKind, - m3a: Address, + //m3a: Address, ) -> (Self, oneshot::Receiver) { let (tx, rx) = oneshot::channel(); - (Self { call: kind.into_call3(m3a), tx }, rx) + (Self { kind, tx }, rx) } } @@ -179,7 +202,7 @@ impl CallBatchMsgKind { /// See [`CallBatchLayer`] for more information. pub struct CallBatchProvider { provider: Arc

, - inner: CallBatchProviderInner, + inner: CallBatchProviderInner, _pd: PhantomData, } @@ -210,19 +233,19 @@ impl + 'static, N: Network> CallBatchProvider { } #[derive(Clone)] -struct CallBatchProviderInner { - tx: mpsc::UnboundedSender, +struct CallBatchProviderInner { + tx: mpsc::UnboundedSender>, m3a: Address, } -impl CallBatchProviderInner { +impl CallBatchProviderInner { /// We only want to perform a scheduled multicall if: /// - The request has no block ID or state overrides, /// - The request has a target address, /// - The request has no other properties (`nonce`, `gas`, etc cannot be sent with a multicall). /// /// Ref: - fn should_batch_call(&self, params: &crate::EthCallParams) -> bool { + fn should_batch_call(&self, params: &crate::EthCallParams) -> bool { // TODO: block ID is not yet implemented if params.block().is_some_and(|block| block != BlockId::latest()) { return false; @@ -242,8 +265,8 @@ impl CallBatchProviderInner { true } - async fn schedule(self, msg: CallBatchMsgKind) -> TransportResult { - let (msg, rx) = CallBatchMsg::new(msg, self.m3a); + async fn schedule(self, msg: CallBatchMsgKind) -> TransportResult { + let (msg, rx) = CallBatchMsg::new(msg); self.tx.send(msg).map_err(|_| TransportErrorKind::backend_gone())?; let IMulticall3::Result { success, returnData: data } = @@ -257,7 +280,7 @@ impl CallBatchProviderInner { Ok(data) } - async fn schedule_and_decode( + async fn schedule_and_decode( self, msg: CallBatchMsgKind, ) -> TransportResult @@ -273,13 +296,13 @@ struct CallBatchBackend { inner: Arc

, m3a: Address, wait: Duration, - rx: mpsc::UnboundedReceiver, - pending: Vec, + rx: mpsc::UnboundedReceiver>, + pending: Vec>, _pd: PhantomData, } impl + 'static, N: Network> CallBatchBackend { - fn spawn(inner: Arc

, layer: &CallBatchLayer) -> mpsc::UnboundedSender { + fn spawn(inner: Arc

, layer: &CallBatchLayer) -> mpsc::UnboundedSender> { let CallBatchLayer { m3a, wait } = *layer; let (tx, rx) = mpsc::unbounded_channel(); let this = Self { inner, m3a, wait, rx, pending: Vec::new(), _pd: PhantomData }; @@ -311,13 +334,39 @@ impl + 'static, N: Network> CallBatchBackend { } } - fn process_msg(&mut self, msg: CallBatchMsg) { + fn process_msg(&mut self, msg: CallBatchMsg) { self.pending.push(msg); } async fn send_batch(&mut self) { - let result = self.send_batch_inner().await; + let pending = std::mem::take(&mut self.pending); + + if pending.len() == 1 { + let msg = pending.into_iter().next().unwrap(); + + let result = match msg.kind { + CallBatchMsgKind::Call(tx) => self.inner.call(tx).await, + CallBatchMsgKind::Balance(addr) => { + self.inner.get_balance(addr).into_future().await + .map(|val| alloy_primitives::Bytes::from(alloy_rlp::encode(&val))) + }, + CallBatchMsgKind::BlockNumber => { + self.inner.get_block_number().into_future().await + .map(|val| alloy_primitives::Bytes::from(alloy_rlp::encode(&val))) + }, + CallBatchMsgKind::ChainId => { + self.inner.get_chain_id().into_future().await + .map(|val| alloy_primitives::Bytes::from(alloy_rlp::encode(&val))) + }, + }.map_err(TransportErrorKind::custom); + + let _ = msg.tx.send(result); + return; + } + + + let result = self.send_batch_inner(&pending).await; match result { Ok(results) => { debug_assert_eq!(results.len(), pending.len()); @@ -333,28 +382,32 @@ impl + 'static, N: Network> CallBatchBackend { } } - async fn send_batch_inner(&mut self) -> TransportResult> { - debug_assert!(!self.pending.is_empty()); - debug!(len = self.pending.len(), "sending multicall"); - let tx = N::TransactionRequest::default().with_to(self.m3a).with_input(self.make_payload()); + async fn send_batch_inner(&self, pending: &[CallBatchMsg]) -> TransportResult> { + let call3s: Vec<_> = pending + .iter() + .map(|msg| msg.kind.clone().into_call3(self.m3a)) + .collect(); + + let tx = N::TransactionRequest::default() + .with_to(self.m3a) + .with_input(IMulticall3::aggregate3Call { calls: call3s }.abi_encode()); + let bytes = self.inner.call(tx).await?; if bytes.is_empty() { - return Err(TransportErrorKind::custom_str(&format!( - "Multicall3 not deployed at {}", - self.m3a - ))); + return Err(TransportErrorKind::custom_str(&format!("Multicall3 not deployed at {}", self.m3a))); } + let ret = IMulticall3::aggregate3Call::abi_decode_returns(&bytes) .map_err(TransportErrorKind::custom)?; Ok(ret) - } - - fn make_payload(&self) -> Vec { - IMulticall3::aggregate3Call { - calls: self.pending.iter().map(|msg| msg.call.clone()).collect(), - } - .abi_encode() - } + } + + // fn make_payload(&self) -> Vec { + // IMulticall3::aggregate3Call { + // calls: self.pending.iter().map(|msg| msg.call.clone()).collect(), + // } + // .abi_encode() + // } } impl + 'static, N: Network> Provider for CallBatchProvider { @@ -374,7 +427,7 @@ impl + 'static, N: Network> Provider for CallBatchProvider { crate::ProviderCall::BoxedFuture(Box::pin( - self.inner.clone().schedule_and_decode::(CallBatchMsgKind::BlockNumber), + self.inner.clone().schedule_and_decode::(CallBatchMsgKind::BlockNumber), )) } @@ -386,7 +439,7 @@ impl + 'static, N: Network> Provider for CallBatchProvider { crate::ProviderCall::BoxedFuture(Box::pin( - self.inner.clone().schedule_and_decode::(CallBatchMsgKind::ChainId), + self.inner.clone().schedule_and_decode::(CallBatchMsgKind::ChainId), )) } @@ -399,25 +452,25 @@ impl + 'static, N: Network> Provider for CallBatchProvider(CallBatchMsgKind::Balance(address)), + .schedule_and_decode::(CallBatchMsgKind::Balance(address)), )) } }) } } -struct CallBatchCaller { - inner: CallBatchProviderInner, +struct CallBatchCaller { + inner: CallBatchProviderInner, weak: WeakClient, } -impl CallBatchCaller { - fn new, N: Network>(provider: &CallBatchProvider) -> Self { +impl CallBatchCaller { + fn new>(provider: &CallBatchProvider) -> Self { Self { inner: provider.inner.clone(), weak: provider.provider.weak_client() } } } -impl Caller for CallBatchCaller { +impl Caller for CallBatchCaller { fn call( &self, params: crate::EthCallParams, @@ -427,7 +480,7 @@ impl Caller for CallBatchCaller { } Ok(crate::ProviderCall::BoxedFuture(Box::pin( - self.inner.clone().schedule::(CallBatchMsgKind::Call(params.into_data())), + self.inner.clone().schedule(CallBatchMsgKind::Call(params.into_data())), ))) } From b42c8336ba851a4f07bb2bc4cb30a3290ee9c015 Mon Sep 17 00:00:00 2001 From: Ayushdubey86 Date: Mon, 5 May 2025 17:48:16 +0530 Subject: [PATCH 02/11] Single Rpc Call --- crates/provider/src/layers/batch.rs | 211 +++++++++++++++------------- 1 file changed, 117 insertions(+), 94 deletions(-) diff --git a/crates/provider/src/layers/batch.rs b/crates/provider/src/layers/batch.rs index 0d1a61529b6..323085a4d77 100644 --- a/crates/provider/src/layers/batch.rs +++ b/crates/provider/src/layers/batch.rs @@ -8,7 +8,7 @@ use alloy_primitives::{Address, Bytes, U256}; use alloy_rpc_client::WeakClient; use alloy_sol_types::{SolCall, SolType, SolValue}; use alloy_transport::{utils::Spawnable, TransportErrorKind, TransportResult}; -use std::{fmt, future::IntoFuture, marker::PhantomData, sync::Arc, time::Duration}; +use std::{ fmt, future::IntoFuture, marker::PhantomData, sync::Arc, time::Duration}; use tokio::sync::{mpsc, oneshot}; #[cfg(target_family = "wasm")] @@ -81,6 +81,13 @@ impl Default for CallBatchLayer { } } +#[allow(dead_code)] +#[derive(Debug)] +enum CallResult { + Multicall(IMulticall3::Result), + Single(Bytes), +} + impl CallBatchLayer { /// Create a new `CallBatchLayer` with a default wait of 1ms. pub fn new() -> Self { @@ -121,7 +128,7 @@ where } } -type CallBatchMsgTx = TransportResult; +type CallBatchMsgTx = TransportResult; struct CallBatchMsg { kind: CallBatchMsgKind, @@ -232,6 +239,7 @@ impl + 'static, N: Network> CallBatchProvider { } } +#[allow(dead_code)] #[derive(Clone)] struct CallBatchProviderInner { tx: mpsc::UnboundedSender>, @@ -268,17 +276,27 @@ impl CallBatchProviderInner { async fn schedule(self, msg: CallBatchMsgKind) -> TransportResult { let (msg, rx) = CallBatchMsg::new(msg); self.tx.send(msg).map_err(|_| TransportErrorKind::backend_gone())?; - - let IMulticall3::Result { success, returnData: data } = - rx.await.map_err(|_| TransportErrorKind::backend_gone())??; - if !success { - let revert_data = if data.is_empty() { "" } else { &format!(" with data: {data}") }; - return Err(TransportErrorKind::custom_str(&format!( - "multicall batched call reverted{revert_data}" - ))); + + let result = rx.await.map_err(|_| TransportErrorKind::backend_gone())??; + + match result { + CallResult::Multicall(IMulticall3::Result { success, returnData }) => { + if !success { + let revert_data = if returnData.is_empty() { + "".to_string() + } else { + format!(" with data: {returnData}") + }; + Err(TransportErrorKind::custom_str(&format!( + "multicall batched call reverted{revert_data}" + ))) + } else { + Ok(returnData) + } + } + CallResult::Single(_) => Err(TransportErrorKind::custom_str("expected multicall result")), } - Ok(data) - } + } async fn schedule_and_decode( self, @@ -345,21 +363,24 @@ impl + 'static, N: Network> CallBatchBackend { if pending.len() == 1 { let msg = pending.into_iter().next().unwrap(); - let result = match msg.kind { - CallBatchMsgKind::Call(tx) => self.inner.call(tx).await, - CallBatchMsgKind::Balance(addr) => { - self.inner.get_balance(addr).into_future().await - .map(|val| alloy_primitives::Bytes::from(alloy_rlp::encode(&val))) - }, + let result: Result = match msg.kind { + CallBatchMsgKind::Call(tx) => { + let res = self.inner.call(tx).await.unwrap(); + Ok(CallResult::Single(res)) + } CallBatchMsgKind::BlockNumber => { - self.inner.get_block_number().into_future().await - .map(|val| alloy_primitives::Bytes::from(alloy_rlp::encode(&val))) - }, + let result = self.inner.get_block_number().into_future().await.unwrap(); + Ok(CallResult::Single(Bytes::from(result.to_be_bytes()))) + } CallBatchMsgKind::ChainId => { - self.inner.get_chain_id().into_future().await - .map(|val| alloy_primitives::Bytes::from(alloy_rlp::encode(&val))) - }, - }.map_err(TransportErrorKind::custom); + let result = self.inner.get_chain_id().into_future().await.unwrap(); + Ok(CallResult::Single(Bytes::from(result.to_be_bytes()))) + } + CallBatchMsgKind::Balance(addr) => { + let result = self.inner.get_balance(addr).into_future().await.unwrap(); + Ok(CallResult::Single(Bytes::from(result.to_be_bytes::<32>()))) + } + }; let _ = msg.tx.send(result); return; @@ -371,7 +392,7 @@ impl + 'static, N: Network> CallBatchBackend { Ok(results) => { debug_assert_eq!(results.len(), pending.len()); for (result, msg) in results.into_iter().zip(pending) { - let _ = msg.tx.send(Ok(result)); + let _ = msg.tx.send(Ok(CallResult::Multicall(result))); } } Err(e) => { @@ -525,74 +546,76 @@ mod tests { ) } - #[tokio::test] - async fn basic_mocked() { - let asserter = Asserter::new(); - let provider = - ProviderBuilder::new().with_call_batching().connect_mocked_client(asserter.clone()); - push_m3_success( - &asserter, - &[ - (true, 1.abi_encode()), // IMulticall3::getBlockNumberCall - (true, 2.abi_encode()), // IMulticall3::getChainIdCall - (false, 3.abi_encode()), // IMulticall3::getBlockNumberCall - (false, 4.abi_encode()), // IMulticall3::getChainIdCall - ], - ); - let (block_number_ok, chain_id_ok, block_number_err, chain_id_err) = tokio::join!( - provider.get_block_number(), - provider.get_chain_id(), - provider.get_block_number(), - provider.get_chain_id(), - ); - assert_eq!(block_number_ok.unwrap(), 1); - assert_eq!(chain_id_ok.unwrap(), 2); - assert!(block_number_err.unwrap_err().to_string().contains("reverted")); - assert!(chain_id_err.unwrap_err().to_string().contains("reverted")); - assert!(asserter.read_q().is_empty(), "only 1 request should've been made"); - } + // #[tokio::test] + // async fn basic_mocked() { + // let asserter = Asserter::new(); + // let provider = + // ProviderBuilder::new().with_call_batching().connect_mocked_client(asserter.clone()); + // push_m3_success( + // &asserter, + // &[ + // (true, 1.abi_encode()), // IMulticall3::getBlockNumberCall + // (true, 2.abi_encode()), // IMulticall3::getChainIdCall + // (false, 3.abi_encode()), // IMulticall3::getBlockNumberCall + // (false, 4.abi_encode()), // IMulticall3::getChainIdCall + // ], + // ); + // let (block_number_ok, chain_id_ok, block_number_err, chain_id_err) = tokio::join!( + // provider.get_block_number(), + // provider.get_chain_id(), + // provider.get_block_number(), + // provider.get_chain_id(), + // ); + // assert_eq!(block_number_ok.unwrap(), 1); + // assert_eq!(chain_id_ok.unwrap(), 2); + // assert!(block_number_err.unwrap_err().to_string().contains("reverted")); + // assert!(chain_id_err.unwrap_err().to_string().contains("reverted")); + // assert!(asserter.read_q().is_empty(), "only 1 request should've been made"); + // } + + // #[tokio::test] + // #[cfg(feature = "anvil-api")] + // async fn basic() { + // use crate::ext::AnvilApi; + // let provider = ProviderBuilder::new().with_call_batching().connect_anvil(); + // provider.anvil_set_code(COUNTER_ADDRESS, COUNTER_DEPLOYED_CODE.into()).await.unwrap(); + // provider.anvil_set_balance(COUNTER_ADDRESS, U256::from(123)).await.unwrap(); + + // let do_calls = || async { + // tokio::join!( + // provider.call( + // TransactionRequest::default() + // .with_to(COUNTER_ADDRESS) + // .with_input(hex!("0x8381f58a")) // number() + // ), + // provider.call( + // TransactionRequest::default() + // .with_to(MULTICALL3_ADDRESS) + // .with_input(IMulticall3::getBlockNumberCall {}.abi_encode()) + // ), + // provider.get_block_number(), + // provider.get_chain_id(), + // provider.get_balance(COUNTER_ADDRESS), + // ) + // }; + + // // Multicall3 has not yet been deployed. + // let (a, b, c, d, e) = do_calls().await; + // assert!(a.unwrap_err().to_string().contains("Multicall3 not deployed")); + // assert!(b.unwrap_err().to_string().contains("Multicall3 not deployed")); + // assert!(c.unwrap_err().to_string().contains("Multicall3 not deployed")); + // assert!(d.unwrap_err().to_string().contains("Multicall3 not deployed")); + // assert!(e.unwrap_err().to_string().contains("Multicall3 not deployed")); + + // provider.anvil_set_code(MULTICALL3_ADDRESS, MULTICALL3_DEPLOYED_CODE.into()).await.unwrap(); + + // let (counter, block_number_raw, block_number, chain_id, balance) = do_calls().await; + // assert_eq!(counter.unwrap(), 0u64.abi_encode()); + // assert_eq!(block_number_raw.unwrap(), 1u64.abi_encode()); + // assert_eq!(block_number.unwrap(), 1); + // assert_eq!(chain_id.unwrap(), alloy_chains::NamedChain::AnvilHardhat as u64); + // assert_eq!(balance.unwrap(), U256::from(123)); + // } - #[tokio::test] - #[cfg(feature = "anvil-api")] - async fn basic() { - use crate::ext::AnvilApi; - let provider = ProviderBuilder::new().with_call_batching().connect_anvil(); - provider.anvil_set_code(COUNTER_ADDRESS, COUNTER_DEPLOYED_CODE.into()).await.unwrap(); - provider.anvil_set_balance(COUNTER_ADDRESS, U256::from(123)).await.unwrap(); - - let do_calls = || async { - tokio::join!( - provider.call( - TransactionRequest::default() - .with_to(COUNTER_ADDRESS) - .with_input(hex!("0x8381f58a")) // number() - ), - provider.call( - TransactionRequest::default() - .with_to(MULTICALL3_ADDRESS) - .with_input(IMulticall3::getBlockNumberCall {}.abi_encode()) - ), - provider.get_block_number(), - provider.get_chain_id(), - provider.get_balance(COUNTER_ADDRESS), - ) - }; - // Multicall3 has not yet been deployed. - let (a, b, c, d, e) = do_calls().await; - assert!(a.unwrap_err().to_string().contains("Multicall3 not deployed")); - assert!(b.unwrap_err().to_string().contains("Multicall3 not deployed")); - assert!(c.unwrap_err().to_string().contains("Multicall3 not deployed")); - assert!(d.unwrap_err().to_string().contains("Multicall3 not deployed")); - assert!(e.unwrap_err().to_string().contains("Multicall3 not deployed")); - - provider.anvil_set_code(MULTICALL3_ADDRESS, MULTICALL3_DEPLOYED_CODE.into()).await.unwrap(); - - let (counter, block_number_raw, block_number, chain_id, balance) = do_calls().await; - assert_eq!(counter.unwrap(), 0u64.abi_encode()); - assert_eq!(block_number_raw.unwrap(), 1u64.abi_encode()); - assert_eq!(block_number.unwrap(), 1); - assert_eq!(chain_id.unwrap(), alloy_chains::NamedChain::AnvilHardhat as u64); - assert_eq!(balance.unwrap(), U256::from(123)); - } } From 637cae7eabbb75bfd2cef4450d9a7b3f47b8dd93 Mon Sep 17 00:00:00 2001 From: Ayushdubey86 Date: Mon, 5 May 2025 17:50:43 +0530 Subject: [PATCH 03/11] numbing testcase --- crates/provider/src/layers/batch.rs | 50 ++++++++++++++--------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/crates/provider/src/layers/batch.rs b/crates/provider/src/layers/batch.rs index 323085a4d77..f3a60b87a0e 100644 --- a/crates/provider/src/layers/batch.rs +++ b/crates/provider/src/layers/batch.rs @@ -520,31 +520,31 @@ impl Caller for CallBatchCaller { } } -#[cfg(test)] -mod tests { - use super::*; - use crate::ProviderBuilder; - use alloy_primitives::{address, hex}; - use alloy_rpc_types_eth::TransactionRequest; - use alloy_transport::mock::Asserter; - - // https://etherscan.io/address/0xcA11bde05977b3631167028862bE2a173976CA11#code - const MULTICALL3_DEPLOYED_CODE: &[u8] = &hex!("0x6080604052600436106100f35760003560e01c80634d2301cc1161008a578063a8b0574e11610059578063a8b0574e1461025a578063bce38bd714610275578063c3077fa914610288578063ee82ac5e1461029b57600080fd5b80634d2301cc146101ec57806372425d9d1461022157806382ad56cb1461023457806386d516e81461024757600080fd5b80633408e470116100c65780633408e47014610191578063399542e9146101a45780633e64a696146101c657806342cbb15c146101d957600080fd5b80630f28c97d146100f8578063174dea711461011a578063252dba421461013a57806327e86d6e1461015b575b600080fd5b34801561010457600080fd5b50425b6040519081526020015b60405180910390f35b61012d610128366004610a85565b6102ba565b6040516101119190610bbe565b61014d610148366004610a85565b6104ef565b604051610111929190610bd8565b34801561016757600080fd5b50437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0140610107565b34801561019d57600080fd5b5046610107565b6101b76101b2366004610c60565b610690565b60405161011193929190610cba565b3480156101d257600080fd5b5048610107565b3480156101e557600080fd5b5043610107565b3480156101f857600080fd5b50610107610207366004610ce2565b73ffffffffffffffffffffffffffffffffffffffff163190565b34801561022d57600080fd5b5044610107565b61012d610242366004610a85565b6106ab565b34801561025357600080fd5b5045610107565b34801561026657600080fd5b50604051418152602001610111565b61012d610283366004610c60565b61085a565b6101b7610296366004610a85565b610a1a565b3480156102a757600080fd5b506101076102b6366004610d18565b4090565b60606000828067ffffffffffffffff8111156102d8576102d8610d31565b60405190808252806020026020018201604052801561031e57816020015b6040805180820190915260008152606060208201528152602001906001900390816102f65790505b5092503660005b8281101561047757600085828151811061034157610341610d60565b6020026020010151905087878381811061035d5761035d610d60565b905060200281019061036f9190610d8f565b6040810135958601959093506103886020850185610ce2565b73ffffffffffffffffffffffffffffffffffffffff16816103ac6060870187610dcd565b6040516103ba929190610e32565b60006040518083038185875af1925050503d80600081146103f7576040519150601f19603f3d011682016040523d82523d6000602084013e6103fc565b606091505b50602080850191909152901515808452908501351761046d577f08c379a000000000000000000000000000000000000000000000000000000000600052602060045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260846000fd5b5050600101610325565b508234146104e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d756c746963616c6c333a2076616c7565206d69736d6174636800000000000060448201526064015b60405180910390fd5b50505092915050565b436060828067ffffffffffffffff81111561050c5761050c610d31565b60405190808252806020026020018201604052801561053f57816020015b606081526020019060019003908161052a5790505b5091503660005b8281101561068657600087878381811061056257610562610d60565b90506020028101906105749190610e42565b92506105836020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff166105a66020850185610dcd565b6040516105b4929190610e32565b6000604051808303816000865af19150503d80600081146105f1576040519150601f19603f3d011682016040523d82523d6000602084013e6105f6565b606091505b5086848151811061060957610609610d60565b602090810291909101015290508061067d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060448201526064016104dd565b50600101610546565b5050509250929050565b43804060606106a086868661085a565b905093509350939050565b6060818067ffffffffffffffff8111156106c7576106c7610d31565b60405190808252806020026020018201604052801561070d57816020015b6040805180820190915260008152606060208201528152602001906001900390816106e55790505b5091503660005b828110156104e657600084828151811061073057610730610d60565b6020026020010151905086868381811061074c5761074c610d60565b905060200281019061075e9190610e76565b925061076d6020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff166107906040850185610dcd565b60405161079e929190610e32565b6000604051808303816000865af19150503d80600081146107db576040519150601f19603f3d011682016040523d82523d6000602084013e6107e0565b606091505b506020808401919091529015158083529084013517610851577f08c379a000000000000000000000000000000000000000000000000000000000600052602060045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260646000fd5b50600101610714565b6060818067ffffffffffffffff81111561087657610876610d31565b6040519080825280602002602001820160405280156108bc57816020015b6040805180820190915260008152606060208201528152602001906001900390816108945790505b5091503660005b82811015610a105760008482815181106108df576108df610d60565b602002602001015190508686838181106108fb576108fb610d60565b905060200281019061090d9190610e42565b925061091c6020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff1661093f6020850185610dcd565b60405161094d929190610e32565b6000604051808303816000865af19150503d806000811461098a576040519150601f19603f3d011682016040523d82523d6000602084013e61098f565b606091505b506020830152151581528715610a07578051610a07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060448201526064016104dd565b506001016108c3565b5050509392505050565b6000806060610a2b60018686610690565b919790965090945092505050565b60008083601f840112610a4b57600080fd5b50813567ffffffffffffffff811115610a6357600080fd5b6020830191508360208260051b8501011115610a7e57600080fd5b9250929050565b60008060208385031215610a9857600080fd5b823567ffffffffffffffff811115610aaf57600080fd5b610abb85828601610a39565b90969095509350505050565b6000815180845260005b81811015610aed57602081850181015186830182015201610ad1565b81811115610aff576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600082825180855260208086019550808260051b84010181860160005b84811015610bb1578583037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001895281518051151584528401516040858501819052610b9d81860183610ac7565b9a86019a9450505090830190600101610b4f565b5090979650505050505050565b602081526000610bd16020830184610b32565b9392505050565b600060408201848352602060408185015281855180845260608601915060608160051b870101935082870160005b82811015610c52577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0888703018452610c40868351610ac7565b95509284019290840190600101610c06565b509398975050505050505050565b600080600060408486031215610c7557600080fd5b83358015158114610c8557600080fd5b9250602084013567ffffffffffffffff811115610ca157600080fd5b610cad86828701610a39565b9497909650939450505050565b838152826020820152606060408201526000610cd96060830184610b32565b95945050505050565b600060208284031215610cf457600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610bd157600080fd5b600060208284031215610d2a57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112610dc357600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112610e0257600080fd5b83018035915067ffffffffffffffff821115610e1d57600080fd5b602001915036819003821315610a7e57600080fd5b8183823760009101908152919050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112610dc357600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa1833603018112610dc357600080fdfea2646970667358221220bb2b5c71a328032f97c676ae39a1ec2148d3e5d6f73d95e9b17910152d61f16264736f6c634300080c0033"); - const COUNTER_ADDRESS: Address = address!("0x1234123412341234123412341234123412341234"); - const COUNTER_DEPLOYED_CODE: &[u8] = &hex!("0x6080604052348015600e575f5ffd5b5060043610603a575f3560e01c80633fb5c1cb14603e5780638381f58a14604f578063d09de08a146068575b5f5ffd5b604d6049366004607d565b5f55565b005b60565f5481565b60405190815260200160405180910390f35b604d5f805490806076836093565b9190505550565b5f60208284031215608c575f5ffd5b5035919050565b5f6001820160af57634e487b7160e01b5f52601160045260245ffd5b506001019056fea2646970667358221220f423ff7a9a85bf49c3769164d3bd24403940510478df27a6b1deac980db69e5664736f6c634300081b0033"); - - fn push_m3_success(asserter: &Asserter, returns: &[(bool, Vec)]) { - asserter.push_success( - &returns - .iter() - .map(|&(success, ref data)| IMulticall3::Result { - success, - returnData: Bytes::copy_from_slice(data), - }) - .collect::>() - .abi_encode(), - ) - } +// #[cfg(test)] +// mod tests { +// use super::*; +// use crate::ProviderBuilder; +// use alloy_primitives::{address, hex}; +// use alloy_rpc_types_eth::TransactionRequest; +// use alloy_transport::mock::Asserter; + +// // https://etherscan.io/address/0xcA11bde05977b3631167028862bE2a173976CA11#code +// const MULTICALL3_DEPLOYED_CODE: &[u8] = &hex!("0x6080604052600436106100f35760003560e01c80634d2301cc1161008a578063a8b0574e11610059578063a8b0574e1461025a578063bce38bd714610275578063c3077fa914610288578063ee82ac5e1461029b57600080fd5b80634d2301cc146101ec57806372425d9d1461022157806382ad56cb1461023457806386d516e81461024757600080fd5b80633408e470116100c65780633408e47014610191578063399542e9146101a45780633e64a696146101c657806342cbb15c146101d957600080fd5b80630f28c97d146100f8578063174dea711461011a578063252dba421461013a57806327e86d6e1461015b575b600080fd5b34801561010457600080fd5b50425b6040519081526020015b60405180910390f35b61012d610128366004610a85565b6102ba565b6040516101119190610bbe565b61014d610148366004610a85565b6104ef565b604051610111929190610bd8565b34801561016757600080fd5b50437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0140610107565b34801561019d57600080fd5b5046610107565b6101b76101b2366004610c60565b610690565b60405161011193929190610cba565b3480156101d257600080fd5b5048610107565b3480156101e557600080fd5b5043610107565b3480156101f857600080fd5b50610107610207366004610ce2565b73ffffffffffffffffffffffffffffffffffffffff163190565b34801561022d57600080fd5b5044610107565b61012d610242366004610a85565b6106ab565b34801561025357600080fd5b5045610107565b34801561026657600080fd5b50604051418152602001610111565b61012d610283366004610c60565b61085a565b6101b7610296366004610a85565b610a1a565b3480156102a757600080fd5b506101076102b6366004610d18565b4090565b60606000828067ffffffffffffffff8111156102d8576102d8610d31565b60405190808252806020026020018201604052801561031e57816020015b6040805180820190915260008152606060208201528152602001906001900390816102f65790505b5092503660005b8281101561047757600085828151811061034157610341610d60565b6020026020010151905087878381811061035d5761035d610d60565b905060200281019061036f9190610d8f565b6040810135958601959093506103886020850185610ce2565b73ffffffffffffffffffffffffffffffffffffffff16816103ac6060870187610dcd565b6040516103ba929190610e32565b60006040518083038185875af1925050503d80600081146103f7576040519150601f19603f3d011682016040523d82523d6000602084013e6103fc565b606091505b50602080850191909152901515808452908501351761046d577f08c379a000000000000000000000000000000000000000000000000000000000600052602060045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260846000fd5b5050600101610325565b508234146104e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d756c746963616c6c333a2076616c7565206d69736d6174636800000000000060448201526064015b60405180910390fd5b50505092915050565b436060828067ffffffffffffffff81111561050c5761050c610d31565b60405190808252806020026020018201604052801561053f57816020015b606081526020019060019003908161052a5790505b5091503660005b8281101561068657600087878381811061056257610562610d60565b90506020028101906105749190610e42565b92506105836020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff166105a66020850185610dcd565b6040516105b4929190610e32565b6000604051808303816000865af19150503d80600081146105f1576040519150601f19603f3d011682016040523d82523d6000602084013e6105f6565b606091505b5086848151811061060957610609610d60565b602090810291909101015290508061067d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060448201526064016104dd565b50600101610546565b5050509250929050565b43804060606106a086868661085a565b905093509350939050565b6060818067ffffffffffffffff8111156106c7576106c7610d31565b60405190808252806020026020018201604052801561070d57816020015b6040805180820190915260008152606060208201528152602001906001900390816106e55790505b5091503660005b828110156104e657600084828151811061073057610730610d60565b6020026020010151905086868381811061074c5761074c610d60565b905060200281019061075e9190610e76565b925061076d6020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff166107906040850185610dcd565b60405161079e929190610e32565b6000604051808303816000865af19150503d80600081146107db576040519150601f19603f3d011682016040523d82523d6000602084013e6107e0565b606091505b506020808401919091529015158083529084013517610851577f08c379a000000000000000000000000000000000000000000000000000000000600052602060045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260646000fd5b50600101610714565b6060818067ffffffffffffffff81111561087657610876610d31565b6040519080825280602002602001820160405280156108bc57816020015b6040805180820190915260008152606060208201528152602001906001900390816108945790505b5091503660005b82811015610a105760008482815181106108df576108df610d60565b602002602001015190508686838181106108fb576108fb610d60565b905060200281019061090d9190610e42565b925061091c6020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff1661093f6020850185610dcd565b60405161094d929190610e32565b6000604051808303816000865af19150503d806000811461098a576040519150601f19603f3d011682016040523d82523d6000602084013e61098f565b606091505b506020830152151581528715610a07578051610a07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060448201526064016104dd565b506001016108c3565b5050509392505050565b6000806060610a2b60018686610690565b919790965090945092505050565b60008083601f840112610a4b57600080fd5b50813567ffffffffffffffff811115610a6357600080fd5b6020830191508360208260051b8501011115610a7e57600080fd5b9250929050565b60008060208385031215610a9857600080fd5b823567ffffffffffffffff811115610aaf57600080fd5b610abb85828601610a39565b90969095509350505050565b6000815180845260005b81811015610aed57602081850181015186830182015201610ad1565b81811115610aff576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600082825180855260208086019550808260051b84010181860160005b84811015610bb1578583037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001895281518051151584528401516040858501819052610b9d81860183610ac7565b9a86019a9450505090830190600101610b4f565b5090979650505050505050565b602081526000610bd16020830184610b32565b9392505050565b600060408201848352602060408185015281855180845260608601915060608160051b870101935082870160005b82811015610c52577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0888703018452610c40868351610ac7565b95509284019290840190600101610c06565b509398975050505050505050565b600080600060408486031215610c7557600080fd5b83358015158114610c8557600080fd5b9250602084013567ffffffffffffffff811115610ca157600080fd5b610cad86828701610a39565b9497909650939450505050565b838152826020820152606060408201526000610cd96060830184610b32565b95945050505050565b600060208284031215610cf457600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610bd157600080fd5b600060208284031215610d2a57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112610dc357600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112610e0257600080fd5b83018035915067ffffffffffffffff821115610e1d57600080fd5b602001915036819003821315610a7e57600080fd5b8183823760009101908152919050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112610dc357600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa1833603018112610dc357600080fdfea2646970667358221220bb2b5c71a328032f97c676ae39a1ec2148d3e5d6f73d95e9b17910152d61f16264736f6c634300080c0033"); +// const COUNTER_ADDRESS: Address = address!("0x1234123412341234123412341234123412341234"); +// const COUNTER_DEPLOYED_CODE: &[u8] = &hex!("0x6080604052348015600e575f5ffd5b5060043610603a575f3560e01c80633fb5c1cb14603e5780638381f58a14604f578063d09de08a146068575b5f5ffd5b604d6049366004607d565b5f55565b005b60565f5481565b60405190815260200160405180910390f35b604d5f805490806076836093565b9190505550565b5f60208284031215608c575f5ffd5b5035919050565b5f6001820160af57634e487b7160e01b5f52601160045260245ffd5b506001019056fea2646970667358221220f423ff7a9a85bf49c3769164d3bd24403940510478df27a6b1deac980db69e5664736f6c634300081b0033"); + +// fn push_m3_success(asserter: &Asserter, returns: &[(bool, Vec)]) { +// asserter.push_success( +// &returns +// .iter() +// .map(|&(success, ref data)| IMulticall3::Result { +// success, +// returnData: Bytes::copy_from_slice(data), +// }) +// .collect::>() +// .abi_encode(), +// ) +// } // #[tokio::test] // async fn basic_mocked() { From 982497397adf18d2ca8e5d1a3f5a6c4fb49b9cfd Mon Sep 17 00:00:00 2001 From: Ayushdubey86 Date: Mon, 5 May 2025 17:59:06 +0530 Subject: [PATCH 04/11] numbing tc --- crates/provider/src/layers/batch.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/provider/src/layers/batch.rs b/crates/provider/src/layers/batch.rs index f3a60b87a0e..e8fccf16e25 100644 --- a/crates/provider/src/layers/batch.rs +++ b/crates/provider/src/layers/batch.rs @@ -618,4 +618,4 @@ impl Caller for CallBatchCaller { // } -} +// } From 09844d277e22c8ded89269784b91682956665e5e Mon Sep 17 00:00:00 2001 From: Ayushdubey86 Date: Mon, 5 May 2025 18:18:03 +0530 Subject: [PATCH 05/11] numbing tc + fmt --- crates/provider/src/layers/batch.rs | 162 +++++----------------------- 1 file changed, 25 insertions(+), 137 deletions(-) diff --git a/crates/provider/src/layers/batch.rs b/crates/provider/src/layers/batch.rs index e8fccf16e25..bd827efbf0f 100644 --- a/crates/provider/src/layers/batch.rs +++ b/crates/provider/src/layers/batch.rs @@ -149,16 +149,7 @@ where } } -// impl Clone for CallBatchMsg -// where -// CallBatchMsgKind: Clone, -// { -// fn clone(&self) -> Self { -// panic!("CallBatchMsg cannot be cloned because oneshot::Sender is not cloneable"); -// } -// } - -impl fmt::Debug for CallBatchMsg{ +impl fmt::Debug for CallBatchMsg { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("BatchProviderMessage(")?; self.kind.fmt(f)?; @@ -276,9 +267,9 @@ impl CallBatchProviderInner { async fn schedule(self, msg: CallBatchMsgKind) -> TransportResult { let (msg, rx) = CallBatchMsg::new(msg); self.tx.send(msg).map_err(|_| TransportErrorKind::backend_gone())?; - + let result = rx.await.map_err(|_| TransportErrorKind::backend_gone())??; - + match result { CallResult::Multicall(IMulticall3::Result { success, returnData }) => { if !success { @@ -294,14 +285,13 @@ impl CallBatchProviderInner { Ok(returnData) } } - CallResult::Single(_) => Err(TransportErrorKind::custom_str("expected multicall result")), + CallResult::Single(_) => { + Err(TransportErrorKind::custom_str("expected multicall result")) + } } - } + } - async fn schedule_and_decode( - self, - msg: CallBatchMsgKind, - ) -> TransportResult + async fn schedule_and_decode(self, msg: CallBatchMsgKind) -> TransportResult where T: SolValue + From<::RustType>, { @@ -357,7 +347,7 @@ impl + 'static, N: Network> CallBatchBackend { } async fn send_batch(&mut self) { - + let pending = std::mem::take(&mut self.pending); if pending.len() == 1 { @@ -380,12 +370,11 @@ impl + 'static, N: Network> CallBatchBackend { let result = self.inner.get_balance(addr).into_future().await.unwrap(); Ok(CallResult::Single(Bytes::from(result.to_be_bytes::<32>()))) } - }; + }; let _ = msg.tx.send(result); return; } - let result = self.send_batch_inner(&pending).await; match result { @@ -403,32 +392,30 @@ impl + 'static, N: Network> CallBatchBackend { } } - async fn send_batch_inner(&self, pending: &[CallBatchMsg]) -> TransportResult> { - let call3s: Vec<_> = pending - .iter() - .map(|msg| msg.kind.clone().into_call3(self.m3a)) - .collect(); + async fn send_batch_inner( + &self, + pending: &[CallBatchMsg], + ) -> TransportResult> { + let call3s: Vec<_> = + pending.iter().map(|msg| msg.kind.clone().into_call3(self.m3a)).collect(); let tx = N::TransactionRequest::default() .with_to(self.m3a) .with_input(IMulticall3::aggregate3Call { calls: call3s }.abi_encode()); - + let bytes = self.inner.call(tx).await?; if bytes.is_empty() { - return Err(TransportErrorKind::custom_str(&format!("Multicall3 not deployed at {}", self.m3a))); + return Err(TransportErrorKind::custom_str(&format!( + "Multicall3 not deployed at {}", + self.m3a + ))); } - + let ret = IMulticall3::aggregate3Call::abi_decode_returns(&bytes) .map_err(TransportErrorKind::custom)?; Ok(ret) - } - - // fn make_payload(&self) -> Vec { - // IMulticall3::aggregate3Call { - // calls: self.pending.iter().map(|msg| msg.call.clone()).collect(), - // } - // .abi_encode() - // } + } + } impl + 'static, N: Network> Provider for CallBatchProvider { @@ -485,7 +472,7 @@ struct CallBatchCaller { weak: WeakClient, } -impl CallBatchCaller { +impl CallBatchCaller { fn new>(provider: &CallBatchProvider) -> Self { Self { inner: provider.inner.clone(), weak: provider.provider.weak_client() } } @@ -520,102 +507,3 @@ impl Caller for CallBatchCaller { } } -// #[cfg(test)] -// mod tests { -// use super::*; -// use crate::ProviderBuilder; -// use alloy_primitives::{address, hex}; -// use alloy_rpc_types_eth::TransactionRequest; -// use alloy_transport::mock::Asserter; - -// // https://etherscan.io/address/0xcA11bde05977b3631167028862bE2a173976CA11#code -// const MULTICALL3_DEPLOYED_CODE: &[u8] = &hex!("0x6080604052600436106100f35760003560e01c80634d2301cc1161008a578063a8b0574e11610059578063a8b0574e1461025a578063bce38bd714610275578063c3077fa914610288578063ee82ac5e1461029b57600080fd5b80634d2301cc146101ec57806372425d9d1461022157806382ad56cb1461023457806386d516e81461024757600080fd5b80633408e470116100c65780633408e47014610191578063399542e9146101a45780633e64a696146101c657806342cbb15c146101d957600080fd5b80630f28c97d146100f8578063174dea711461011a578063252dba421461013a57806327e86d6e1461015b575b600080fd5b34801561010457600080fd5b50425b6040519081526020015b60405180910390f35b61012d610128366004610a85565b6102ba565b6040516101119190610bbe565b61014d610148366004610a85565b6104ef565b604051610111929190610bd8565b34801561016757600080fd5b50437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0140610107565b34801561019d57600080fd5b5046610107565b6101b76101b2366004610c60565b610690565b60405161011193929190610cba565b3480156101d257600080fd5b5048610107565b3480156101e557600080fd5b5043610107565b3480156101f857600080fd5b50610107610207366004610ce2565b73ffffffffffffffffffffffffffffffffffffffff163190565b34801561022d57600080fd5b5044610107565b61012d610242366004610a85565b6106ab565b34801561025357600080fd5b5045610107565b34801561026657600080fd5b50604051418152602001610111565b61012d610283366004610c60565b61085a565b6101b7610296366004610a85565b610a1a565b3480156102a757600080fd5b506101076102b6366004610d18565b4090565b60606000828067ffffffffffffffff8111156102d8576102d8610d31565b60405190808252806020026020018201604052801561031e57816020015b6040805180820190915260008152606060208201528152602001906001900390816102f65790505b5092503660005b8281101561047757600085828151811061034157610341610d60565b6020026020010151905087878381811061035d5761035d610d60565b905060200281019061036f9190610d8f565b6040810135958601959093506103886020850185610ce2565b73ffffffffffffffffffffffffffffffffffffffff16816103ac6060870187610dcd565b6040516103ba929190610e32565b60006040518083038185875af1925050503d80600081146103f7576040519150601f19603f3d011682016040523d82523d6000602084013e6103fc565b606091505b50602080850191909152901515808452908501351761046d577f08c379a000000000000000000000000000000000000000000000000000000000600052602060045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260846000fd5b5050600101610325565b508234146104e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d756c746963616c6c333a2076616c7565206d69736d6174636800000000000060448201526064015b60405180910390fd5b50505092915050565b436060828067ffffffffffffffff81111561050c5761050c610d31565b60405190808252806020026020018201604052801561053f57816020015b606081526020019060019003908161052a5790505b5091503660005b8281101561068657600087878381811061056257610562610d60565b90506020028101906105749190610e42565b92506105836020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff166105a66020850185610dcd565b6040516105b4929190610e32565b6000604051808303816000865af19150503d80600081146105f1576040519150601f19603f3d011682016040523d82523d6000602084013e6105f6565b606091505b5086848151811061060957610609610d60565b602090810291909101015290508061067d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060448201526064016104dd565b50600101610546565b5050509250929050565b43804060606106a086868661085a565b905093509350939050565b6060818067ffffffffffffffff8111156106c7576106c7610d31565b60405190808252806020026020018201604052801561070d57816020015b6040805180820190915260008152606060208201528152602001906001900390816106e55790505b5091503660005b828110156104e657600084828151811061073057610730610d60565b6020026020010151905086868381811061074c5761074c610d60565b905060200281019061075e9190610e76565b925061076d6020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff166107906040850185610dcd565b60405161079e929190610e32565b6000604051808303816000865af19150503d80600081146107db576040519150601f19603f3d011682016040523d82523d6000602084013e6107e0565b606091505b506020808401919091529015158083529084013517610851577f08c379a000000000000000000000000000000000000000000000000000000000600052602060045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260646000fd5b50600101610714565b6060818067ffffffffffffffff81111561087657610876610d31565b6040519080825280602002602001820160405280156108bc57816020015b6040805180820190915260008152606060208201528152602001906001900390816108945790505b5091503660005b82811015610a105760008482815181106108df576108df610d60565b602002602001015190508686838181106108fb576108fb610d60565b905060200281019061090d9190610e42565b925061091c6020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff1661093f6020850185610dcd565b60405161094d929190610e32565b6000604051808303816000865af19150503d806000811461098a576040519150601f19603f3d011682016040523d82523d6000602084013e61098f565b606091505b506020830152151581528715610a07578051610a07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060448201526064016104dd565b506001016108c3565b5050509392505050565b6000806060610a2b60018686610690565b919790965090945092505050565b60008083601f840112610a4b57600080fd5b50813567ffffffffffffffff811115610a6357600080fd5b6020830191508360208260051b8501011115610a7e57600080fd5b9250929050565b60008060208385031215610a9857600080fd5b823567ffffffffffffffff811115610aaf57600080fd5b610abb85828601610a39565b90969095509350505050565b6000815180845260005b81811015610aed57602081850181015186830182015201610ad1565b81811115610aff576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600082825180855260208086019550808260051b84010181860160005b84811015610bb1578583037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001895281518051151584528401516040858501819052610b9d81860183610ac7565b9a86019a9450505090830190600101610b4f565b5090979650505050505050565b602081526000610bd16020830184610b32565b9392505050565b600060408201848352602060408185015281855180845260608601915060608160051b870101935082870160005b82811015610c52577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0888703018452610c40868351610ac7565b95509284019290840190600101610c06565b509398975050505050505050565b600080600060408486031215610c7557600080fd5b83358015158114610c8557600080fd5b9250602084013567ffffffffffffffff811115610ca157600080fd5b610cad86828701610a39565b9497909650939450505050565b838152826020820152606060408201526000610cd96060830184610b32565b95945050505050565b600060208284031215610cf457600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610bd157600080fd5b600060208284031215610d2a57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112610dc357600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112610e0257600080fd5b83018035915067ffffffffffffffff821115610e1d57600080fd5b602001915036819003821315610a7e57600080fd5b8183823760009101908152919050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112610dc357600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa1833603018112610dc357600080fdfea2646970667358221220bb2b5c71a328032f97c676ae39a1ec2148d3e5d6f73d95e9b17910152d61f16264736f6c634300080c0033"); -// const COUNTER_ADDRESS: Address = address!("0x1234123412341234123412341234123412341234"); -// const COUNTER_DEPLOYED_CODE: &[u8] = &hex!("0x6080604052348015600e575f5ffd5b5060043610603a575f3560e01c80633fb5c1cb14603e5780638381f58a14604f578063d09de08a146068575b5f5ffd5b604d6049366004607d565b5f55565b005b60565f5481565b60405190815260200160405180910390f35b604d5f805490806076836093565b9190505550565b5f60208284031215608c575f5ffd5b5035919050565b5f6001820160af57634e487b7160e01b5f52601160045260245ffd5b506001019056fea2646970667358221220f423ff7a9a85bf49c3769164d3bd24403940510478df27a6b1deac980db69e5664736f6c634300081b0033"); - -// fn push_m3_success(asserter: &Asserter, returns: &[(bool, Vec)]) { -// asserter.push_success( -// &returns -// .iter() -// .map(|&(success, ref data)| IMulticall3::Result { -// success, -// returnData: Bytes::copy_from_slice(data), -// }) -// .collect::>() -// .abi_encode(), -// ) -// } - - // #[tokio::test] - // async fn basic_mocked() { - // let asserter = Asserter::new(); - // let provider = - // ProviderBuilder::new().with_call_batching().connect_mocked_client(asserter.clone()); - // push_m3_success( - // &asserter, - // &[ - // (true, 1.abi_encode()), // IMulticall3::getBlockNumberCall - // (true, 2.abi_encode()), // IMulticall3::getChainIdCall - // (false, 3.abi_encode()), // IMulticall3::getBlockNumberCall - // (false, 4.abi_encode()), // IMulticall3::getChainIdCall - // ], - // ); - // let (block_number_ok, chain_id_ok, block_number_err, chain_id_err) = tokio::join!( - // provider.get_block_number(), - // provider.get_chain_id(), - // provider.get_block_number(), - // provider.get_chain_id(), - // ); - // assert_eq!(block_number_ok.unwrap(), 1); - // assert_eq!(chain_id_ok.unwrap(), 2); - // assert!(block_number_err.unwrap_err().to_string().contains("reverted")); - // assert!(chain_id_err.unwrap_err().to_string().contains("reverted")); - // assert!(asserter.read_q().is_empty(), "only 1 request should've been made"); - // } - - // #[tokio::test] - // #[cfg(feature = "anvil-api")] - // async fn basic() { - // use crate::ext::AnvilApi; - // let provider = ProviderBuilder::new().with_call_batching().connect_anvil(); - // provider.anvil_set_code(COUNTER_ADDRESS, COUNTER_DEPLOYED_CODE.into()).await.unwrap(); - // provider.anvil_set_balance(COUNTER_ADDRESS, U256::from(123)).await.unwrap(); - - // let do_calls = || async { - // tokio::join!( - // provider.call( - // TransactionRequest::default() - // .with_to(COUNTER_ADDRESS) - // .with_input(hex!("0x8381f58a")) // number() - // ), - // provider.call( - // TransactionRequest::default() - // .with_to(MULTICALL3_ADDRESS) - // .with_input(IMulticall3::getBlockNumberCall {}.abi_encode()) - // ), - // provider.get_block_number(), - // provider.get_chain_id(), - // provider.get_balance(COUNTER_ADDRESS), - // ) - // }; - - // // Multicall3 has not yet been deployed. - // let (a, b, c, d, e) = do_calls().await; - // assert!(a.unwrap_err().to_string().contains("Multicall3 not deployed")); - // assert!(b.unwrap_err().to_string().contains("Multicall3 not deployed")); - // assert!(c.unwrap_err().to_string().contains("Multicall3 not deployed")); - // assert!(d.unwrap_err().to_string().contains("Multicall3 not deployed")); - // assert!(e.unwrap_err().to_string().contains("Multicall3 not deployed")); - - // provider.anvil_set_code(MULTICALL3_ADDRESS, MULTICALL3_DEPLOYED_CODE.into()).await.unwrap(); - - // let (counter, block_number_raw, block_number, chain_id, balance) = do_calls().await; - // assert_eq!(counter.unwrap(), 0u64.abi_encode()); - // assert_eq!(block_number_raw.unwrap(), 1u64.abi_encode()); - // assert_eq!(block_number.unwrap(), 1); - // assert_eq!(chain_id.unwrap(), alloy_chains::NamedChain::AnvilHardhat as u64); - // assert_eq!(balance.unwrap(), U256::from(123)); - // } - - -// } From 243db1972070ccd461d18351263edc34049b481e Mon Sep 17 00:00:00 2001 From: Ayushdubey86 Date: Mon, 5 May 2025 18:20:30 +0530 Subject: [PATCH 06/11] fmt --- crates/provider/src/layers/batch.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/crates/provider/src/layers/batch.rs b/crates/provider/src/layers/batch.rs index bd827efbf0f..ee18496008a 100644 --- a/crates/provider/src/layers/batch.rs +++ b/crates/provider/src/layers/batch.rs @@ -8,7 +8,7 @@ use alloy_primitives::{Address, Bytes, U256}; use alloy_rpc_client::WeakClient; use alloy_sol_types::{SolCall, SolType, SolValue}; use alloy_transport::{utils::Spawnable, TransportErrorKind, TransportResult}; -use std::{ fmt, future::IntoFuture, marker::PhantomData, sync::Arc, time::Duration}; +use std::{fmt, future::IntoFuture, marker::PhantomData, sync::Arc, time::Duration}; use tokio::sync::{mpsc, oneshot}; #[cfg(target_family = "wasm")] @@ -347,7 +347,6 @@ impl + 'static, N: Network> CallBatchBackend { } async fn send_batch(&mut self) { - let pending = std::mem::take(&mut self.pending); if pending.len() == 1 { @@ -415,7 +414,6 @@ impl + 'static, N: Network> CallBatchBackend { .map_err(TransportErrorKind::custom)?; Ok(ret) } - } impl + 'static, N: Network> Provider for CallBatchProvider { @@ -506,4 +504,3 @@ impl Caller for CallBatchCaller { Caller::::call_many(&self.weak, params) } } - From 6000c1bcd058f97750eca5c1a6b7d088b4d4503e Mon Sep 17 00:00:00 2001 From: Ayushdubey86 Date: Thu, 8 May 2025 18:44:24 +0530 Subject: [PATCH 07/11] Refactor+ adding tc --- crates/provider/src/layers/batch.rs | 186 ++++++++++++++++++++++------ 1 file changed, 145 insertions(+), 41 deletions(-) diff --git a/crates/provider/src/layers/batch.rs b/crates/provider/src/layers/batch.rs index ee18496008a..30746481e6f 100644 --- a/crates/provider/src/layers/batch.rs +++ b/crates/provider/src/layers/batch.rs @@ -81,13 +81,6 @@ impl Default for CallBatchLayer { } } -#[allow(dead_code)] -#[derive(Debug)] -enum CallResult { - Multicall(IMulticall3::Result), - Single(Bytes), -} - impl CallBatchLayer { /// Create a new `CallBatchLayer` with a default wait of 1ms. pub fn new() -> Self { @@ -128,7 +121,7 @@ where } } -type CallBatchMsgTx = TransportResult; +type CallBatchMsgTx = TransportResult; struct CallBatchMsg { kind: CallBatchMsgKind, @@ -168,7 +161,6 @@ enum CallBatchMsgKind { impl CallBatchMsg { fn new( kind: CallBatchMsgKind, - //m3a: Address, ) -> (Self, oneshot::Receiver) { let (tx, rx) = oneshot::channel(); (Self { kind, tx }, rx) @@ -267,30 +259,24 @@ impl CallBatchProviderInner { async fn schedule(self, msg: CallBatchMsgKind) -> TransportResult { let (msg, rx) = CallBatchMsg::new(msg); self.tx.send(msg).map_err(|_| TransportErrorKind::backend_gone())?; - - let result = rx.await.map_err(|_| TransportErrorKind::backend_gone())??; - - match result { - CallResult::Multicall(IMulticall3::Result { success, returnData }) => { - if !success { - let revert_data = if returnData.is_empty() { - "".to_string() - } else { - format!(" with data: {returnData}") - }; - Err(TransportErrorKind::custom_str(&format!( - "multicall batched call reverted{revert_data}" - ))) - } else { - Ok(returnData) - } - } - CallResult::Single(_) => { - Err(TransportErrorKind::custom_str("expected multicall result")) - } + + let IMulticall3::Result { success, returnData } = + rx.await.map_err(|_| TransportErrorKind::backend_gone())??; + + if !success { + let revert_data = if returnData.is_empty() { + "".to_string() + } else { + format!(" with data: {returnData}") + }; + Err(TransportErrorKind::custom_str(&format!( + "multicall batched call reverted{revert_data}" + ))) + } else { + Ok(returnData) } } - + async fn schedule_and_decode(self, msg: CallBatchMsgKind) -> TransportResult where T: SolValue + From<::RustType>, @@ -352,22 +338,42 @@ impl + 'static, N: Network> CallBatchBackend { if pending.len() == 1 { let msg = pending.into_iter().next().unwrap(); - let result: Result = match msg.kind { + let result: TransportResult = match msg.kind { CallBatchMsgKind::Call(tx) => { - let res = self.inner.call(tx).await.unwrap(); - Ok(CallResult::Single(res)) + self.inner.call(tx).await.map(|res| IMulticall3::Result { + success: true, + returnData: res, + }) } CallBatchMsgKind::BlockNumber => { - let result = self.inner.get_block_number().into_future().await.unwrap(); - Ok(CallResult::Single(Bytes::from(result.to_be_bytes()))) + self.inner + .get_block_number() + .into_future() + .await + .map(|res| IMulticall3::Result { + success: true, + returnData: res.abi_encode().into(), + }) } CallBatchMsgKind::ChainId => { - let result = self.inner.get_chain_id().into_future().await.unwrap(); - Ok(CallResult::Single(Bytes::from(result.to_be_bytes()))) + self.inner + .get_chain_id() + .into_future() + .await + .map(|res| IMulticall3::Result { + success: true, + returnData: res.abi_encode().into(), + }) } CallBatchMsgKind::Balance(addr) => { - let result = self.inner.get_balance(addr).into_future().await.unwrap(); - Ok(CallResult::Single(Bytes::from(result.to_be_bytes::<32>()))) + self.inner + .get_balance(addr) + .into_future() + .await + .map(|res| IMulticall3::Result { + success: true, + returnData: res.abi_encode().into(), + }) } }; @@ -380,7 +386,7 @@ impl + 'static, N: Network> CallBatchBackend { Ok(results) => { debug_assert_eq!(results.len(), pending.len()); for (result, msg) in results.into_iter().zip(pending) { - let _ = msg.tx.send(Ok(CallResult::Multicall(result))); + let _ = msg.tx.send(Ok(result)); } } Err(e) => { @@ -504,3 +510,101 @@ impl Caller for CallBatchCaller { Caller::::call_many(&self.weak, params) } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::ProviderBuilder; + use alloy_primitives::{address, hex}; + use alloy_rpc_types_eth::TransactionRequest; + use alloy_transport::mock::Asserter; + + // https://etherscan.io/address/0xcA11bde05977b3631167028862bE2a173976CA11#code + const MULTICALL3_DEPLOYED_CODE: &[u8] = &hex!("0x6080604052600436106100f35760003560e01c80634d2301cc1161008a578063a8b0574e11610059578063a8b0574e1461025a578063bce38bd714610275578063c3077fa914610288578063ee82ac5e1461029b57600080fd5b80634d2301cc146101ec57806372425d9d1461022157806382ad56cb1461023457806386d516e81461024757600080fd5b80633408e470116100c65780633408e47014610191578063399542e9146101a45780633e64a696146101c657806342cbb15c146101d957600080fd5b80630f28c97d146100f8578063174dea711461011a578063252dba421461013a57806327e86d6e1461015b575b600080fd5b34801561010457600080fd5b50425b6040519081526020015b60405180910390f35b61012d610128366004610a85565b6102ba565b6040516101119190610bbe565b61014d610148366004610a85565b6104ef565b604051610111929190610bd8565b34801561016757600080fd5b50437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0140610107565b34801561019d57600080fd5b5046610107565b6101b76101b2366004610c60565b610690565b60405161011193929190610cba565b3480156101d257600080fd5b5048610107565b3480156101e557600080fd5b5043610107565b3480156101f857600080fd5b50610107610207366004610ce2565b73ffffffffffffffffffffffffffffffffffffffff163190565b34801561022d57600080fd5b5044610107565b61012d610242366004610a85565b6106ab565b34801561025357600080fd5b5045610107565b34801561026657600080fd5b50604051418152602001610111565b61012d610283366004610c60565b61085a565b6101b7610296366004610a85565b610a1a565b3480156102a757600080fd5b506101076102b6366004610d18565b4090565b60606000828067ffffffffffffffff8111156102d8576102d8610d31565b60405190808252806020026020018201604052801561031e57816020015b6040805180820190915260008152606060208201528152602001906001900390816102f65790505b5092503660005b8281101561047757600085828151811061034157610341610d60565b6020026020010151905087878381811061035d5761035d610d60565b905060200281019061036f9190610d8f565b6040810135958601959093506103886020850185610ce2565b73ffffffffffffffffffffffffffffffffffffffff16816103ac6060870187610dcd565b6040516103ba929190610e32565b60006040518083038185875af1925050503d80600081146103f7576040519150601f19603f3d011682016040523d82523d6000602084013e6103fc565b606091505b50602080850191909152901515808452908501351761046d577f08c379a000000000000000000000000000000000000000000000000000000000600052602060045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260846000fd5b5050600101610325565b508234146104e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d756c746963616c6c333a2076616c7565206d69736d6174636800000000000060448201526064015b60405180910390fd5b50505092915050565b436060828067ffffffffffffffff81111561050c5761050c610d31565b60405190808252806020026020018201604052801561053f57816020015b606081526020019060019003908161052a5790505b5091503660005b8281101561068657600087878381811061056257610562610d60565b90506020028101906105749190610e42565b92506105836020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff166105a66020850185610dcd565b6040516105b4929190610e32565b6000604051808303816000865af19150503d80600081146105f1576040519150601f19603f3d011682016040523d82523d6000602084013e6105f6565b606091505b5086848151811061060957610609610d60565b602090810291909101015290508061067d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060448201526064016104dd565b50600101610546565b5050509250929050565b43804060606106a086868661085a565b905093509350939050565b6060818067ffffffffffffffff8111156106c7576106c7610d31565b60405190808252806020026020018201604052801561070d57816020015b6040805180820190915260008152606060208201528152602001906001900390816106e55790505b5091503660005b828110156104e657600084828151811061073057610730610d60565b6020026020010151905086868381811061074c5761074c610d60565b905060200281019061075e9190610e76565b925061076d6020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff166107906040850185610dcd565b60405161079e929190610e32565b6000604051808303816000865af19150503d80600081146107db576040519150601f19603f3d011682016040523d82523d6000602084013e6107e0565b606091505b506020808401919091529015158083529084013517610851577f08c379a000000000000000000000000000000000000000000000000000000000600052602060045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260646000fd5b50600101610714565b6060818067ffffffffffffffff81111561087657610876610d31565b6040519080825280602002602001820160405280156108bc57816020015b6040805180820190915260008152606060208201528152602001906001900390816108945790505b5091503660005b82811015610a105760008482815181106108df576108df610d60565b602002602001015190508686838181106108fb576108fb610d60565b905060200281019061090d9190610e42565b925061091c6020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff1661093f6020850185610dcd565b60405161094d929190610e32565b6000604051808303816000865af19150503d806000811461098a576040519150601f19603f3d011682016040523d82523d6000602084013e61098f565b606091505b506020830152151581528715610a07578051610a07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060448201526064016104dd565b506001016108c3565b5050509392505050565b6000806060610a2b60018686610690565b919790965090945092505050565b60008083601f840112610a4b57600080fd5b50813567ffffffffffffffff811115610a6357600080fd5b6020830191508360208260051b8501011115610a7e57600080fd5b9250929050565b60008060208385031215610a9857600080fd5b823567ffffffffffffffff811115610aaf57600080fd5b610abb85828601610a39565b90969095509350505050565b6000815180845260005b81811015610aed57602081850181015186830182015201610ad1565b81811115610aff576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600082825180855260208086019550808260051b84010181860160005b84811015610bb1578583037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001895281518051151584528401516040858501819052610b9d81860183610ac7565b9a86019a9450505090830190600101610b4f565b5090979650505050505050565b602081526000610bd16020830184610b32565b9392505050565b600060408201848352602060408185015281855180845260608601915060608160051b870101935082870160005b82811015610c52577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0888703018452610c40868351610ac7565b95509284019290840190600101610c06565b509398975050505050505050565b600080600060408486031215610c7557600080fd5b83358015158114610c8557600080fd5b9250602084013567ffffffffffffffff811115610ca157600080fd5b610cad86828701610a39565b9497909650939450505050565b838152826020820152606060408201526000610cd96060830184610b32565b95945050505050565b600060208284031215610cf457600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610bd157600080fd5b600060208284031215610d2a57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112610dc357600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112610e0257600080fd5b83018035915067ffffffffffffffff821115610e1d57600080fd5b602001915036819003821315610a7e57600080fd5b8183823760009101908152919050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112610dc357600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa1833603018112610dc357600080fdfea2646970667358221220bb2b5c71a328032f97c676ae39a1ec2148d3e5d6f73d95e9b17910152d61f16264736f6c634300080c0033"); + const COUNTER_ADDRESS: Address = address!("0x1234123412341234123412341234123412341234"); + const COUNTER_DEPLOYED_CODE: &[u8] = &hex!("0x6080604052348015600e575f5ffd5b5060043610603a575f3560e01c80633fb5c1cb14603e5780638381f58a14604f578063d09de08a146068575b5f5ffd5b604d6049366004607d565b5f55565b005b60565f5481565b60405190815260200160405180910390f35b604d5f805490806076836093565b9190505550565b5f60208284031215608c575f5ffd5b5035919050565b5f6001820160af57634e487b7160e01b5f52601160045260245ffd5b506001019056fea2646970667358221220f423ff7a9a85bf49c3769164d3bd24403940510478df27a6b1deac980db69e5664736f6c634300081b0033"); + + fn push_m3_success(asserter: &Asserter, returns: &[(bool, Vec)]) { + asserter.push_success( + &returns + .iter() + .map(|&(success, ref data)| IMulticall3::Result { + success, + returnData: Bytes::copy_from_slice(data), + }) + .collect::>() + .abi_encode(), + ) + } + + #[tokio::test] + async fn basic_mocked() { + let asserter = Asserter::new(); + let provider = + ProviderBuilder::new().with_call_batching().connect_mocked_client(asserter.clone()); + push_m3_success( + &asserter, + &[ + (true, 1.abi_encode()), // IMulticall3::getBlockNumberCall + (true, 2.abi_encode()), // IMulticall3::getChainIdCall + (false, 3.abi_encode()), // IMulticall3::getBlockNumberCall + (false, 4.abi_encode()), // IMulticall3::getChainIdCall + ], + ); + let (block_number_ok, chain_id_ok, block_number_err, chain_id_err) = tokio::join!( + provider.get_block_number(), + provider.get_chain_id(), + provider.get_block_number(), + provider.get_chain_id(), + ); + assert_eq!(block_number_ok.unwrap(), 1); + assert_eq!(chain_id_ok.unwrap(), 2); + assert!(block_number_err.unwrap_err().to_string().contains("reverted")); + assert!(chain_id_err.unwrap_err().to_string().contains("reverted")); + assert!(asserter.read_q().is_empty(), "only 1 request should've been made"); + } + + #[tokio::test] + #[cfg(feature = "anvil-api")] + async fn basic() { + use crate::ext::AnvilApi; + let provider = ProviderBuilder::new().with_call_batching().connect_anvil(); + provider.anvil_set_code(COUNTER_ADDRESS, COUNTER_DEPLOYED_CODE.into()).await.unwrap(); + provider.anvil_set_balance(COUNTER_ADDRESS, U256::from(123)).await.unwrap(); + + let do_calls = || async { + tokio::join!( + provider.call( + TransactionRequest::default() + .with_to(COUNTER_ADDRESS) + .with_input(hex!("0x8381f58a")) // number() + ), + provider.call( + TransactionRequest::default() + .with_to(MULTICALL3_ADDRESS) + .with_input(IMulticall3::getBlockNumberCall {}.abi_encode()) + ), + provider.get_block_number(), + provider.get_chain_id(), + provider.get_balance(COUNTER_ADDRESS), + ) + }; + + // Multicall3 has not yet been deployed. + let (a, b, c, d, e) = do_calls().await; + assert!(a.unwrap_err().to_string().contains("Multicall3 not deployed")); + assert!(b.unwrap_err().to_string().contains("Multicall3 not deployed")); + assert!(c.unwrap_err().to_string().contains("Multicall3 not deployed")); + assert!(d.unwrap_err().to_string().contains("Multicall3 not deployed")); + assert!(e.unwrap_err().to_string().contains("Multicall3 not deployed")); + + provider.anvil_set_code(MULTICALL3_ADDRESS, MULTICALL3_DEPLOYED_CODE.into()).await.unwrap(); + + let (counter, block_number_raw, block_number, chain_id, balance) = do_calls().await; + assert_eq!(counter.unwrap(), 0u64.abi_encode()); + assert_eq!(block_number_raw.unwrap(), 1u64.abi_encode()); + assert_eq!(block_number.unwrap(), 1); + assert_eq!(chain_id.unwrap(), alloy_chains::NamedChain::AnvilHardhat as u64); + assert_eq!(balance.unwrap(), U256::from(123)); + } +} From b2611de8f0f5cfc8eff23d049361583d59ce2962 Mon Sep 17 00:00:00 2001 From: Ayushdubey86 Date: Thu, 8 May 2025 19:04:47 +0530 Subject: [PATCH 08/11] fmt --- crates/provider/src/layers/batch.rs | 241 +++++++++++++--------------- 1 file changed, 112 insertions(+), 129 deletions(-) diff --git a/crates/provider/src/layers/batch.rs b/crates/provider/src/layers/batch.rs index 30746481e6f..196db04fd13 100644 --- a/crates/provider/src/layers/batch.rs +++ b/crates/provider/src/layers/batch.rs @@ -159,9 +159,7 @@ enum CallBatchMsgKind { } impl CallBatchMsg { - fn new( - kind: CallBatchMsgKind, - ) -> (Self, oneshot::Receiver) { + fn new(kind: CallBatchMsgKind) -> (Self, oneshot::Receiver) { let (tx, rx) = oneshot::channel(); (Self { kind, tx }, rx) } @@ -259,10 +257,10 @@ impl CallBatchProviderInner { async fn schedule(self, msg: CallBatchMsgKind) -> TransportResult { let (msg, rx) = CallBatchMsg::new(msg); self.tx.send(msg).map_err(|_| TransportErrorKind::backend_gone())?; - + let IMulticall3::Result { success, returnData } = rx.await.map_err(|_| TransportErrorKind::backend_gone())??; - + if !success { let revert_data = if returnData.is_empty() { "".to_string() @@ -276,7 +274,7 @@ impl CallBatchProviderInner { Ok(returnData) } } - + async fn schedule_and_decode(self, msg: CallBatchMsgKind) -> TransportResult where T: SolValue + From<::RustType>, @@ -339,41 +337,26 @@ impl + 'static, N: Network> CallBatchBackend { let msg = pending.into_iter().next().unwrap(); let result: TransportResult = match msg.kind { - CallBatchMsgKind::Call(tx) => { - self.inner.call(tx).await.map(|res| IMulticall3::Result { - success: true, - returnData: res, + CallBatchMsgKind::Call(tx) => self + .inner + .call(tx) + .await + .map(|res| IMulticall3::Result { success: true, returnData: res }), + CallBatchMsgKind::BlockNumber => { + self.inner.get_block_number().into_future().await.map(|res| { + IMulticall3::Result { success: true, returnData: res.abi_encode().into() } }) } - CallBatchMsgKind::BlockNumber => { - self.inner - .get_block_number() - .into_future() - .await - .map(|res| IMulticall3::Result { - success: true, - returnData: res.abi_encode().into(), - }) - } CallBatchMsgKind::ChainId => { - self.inner - .get_chain_id() - .into_future() - .await - .map(|res| IMulticall3::Result { - success: true, - returnData: res.abi_encode().into(), - }) + self.inner.get_chain_id().into_future().await.map(|res| IMulticall3::Result { + success: true, + returnData: res.abi_encode().into(), + }) } CallBatchMsgKind::Balance(addr) => { - self.inner - .get_balance(addr) - .into_future() - .await - .map(|res| IMulticall3::Result { - success: true, - returnData: res.abi_encode().into(), - }) + self.inner.get_balance(addr).into_future().await.map(|res| { + IMulticall3::Result { success: true, returnData: res.abi_encode().into() } + }) } }; @@ -513,98 +496,98 @@ impl Caller for CallBatchCaller { #[cfg(test)] mod tests { - use super::*; - use crate::ProviderBuilder; - use alloy_primitives::{address, hex}; - use alloy_rpc_types_eth::TransactionRequest; - use alloy_transport::mock::Asserter; - - // https://etherscan.io/address/0xcA11bde05977b3631167028862bE2a173976CA11#code - const MULTICALL3_DEPLOYED_CODE: &[u8] = &hex!("0x6080604052600436106100f35760003560e01c80634d2301cc1161008a578063a8b0574e11610059578063a8b0574e1461025a578063bce38bd714610275578063c3077fa914610288578063ee82ac5e1461029b57600080fd5b80634d2301cc146101ec57806372425d9d1461022157806382ad56cb1461023457806386d516e81461024757600080fd5b80633408e470116100c65780633408e47014610191578063399542e9146101a45780633e64a696146101c657806342cbb15c146101d957600080fd5b80630f28c97d146100f8578063174dea711461011a578063252dba421461013a57806327e86d6e1461015b575b600080fd5b34801561010457600080fd5b50425b6040519081526020015b60405180910390f35b61012d610128366004610a85565b6102ba565b6040516101119190610bbe565b61014d610148366004610a85565b6104ef565b604051610111929190610bd8565b34801561016757600080fd5b50437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0140610107565b34801561019d57600080fd5b5046610107565b6101b76101b2366004610c60565b610690565b60405161011193929190610cba565b3480156101d257600080fd5b5048610107565b3480156101e557600080fd5b5043610107565b3480156101f857600080fd5b50610107610207366004610ce2565b73ffffffffffffffffffffffffffffffffffffffff163190565b34801561022d57600080fd5b5044610107565b61012d610242366004610a85565b6106ab565b34801561025357600080fd5b5045610107565b34801561026657600080fd5b50604051418152602001610111565b61012d610283366004610c60565b61085a565b6101b7610296366004610a85565b610a1a565b3480156102a757600080fd5b506101076102b6366004610d18565b4090565b60606000828067ffffffffffffffff8111156102d8576102d8610d31565b60405190808252806020026020018201604052801561031e57816020015b6040805180820190915260008152606060208201528152602001906001900390816102f65790505b5092503660005b8281101561047757600085828151811061034157610341610d60565b6020026020010151905087878381811061035d5761035d610d60565b905060200281019061036f9190610d8f565b6040810135958601959093506103886020850185610ce2565b73ffffffffffffffffffffffffffffffffffffffff16816103ac6060870187610dcd565b6040516103ba929190610e32565b60006040518083038185875af1925050503d80600081146103f7576040519150601f19603f3d011682016040523d82523d6000602084013e6103fc565b606091505b50602080850191909152901515808452908501351761046d577f08c379a000000000000000000000000000000000000000000000000000000000600052602060045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260846000fd5b5050600101610325565b508234146104e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d756c746963616c6c333a2076616c7565206d69736d6174636800000000000060448201526064015b60405180910390fd5b50505092915050565b436060828067ffffffffffffffff81111561050c5761050c610d31565b60405190808252806020026020018201604052801561053f57816020015b606081526020019060019003908161052a5790505b5091503660005b8281101561068657600087878381811061056257610562610d60565b90506020028101906105749190610e42565b92506105836020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff166105a66020850185610dcd565b6040516105b4929190610e32565b6000604051808303816000865af19150503d80600081146105f1576040519150601f19603f3d011682016040523d82523d6000602084013e6105f6565b606091505b5086848151811061060957610609610d60565b602090810291909101015290508061067d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060448201526064016104dd565b50600101610546565b5050509250929050565b43804060606106a086868661085a565b905093509350939050565b6060818067ffffffffffffffff8111156106c7576106c7610d31565b60405190808252806020026020018201604052801561070d57816020015b6040805180820190915260008152606060208201528152602001906001900390816106e55790505b5091503660005b828110156104e657600084828151811061073057610730610d60565b6020026020010151905086868381811061074c5761074c610d60565b905060200281019061075e9190610e76565b925061076d6020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff166107906040850185610dcd565b60405161079e929190610e32565b6000604051808303816000865af19150503d80600081146107db576040519150601f19603f3d011682016040523d82523d6000602084013e6107e0565b606091505b506020808401919091529015158083529084013517610851577f08c379a000000000000000000000000000000000000000000000000000000000600052602060045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260646000fd5b50600101610714565b6060818067ffffffffffffffff81111561087657610876610d31565b6040519080825280602002602001820160405280156108bc57816020015b6040805180820190915260008152606060208201528152602001906001900390816108945790505b5091503660005b82811015610a105760008482815181106108df576108df610d60565b602002602001015190508686838181106108fb576108fb610d60565b905060200281019061090d9190610e42565b925061091c6020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff1661093f6020850185610dcd565b60405161094d929190610e32565b6000604051808303816000865af19150503d806000811461098a576040519150601f19603f3d011682016040523d82523d6000602084013e61098f565b606091505b506020830152151581528715610a07578051610a07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060448201526064016104dd565b506001016108c3565b5050509392505050565b6000806060610a2b60018686610690565b919790965090945092505050565b60008083601f840112610a4b57600080fd5b50813567ffffffffffffffff811115610a6357600080fd5b6020830191508360208260051b8501011115610a7e57600080fd5b9250929050565b60008060208385031215610a9857600080fd5b823567ffffffffffffffff811115610aaf57600080fd5b610abb85828601610a39565b90969095509350505050565b6000815180845260005b81811015610aed57602081850181015186830182015201610ad1565b81811115610aff576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600082825180855260208086019550808260051b84010181860160005b84811015610bb1578583037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001895281518051151584528401516040858501819052610b9d81860183610ac7565b9a86019a9450505090830190600101610b4f565b5090979650505050505050565b602081526000610bd16020830184610b32565b9392505050565b600060408201848352602060408185015281855180845260608601915060608160051b870101935082870160005b82811015610c52577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0888703018452610c40868351610ac7565b95509284019290840190600101610c06565b509398975050505050505050565b600080600060408486031215610c7557600080fd5b83358015158114610c8557600080fd5b9250602084013567ffffffffffffffff811115610ca157600080fd5b610cad86828701610a39565b9497909650939450505050565b838152826020820152606060408201526000610cd96060830184610b32565b95945050505050565b600060208284031215610cf457600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610bd157600080fd5b600060208284031215610d2a57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112610dc357600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112610e0257600080fd5b83018035915067ffffffffffffffff821115610e1d57600080fd5b602001915036819003821315610a7e57600080fd5b8183823760009101908152919050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112610dc357600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa1833603018112610dc357600080fdfea2646970667358221220bb2b5c71a328032f97c676ae39a1ec2148d3e5d6f73d95e9b17910152d61f16264736f6c634300080c0033"); - const COUNTER_ADDRESS: Address = address!("0x1234123412341234123412341234123412341234"); - const COUNTER_DEPLOYED_CODE: &[u8] = &hex!("0x6080604052348015600e575f5ffd5b5060043610603a575f3560e01c80633fb5c1cb14603e5780638381f58a14604f578063d09de08a146068575b5f5ffd5b604d6049366004607d565b5f55565b005b60565f5481565b60405190815260200160405180910390f35b604d5f805490806076836093565b9190505550565b5f60208284031215608c575f5ffd5b5035919050565b5f6001820160af57634e487b7160e01b5f52601160045260245ffd5b506001019056fea2646970667358221220f423ff7a9a85bf49c3769164d3bd24403940510478df27a6b1deac980db69e5664736f6c634300081b0033"); - - fn push_m3_success(asserter: &Asserter, returns: &[(bool, Vec)]) { - asserter.push_success( - &returns - .iter() - .map(|&(success, ref data)| IMulticall3::Result { - success, - returnData: Bytes::copy_from_slice(data), - }) - .collect::>() - .abi_encode(), - ) - } - - #[tokio::test] - async fn basic_mocked() { - let asserter = Asserter::new(); - let provider = - ProviderBuilder::new().with_call_batching().connect_mocked_client(asserter.clone()); - push_m3_success( - &asserter, - &[ - (true, 1.abi_encode()), // IMulticall3::getBlockNumberCall - (true, 2.abi_encode()), // IMulticall3::getChainIdCall - (false, 3.abi_encode()), // IMulticall3::getBlockNumberCall - (false, 4.abi_encode()), // IMulticall3::getChainIdCall - ], - ); - let (block_number_ok, chain_id_ok, block_number_err, chain_id_err) = tokio::join!( - provider.get_block_number(), - provider.get_chain_id(), - provider.get_block_number(), - provider.get_chain_id(), - ); - assert_eq!(block_number_ok.unwrap(), 1); - assert_eq!(chain_id_ok.unwrap(), 2); - assert!(block_number_err.unwrap_err().to_string().contains("reverted")); - assert!(chain_id_err.unwrap_err().to_string().contains("reverted")); - assert!(asserter.read_q().is_empty(), "only 1 request should've been made"); - } - - #[tokio::test] - #[cfg(feature = "anvil-api")] - async fn basic() { - use crate::ext::AnvilApi; - let provider = ProviderBuilder::new().with_call_batching().connect_anvil(); - provider.anvil_set_code(COUNTER_ADDRESS, COUNTER_DEPLOYED_CODE.into()).await.unwrap(); - provider.anvil_set_balance(COUNTER_ADDRESS, U256::from(123)).await.unwrap(); + use super::*; + use crate::ProviderBuilder; + use alloy_primitives::{address, hex}; + use alloy_rpc_types_eth::TransactionRequest; + use alloy_transport::mock::Asserter; + + // https://etherscan.io/address/0xcA11bde05977b3631167028862bE2a173976CA11#code + const MULTICALL3_DEPLOYED_CODE: &[u8] = &hex!("0x6080604052600436106100f35760003560e01c80634d2301cc1161008a578063a8b0574e11610059578063a8b0574e1461025a578063bce38bd714610275578063c3077fa914610288578063ee82ac5e1461029b57600080fd5b80634d2301cc146101ec57806372425d9d1461022157806382ad56cb1461023457806386d516e81461024757600080fd5b80633408e470116100c65780633408e47014610191578063399542e9146101a45780633e64a696146101c657806342cbb15c146101d957600080fd5b80630f28c97d146100f8578063174dea711461011a578063252dba421461013a57806327e86d6e1461015b575b600080fd5b34801561010457600080fd5b50425b6040519081526020015b60405180910390f35b61012d610128366004610a85565b6102ba565b6040516101119190610bbe565b61014d610148366004610a85565b6104ef565b604051610111929190610bd8565b34801561016757600080fd5b50437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0140610107565b34801561019d57600080fd5b5046610107565b6101b76101b2366004610c60565b610690565b60405161011193929190610cba565b3480156101d257600080fd5b5048610107565b3480156101e557600080fd5b5043610107565b3480156101f857600080fd5b50610107610207366004610ce2565b73ffffffffffffffffffffffffffffffffffffffff163190565b34801561022d57600080fd5b5044610107565b61012d610242366004610a85565b6106ab565b34801561025357600080fd5b5045610107565b34801561026657600080fd5b50604051418152602001610111565b61012d610283366004610c60565b61085a565b6101b7610296366004610a85565b610a1a565b3480156102a757600080fd5b506101076102b6366004610d18565b4090565b60606000828067ffffffffffffffff8111156102d8576102d8610d31565b60405190808252806020026020018201604052801561031e57816020015b6040805180820190915260008152606060208201528152602001906001900390816102f65790505b5092503660005b8281101561047757600085828151811061034157610341610d60565b6020026020010151905087878381811061035d5761035d610d60565b905060200281019061036f9190610d8f565b6040810135958601959093506103886020850185610ce2565b73ffffffffffffffffffffffffffffffffffffffff16816103ac6060870187610dcd565b6040516103ba929190610e32565b60006040518083038185875af1925050503d80600081146103f7576040519150601f19603f3d011682016040523d82523d6000602084013e6103fc565b606091505b50602080850191909152901515808452908501351761046d577f08c379a000000000000000000000000000000000000000000000000000000000600052602060045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260846000fd5b5050600101610325565b508234146104e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d756c746963616c6c333a2076616c7565206d69736d6174636800000000000060448201526064015b60405180910390fd5b50505092915050565b436060828067ffffffffffffffff81111561050c5761050c610d31565b60405190808252806020026020018201604052801561053f57816020015b606081526020019060019003908161052a5790505b5091503660005b8281101561068657600087878381811061056257610562610d60565b90506020028101906105749190610e42565b92506105836020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff166105a66020850185610dcd565b6040516105b4929190610e32565b6000604051808303816000865af19150503d80600081146105f1576040519150601f19603f3d011682016040523d82523d6000602084013e6105f6565b606091505b5086848151811061060957610609610d60565b602090810291909101015290508061067d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060448201526064016104dd565b50600101610546565b5050509250929050565b43804060606106a086868661085a565b905093509350939050565b6060818067ffffffffffffffff8111156106c7576106c7610d31565b60405190808252806020026020018201604052801561070d57816020015b6040805180820190915260008152606060208201528152602001906001900390816106e55790505b5091503660005b828110156104e657600084828151811061073057610730610d60565b6020026020010151905086868381811061074c5761074c610d60565b905060200281019061075e9190610e76565b925061076d6020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff166107906040850185610dcd565b60405161079e929190610e32565b6000604051808303816000865af19150503d80600081146107db576040519150601f19603f3d011682016040523d82523d6000602084013e6107e0565b606091505b506020808401919091529015158083529084013517610851577f08c379a000000000000000000000000000000000000000000000000000000000600052602060045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260646000fd5b50600101610714565b6060818067ffffffffffffffff81111561087657610876610d31565b6040519080825280602002602001820160405280156108bc57816020015b6040805180820190915260008152606060208201528152602001906001900390816108945790505b5091503660005b82811015610a105760008482815181106108df576108df610d60565b602002602001015190508686838181106108fb576108fb610d60565b905060200281019061090d9190610e42565b925061091c6020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff1661093f6020850185610dcd565b60405161094d929190610e32565b6000604051808303816000865af19150503d806000811461098a576040519150601f19603f3d011682016040523d82523d6000602084013e61098f565b606091505b506020830152151581528715610a07578051610a07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060448201526064016104dd565b506001016108c3565b5050509392505050565b6000806060610a2b60018686610690565b919790965090945092505050565b60008083601f840112610a4b57600080fd5b50813567ffffffffffffffff811115610a6357600080fd5b6020830191508360208260051b8501011115610a7e57600080fd5b9250929050565b60008060208385031215610a9857600080fd5b823567ffffffffffffffff811115610aaf57600080fd5b610abb85828601610a39565b90969095509350505050565b6000815180845260005b81811015610aed57602081850181015186830182015201610ad1565b81811115610aff576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600082825180855260208086019550808260051b84010181860160005b84811015610bb1578583037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001895281518051151584528401516040858501819052610b9d81860183610ac7565b9a86019a9450505090830190600101610b4f565b5090979650505050505050565b602081526000610bd16020830184610b32565b9392505050565b600060408201848352602060408185015281855180845260608601915060608160051b870101935082870160005b82811015610c52577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0888703018452610c40868351610ac7565b95509284019290840190600101610c06565b509398975050505050505050565b600080600060408486031215610c7557600080fd5b83358015158114610c8557600080fd5b9250602084013567ffffffffffffffff811115610ca157600080fd5b610cad86828701610a39565b9497909650939450505050565b838152826020820152606060408201526000610cd96060830184610b32565b95945050505050565b600060208284031215610cf457600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610bd157600080fd5b600060208284031215610d2a57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112610dc357600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112610e0257600080fd5b83018035915067ffffffffffffffff821115610e1d57600080fd5b602001915036819003821315610a7e57600080fd5b8183823760009101908152919050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112610dc357600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa1833603018112610dc357600080fdfea2646970667358221220bb2b5c71a328032f97c676ae39a1ec2148d3e5d6f73d95e9b17910152d61f16264736f6c634300080c0033"); + const COUNTER_ADDRESS: Address = address!("0x1234123412341234123412341234123412341234"); + const COUNTER_DEPLOYED_CODE: &[u8] = &hex!("0x6080604052348015600e575f5ffd5b5060043610603a575f3560e01c80633fb5c1cb14603e5780638381f58a14604f578063d09de08a146068575b5f5ffd5b604d6049366004607d565b5f55565b005b60565f5481565b60405190815260200160405180910390f35b604d5f805490806076836093565b9190505550565b5f60208284031215608c575f5ffd5b5035919050565b5f6001820160af57634e487b7160e01b5f52601160045260245ffd5b506001019056fea2646970667358221220f423ff7a9a85bf49c3769164d3bd24403940510478df27a6b1deac980db69e5664736f6c634300081b0033"); + + fn push_m3_success(asserter: &Asserter, returns: &[(bool, Vec)]) { + asserter.push_success( + &returns + .iter() + .map(|&(success, ref data)| IMulticall3::Result { + success, + returnData: Bytes::copy_from_slice(data), + }) + .collect::>() + .abi_encode(), + ) + } + + #[tokio::test] + async fn basic_mocked() { + let asserter = Asserter::new(); + let provider = + ProviderBuilder::new().with_call_batching().connect_mocked_client(asserter.clone()); + push_m3_success( + &asserter, + &[ + (true, 1.abi_encode()), // IMulticall3::getBlockNumberCall + (true, 2.abi_encode()), // IMulticall3::getChainIdCall + (false, 3.abi_encode()), // IMulticall3::getBlockNumberCall + (false, 4.abi_encode()), // IMulticall3::getChainIdCall + ], + ); + let (block_number_ok, chain_id_ok, block_number_err, chain_id_err) = tokio::join!( + provider.get_block_number(), + provider.get_chain_id(), + provider.get_block_number(), + provider.get_chain_id(), + ); + assert_eq!(block_number_ok.unwrap(), 1); + assert_eq!(chain_id_ok.unwrap(), 2); + assert!(block_number_err.unwrap_err().to_string().contains("reverted")); + assert!(chain_id_err.unwrap_err().to_string().contains("reverted")); + assert!(asserter.read_q().is_empty(), "only 1 request should've been made"); + } + + #[tokio::test] + #[cfg(feature = "anvil-api")] + async fn basic() { + use crate::ext::AnvilApi; + let provider = ProviderBuilder::new().with_call_batching().connect_anvil(); + provider.anvil_set_code(COUNTER_ADDRESS, COUNTER_DEPLOYED_CODE.into()).await.unwrap(); + provider.anvil_set_balance(COUNTER_ADDRESS, U256::from(123)).await.unwrap(); let do_calls = || async { - tokio::join!( - provider.call( - TransactionRequest::default() - .with_to(COUNTER_ADDRESS) - .with_input(hex!("0x8381f58a")) // number() - ), - provider.call( - TransactionRequest::default() - .with_to(MULTICALL3_ADDRESS) - .with_input(IMulticall3::getBlockNumberCall {}.abi_encode()) - ), - provider.get_block_number(), - provider.get_chain_id(), - provider.get_balance(COUNTER_ADDRESS), - ) - }; - - // Multicall3 has not yet been deployed. - let (a, b, c, d, e) = do_calls().await; - assert!(a.unwrap_err().to_string().contains("Multicall3 not deployed")); - assert!(b.unwrap_err().to_string().contains("Multicall3 not deployed")); - assert!(c.unwrap_err().to_string().contains("Multicall3 not deployed")); - assert!(d.unwrap_err().to_string().contains("Multicall3 not deployed")); - assert!(e.unwrap_err().to_string().contains("Multicall3 not deployed")); - - provider.anvil_set_code(MULTICALL3_ADDRESS, MULTICALL3_DEPLOYED_CODE.into()).await.unwrap(); - - let (counter, block_number_raw, block_number, chain_id, balance) = do_calls().await; - assert_eq!(counter.unwrap(), 0u64.abi_encode()); - assert_eq!(block_number_raw.unwrap(), 1u64.abi_encode()); - assert_eq!(block_number.unwrap(), 1); - assert_eq!(chain_id.unwrap(), alloy_chains::NamedChain::AnvilHardhat as u64); - assert_eq!(balance.unwrap(), U256::from(123)); - } -} + tokio::join!( + provider.call( + TransactionRequest::default() + .with_to(COUNTER_ADDRESS) + .with_input(hex!("0x8381f58a")) // number() + ), + provider.call( + TransactionRequest::default() + .with_to(MULTICALL3_ADDRESS) + .with_input(IMulticall3::getBlockNumberCall {}.abi_encode()) + ), + provider.get_block_number(), + provider.get_chain_id(), + provider.get_balance(COUNTER_ADDRESS), + ) + }; + + // Multicall3 has not yet been deployed. + let (a, b, c, d, e) = do_calls().await; + assert!(a.unwrap_err().to_string().contains("Multicall3 not deployed")); + assert!(b.unwrap_err().to_string().contains("Multicall3 not deployed")); + assert!(c.unwrap_err().to_string().contains("Multicall3 not deployed")); + assert!(d.unwrap_err().to_string().contains("Multicall3 not deployed")); + assert!(e.unwrap_err().to_string().contains("Multicall3 not deployed")); + + provider.anvil_set_code(MULTICALL3_ADDRESS, MULTICALL3_DEPLOYED_CODE.into()).await.unwrap(); + + let (counter, block_number_raw, block_number, chain_id, balance) = do_calls().await; + assert_eq!(counter.unwrap(), 0u64.abi_encode()); + assert_eq!(block_number_raw.unwrap(), 1u64.abi_encode()); + assert_eq!(block_number.unwrap(), 1); + assert_eq!(chain_id.unwrap(), alloy_chains::NamedChain::AnvilHardhat as u64); + assert_eq!(balance.unwrap(), U256::from(123)); + } +} From 2a45415b2e0ad21202fd2c6f66fe578dcc484d84 Mon Sep 17 00:00:00 2001 From: Ayushdubey86 Date: Thu, 8 May 2025 19:09:34 +0530 Subject: [PATCH 09/11] fmt --- crates/provider/src/layers/batch.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/provider/src/layers/batch.rs b/crates/provider/src/layers/batch.rs index 196db04fd13..5df69b48baf 100644 --- a/crates/provider/src/layers/batch.rs +++ b/crates/provider/src/layers/batch.rs @@ -342,7 +342,7 @@ impl + 'static, N: Network> CallBatchBackend { .call(tx) .await .map(|res| IMulticall3::Result { success: true, returnData: res }), - CallBatchMsgKind::BlockNumber => { + CallBatchMsgKind::BlockNumber => { self.inner.get_block_number().into_future().await.map(|res| { IMulticall3::Result { success: true, returnData: res.abi_encode().into() } }) @@ -555,7 +555,7 @@ mod tests { provider.anvil_set_code(COUNTER_ADDRESS, COUNTER_DEPLOYED_CODE.into()).await.unwrap(); provider.anvil_set_balance(COUNTER_ADDRESS, U256::from(123)).await.unwrap(); - let do_calls = || async { + let do_calls = || async { tokio::join!( provider.call( TransactionRequest::default() From 8254b4b0f1837277929c598e24d595c0d709a5d8 Mon Sep 17 00:00:00 2001 From: Ayushdubey86 Date: Fri, 9 May 2025 03:20:25 +0530 Subject: [PATCH 10/11] doc + removing clone --- crates/provider/src/layers/batch.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/crates/provider/src/layers/batch.rs b/crates/provider/src/layers/batch.rs index 5df69b48baf..41e9cd5ee9b 100644 --- a/crates/provider/src/layers/batch.rs +++ b/crates/provider/src/layers/batch.rs @@ -166,7 +166,7 @@ impl CallBatchMsg { } impl CallBatchMsgKind { - fn into_call3(self, m3a: Address) -> IMulticall3::Call3 { + fn to_call3(&self, m3a: Address) -> IMulticall3::Call3 { let m3a_call = |data: Vec| IMulticall3::Call3 { target: m3a, allowFailure: true, @@ -180,7 +180,7 @@ impl CallBatchMsgKind { }, Self::BlockNumber => m3a_call(IMulticall3::getBlockNumberCall {}.abi_encode()), Self::ChainId => m3a_call(IMulticall3::getChainIdCall {}.abi_encode()), - Self::Balance(addr) => m3a_call(IMulticall3::getEthBalanceCall { addr }.abi_encode()), + Self::Balance(addr) => m3a_call(IMulticall3::getEthBalanceCall { addr: *addr }.abi_encode()), } } } @@ -333,6 +333,8 @@ impl + 'static, N: Network> CallBatchBackend { async fn send_batch(&mut self) { let pending = std::mem::take(&mut self.pending); + // If there's only a single call, avoid batching and perform the request directly. + // Instead, execute the call directly and wrap the result in a Multicall3-style response. if pending.len() == 1 { let msg = pending.into_iter().next().unwrap(); @@ -385,7 +387,7 @@ impl + 'static, N: Network> CallBatchBackend { pending: &[CallBatchMsg], ) -> TransportResult> { let call3s: Vec<_> = - pending.iter().map(|msg| msg.kind.clone().into_call3(self.m3a)).collect(); + pending.iter().map(|msg| msg.kind.to_call3(self.m3a)).collect(); let tx = N::TransactionRequest::default() .with_to(self.m3a) From 516d80eb4711ed46dc24b8ff1b3cb198295e7f43 Mon Sep 17 00:00:00 2001 From: Ayushdubey86 Date: Fri, 9 May 2025 03:23:50 +0530 Subject: [PATCH 11/11] fmt --- crates/provider/src/layers/batch.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/provider/src/layers/batch.rs b/crates/provider/src/layers/batch.rs index 41e9cd5ee9b..e898c44e257 100644 --- a/crates/provider/src/layers/batch.rs +++ b/crates/provider/src/layers/batch.rs @@ -180,7 +180,9 @@ impl CallBatchMsgKind { }, Self::BlockNumber => m3a_call(IMulticall3::getBlockNumberCall {}.abi_encode()), Self::ChainId => m3a_call(IMulticall3::getChainIdCall {}.abi_encode()), - Self::Balance(addr) => m3a_call(IMulticall3::getEthBalanceCall { addr: *addr }.abi_encode()), + Self::Balance(addr) => { + m3a_call(IMulticall3::getEthBalanceCall { addr: *addr }.abi_encode()) + } } } } @@ -386,8 +388,7 @@ impl + 'static, N: Network> CallBatchBackend { &self, pending: &[CallBatchMsg], ) -> TransportResult> { - let call3s: Vec<_> = - pending.iter().map(|msg| msg.kind.to_call3(self.m3a)).collect(); + let call3s: Vec<_> = pending.iter().map(|msg| msg.kind.to_call3(self.m3a)).collect(); let tx = N::TransactionRequest::default() .with_to(self.m3a)