mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-08 12:19:24 +00:00
Take advantage of RangeInclusive for specifying filters' blocks
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
#![doc = include_str!("../README.md")]
|
#![doc = include_str!("../README.md")]
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
|
use core::ops::RangeInclusive;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use alloy_core::primitives::{Address, U256};
|
use alloy_core::primitives::{Address, U256};
|
||||||
@@ -76,8 +77,8 @@ pub struct TopLevelTransfers {
|
|||||||
pub struct Erc20;
|
pub struct Erc20;
|
||||||
impl Erc20 {
|
impl Erc20 {
|
||||||
/// The filter for transfer logs of the specified ERC20, to the specified recipient.
|
/// 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 {
|
fn transfer_filter(blocks: RangeInclusive<u64>, erc20: Address, to: Address) -> Filter {
|
||||||
let filter = Filter::new().from_block(from_block).to_block(to_block);
|
let filter = Filter::new().select(blocks);
|
||||||
filter.address(erc20).event_signature(Transfer::SIGNATURE_HASH).topic2(to.into_word())
|
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.
|
/// The `transfers` in the result are unordered. The `logs` are sorted by index.
|
||||||
pub async fn top_level_transfers_unordered(
|
pub async fn top_level_transfers_unordered(
|
||||||
provider: &RootProvider<SimpleRequest>,
|
provider: &RootProvider<SimpleRequest>,
|
||||||
from_block: u64,
|
blocks: RangeInclusive<u64>,
|
||||||
to_block: u64,
|
|
||||||
erc20: Address,
|
erc20: Address,
|
||||||
to: Address,
|
to: Address,
|
||||||
) -> Result<TopLevelTransfers, RpcError<TransportErrorKind>> {
|
) -> Result<TopLevelTransfers, RpcError<TransportErrorKind>> {
|
||||||
let mut logs = {
|
let mut logs = {
|
||||||
// Get all transfers within these blocks
|
// 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
|
// The logs, indexed by their transactions
|
||||||
let mut transaction_logs = HashMap::new();
|
let mut transaction_logs = HashMap::new();
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#![doc = include_str!("../README.md")]
|
#![doc = include_str!("../README.md")]
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
|
use core::ops::RangeInclusive;
|
||||||
use std::{
|
use std::{
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
collections::{HashSet, HashMap},
|
collections::{HashSet, HashMap},
|
||||||
@@ -459,13 +460,13 @@ impl Router {
|
|||||||
/// This is not guaranteed to return them in any order.
|
/// This is not guaranteed to return them in any order.
|
||||||
pub async fn in_instructions_unordered(
|
pub async fn in_instructions_unordered(
|
||||||
&self,
|
&self,
|
||||||
from_block: u64,
|
blocks: RangeInclusive<u64>,
|
||||||
to_block: u64,
|
|
||||||
allowed_erc20s: &HashSet<Address>,
|
allowed_erc20s: &HashSet<Address>,
|
||||||
) -> Result<Vec<InInstruction>, RpcError<TransportErrorKind>> {
|
) -> Result<Vec<InInstruction>, RpcError<TransportErrorKind>> {
|
||||||
// The InInstruction events for this block
|
// The InInstruction events for this block
|
||||||
let in_instruction_logs = {
|
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);
|
let filter = filter.event_signature(InInstructionEvent::SIGNATURE_HASH);
|
||||||
self.provider.get_logs(&filter).await?
|
self.provider.get_logs(&filter).await?
|
||||||
};
|
};
|
||||||
@@ -478,18 +479,15 @@ impl Router {
|
|||||||
let erc20_transfer_logs = {
|
let erc20_transfer_logs = {
|
||||||
let mut transfers = FuturesUnordered::new();
|
let mut transfers = FuturesUnordered::new();
|
||||||
for erc20 in allowed_erc20s {
|
for erc20 in allowed_erc20s {
|
||||||
transfers.push(async move {
|
transfers.push({
|
||||||
(
|
// https://github.com/rust-lang/rust/issues/27186
|
||||||
erc20,
|
let blocks: RangeInclusive<u64> = blocks.clone();
|
||||||
Erc20::top_level_transfers_unordered(
|
async move {
|
||||||
&self.provider,
|
let transfers =
|
||||||
from_block,
|
Erc20::top_level_transfers_unordered(&self.provider, blocks, *erc20, self.address)
|
||||||
to_block,
|
.await;
|
||||||
*erc20,
|
(erc20, transfers)
|
||||||
self.address,
|
}
|
||||||
)
|
|
||||||
.await,
|
|
||||||
)
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -626,8 +624,7 @@ impl Router {
|
|||||||
/// Fetch the executed actions for the specified range of blocks.
|
/// Fetch the executed actions for the specified range of blocks.
|
||||||
pub async fn executed(
|
pub async fn executed(
|
||||||
&self,
|
&self,
|
||||||
from_block: u64,
|
blocks: RangeInclusive<u64>,
|
||||||
to_block: u64,
|
|
||||||
) -> Result<Vec<Executed>, RpcError<TransportErrorKind>> {
|
) -> Result<Vec<Executed>, RpcError<TransportErrorKind>> {
|
||||||
fn decode<E: SolEvent>(log: &Log) -> Result<E, RpcError<TransportErrorKind>> {
|
fn decode<E: SolEvent>(log: &Log) -> Result<E, RpcError<TransportErrorKind>> {
|
||||||
Ok(
|
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?;
|
let mut logs = self.provider.get_logs(&filter).await?;
|
||||||
logs.sort_by_key(|log| (log.block_number, log.log_index));
|
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.
|
/// Fetch the `Escape`s from the smart contract through the escape hatch.
|
||||||
pub async fn escapes(
|
pub async fn escapes(
|
||||||
&self,
|
&self,
|
||||||
from_block: u64,
|
blocks: RangeInclusive<u64>,
|
||||||
to_block: u64,
|
|
||||||
) -> Result<Vec<Escape>, RpcError<TransportErrorKind>> {
|
) -> Result<Vec<Escape>, RpcError<TransportErrorKind>> {
|
||||||
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 =
|
let mut logs =
|
||||||
self.provider.get_logs(&filter.event_signature(EscapedEvent::SIGNATURE_HASH)).await?;
|
self.provider.get_logs(&filter.event_signature(EscapedEvent::SIGNATURE_HASH)).await?;
|
||||||
logs.sort_by_key(|log| (log.block_number, log.log_index));
|
logs.sort_by_key(|log| (log.block_number, log.log_index));
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ impl Test {
|
|||||||
// Confirm nonce 0 was used as such
|
// Confirm nonce 0 was used as such
|
||||||
{
|
{
|
||||||
let block = receipt.block_number.unwrap();
|
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.len(), 1);
|
||||||
assert_eq!(executed[0], Executed::NextSeraiKeySet { nonce: 0, key: public_key.eth_repr() });
|
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 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.len(), 1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
executed[0],
|
executed[0],
|
||||||
@@ -236,7 +236,7 @@ impl Test {
|
|||||||
|
|
||||||
{
|
{
|
||||||
let block = receipt.block_number.unwrap();
|
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.len(), 1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
executed[0],
|
executed[0],
|
||||||
@@ -283,15 +283,14 @@ impl Test {
|
|||||||
if matches!(coin, Coin::Erc20(_)) {
|
if matches!(coin, Coin::Erc20(_)) {
|
||||||
// If we don't whitelist this token, we shouldn't be yielded an InInstruction
|
// If we don't whitelist this token, we shouldn't be yielded an InInstruction
|
||||||
let in_instructions =
|
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());
|
assert!(in_instructions.is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
let in_instructions = self
|
let in_instructions = self
|
||||||
.router
|
.router
|
||||||
.in_instructions_unordered(
|
.in_instructions_unordered(
|
||||||
block,
|
block ..= block,
|
||||||
block,
|
|
||||||
&if let Coin::Erc20(token) = coin { HashSet::from([token]) } else { HashSet::new() },
|
&if let Coin::Erc20(token) = coin { HashSet::from([token]) } else { HashSet::new() },
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
@@ -359,7 +358,7 @@ impl Test {
|
|||||||
|
|
||||||
{
|
{
|
||||||
let block = receipt.block_number.unwrap();
|
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.len(), 1);
|
||||||
assert_eq!(executed[0], Executed::EscapeHatch { nonce: self.state.next_nonce, escape_to });
|
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();
|
let block = receipt.block_number.unwrap();
|
||||||
assert_eq!(
|
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) }],
|
vec![Escape { coin: Coin::Ether, amount: U256::from(1) }],
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -730,7 +729,7 @@ async fn test_escape_hatch() {
|
|||||||
assert!(receipt.status());
|
assert!(receipt.status());
|
||||||
|
|
||||||
let block = receipt.block_number.unwrap();
|
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.router.address()).await, U256::from(0));
|
||||||
assert_eq!(erc20.balance_of(&test, test.state.escaped_to.unwrap()).await, amount);
|
assert_eq!(erc20.balance_of(&test, test.state.escaped_to.unwrap()).await, amount);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -160,10 +160,10 @@ impl<D: Db> ScannerFeed for Rpc<D> {
|
|||||||
block: Header,
|
block: Header,
|
||||||
) -> Result<(Vec<EthereumInInstruction>, Vec<Executed>), RpcError<TransportErrorKind>> {
|
) -> Result<(Vec<EthereumInInstruction>, Vec<Executed>), RpcError<TransportErrorKind>> {
|
||||||
let instructions = router
|
let instructions = router
|
||||||
.in_instructions_unordered(block.number, block.number, &HashSet::from(TOKENS))
|
.in_instructions_unordered(block.number ..= block.number, &HashSet::from(TOKENS))
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let executed = router.executed(block.number, block.number).await?;
|
let executed = router.executed(block.number ..= block.number).await?;
|
||||||
|
|
||||||
Ok((instructions, executed))
|
Ok((instructions, executed))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user