Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ reqwest = { version = "0.13.4", features = ["hickory-dns"] }
rstest = "0.26"
ruint = { version = "1.17.2", default-features = false }
rust_decimal = { version = "1.35.0", default-features = false }
rustls = { version = "0.23.41", default-features = false }
s3 = { path = "crates/s3" }
schemars = { version = "1.2", features = ["chrono04"] }
scopeguard = "1.2.0"
Expand Down
4 changes: 1 addition & 3 deletions crates/driver/src/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,6 @@ fn simulator(
eth: simulator::Ethereum,
http_factory: &HttpClientFactory,
) -> Simulator {
let block_stream = eth.current_block().clone();
let mut simulator = match &config.simulator {
configs::simulator::Config {
kind: configs::simulator::SimulatorKind::Tenderly(config),
Expand All @@ -181,8 +180,7 @@ fn simulator(
simulator.disable_gas(gas);
}
if let Some(cfg) = &config.simulator.state_override_stream {
simulator
.set_simulation_overrides(simulator::state_override_stream::spawn(cfg, block_stream));
simulator.set_simulation_overrides(simulator::state_override_stream::spawn(cfg));
}

simulator
Expand Down
11 changes: 9 additions & 2 deletions crates/e2e/tests/e2e/state_override.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use {
alloy::{
eips::BlockId,
primitives::{Address, B256, U256},
rpc::types::state::{AccountOverride, StateOverride},
sol,
Expand Down Expand Up @@ -54,14 +55,20 @@ async fn estimate_gas_state_override(web3: Web3) {
let eth = ethereum(web3).await;

let gated_call = gated_contract.gate().into_transaction_request();
let without = eth.estimate_gas(gated_call.clone(), None).await;
let without = eth
.estimate_gas(gated_call.clone(), None, BlockId::pending())
.await;
assert!(
without.is_err(),
"gate() should revert without the slot-0 override, got {without:?}",
);

let with = eth
.estimate_gas(gated_call, Some(unlock_override(*gated_contract.address())))
.estimate_gas(
gated_call,
Some(unlock_override(*gated_contract.address())),
BlockId::pending(),
)
.await;
assert!(
with.is_ok(),
Expand Down
2 changes: 1 addition & 1 deletion crates/price-estimation/src/factory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ impl<'a> PriceEstimatorFactory<'a> {
let simulation_overrides = args
.state_override_stream
.as_ref()
.map(|cfg| simulator::state_override_stream::spawn(cfg, network.block_stream.clone()));
.map(simulator::state_override_stream::spawn);
let simulator = SettlementSimulator::new(
settlement_contract,
network.flash_loan_router,
Expand Down
1 change: 1 addition & 0 deletions crates/simulator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ url = { workspace = true }

[dev-dependencies]
mockall = { workspace = true }
rustls = { workspace = true, features = ["aws-lc-rs"] }
testlib = { workspace = true }

[features]
Expand Down
16 changes: 10 additions & 6 deletions crates/simulator/src/encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,9 +348,12 @@ pub(crate) async fn finish_simulation_builder(
return Err(BuildError::NoOrder);
}

let block = match builder.block {
Block::Latest => builder.simulator.0.current_block.borrow().number,
Block::Number(n) => n,
let (block, block_timestamp) = match builder.block {
Block::Latest => {
let block = builder.simulator.0.current_block.borrow();
(block.number, Some(block.timestamp))
}
Block::Number(n) => (n, None),
};

let executed_amounts = futures::future::try_join_all(
Expand Down Expand Up @@ -498,10 +501,11 @@ pub(crate) async fn finish_simulation_builder(
// propAMM state when simulated on historic blocks is slightly different
// from what you would have gotten if you actually traded with the propAMM
// on that block but we can't do anything about it and most likely the
// price is close enough to not affect the simulation.
if matches!(builder.block, Block::Latest)
// price is close enough to not affect the simulation. Only the tip has a
// known timestamp, which is what gates the overrides to it here.
if let Some(block_timestamp) = block_timestamp
&& let Some(stream) = builder.simulator.0.simulation_overrides.as_ref()
&& let Some(state_overrides) = stream.current()
&& let Some(state_overrides) = stream.overrides_for(block, block_timestamp)
{
for (account, state) in state_overrides {
builder
Expand Down
4 changes: 3 additions & 1 deletion crates/simulator/src/ethereum/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use {
crate::ethereum::contracts::Contracts,
alloy_eips::BlockId,
alloy_primitives::U256,
alloy_provider::{Provider, network::TransactionBuilder},
alloy_rpc_types::{TransactionRequest, state::StateOverride},
Expand Down Expand Up @@ -124,6 +125,7 @@ impl Ethereum {
&self,
tx: T,
overrides: Option<StateOverride>,
block: BlockId,
) -> Result<eth_domain_types::Gas, Error>
where
T: Into<TransactionRequest>,
Expand All @@ -139,7 +141,7 @@ impl Ethereum {
.provider
.estimate_gas(tx)
.overrides_opt(overrides)
.pending()
.block(block)
.await
.map_err(Error::Rpc)?
.into();
Expand Down
19 changes: 16 additions & 3 deletions crates/simulator/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ mod utils;

use {
crate::state_override_stream::SimulationOverrides,
alloy_eips::BlockId,
alloy_primitives::Address,
eth_domain_types::{self as eth, AccessList, Tx},
http_client::HttpClientFactory,
Expand Down Expand Up @@ -119,11 +120,23 @@ impl Simulator {
if let Some(gas) = self.disable_gas {
return Ok(gas);
}
let block: eth::BlockNo = self.eth.current_block().borrow().number.into();
let (block_number, block_timestamp) = {
let block = self.eth.current_block().borrow();
(block.number, block.timestamp)
};
let block: eth::BlockNo = block_number.into();
let state_overrides = self
.simulation_overrides
.as_ref()
.and_then(|overrides| overrides.current());
.and_then(|overrides| overrides.overrides_for(block_number, block_timestamp));
// The overrides are stamped for `block_number`, so the estimate has to
// run against that block. `pending` can't carry them: its timestamp is
// the node's wall clock, which is unknowable when the request is built
// and moves between calls. Without overrides nothing changes.
let block_id = match state_overrides {
Some(_) => BlockId::number(block_number),
None => BlockId::pending(),
};
Ok(match &self.inner {
Inner::Tenderly(tenderly) => {
tenderly
Expand All @@ -140,7 +153,7 @@ impl Simulator {
}
Inner::Ethereum => self
.eth
.estimate_gas(tx.clone(), state_overrides)
.estimate_gas(tx.clone(), state_overrides, block_id)
.await
.map_err(with(tx, block))?,
})
Expand Down
Loading
Loading