Skip to content

Commit e0ad278

Browse files
naps62grandizzy
andauthored
fix(anvil): recomputing next-base-fee after reloading state (#10488)
* recomputing next-base-fee after reloading state * unit test --------- Co-authored-by: grandizzy <[email protected]>
1 parent 155220e commit e0ad278

File tree

2 files changed

+52
-0
lines changed

2 files changed

+52
-0
lines changed

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,6 +1006,26 @@ impl Backend {
10061006
}
10071007
}
10081008

1009+
if let Some(block) = state.blocks.last() {
1010+
let header = &block.header;
1011+
let next_block_base_fee = self.fees.get_next_block_base_fee_per_gas(
1012+
header.gas_used as u128,
1013+
header.gas_limit as u128,
1014+
header.base_fee_per_gas.unwrap_or_default(),
1015+
);
1016+
let next_block_excess_blob_gas = self.fees.get_next_block_blob_excess_gas(
1017+
header.excess_blob_gas.map(|g| g as u128).unwrap_or_default(),
1018+
header.blob_gas_used.map(|g| g as u128).unwrap_or_default(),
1019+
);
1020+
1021+
// update next base fee
1022+
self.fees.set_base_fee(next_block_base_fee);
1023+
self.fees.set_blob_excess_gas_and_price(BlobExcessGasAndPrice::new(
1024+
next_block_excess_blob_gas,
1025+
false,
1026+
));
1027+
}
1028+
10091029
if !self.db.write().await.load_state(state.clone())? {
10101030
return Err(RpcError::invalid_params(
10111031
"Loading state not supported with the current configuration",

crates/anvil/tests/it/state.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,3 +276,35 @@ async fn test_fork_load_state_with_greater_state_block() {
276276

277277
assert_eq!(new_block_number, block_number);
278278
}
279+
280+
// <https://github.com/foundry-rs/foundry/issues/10488>
281+
#[tokio::test(flavor = "multi_thread")]
282+
async fn computes_next_base_fee_after_loading_state() {
283+
let tmp = tempfile::tempdir().unwrap();
284+
let state_file = tmp.path().join("state.json");
285+
286+
let (api, handle) = spawn(NodeConfig::test()).await;
287+
288+
let bob = address!("0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266");
289+
let alice = address!("0x9276449EaC5b4f7Bc17cFC6700f7BeeB86F9bCd0");
290+
291+
let provider = handle.http_provider();
292+
293+
let value = Unit::ETHER.wei().saturating_mul(U256::from(1)); // 1 ether
294+
let tx = TransactionRequest::default().with_to(alice).with_value(value).with_from(bob);
295+
let tx = WithOtherFields::new(tx);
296+
297+
let base_fee_empty_chain = api.backend.fees().base_fee();
298+
provider.send_transaction(tx).await.unwrap().get_receipt().await.unwrap();
299+
300+
let base_fee_after_one_tx = api.backend.fees().base_fee();
301+
// the test is meaningless if this does not hold
302+
assert!(base_fee_empty_chain != base_fee_after_one_tx);
303+
304+
let ser_state = api.serialized_state(true).await.unwrap();
305+
foundry_common::fs::write_json_file(&state_file, &ser_state).unwrap();
306+
307+
let (api, _handle) = spawn(NodeConfig::test().with_init_state_path(state_file)).await;
308+
let base_fee_after_reload = api.backend.fees().base_fee();
309+
assert_eq!(base_fee_after_reload, base_fee_after_one_tx);
310+
}

0 commit comments

Comments
 (0)