diff --git a/processor/ethereum/erc20/src/lib.rs b/processor/ethereum/erc20/src/lib.rs index 4d0cb0ff..20e086aa 100644 --- a/processor/ethereum/erc20/src/lib.rs +++ b/processor/ethereum/erc20/src/lib.rs @@ -2,6 +2,7 @@ #![doc = include_str!("../README.md")] #![deny(missing_docs)] +use core::ops::RangeInclusive; use std::collections::HashMap; use alloy_core::primitives::{Address, U256}; @@ -76,8 +77,8 @@ pub struct TopLevelTransfers { pub struct Erc20; impl Erc20 { /// The filter for transfer logs of the specified ERC20, to the specified recipient. - fn transfer_filter(from_block: u64, to_block: u64, erc20: Address, to: Address) -> Filter { - let filter = Filter::new().from_block(from_block).to_block(to_block); + fn transfer_filter(blocks: RangeInclusive, erc20: Address, to: Address) -> Filter { + let filter = Filter::new().select(blocks); filter.address(erc20).event_signature(Transfer::SIGNATURE_HASH).topic2(to.into_word()) } @@ -180,14 +181,13 @@ impl Erc20 { /// The `transfers` in the result are unordered. The `logs` are sorted by index. pub async fn top_level_transfers_unordered( provider: &RootProvider, - from_block: u64, - to_block: u64, + blocks: RangeInclusive, erc20: Address, to: Address, ) -> Result> { let mut logs = { // Get all transfers within these blocks - let logs = provider.get_logs(&Self::transfer_filter(from_block, to_block, erc20, to)).await?; + let logs = provider.get_logs(&Self::transfer_filter(blocks, erc20, to)).await?; // The logs, indexed by their transactions let mut transaction_logs = HashMap::new(); diff --git a/processor/ethereum/router/src/lib.rs b/processor/ethereum/router/src/lib.rs index de9531f7..42495b13 100644 --- a/processor/ethereum/router/src/lib.rs +++ b/processor/ethereum/router/src/lib.rs @@ -2,6 +2,7 @@ #![doc = include_str!("../README.md")] #![deny(missing_docs)] +use core::ops::RangeInclusive; use std::{ sync::Arc, collections::{HashSet, HashMap}, @@ -459,13 +460,13 @@ impl Router { /// This is not guaranteed to return them in any order. pub async fn in_instructions_unordered( &self, - from_block: u64, - to_block: u64, + blocks: RangeInclusive, allowed_erc20s: &HashSet
, ) -> Result, RpcError> { // The InInstruction events for this block let in_instruction_logs = { - let filter = Filter::new().from_block(from_block).to_block(to_block).address(self.address); + // https://github.com/rust-lang/rust/issues/27186 + let filter = Filter::new().select(blocks.clone()).address(self.address); let filter = filter.event_signature(InInstructionEvent::SIGNATURE_HASH); self.provider.get_logs(&filter).await? }; @@ -478,18 +479,15 @@ impl Router { let erc20_transfer_logs = { let mut transfers = FuturesUnordered::new(); for erc20 in allowed_erc20s { - transfers.push(async move { - ( - erc20, - Erc20::top_level_transfers_unordered( - &self.provider, - from_block, - to_block, - *erc20, - self.address, - ) - .await, - ) + transfers.push({ + // https://github.com/rust-lang/rust/issues/27186 + let blocks: RangeInclusive = blocks.clone(); + async move { + let transfers = + Erc20::top_level_transfers_unordered(&self.provider, blocks, *erc20, self.address) + .await; + (erc20, transfers) + } }); } @@ -626,8 +624,7 @@ impl Router { /// Fetch the executed actions for the specified range of blocks. pub async fn executed( &self, - from_block: u64, - to_block: u64, + blocks: RangeInclusive, ) -> Result, RpcError> { fn decode(log: &Log) -> Result> { Ok( @@ -643,7 +640,7 @@ impl Router { ) } - let filter = Filter::new().from_block(from_block).to_block(to_block).address(self.address); + let filter = Filter::new().select(blocks).address(self.address); let mut logs = self.provider.get_logs(&filter).await?; logs.sort_by_key(|log| (log.block_number, log.log_index)); @@ -707,10 +704,9 @@ impl Router { /// Fetch the `Escape`s from the smart contract through the escape hatch. pub async fn escapes( &self, - from_block: u64, - to_block: u64, + blocks: RangeInclusive, ) -> Result, RpcError> { - let filter = Filter::new().from_block(from_block).to_block(to_block).address(self.address); + let filter = Filter::new().select(blocks).address(self.address); let mut logs = self.provider.get_logs(&filter.event_signature(EscapedEvent::SIGNATURE_HASH)).await?; logs.sort_by_key(|log| (log.block_number, log.log_index)); diff --git a/processor/ethereum/router/src/tests/mod.rs b/processor/ethereum/router/src/tests/mod.rs index a94e4cbb..5b9748b3 100644 --- a/processor/ethereum/router/src/tests/mod.rs +++ b/processor/ethereum/router/src/tests/mod.rs @@ -144,7 +144,7 @@ impl Test { // Confirm nonce 0 was used as such { let block = receipt.block_number.unwrap(); - let executed = router.executed(block, block).await.unwrap(); + let executed = router.executed(block ..= block).await.unwrap(); assert_eq!(executed.len(), 1); assert_eq!(executed[0], Executed::NextSeraiKeySet { nonce: 0, key: public_key.eth_repr() }); } @@ -191,7 +191,7 @@ impl Test { { let block = receipt.block_number.unwrap(); - let executed = self.router.executed(block, block).await.unwrap(); + let executed = self.router.executed(block ..= block).await.unwrap(); assert_eq!(executed.len(), 1); assert_eq!( executed[0], @@ -236,7 +236,7 @@ impl Test { { let block = receipt.block_number.unwrap(); - let executed = self.router.executed(block, block).await.unwrap(); + let executed = self.router.executed(block ..= block).await.unwrap(); assert_eq!(executed.len(), 1); assert_eq!( executed[0], @@ -283,15 +283,14 @@ impl Test { if matches!(coin, Coin::Erc20(_)) { // If we don't whitelist this token, we shouldn't be yielded an InInstruction let in_instructions = - self.router.in_instructions_unordered(block, block, &HashSet::new()).await.unwrap(); + self.router.in_instructions_unordered(block ..= block, &HashSet::new()).await.unwrap(); assert!(in_instructions.is_empty()); } let in_instructions = self .router .in_instructions_unordered( - block, - block, + block ..= block, &if let Coin::Erc20(token) = coin { HashSet::from([token]) } else { HashSet::new() }, ) .await @@ -359,7 +358,7 @@ impl Test { { let block = receipt.block_number.unwrap(); - let executed = self.router.executed(block, block).await.unwrap(); + let executed = self.router.executed(block ..= block).await.unwrap(); assert_eq!(executed.len(), 1); assert_eq!(executed[0], Executed::EscapeHatch { nonce: self.state.next_nonce, escape_to }); } @@ -707,7 +706,7 @@ async fn test_escape_hatch() { let block = receipt.block_number.unwrap(); assert_eq!( - test.router.escapes(block, block).await.unwrap(), + test.router.escapes(block ..= block).await.unwrap(), vec![Escape { coin: Coin::Ether, amount: U256::from(1) }], ); @@ -730,7 +729,7 @@ async fn test_escape_hatch() { assert!(receipt.status()); let block = receipt.block_number.unwrap(); - assert_eq!(test.router.escapes(block, block).await.unwrap(), vec![Escape { coin, amount }],); + assert_eq!(test.router.escapes(block ..= block).await.unwrap(), vec![Escape { coin, amount }],); assert_eq!(erc20.balance_of(&test, test.router.address()).await, U256::from(0)); assert_eq!(erc20.balance_of(&test, test.state.escaped_to.unwrap()).await, amount); } diff --git a/processor/ethereum/src/rpc.rs b/processor/ethereum/src/rpc.rs index 9305fd91..b5b50cfa 100644 --- a/processor/ethereum/src/rpc.rs +++ b/processor/ethereum/src/rpc.rs @@ -160,10 +160,10 @@ impl ScannerFeed for Rpc { block: Header, ) -> Result<(Vec, Vec), RpcError> { let instructions = router - .in_instructions_unordered(block.number, block.number, &HashSet::from(TOKENS)) + .in_instructions_unordered(block.number ..= block.number, &HashSet::from(TOKENS)) .await?; - let executed = router.executed(block.number, block.number).await?; + let executed = router.executed(block.number ..= block.number).await?; Ok((instructions, executed)) }