Skip to content
Merged
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
10 changes: 5 additions & 5 deletions Cargo.lock

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

6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ clap = { version = "4.5.6", features = ["derive", "env"] }
dashmap = "6.1.0"
derivative = "2.2.0"
derive_more = { version = "1.0.0", features = ["full"] }
ethcontract = { git = "https://github.com/cowprotocol/ethcontract-rs", rev = "8817f4ba868e686f21cda886d6c8b75834eb51f2", default-features = false, features = ["aws-kms"] }
ethcontract = { git = "https://github.com/cowprotocol/ethcontract-rs", rev = "c057a6e78827d762e1827c8d57cb687fc1f0af1a", default-features = false, features = ["aws-kms"] }
mimalloc = "0.1.43"
ethcontract-generate = { git = "https://github.com/cowprotocol/ethcontract-rs", rev = "8817f4ba868e686f21cda886d6c8b75834eb51f2", default-features = false }
ethcontract-mock = { git = "https://github.com/cowprotocol/ethcontract-rs", rev = "8817f4ba868e686f21cda886d6c8b75834eb51f2", default-features = false }
ethcontract-generate = { git = "https://github.com/cowprotocol/ethcontract-rs", rev = "c057a6e78827d762e1827c8d57cb687fc1f0af1a", default-features = false }
ethcontract-mock = { git = "https://github.com/cowprotocol/ethcontract-rs", rev = "c057a6e78827d762e1827c8d57cb687fc1f0af1a", default-features = false }
ethereum-types = "0.14.1"
flate2 = "1.0.30"
futures = "0.3.30"
Expand Down
47 changes: 12 additions & 35 deletions crates/ethrpc/src/extensions.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
//! Module containing Ethereum RPC extension methods.

use {
serde::{Deserialize, Serialize},
std::collections::HashMap,
ethcontract::state_overrides::StateOverrides,
serde::Deserialize,
tracing::{Instrument, instrument::Instrumented},
web3::{
self,
Transport,
api::Namespace,
helpers::{self, CallFuture},
types::{BlockId, Bytes, CallRequest, H160, H256, U64, U256},
types::{BlockId, Bytes, CallRequest, H256},
},
};

Expand All @@ -22,7 +22,7 @@ where
&self,
call: CallRequest,
block: BlockId,
overrides: HashMap<H160, StateOverride>,
overrides: StateOverrides,
) -> Instrumented<CallFuture<Bytes, T::Out>>;
}

Expand All @@ -48,36 +48,6 @@ where
}
}

/// State overrides.
pub type StateOverrides = HashMap<H160, StateOverride>;

/// State override object.
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct StateOverride {
/// Fake balance to set for the account before executing the call.
#[serde(skip_serializing_if = "Option::is_none")]
pub balance: Option<U256>,

/// Fake nonce to set for the account before executing the call.
#[serde(skip_serializing_if = "Option::is_none")]
pub nonce: Option<U64>,

/// Fake EVM bytecode to inject into the account before executing the call.
#[serde(skip_serializing_if = "Option::is_none")]
pub code: Option<Bytes>,

/// Fake key-value mapping to override **all** slots in the account storage
/// before executing the call.
#[serde(skip_serializing_if = "Option::is_none")]
pub state: Option<HashMap<H256, H256>>,

/// Fake key-value mapping to override **individual** slots in the account
/// storage before executing the call.
#[serde(skip_serializing_if = "Option::is_none")]
pub state_diff: Option<HashMap<H256, H256>>,
}

/// Debug namespace extension trait.
pub trait DebugNamespace<T>
where
Expand Down Expand Up @@ -140,7 +110,14 @@ pub struct CallFrame {

#[cfg(test)]
mod tests {
use {super::*, crate::Web3, hex_literal::hex, maplit::hashmap, web3::types::BlockNumber};
use {
super::*,
crate::Web3,
ethcontract::{H160, state_overrides::StateOverride},
hex_literal::hex,
maplit::hashmap,
web3::types::BlockNumber,
};

#[ignore]
#[tokio::test]
Expand Down
8 changes: 4 additions & 4 deletions crates/shared/src/code_simulation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ use {
crate::tenderly_api::{SimulationKind, SimulationRequest, StateObject, TenderlyApi},
anyhow::{Context as _, Result, ensure},
contracts::errors::EthcontractErrorType,
ethcontract::errors::ExecutionError,
ethrpc::{
Web3,
extensions::{EthExt as _, StateOverride, StateOverrides},
ethcontract::{
errors::ExecutionError,
state_overrides::{StateOverride, StateOverrides},
},
ethrpc::{Web3, extensions::EthExt as _},
std::sync::Arc,
thiserror::Error,
tracing::instrument,
Expand Down
2 changes: 1 addition & 1 deletion crates/shared/src/price_estimation/factory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ impl<'a> PriceEstimatorFactory<'a> {
None => Arc::new(web3.clone()),
};

let balance_overrides = args.balance_overrides.init(simulator.clone());
let balance_overrides = args.balance_overrides.init(web3.clone());

let verifier = TradeVerifier::new(
web3,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
use {
super::Strategy,
crate::code_simulation::{CodeSimulating, SimulationError},
contracts::{ERC20, dummy_contract},
ethcontract::{Address, H256, U256},
ethrpc::extensions::StateOverride,
crate::code_simulation::SimulationError,
anyhow::Context,
contracts::ERC20,
ethcontract::{Address, H256, U256, state_overrides::StateOverride},
maplit::hashmap,
std::{
collections::HashMap,
fmt::{self, Debug, Formatter},
sync::Arc,
},
thiserror::Error,
web3::{signing::keccak256, types::CallRequest},
web3::signing::keccak256,
};

/// A heuristic balance override detector based on `eth_call` simulations.
Expand All @@ -21,7 +21,7 @@ use {
pub struct Detector(Arc<Inner>);

pub struct Inner {
simulator: Arc<dyn CodeSimulating>,
web3: ethrpc::Web3,
/// address that we try to override the balances for
holder: Address,
/// all strategies used to detect successful balance overrides
Expand All @@ -40,7 +40,7 @@ impl std::ops::Deref for Detector {

impl Detector {
/// Creates a new balance override detector.
pub fn new(simulator: Arc<dyn CodeSimulating>, probing_depth: u8) -> Self {
pub fn new(web3: ethrpc::Web3, probing_depth: u8) -> Self {
let holder = {
// On a technical note, Ethereum public addresses are, for the most
// part, generated by taking the 20 last bytes of a Keccak-256 hash (for
Expand Down Expand Up @@ -89,7 +89,7 @@ impl Detector {
.collect::<HashMap<_, _>>();

Self(Arc::new(Inner {
simulator,
web3,
holder,
strategies,
state_overrides,
Expand All @@ -100,23 +100,19 @@ impl Detector {
/// Returns an `Err` if it cannot detect the strategy or an internal
/// simulation fails.
pub async fn detect(&self, token: Address) -> Result<Strategy, DetectionError> {
let token = dummy_contract!(ERC20, token);
let call = CallRequest {
to: Some(token.address()),
data: token.methods().balance_of(self.holder).m.tx.data,
..Default::default()
};
let token = ERC20::at(&self.web3, token);
let overrides = hashmap! {
token.address() => StateOverride {
state_diff: Some(self.state_overrides.clone()),
..Default::default()
},
};

let output = self.simulator.simulate(call, overrides, None).await?;
let balance = (output.len() == 32)
.then(|| U256::from_big_endian(&output))
.ok_or(DetectionError::Decode)?;
let balance = token
.balance_of(self.holder)
.call_with_state_overrides(&overrides)
.await
.context("eth_call with state overrides failed")
.map_err(|e| DetectionError::Simulation(SimulationError::Other(e)))?;

self.strategies
.iter()
Expand Down Expand Up @@ -167,8 +163,6 @@ impl Debug for Detector {
pub enum DetectionError {
#[error("could not detect a balance override strategy")]
NotFound,
#[error("unable to decode simulation return data")]
Decode,
#[error(transparent)]
Simulation(#[from] SimulationError),
}
Expand All @@ -183,7 +177,7 @@ mod tests {
#[ignore]
#[tokio::test]
async fn detects_storage_slots_mainnet() {
let detector = Detector::new(Arc::new(Web3::new_from_env()), 60);
let detector = Detector::new(Web3::new_from_env(), 60);

let storage = detector
.detect(addr!("c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"))
Expand Down Expand Up @@ -215,7 +209,7 @@ mod tests {
#[ignore]
#[tokio::test]
async fn detects_storage_slots_arbitrum() {
let detector = Detector::new(Arc::new(Web3::new_from_env()), 60);
let detector = Detector::new(Web3::new_from_env(), 60);

// all bridged tokens on arbitrum require a ton of probing
let storage = detector
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@ mod detector;

use {
self::detector::{DetectionError, Detector},
crate::code_simulation::CodeSimulating,
anyhow::Context as _,
cached::{Cached, SizedCache},
ethcontract::{Address, H256, U256},
ethrpc::extensions::StateOverride,
ethcontract::{Address, H256, U256, state_overrides::StateOverride},
maplit::hashmap,
std::{
collections::HashMap,
Expand Down Expand Up @@ -51,13 +49,13 @@ pub struct Arguments {

impl Arguments {
/// Creates a balance overrides instance from the current configuration.
pub fn init(&self, simulator: Arc<dyn CodeSimulating>) -> Arc<dyn BalanceOverriding> {
pub fn init(&self, web3: ethrpc::Web3) -> Arc<dyn BalanceOverriding> {
Arc::new(BalanceOverrides {
hardcoded: self.quote_token_balance_overrides.0.clone(),
detector: self.quote_autodetect_token_balance_overrides.then(|| {
(
Detector::new(
simulator,
web3,
self.quote_autodetect_token_balance_overrides_probing_depth,
),
Mutex::new(SizedCache::with_size(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ use {
dummy_contract,
support::{AnyoneAuthenticator, Solver, Spardose, Trader},
},
ethcontract::{Bytes, H160, U256, tokens::Tokenize},
ethrpc::{Web3, block_stream::CurrentBlockWatcher, extensions::StateOverride},
ethcontract::{Bytes, H160, U256, state_overrides::StateOverride, tokens::Tokenize},
ethrpc::{Web3, block_stream::CurrentBlockWatcher},
model::{
DomainSeparator,
order::{BUY_ETH_ADDRESS, OrderData, OrderKind},
Expand Down
Loading