Skip to content

Commit e867a6c

Browse files
authored
feat: support negative forkblock numbers (#10263)
1 parent 3b7c139 commit e867a6c

File tree

3 files changed

+33
-9
lines changed

3 files changed

+33
-9
lines changed

crates/anvil/src/cmd.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,12 @@ impl NodeArgs {
238238
.with_fork_choice(match (self.evm.fork_block_number, self.evm.fork_transaction_hash) {
239239
(Some(block), None) => Some(ForkChoice::Block(block)),
240240
(None, Some(hash)) => Some(ForkChoice::Transaction(hash)),
241-
_ => self.evm.fork_url.as_ref().and_then(|f| f.block).map(ForkChoice::Block),
241+
_ => self
242+
.evm
243+
.fork_url
244+
.as_ref()
245+
.and_then(|f| f.block)
246+
.map(|num| ForkChoice::Block(num as i128)),
242247
})
243248
.with_fork_headers(self.evm.fork_headers)
244249
.with_fork_chain_id(self.evm.fork_chain_id.map(u64::from).map(U256::from))
@@ -428,9 +433,17 @@ pub struct AnvilEvmArgs {
428433

429434
/// Fetch state from a specific block number over a remote endpoint.
430435
///
436+
/// If a negative the the given value is subtracted from the `latest` block number.
437+
///
431438
/// See --fork-url.
432-
#[arg(long, requires = "fork_url", value_name = "BLOCK", help_heading = "Fork config")]
433-
pub fork_block_number: Option<u64>,
439+
#[arg(
440+
long,
441+
requires = "fork_url",
442+
value_name = "BLOCK",
443+
help_heading = "Fork config",
444+
allow_hyphen_values = true
445+
)]
446+
pub fork_block_number: Option<i128>,
434447

435448
/// Fetch state from a specific transaction hash over a remote endpoint.
436449
///

crates/anvil/src/config.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1361,7 +1361,16 @@ async fn derive_block_and_transactions(
13611361
provider: &Arc<RetryProvider>,
13621362
) -> eyre::Result<(BlockNumber, Option<Vec<PoolTransaction>>)> {
13631363
match fork_choice {
1364-
ForkChoice::Block(block_number) => Ok((block_number.to_owned(), None)),
1364+
ForkChoice::Block(block_number) => {
1365+
let block_number = *block_number;
1366+
if block_number >= 0 {
1367+
return Ok((block_number as u64, None))
1368+
}
1369+
// subtract from latest block number
1370+
let latest = provider.get_block_number().await?;
1371+
1372+
Ok((block_number.saturating_add(latest as i128) as u64, None))
1373+
}
13651374
ForkChoice::Transaction(transaction_hash) => {
13661375
// Determine the block that this transaction was mined in
13671376
let transaction = provider
@@ -1400,15 +1409,17 @@ async fn derive_block_and_transactions(
14001409
/// Fork delimiter used to specify which block or transaction to fork from
14011410
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
14021411
pub enum ForkChoice {
1403-
/// Block number to fork from
1404-
Block(BlockNumber),
1412+
/// Block number to fork from.
1413+
///
1414+
/// f a negative the the given value is subtracted from the `latest` block number.
1415+
Block(i128),
14051416
/// Transaction hash to fork from
14061417
Transaction(TxHash),
14071418
}
14081419

14091420
impl ForkChoice {
14101421
/// Returns the block number to fork from
1411-
pub fn block_number(&self) -> Option<BlockNumber> {
1422+
pub fn block_number(&self) -> Option<i128> {
14121423
match self {
14131424
Self::Block(block_number) => Some(*block_number),
14141425
Self::Transaction(_) => None,
@@ -1434,7 +1445,7 @@ impl From<TxHash> for ForkChoice {
14341445
/// Convert a decimal block number into a ForkChoice
14351446
impl From<u64> for ForkChoice {
14361447
fn from(block: u64) -> Self {
1437-
Self::Block(block)
1448+
Self::Block(block as i128)
14381449
}
14391450
}
14401451

crates/anvil/src/eth/backend/mem/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -611,7 +611,7 @@ impl Backend {
611611
fork_block_number: u64,
612612
) -> Result<(), BlockchainError> {
613613
let mut node_config = self.node_config.write().await;
614-
node_config.fork_choice = Some(ForkChoice::Block(fork_block_number));
614+
node_config.fork_choice = Some(ForkChoice::Block(fork_block_number as i128));
615615

616616
let mut env = self.env.read().clone();
617617
let (forked_db, client_fork_config) =

0 commit comments

Comments
 (0)