From e4c083b8ef019992c308bcf6c2adcbefebb59376 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=CC=81=20Duarte?= Date: Mon, 15 Dec 2025 15:58:50 +0000 Subject: [PATCH 01/24] Clean up usage of ethcontract exports --- Cargo.lock | 2 +- Cargo.toml | 1 + crates/driver/Cargo.toml | 2 +- .../driver/src/infra/blockchain/contracts.rs | 18 +----------- .../src/infra/notify/liquidity_sources/mod.rs | 3 +- crates/driver/src/tests/setup/blockchain.rs | 28 ++++++++----------- .../e2e/src/setup/onchain_components/safe.rs | 21 +------------- crates/ethrpc/Cargo.toml | 1 + crates/ethrpc/src/http.rs | 1 - crates/ethrpc/src/lib.rs | 3 +- crates/shared/src/ethrpc.rs | 2 +- crates/shared/src/macros.rs | 7 ----- .../src/price_estimation/instrumented.rs | 3 +- crates/shared/src/sources/uniswap_v2/mod.rs | 8 +++--- .../src/sources/uniswap_v2/pair_provider.rs | 5 +++- crates/solvers/Cargo.toml | 1 - crates/solvers/src/domain/eth/mod.rs | 2 +- 17 files changed, 30 insertions(+), 78 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 76ef1e4e71..532617fd46 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3033,6 +3033,7 @@ dependencies = [ "futures", "hex-literal", "itertools 0.14.0", + "jsonrpc-core", "maplit", "mockall", "observe", @@ -6443,7 +6444,6 @@ dependencies = [ "tracing", "url", "vergen", - "web3", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 3f3bbd3f21..6d41e5873d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -106,6 +106,7 @@ prettyplease = "0.2.37" proc-macro2 = "1.0.103" alloy-sol-macro-input = "1.4.1" alloy-sol-macro-expander = "1.4.1" +jsonrpc-core = "18.0.0" [workspace.lints] clippy.cast_possible_wrap = "deny" diff --git a/crates/driver/Cargo.toml b/crates/driver/Cargo.toml index 1d5b23deab..db9c3a2263 100644 --- a/crates/driver/Cargo.toml +++ b/crates/driver/Cargo.toml @@ -15,7 +15,7 @@ name = "driver" path = "src/main.rs" [dependencies] -alloy = { workspace = true, features = ["sol-types", "provider-txpool-api", "rand"] } +alloy = { workspace = true, features = ["sol-types", "provider-txpool-api", "rand", "provider-anvil-api"] } app-data = { workspace = true } async-trait = { workspace = true } axum = { workspace = true } diff --git a/crates/driver/src/infra/blockchain/contracts.rs b/crates/driver/src/infra/blockchain/contracts.rs index e602ee42e2..deb0aed0c2 100644 --- a/crates/driver/src/infra/blockchain/contracts.rs +++ b/crates/driver/src/infra/blockchain/contracts.rs @@ -8,7 +8,7 @@ use { WETH9, support::Balances, }, - ethrpc::{Web3, alloy::conversions::IntoAlloy}, + ethrpc::Web3, std::collections::HashMap, thiserror::Error, }; @@ -165,22 +165,6 @@ impl Contracts { } } -/// Returns the address of a contract for the specified network, or `None` if -/// there is no known deployment for the contract on that network. -pub fn deployment_address( - contract: ðcontract::Contract, - chain: Chain, -) -> Option { - Some( - contract - .networks - .get(&chain.id().to_string())? - .address - .into_alloy() - .into(), - ) -} - #[derive(Debug, Error)] pub enum Error { #[error("method error: {0:?}")] diff --git a/crates/driver/src/infra/notify/liquidity_sources/mod.rs b/crates/driver/src/infra/notify/liquidity_sources/mod.rs index 2a7c409bf0..43adda3549 100644 --- a/crates/driver/src/infra/notify/liquidity_sources/mod.rs +++ b/crates/driver/src/infra/notify/liquidity_sources/mod.rs @@ -8,14 +8,13 @@ /// need to know as early as possible that their quote will be used for the /// settlement. It is crucial for risk management and leads to better /// pricing. -use futures::FutureExt; pub mod config; pub mod liquorice; pub use config::Config; use { crate::domain::competition::solution::settlement::Settlement, - ethcontract::jsonrpc::futures_util::future::join_all, + futures::{FutureExt, future::join_all}, std::{collections::HashMap, sync::Arc}, }; diff --git a/crates/driver/src/tests/setup/blockchain.rs b/crates/driver/src/tests/setup/blockchain.rs index 9668034b64..f08b2dd2a3 100644 --- a/crates/driver/src/tests/setup/blockchain.rs +++ b/crates/driver/src/tests/setup/blockchain.rs @@ -6,6 +6,7 @@ use { }, alloy::{ primitives::{Address, U256}, + providers::{Provider, ext::AnvilApi}, signers::local::{MnemonicBuilder, PrivateKeySigner}, sol_types::SolCall, }, @@ -347,8 +348,14 @@ impl Blockchain { .unwrap() .0; - set_code(&web3, vault_relayer, &vault_relayer_code).await; - set_code(&web3, settlement_address, &settlement_code).await; + web3.alloy + .anvil_set_code(vault_relayer, vault_relayer_code.into()) + .await + .unwrap(); + web3.alloy + .anvil_set_code(*settlement.address(), settlement_code.into()) + .await + .unwrap(); settlement = GPv2Settlement::GPv2Settlement::new(settlement_address, web3.alloy.clone()); @@ -980,7 +987,7 @@ impl Drop for Node { /// wait for transactions to be confirmed before proceeding with the test. When /// switching from geth back to hardhat, this function can be removed. pub async fn wait_for(web3: &Web3, fut: impl Future) -> T { - let block = web3.eth().block_number().await.unwrap().as_u64(); + let block = web3.alloy.get_block_number().await.unwrap(); let result = fut.await; wait_for_block(web3, block + 1).await; result @@ -990,7 +997,7 @@ pub async fn wait_for(web3: &Web3, fut: impl Future) -> T { pub async fn wait_for_block(web3: &Web3, block: u64) { tokio::time::timeout(std::time::Duration::from_secs(15), async { loop { - let next_block = web3.eth().block_number().await.unwrap().as_u64(); + let next_block = web3.alloy.get_block_number().await.unwrap(); if next_block >= block { break; } @@ -1000,16 +1007,3 @@ pub async fn wait_for_block(web3: &Web3, block: u64) { .await .expect("timeout while waiting for next block to be mined"); } - -/// Sets code at a specific address for testing. -pub async fn set_code(web3: &Web3, address: eth::Address, code: &[u8]) { - use web3::Transport; - - web3.transport() - .execute( - "anvil_setCode", - vec![json!(address), json!(const_hex::encode_prefixed(code))], - ) - .await - .unwrap(); -} diff --git a/crates/e2e/src/setup/onchain_components/safe.rs b/crates/e2e/src/setup/onchain_components/safe.rs index 954e8c944d..290e9b8e83 100644 --- a/crates/e2e/src/setup/onchain_components/safe.rs +++ b/crates/e2e/src/setup/onchain_components/safe.rs @@ -11,11 +11,7 @@ use { GnosisSafeProxy, GnosisSafeProxyFactory, }, - ethcontract::transaction::TransactionBuilder, - ethrpc::{ - AlloyProvider, - alloy::{CallBuilderExt, conversions::IntoAlloy}, - }, + ethrpc::{AlloyProvider, alloy::CallBuilderExt}, hex_literal::hex, model::{ DomainSeparator, @@ -139,21 +135,6 @@ impl Safe { .unwrap(); } - pub async fn exec_call( - &self, - tx: ethcontract::dyns::DynMethodBuilder, - ) { - let TransactionBuilder { - data, value, to, .. - } = tx.tx; - self.exec_alloy_tx( - to.unwrap().into_alloy(), - value.unwrap_or_default().into_alloy(), - alloy::primitives::Bytes::from(data.unwrap_or_default().0), - ) - .await; - } - pub async fn exec_alloy_call(&self, tx: TransactionRequest) { let to = tx.to.unwrap().into_to().unwrap(); let value = tx.value.unwrap_or_default(); diff --git a/crates/ethrpc/Cargo.toml b/crates/ethrpc/Cargo.toml index 0d22f20865..7c8c4315a2 100644 --- a/crates/ethrpc/Cargo.toml +++ b/crates/ethrpc/Cargo.toml @@ -35,6 +35,7 @@ tracing = { workspace = true } url = { workspace = true } web3 = { workspace = true } mockall = { workspace = true, optional = true } +jsonrpc-core.workspace = true [dev-dependencies] mockall = { workspace = true } diff --git a/crates/ethrpc/src/http.rs b/crates/ethrpc/src/http.rs index 20f110b77f..2f1d89fd54 100644 --- a/crates/ethrpc/src/http.rs +++ b/crates/ethrpc/src/http.rs @@ -1,5 +1,4 @@ use { - ethcontract::jsonrpc as jsonrpc_core, futures::{FutureExt, future::BoxFuture}, jsonrpc_core::types::{Call, Output, Request, Value}, observe::tracing::tracing_headers, diff --git a/crates/ethrpc/src/lib.rs b/crates/ethrpc/src/lib.rs index fe306109d0..5546cdebbf 100644 --- a/crates/ethrpc/src/lib.rs +++ b/crates/ethrpc/src/lib.rs @@ -11,7 +11,7 @@ use { self::{buffered::BufferedTransport, http::HttpTransport}, crate::alloy::MutWallet, ::alloy::providers::DynProvider, - ethcontract::{batch::CallBatch, transport::DynTransport}, + ethcontract::transport::DynTransport, reqwest::{Client, Url}, std::{num::NonZeroUsize, time::Duration}, web3::Transport, @@ -20,7 +20,6 @@ use { pub const MAX_BATCH_SIZE: usize = 100; pub type Web3Transport = DynTransport; -pub type Web3CallBatch = CallBatch; pub type AlloyProvider = DynProvider; /// This is just a thin wrapper around providers (clients communicating diff --git a/crates/shared/src/ethrpc.rs b/crates/shared/src/ethrpc.rs index 2bf9993ba2..d855f0c7af 100644 --- a/crates/shared/src/ethrpc.rs +++ b/crates/shared/src/ethrpc.rs @@ -1,4 +1,4 @@ -pub use ethrpc::{Web3, Web3CallBatch, Web3Transport}; +pub use ethrpc::{Web3, Web3Transport}; use { crate::http_client::HttpClientFactory, reqwest::Url, diff --git a/crates/shared/src/macros.rs b/crates/shared/src/macros.rs index 628612a230..784e7dc728 100644 --- a/crates/shared/src/macros.rs +++ b/crates/shared/src/macros.rs @@ -14,13 +14,6 @@ macro_rules! bfp { }; } -#[macro_export] -macro_rules! bytes { - ($x:literal) => { - ::ethcontract::web3::types::Bytes(::hex_literal::hex!($x).to_vec()) - }; -} - #[macro_export] macro_rules! json_map { ($($key:expr_2021 => $value:expr_2021),* $(,)?) => {{ diff --git a/crates/shared/src/price_estimation/instrumented.rs b/crates/shared/src/price_estimation/instrumented.rs index ec95ab11d8..6a23c4cd22 100644 --- a/crates/shared/src/price_estimation/instrumented.rs +++ b/crates/shared/src/price_estimation/instrumented.rs @@ -6,8 +6,7 @@ use { native::{NativePriceEstimateResult, NativePriceEstimating}, }, alloy::primitives::Address, - ethcontract::jsonrpc::futures_util::future::BoxFuture, - futures::future::FutureExt, + futures::future::{BoxFuture, FutureExt}, prometheus::{HistogramVec, IntCounterVec}, std::{ sync::Arc, diff --git a/crates/shared/src/sources/uniswap_v2/mod.rs b/crates/shared/src/sources/uniswap_v2/mod.rs index 21cc73fa11..8c07616489 100644 --- a/crates/shared/src/sources/uniswap_v2/mod.rs +++ b/crates/shared/src/sources/uniswap_v2/mod.rs @@ -206,7 +206,7 @@ mod tests { token1: Address, expected_pool_address: Address, ) { - let version_ = web3.eth().chain_id().await.unwrap().to_string(); + let version_ = web3.alloy.get_chain_id().await.unwrap().to_string(); assert_eq!(version_, version, "wrong node for test"); let source = UniV2BaselineSourceParameters::from_baseline_source(source, version) .unwrap() @@ -222,7 +222,7 @@ mod tests { #[ignore] async fn baseline_mainnet() { let web3 = ethrpc::Web3::new_from_env(); - let version = web3.eth().chain_id().await.unwrap().to_string(); + let version = web3.alloy.get_chain_id().await.unwrap().to_string(); assert_eq!(version, "1", "test must be run with mainnet node"); let test = |source, token0, token1, expected| { test_baseline_source(&web3, "1", source, token0, token1, expected) @@ -255,7 +255,7 @@ mod tests { #[ignore] async fn baseline_sepolia() { let web3 = ethrpc::Web3::new_from_env(); - let version = web3.eth().chain_id().await.unwrap().to_string(); + let version = web3.alloy.get_chain_id().await.unwrap().to_string(); assert_eq!(version, "11155111", "test must be run with mainnet node"); let test = |source, token0, token1, expected| { test_baseline_source(&web3, "11155111", source, token0, token1, expected) @@ -275,7 +275,7 @@ mod tests { #[ignore] async fn baseline_xdai() { let web3 = ethrpc::Web3::new_from_env(); - let version = web3.eth().chain_id().await.unwrap().to_string(); + let version = web3.alloy.get_chain_id().await.unwrap().to_string(); assert_eq!(version, "100", "test must be run with xdai node"); let test = |source, token0, token1, expected| { test_baseline_source(&web3, "100", source, token0, token1, expected) diff --git a/crates/shared/src/sources/uniswap_v2/pair_provider.rs b/crates/shared/src/sources/uniswap_v2/pair_provider.rs index 7788195e69..9db91c9a08 100644 --- a/crates/shared/src/sources/uniswap_v2/pair_provider.rs +++ b/crates/shared/src/sources/uniswap_v2/pair_provider.rs @@ -1,4 +1,7 @@ -use {alloy::primitives::Address, model::TokenPair, web3::signing::keccak256}; +use { + alloy::primitives::{Address, keccak256}, + model::TokenPair, +}; #[derive(Clone, Copy, Debug)] pub struct PairProvider { diff --git a/crates/solvers/Cargo.toml b/crates/solvers/Cargo.toml index 82a416785e..25c2b32507 100644 --- a/crates/solvers/Cargo.toml +++ b/crates/solvers/Cargo.toml @@ -42,7 +42,6 @@ toml = { workspace = true } tower = { workspace = true } tower-http = { workspace = true, features = ["limit", "trace"] } url = { workspace = true, features = ["serde"] } -web3 = { workspace = true } # TODO Once solvers are ported and E2E tests set up, slowly migrate code and # remove/re-evaluate these dependencies. diff --git a/crates/solvers/src/domain/eth/mod.rs b/crates/solvers/src/domain/eth/mod.rs index 08896eacc1..677e2a2076 100644 --- a/crates/solvers/src/domain/eth/mod.rs +++ b/crates/solvers/src/domain/eth/mod.rs @@ -1,5 +1,5 @@ pub use alloy::primitives::{Address, B256, U256}; -use {crate::util::bytes::Bytes, derive_more::From, web3::types::AccessList}; +use {crate::util::bytes::Bytes, alloy::rpc::types::AccessList, derive_more::From}; /// A contract address. #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] From 1dd3d2afd009d9af5516dd5d852dd72a4767fcae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=CC=81=20Duarte?= Date: Mon, 15 Dec 2025 17:06:54 +0000 Subject: [PATCH 02/24] lints --- crates/shared/src/sources/uniswap_v2/pair_provider.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/shared/src/sources/uniswap_v2/pair_provider.rs b/crates/shared/src/sources/uniswap_v2/pair_provider.rs index 9db91c9a08..b82cb1e754 100644 --- a/crates/shared/src/sources/uniswap_v2/pair_provider.rs +++ b/crates/shared/src/sources/uniswap_v2/pair_provider.rs @@ -18,7 +18,7 @@ impl PairProvider { let mut buffer = [0u8; 40]; buffer[0..20].copy_from_slice(token0.as_slice()); buffer[20..40].copy_from_slice(token1.as_slice()); - keccak256(&buffer) + keccak256(buffer) }; create2_target_address(self.factory, &salt, &self.init_code_digest) } @@ -33,7 +33,7 @@ fn create2_target_address( preimage[1..21].copy_from_slice(creator.as_slice()); preimage[21..53].copy_from_slice(salt); preimage[53..85].copy_from_slice(init_code_digest); - Address::from_slice(&keccak256(&preimage)[12..]) + Address::from_slice(&keccak256(preimage)[12..]) } #[cfg(test)] From 12eab6f16225918150fba3c61df5d7f77d1be206 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=CC=81=20Duarte?= Date: Mon, 15 Dec 2025 17:25:54 +0000 Subject: [PATCH 03/24] fix driver test issue --- crates/driver/src/tests/setup/blockchain.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/crates/driver/src/tests/setup/blockchain.rs b/crates/driver/src/tests/setup/blockchain.rs index f08b2dd2a3..27f1c2be66 100644 --- a/crates/driver/src/tests/setup/blockchain.rs +++ b/crates/driver/src/tests/setup/blockchain.rs @@ -341,19 +341,16 @@ impl Blockchain { } code }; - let settlement_code = web3 - .eth() - .code(settlement.address().into_legacy(), None) - .await - .unwrap() - .0; - web3.alloy .anvil_set_code(vault_relayer, vault_relayer_code.into()) .await .unwrap(); + + // Note that (settlement.address() == authenticator_address) != + // settlement_address + let settlement_code = web3.alloy.get_code_at(*settlement.address()).await.unwrap(); web3.alloy - .anvil_set_code(*settlement.address(), settlement_code.into()) + .anvil_set_code(settlement_address, settlement_code) .await .unwrap(); From 693126a0935a124c53f28180daca04f7b8804658 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=CC=81=20Duarte?= Date: Mon, 15 Dec 2025 17:26:16 +0000 Subject: [PATCH 04/24] comment --- crates/driver/src/tests/setup/blockchain.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/driver/src/tests/setup/blockchain.rs b/crates/driver/src/tests/setup/blockchain.rs index 27f1c2be66..1bb886f1ae 100644 --- a/crates/driver/src/tests/setup/blockchain.rs +++ b/crates/driver/src/tests/setup/blockchain.rs @@ -346,8 +346,7 @@ impl Blockchain { .await .unwrap(); - // Note that (settlement.address() == authenticator_address) != - // settlement_address + // Note: (settlement.address() == authenticator_address) != settlement_address let settlement_code = web3.alloy.get_code_at(*settlement.address()).await.unwrap(); web3.alloy .anvil_set_code(settlement_address, settlement_code) From 736b9e637d5989f76f5bb3d88179f8b758806568 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=CC=81=20Duarte?= Date: Mon, 15 Dec 2025 19:21:11 +0000 Subject: [PATCH 05/24] Migrate RPC calls into alloy --- crates/autopilot/Cargo.toml | 2 +- crates/autopilot/src/domain/eth/mod.rs | 14 ++- crates/autopilot/src/infra/blockchain/mod.rs | 85 +++++++++---------- crates/autopilot/src/run.rs | 16 ++-- crates/driver/Cargo.toml | 2 +- crates/driver/src/infra/blockchain/mod.rs | 59 +++++++------ crates/driver/src/tests/setup/blockchain.rs | 29 +++++-- crates/driver/src/tests/setup/mod.rs | 10 ++- crates/e2e/src/setup/deploy.rs | 31 ++++--- .../e2e/src/setup/onchain_components/mod.rs | 15 ++-- crates/e2e/src/setup/services.rs | 8 +- crates/e2e/tests/e2e/cow_amm.rs | 22 +++-- crates/e2e/tests/e2e/eth_integration.rs | 24 ++---- crates/e2e/tests/e2e/liquidity.rs | 7 +- crates/e2e/tests/e2e/submission.rs | 74 ++++++++-------- crates/ethrpc/src/extensions.rs | 7 +- crates/orderbook/src/run.rs | 7 +- crates/refunder/src/lib.rs | 7 +- crates/shared/src/bad_token/trace_call.rs | 4 +- crates/shared/src/event_handling.rs | 30 +++---- crates/shared/src/gas_price_estimation/mod.rs | 3 +- .../sources/balancer_v2/pool_fetching/mod.rs | 27 ++++-- crates/shared/src/sources/swapr.rs | 7 +- 23 files changed, 258 insertions(+), 232 deletions(-) diff --git a/crates/autopilot/Cargo.toml b/crates/autopilot/Cargo.toml index 879626807d..ae24fc9b69 100644 --- a/crates/autopilot/Cargo.toml +++ b/crates/autopilot/Cargo.toml @@ -15,7 +15,7 @@ name = "autopilot" path = "src/main.rs" [dependencies] -alloy = { workspace = true, features = ["rand"] } +alloy = { workspace = true, features = ["rand", "provider-debug-api", "provider-trace-api"] } app-data = { workspace = true } bytes-hex = { workspace = true } # may get marked as unused but it's used with serde anyhow = { workspace = true } diff --git a/crates/autopilot/src/domain/eth/mod.rs b/crates/autopilot/src/domain/eth/mod.rs index 23862cdbe7..9e7b9a6ce3 100644 --- a/crates/autopilot/src/domain/eth/mod.rs +++ b/crates/autopilot/src/domain/eth/mod.rs @@ -148,12 +148,24 @@ impl num::Saturating for SellTokenAmount { #[derive(Debug, Default, Display, Clone, Copy, Ord, Eq, PartialOrd, PartialEq, From, Into)] pub struct Gas(pub U256); +impl From for Gas { + fn from(value: u64) -> Self { + Self(U256::from(value)) + } +} + /// The `effective_gas_price` as defined by EIP-1559. /// /// https://eips.ethereum.org/EIPS/eip-1559#specification #[derive(Debug, Clone, Copy, Display, Default)] pub struct EffectiveGasPrice(pub Ether); +impl From for EffectiveGasPrice { + fn from(value: u128) -> Self { + Self(U256::from(value).into()) + } +} + impl From for EffectiveGasPrice { fn from(value: U256) -> Self { Self(value.into()) @@ -302,7 +314,7 @@ impl std::iter::Sum for Ether { pub struct DomainSeparator(pub [u8; 32]); /// Originated from the blockchain transaction input data. -pub type Calldata = crate::util::Bytes>; +pub type Calldata = alloy::primitives::Bytes; /// A settlement event emitted by a settlement smart contract. #[derive(Debug, Clone, Copy)] diff --git a/crates/autopilot/src/infra/blockchain/mod.rs b/crates/autopilot/src/infra/blockchain/mod.rs index f07b2689c6..f9dabc916e 100644 --- a/crates/autopilot/src/infra/blockchain/mod.rs +++ b/crates/autopilot/src/infra/blockchain/mod.rs @@ -1,14 +1,16 @@ use { self::contracts::Contracts, crate::{boundary, domain::eth}, - alloy::{primitives::U256, providers::Provider}, - chain::Chain, - ethrpc::{ - Web3, - alloy::conversions::{IntoAlloy, IntoLegacy}, - block_stream::CurrentBlockWatcher, - extensions::DebugNamespace, + alloy::{ + providers::{Provider, ext::DebugApi}, + rpc::types::{ + TransactionReceipt, + trace::geth::{CallConfig, GethDebugTracingOptions, GethTrace}, + }, }, + anyhow::bail, + chain::Chain, + ethrpc::{Web3, block_stream::CurrentBlockWatcher}, thiserror::Error, url::Url, }; @@ -110,16 +112,16 @@ impl Ethereum { } pub async fn transaction(&self, hash: eth::TxId) -> Result { - let (transaction, receipt, traces) = tokio::try_join!( - self.web3.eth().transaction(hash.0.into_legacy().into()), - self.web3.eth().transaction_receipt(hash.0.into_legacy()), + let (receipt, traces): (Option, GethTrace) = tokio::try_join!( + self.web3.alloy.get_transaction_receipt(hash.0), // Use unbuffered transport for the Debug API since not all providers support // batched debug calls. - self.unbuffered_web3 - .debug() - .transaction(hash.0.into_legacy()), + self.unbuffered_web3.alloy.debug_trace_transaction( + hash.0, + GethDebugTracingOptions::call_tracer(CallConfig::default()), + ) )?; - let transaction = transaction.ok_or(Error::TransactionNotFound)?; + let receipt = receipt.ok_or(Error::TransactionNotFound)?; let block_hash = receipt @@ -129,54 +131,47 @@ impl Ethereum { )))?; let block = self .web3 - .eth() - .block(block_hash.into()) + .alloy + .get_block_by_hash(block_hash) .await? .ok_or(Error::TransactionNotFound)?; - into_domain(transaction, receipt, traces, block.timestamp.into_alloy()) + + into_domain(receipt, traces, block.header.timestamp) .map_err(Error::IncompleteTransactionData) } } fn into_domain( - transaction: web3::types::Transaction, - receipt: web3::types::TransactionReceipt, - trace_calls: ethrpc::extensions::CallFrame, - timestamp: U256, + receipt: TransactionReceipt, + trace: GethTrace, + timestamp: u64, ) -> anyhow::Result { + let trace_calls = match trace { + GethTrace::CallTracer(call_frame) => call_frame.into(), + trace => bail!("unsupported trace call {trace:?}"), + }; + Ok(eth::Transaction { - hash: transaction.hash.into_alloy().into(), - from: transaction - .from - .map(IntoAlloy::into_alloy) - .ok_or(anyhow::anyhow!("missing from"))?, + hash: receipt.transaction_hash.into(), + from: receipt.from, block: receipt .block_number .ok_or(anyhow::anyhow!("missing block_number"))? - .0[0] - .into(), - gas: receipt - .gas_used - .ok_or(anyhow::anyhow!("missing gas_used"))? - .into_alloy() - .into(), - gas_price: receipt - .effective_gas_price - .ok_or(anyhow::anyhow!("missing effective_gas_price"))? - .into_alloy() .into(), + gas: receipt.gas_used.into(), + gas_price: receipt.effective_gas_price.into(), timestamp: u32::try_from(timestamp)?, - trace_calls: trace_calls.into(), + trace_calls, }) } -impl From for eth::CallFrame { - fn from(frame: ethrpc::extensions::CallFrame) -> Self { - eth::CallFrame { - from: frame.from.into_alloy(), - to: frame.to.map(IntoAlloy::into_alloy), - input: frame.input.0.into(), - calls: frame.calls.into_iter().map(Into::into).collect(), +impl From for eth::CallFrame { + fn from(value: alloy::rpc::types::trace::geth::CallFrame) -> Self { + Self { + from: value.from, + to: value.to, + input: value.input, + calls: value.calls.into_iter().map(Into::into).collect(), } } } diff --git a/crates/autopilot/src/run.rs b/crates/autopilot/src/run.rs index be521e3a9d..4b305f40da 100644 --- a/crates/autopilot/src/run.rs +++ b/crates/autopilot/src/run.rs @@ -24,7 +24,7 @@ use { shutdown_controller::ShutdownController, solvable_orders::SolvableOrdersCache, }, - alloy::{eips::BlockNumberOrTag, primitives::Address}, + alloy::{eips::BlockNumberOrTag, primitives::Address, providers::Provider}, chain::Chain, clap::Parser, contracts::alloy::{BalancerV2Vault, GPv2Settlement, IUniswapV3Factory, WETH9}, @@ -184,12 +184,11 @@ pub async fn run(args: Arguments, shutdown_controller: ShutdownController) { }); let chain_id = web3 - .eth() - .chain_id() + .alloy + .get_chain_id() .instrument(info_span!("chain_id")) .await - .expect("Could not get chainId") - .as_u64(); + .expect("Could not get chainId"); if let Some(expected_chain_id) = args.shared.chain_id { assert_eq!( chain_id, expected_chain_id, @@ -748,11 +747,10 @@ async fn shadow_mode(args: Arguments) -> ! { let trusted_tokens = { let chain_id = web3 - .eth() - .chain_id() + .alloy + .get_chain_id() .await - .expect("Could not get chainId") - .as_u64(); + .expect("Could not get chainId"); if let Some(expected_chain_id) = args.shared.chain_id { assert_eq!( chain_id, expected_chain_id, diff --git a/crates/driver/Cargo.toml b/crates/driver/Cargo.toml index db9c3a2263..b49abdebfb 100644 --- a/crates/driver/Cargo.toml +++ b/crates/driver/Cargo.toml @@ -15,7 +15,7 @@ name = "driver" path = "src/main.rs" [dependencies] -alloy = { workspace = true, features = ["sol-types", "provider-txpool-api", "rand", "provider-anvil-api"] } +alloy = { workspace = true, features = ["sol-types", "provider-txpool-api", "rand", "provider-anvil-api", "json-rpc"] } app-data = { workspace = true } async-trait = { workspace = true } axum = { workspace = true } diff --git a/crates/driver/src/infra/blockchain/mod.rs b/crates/driver/src/infra/blockchain/mod.rs index 47fa795519..da26855ee6 100644 --- a/crates/driver/src/infra/blockchain/mod.rs +++ b/crates/driver/src/infra/blockchain/mod.rs @@ -3,7 +3,7 @@ use { boundary, domain::{eth, eth::U256}, }, - alloy::providers::Provider, + alloy::{providers::Provider, rpc::types::TransactionReceipt, transports::TransportErrorKind}, chain::Chain, ethcontract::errors::ExecutionError, ethrpc::{ @@ -170,8 +170,8 @@ impl Ethereum { /// Check if a smart contract is deployed to the given address. pub async fn is_contract(&self, address: eth::Address) -> Result { - let code = self.web3.eth().code(address.into_legacy(), None).await?; - Ok(!code.0.is_empty()) + let code = self.web3.alloy.get_code_at(address).await?; + Ok(!code.is_empty()) } /// Returns a type that monitors the block chain to inform about the current @@ -253,10 +253,9 @@ impl Ethereum { /// Returns the current [`eth::Ether`] balance of the specified account. pub async fn balance(&self, address: eth::Address) -> Result { self.web3 - .eth() - .balance(address.into_legacy(), None) + .alloy + .get_balance(address) .await - .map(IntoAlloy::into_alloy) .map(Into::into) .map_err(Into::into) } @@ -269,26 +268,29 @@ impl Ethereum { /// Returns the transaction's on-chain inclusion status. pub async fn transaction_status(&self, tx_hash: ð::TxId) -> Result { self.web3 - .eth() - .transaction_receipt(tx_hash.0.into_legacy()) + .alloy + .get_transaction_receipt(tx_hash.0) .await - .map(|result| match result { - Some(web3::types::TransactionReceipt { - status: Some(status), - block_number: Some(block), - .. - }) => { - if status.is_zero() { - eth::TxStatus::Reverted { - block_number: eth::BlockNo(block.as_u64()), - } - } else { - eth::TxStatus::Executed { - block_number: eth::BlockNo(block.as_u64()), - } + .map(|result| { + let Some( + receipt @ TransactionReceipt { + block_number: Some(block_number), + .. + }, + ) = result + else { + return eth::TxStatus::Pending; + }; + + if receipt.status() { + eth::TxStatus::Executed { + block_number: eth::BlockNo(block_number), + } + } else { + eth::TxStatus::Reverted { + block_number: eth::BlockNo(block_number), } } - _ => eth::TxStatus::Pending, }) .map_err(Into::into) } @@ -329,7 +331,9 @@ impl fmt::Debug for Ethereum { #[derive(Debug, Error)] pub enum Error { #[error("method error: {0:?}")] - Rpc(#[from] alloy::contract::Error), + ContractRpc(#[from] alloy::contract::Error), + #[error("alloy rpc error: {0:?}")] + Rpc(#[from] alloy::transports::RpcError), #[error("method error: {0:?}")] Method(#[from] ethcontract::errors::MethodError), #[error("web3 error: {0:?}")] @@ -353,7 +357,8 @@ impl Error { } Error::GasPrice(_) => false, Error::AccessList(_) => true, - Error::Rpc(_) => true, + Error::ContractRpc(_) => true, + Error::Rpc(_) => false, } } } @@ -362,7 +367,7 @@ impl From for Error { fn from(err: contracts::Error) -> Self { match err { contracts::Error::Method(err) => Self::Method(err), - contracts::Error::Rpc(err) => Self::Rpc(err), + contracts::Error::Rpc(err) => Self::ContractRpc(err), } } } @@ -370,7 +375,7 @@ impl From for Error { impl From for Error { fn from(err: SimulationError) -> Self { match err { - SimulationError::Method(err) => Self::Rpc(err), + SimulationError::Method(err) => Self::ContractRpc(err), SimulationError::Web3(err) => Self::Web3(err), } } diff --git a/crates/driver/src/tests/setup/blockchain.rs b/crates/driver/src/tests/setup/blockchain.rs index 1bb886f1ae..385fac8679 100644 --- a/crates/driver/src/tests/setup/blockchain.rs +++ b/crates/driver/src/tests/setup/blockchain.rs @@ -238,6 +238,9 @@ impl Blockchain { let web3 = Web3::new_from_url(&node.url()); let private_key = config.main_trader_secret_key.as_ref(); + web3.wallet + .register_signer(PrivateKeySigner::from_bytes(private_key.into()).unwrap()); + let main_trader_account = ethcontract::Account::Offline( ethcontract::PrivateKey::from_slice(private_key).unwrap(), None, @@ -261,14 +264,18 @@ impl Blockchain { let primary_address = primary_account.address(); // Use the primary account to fund the trader, cow amm and the solver with ETH. - let balance = web3.eth().balance(primary_address, None).await.unwrap(); + let balance = web3 + .alloy + .get_balance(primary_address.into_alloy()) + .await + .unwrap(); wait_for( &web3, web3.eth() .send_transaction(web3::types::TransactionRequest { from: primary_address, to: Some(main_trader_account.address()), - value: Some(balance / 5), + value: Some((balance / alloy::primitives::U256::from(5)).into_legacy()), ..Default::default() }), ) @@ -286,7 +293,7 @@ impl Blockchain { ethcontract::transaction::TransactionBuilder::new(web3.legacy.clone()) .from(primary_account) .to(weth.address().into_legacy()) - .value(balance / 5) + .value((balance / alloy::primitives::U256::from(5)).into_legacy()) .send(), ) .await @@ -328,11 +335,12 @@ impl Blockchain { // replace the vault relayer code to allow the settlement // contract at a specific address. let mut code = web3 - .eth() - .code(vault_relayer.into_legacy(), None) + .alloy + .get_code_at(vault_relayer) .await .unwrap() - .0; + .to_vec(); + for i in 0..code.len() - 20 { let window = &mut code[i..][..20]; if window == settlement.address().as_slice() { @@ -877,15 +885,18 @@ impl Blockchain { pub async fn set_auto_mining(&self, enabled: bool) { self.web3 - .transport() - .execute("evm_setAutomine", vec![json!(enabled)]) + .alloy + .raw_request::<_, ()>("evm_setAutomine".into(), (enabled,)) .await .unwrap(); } } async fn primary_account(web3: &Web3) -> ethcontract::Account { - ethcontract::Account::Local(web3.eth().accounts().await.unwrap()[0], None) + ethcontract::Account::Local( + web3.alloy.get_accounts().await.unwrap()[0].into_legacy(), + None, + ) } /// A blockchain node for development purposes. Dropping this type will diff --git a/crates/driver/src/tests/setup/mod.rs b/crates/driver/src/tests/setup/mod.rs index 391f125b30..80f70578e2 100644 --- a/crates/driver/src/tests/setup/mod.rs +++ b/crates/driver/src/tests/setup/mod.rs @@ -37,7 +37,10 @@ use { }, }, }, - alloy::primitives::{Address, U256, address}, + alloy::{ + primitives::{Address, U256, address}, + providers::Provider, + }, bigdecimal::{BigDecimal, FromPrimitive}, ethcontract::dyns::DynTransport, ethrpc::alloy::conversions::{IntoAlloy, IntoLegacy}, @@ -1175,10 +1178,9 @@ impl Test { "ETH", self.blockchain .web3 - .eth() - .balance(self.trader_address.into_legacy(), None) + .alloy + .get_balance(self.trader_address) .await - .map(IntoAlloy::into_alloy) .unwrap(), ); balances diff --git a/crates/e2e/src/setup/deploy.rs b/crates/e2e/src/setup/deploy.rs index 85cb82dfb7..e7031ba0bc 100644 --- a/crates/e2e/src/setup/deploy.rs +++ b/crates/e2e/src/setup/deploy.rs @@ -1,4 +1,5 @@ use { + alloy::providers::Provider, contracts::alloy::{ BalancerV2Authorizer, BalancerV2Vault, @@ -47,8 +48,8 @@ pub struct Contracts { impl Contracts { pub async fn deployed_with(web3: &Web3, deployed: DeployedContracts) -> Self { let network_id = web3 - .eth() - .chain_id() + .alloy + .get_chain_id() .await .expect("get network ID failed") .to_string(); @@ -120,22 +121,25 @@ impl Contracts { pub async fn deploy(web3: &Web3) -> Self { let network_id = web3 - .eth() - .chain_id() + .alloy + .get_chain_id() .await .expect("get network ID failed") .to_string(); tracing::info!("connected to test network {}", network_id); - let accounts: Vec
= web3.eth().accounts().await.expect("get accounts failed"); + let accounts = web3 + .alloy + .get_accounts() + .await + .expect("get accounts failed"); let admin = accounts[0]; let weth = WETH9::Instance::deploy(web3.alloy.clone()).await.unwrap(); - let balancer_authorizer = - BalancerV2Authorizer::Instance::deploy(web3.alloy.clone(), admin.into_alloy()) - .await - .unwrap(); + let balancer_authorizer = BalancerV2Authorizer::Instance::deploy(web3.alloy.clone(), admin) + .await + .unwrap(); let balancer_vault = BalancerV2Vault::Instance::deploy( web3.alloy.clone(), *balancer_authorizer.address(), @@ -146,10 +150,9 @@ impl Contracts { .await .unwrap(); - let uniswap_v2_factory = - UniswapV2Factory::Instance::deploy(web3.alloy.clone(), accounts[0].into_alloy()) - .await - .unwrap(); + let uniswap_v2_factory = UniswapV2Factory::Instance::deploy(web3.alloy.clone(), admin) + .await + .unwrap(); let uniswap_v2_router = UniswapV2Router02::Instance::deploy( web3.alloy.clone(), *uniswap_v2_factory.address(), @@ -162,7 +165,7 @@ impl Contracts { .await .unwrap(); gp_authenticator - .initializeManager(admin.into_alloy()) + .initializeManager(admin) .send_and_watch() .await .expect("failed to initialize manager"); diff --git a/crates/e2e/src/setup/onchain_components/mod.rs b/crates/e2e/src/setup/onchain_components/mod.rs index 33fc8e668c..d80f87a370 100644 --- a/crates/e2e/src/setup/onchain_components/mod.rs +++ b/crates/e2e/src/setup/onchain_components/mod.rs @@ -6,7 +6,7 @@ use { ::alloy::{ network::{Ethereum, NetworkWallet, TransactionBuilder}, primitives::Address, - providers::Provider, + providers::{Provider, ext::AnvilApi}, rpc::types::TransactionRequest, signers::local::PrivateKeySigner, }, @@ -393,10 +393,11 @@ impl OnchainComponents { ) -> [MintableToken; N] { let minter = Account::Local( self.web3 - .eth() - .accounts() + .alloy + .get_accounts() .await - .expect("getting accounts failed")[0], + .expect("getting accounts failed")[0] + .into_legacy(), None, ); let tokens = self.deploy_tokens::(&minter).await; @@ -665,11 +666,7 @@ impl OnchainComponents { pub async fn mint_block(&self) { tracing::info!("mining block"); - self.web3 - .transport() - .execute("evm_mine", vec![]) - .await - .unwrap(); + self.web3.alloy.evm_mine(None).await.unwrap(); } pub fn contracts(&self) -> &Contracts { diff --git a/crates/e2e/src/setup/services.rs b/crates/e2e/src/setup/services.rs index 34a0cd9504..344cf92faa 100644 --- a/crates/e2e/src/setup/services.rs +++ b/crates/e2e/src/setup/services.rs @@ -10,7 +10,7 @@ use { wait_for_condition, }, }, - alloy::primitives::Address, + alloy::{primitives::Address, providers::ext::AnvilApi}, app_data::{AppDataDocument, AppDataHash}, autopilot::infra::persistence::dto, clap::Parser, @@ -716,11 +716,7 @@ impl<'a> Services<'a> { async fn mint_block(&self) { tracing::info!("mining block"); - self.web3 - .transport() - .execute("evm_mine", vec![]) - .await - .unwrap(); + self.web3.alloy.evm_mine(None).await.unwrap(); } } diff --git a/crates/e2e/tests/e2e/cow_amm.rs b/crates/e2e/tests/e2e/cow_amm.rs index 1fc3bbaf52..6d31aeb089 100644 --- a/crates/e2e/tests/e2e/cow_amm.rs +++ b/crates/e2e/tests/e2e/cow_amm.rs @@ -1,7 +1,10 @@ use { alloy::{ primitives::{Address, Bytes, FixedBytes, U256, address}, - providers::ext::{AnvilApi, ImpersonateConfig}, + providers::{ + Provider, + ext::{AnvilApi, ImpersonateConfig}, + }, }, contracts::alloy::{ ERC20, @@ -19,7 +22,6 @@ use { run_test, wait_for_condition, }, - ethcontract::{BlockId, BlockNumber}, ethrpc::alloy::{ CallBuilderExt, conversions::{IntoAlloy, IntoLegacy}, @@ -206,12 +208,14 @@ async fn cow_amm_jit(web3: Web3) { // a relatively small valid_to and we initialize the chain with a date in // the past so the computer's current time is way ahead of the blockchain. let block = web3 - .eth() - .block(BlockId::Number(BlockNumber::Latest)) + .alloy + .get_block(alloy::eips::BlockId::Number( + alloy::eips::BlockNumberOrTag::Latest, + )) .await .unwrap() .unwrap(); - let valid_to = block.timestamp.as_u32() + 300; + let valid_to = u32::try_from(block.header.timestamp).unwrap() + 300; // CoW AMM order with a limit price extremely close to the AMM's current price. // current price => 1 WETH == 2000 DAI @@ -842,12 +846,14 @@ async fn cow_amm_opposite_direction(web3: Web3) { // Get the current block timestamp let block = web3 - .eth() - .block(BlockId::Number(BlockNumber::Latest)) + .alloy + .get_block(alloy::eips::BlockId::Number( + alloy::eips::BlockNumberOrTag::Latest, + )) .await .unwrap() .unwrap(); - let valid_to = block.timestamp.as_u32() + 300; + let valid_to = u32::try_from(block.header.timestamp).unwrap() + 300; let executed_amount = 230u64.eth(); // CoW AMM order remains the same (selling WETH for DAI) diff --git a/crates/e2e/tests/e2e/eth_integration.rs b/crates/e2e/tests/e2e/eth_integration.rs index 9f94e7c8a9..44d98e750e 100644 --- a/crates/e2e/tests/e2e/eth_integration.rs +++ b/crates/e2e/tests/e2e/eth_integration.rs @@ -1,4 +1,5 @@ use { + ::alloy::providers::Provider, e2e::setup::*, ethcontract::prelude::Address, ethrpc::alloy::{ @@ -54,11 +55,7 @@ async fn eth_integration(web3: Web3) { .await .unwrap(); - let trader_a_eth_balance_before = web3 - .eth() - .balance(trader_a.address().into_legacy(), None) - .await - .unwrap(); + let trader_a_eth_balance_before = web3.alloy.get_balance(trader_a.address()).await.unwrap(); let services = Services::new(&onchain).await; services.start_protocol(solver).await; @@ -121,20 +118,11 @@ async fn eth_integration(web3: Web3) { tracing::info!("Waiting for trade."); onchain.mint_block().await; let trade_happened = || async { - let balance_a = web3 - .eth() - .balance(trader_a.address().into_legacy(), None) - .await - .unwrap(); - let balance_b = web3 - .eth() - .balance(trader_b.address().into_legacy(), None) - .await - .unwrap(); + let balance_a = web3.alloy.get_balance(trader_a.address()).await.unwrap(); + let balance_b = web3.alloy.get_balance(trader_b.address()).await.unwrap(); - let trader_a_eth_decreased = - (balance_a - trader_a_eth_balance_before) == 49u64.eth().into_legacy(); - let trader_b_eth_increased = balance_b >= 49u64.eth().into_legacy(); + let trader_a_eth_decreased = (balance_a - trader_a_eth_balance_before) == 49u64.eth(); + let trader_b_eth_increased = balance_b >= 49u64.eth(); trader_a_eth_decreased && trader_b_eth_increased }; wait_for_condition(TIMEOUT, trade_happened).await.unwrap(); diff --git a/crates/e2e/tests/e2e/liquidity.rs b/crates/e2e/tests/e2e/liquidity.rs index 8fd5804065..c16c736312 100644 --- a/crates/e2e/tests/e2e/liquidity.rs +++ b/crates/e2e/tests/e2e/liquidity.rs @@ -1,7 +1,10 @@ use { alloy::{ primitives::{Address, address}, - providers::ext::{AnvilApi, ImpersonateConfig}, + providers::{ + Provider, + ext::{AnvilApi, ImpersonateConfig}, + }, }, chrono::{NaiveDateTime, Utc}, contracts::alloy::{ERC20, IZeroex}, @@ -169,7 +172,7 @@ async fn zero_ex_liquidity(web3: Web3) { SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), ); - let chain_id = web3.eth().chain_id().await.unwrap().as_u64(); + let chain_id = web3.alloy.get_chain_id().await.unwrap(); let zeroex_liquidity_orders = create_zeroex_liquidity_orders( order.clone(), zeroex_maker.clone(), diff --git a/crates/e2e/tests/e2e/submission.rs b/crates/e2e/tests/e2e/submission.rs index c3948b9e5b..32a75f3f68 100644 --- a/crates/e2e/tests/e2e/submission.rs +++ b/crates/e2e/tests/e2e/submission.rs @@ -1,12 +1,18 @@ use { - ::alloy::primitives::U256, + ::alloy::{ + primitives::{Address, B256, U256}, + providers::{Provider, ext::TxPoolApi}, + rpc::{ + client::PollerStream, + types::{Transaction, TransactionReceipt}, + }, + }, e2e::{nodes::local_node::TestNodeApi, setup::*}, - ethcontract::{BlockId, H160, H256}, ethrpc::alloy::{ CallBuilderExt, conversions::{IntoAlloy, IntoLegacy}, }, - futures::{Stream, StreamExt}, + futures::StreamExt, model::{ order::{OrderCreation, OrderKind}, signature::EcdsaSigningScheme, @@ -14,7 +20,6 @@ use { number::units::EthUnit, secp256k1::SecretKey, shared::ethrpc::Web3, - std::time::Duration, web3::signing::SecretKeyRef, }; @@ -86,29 +91,22 @@ async fn test_cancel_on_expiry(web3: Web3) { onchain.mint_block().await; // Start tracking confirmed blocks so we can find the transaction later - let block_stream = web3 - .eth_filter() - .create_blocks_filter() - .await - .expect("must be able to create blocks filter") - .stream(Duration::from_millis(50)); + let stream = web3.alloy.watch_blocks().await.unwrap().into_stream(); // Wait for settlement tx to appear in txpool wait_for_condition(TIMEOUT, || async { - get_pending_tx(solver.account().address(), &web3) - .await - .is_some() + get_pending_tx(solver.address(), &web3).await.is_some() }) .await .unwrap(); // Restart mining, but with blocks that are too small to fit the settlement - web3.api::>() - .set_block_gas_limit(100_000) + web3.alloy + .raw_request::<(u64,), bool>("evm_setBlockGasLimit".into(), (100_000,)) .await .expect("Must be able to set block gas limit"); - web3.api::>() - .set_mining_interval(1) + web3.alloy + .raw_request::<(u64,), ()>("evm_setIntervalMining".into(), (1,)) .await .expect("Must be able to set mining interval"); @@ -120,39 +118,43 @@ async fn test_cancel_on_expiry(web3: Web3) { // Check that it's actually a cancellation let tx = tokio::time::timeout( TIMEOUT, - get_confirmed_transaction(solver.account().address(), &web3, block_stream), + get_confirmed_transaction(solver.address(), &web3, stream), ) .await .unwrap(); - assert_eq!(tx.to, Some(solver.account().address())) + assert_eq!(tx.to, Some(solver.address())) } -async fn get_pending_tx(account: H160, web3: &Web3) -> Option { +async fn get_pending_tx(account: Address, web3: &Web3) -> Option { let txpool = web3 - .txpool() - .content() + .alloy + .txpool_content() .await .expect("must be able to inspect mempool"); txpool.pending.get(&account)?.values().next().cloned() } async fn get_confirmed_transaction( - account: H160, + account: Address, web3: &Web3, - block_stream: impl Stream>, -) -> web3::types::Transaction { - let mut block_stream = Box::pin(block_stream); + block_hash_stream: PollerStream>, +) -> TransactionReceipt { + let mut block_hash_stream = Box::pin(block_hash_stream); loop { - let block_hash = block_stream.next().await.unwrap().unwrap(); - let block = web3 - .eth() - .block_with_txs(BlockId::Hash(block_hash)) - .await - .expect("must be able to get block by hash") - .expect("block not found"); - for tx in block.transactions { - if tx.from == Some(account) { - return tx; + let block_hashes = block_hash_stream.next().await.unwrap(); + for block_hash in block_hashes { + let transaction_senders = web3 + .alloy + .get_block_receipts(block_hash.into()) + .await + .unwrap() + .into_iter() + .flatten(); + + for tx in transaction_senders { + if tx.from == account { + return tx; + } } } } diff --git a/crates/ethrpc/src/extensions.rs b/crates/ethrpc/src/extensions.rs index 6eac4944c7..5ae0c4bab9 100644 --- a/crates/ethrpc/src/extensions.rs +++ b/crates/ethrpc/src/extensions.rs @@ -1,6 +1,7 @@ //! Module containing Ethereum RPC extension methods. use { + alloy::primitives::Address, ethcontract::state_overrides::StateOverrides, serde::Deserialize, tracing::{Instrument, instrument::Instrumented}, @@ -97,12 +98,12 @@ impl Debug { #[derive(Clone, Debug, Default, PartialEq, Eq, Deserialize)] pub struct CallFrame { /// The address of that initiated the call. - pub from: primitive_types::H160, + pub from: Address, /// The address of the contract that was called. #[serde(default)] - pub to: Option, + pub to: Option
, /// Calldata input. - pub input: Bytes, + pub input: alloy::primitives::Bytes, /// Recorded child calls. #[serde(default)] pub calls: Vec, diff --git a/crates/orderbook/src/run.rs b/crates/orderbook/src/run.rs index 95c343f52a..c748e3eb79 100644 --- a/crates/orderbook/src/run.rs +++ b/crates/orderbook/src/run.rs @@ -89,11 +89,10 @@ pub async fn run(args: Arguments) { }); let chain_id = web3 - .eth() - .chain_id() + .alloy + .get_chain_id() .await - .expect("Could not get chainId") - .as_u64(); + .expect("Could not get chainId"); if let Some(expected_chain_id) = args.shared.chain_id { assert_eq!( chain_id, expected_chain_id, diff --git a/crates/refunder/src/lib.rs b/crates/refunder/src/lib.rs index f114bafaeb..d4137be8c7 100644 --- a/crates/refunder/src/lib.rs +++ b/crates/refunder/src/lib.rs @@ -42,11 +42,10 @@ pub async fn run(args: arguments::Arguments) { let web3 = shared::ethrpc::web3(&args.ethrpc, &http_factory, &args.node_url, "base"); if let Some(expected_chain_id) = args.chain_id { let chain_id = web3 - .eth() - .chain_id() + .alloy + .get_chain_id() .await - .expect("Could not get chainId") - .as_u64(); + .expect("Could not get chainId"); assert_eq!( chain_id, expected_chain_id, "connected to node with incorrect chain ID", diff --git a/crates/shared/src/bad_token/trace_call.rs b/crates/shared/src/bad_token/trace_call.rs index a10871760c..77b768272b 100644 --- a/crates/shared/src/bad_token/trace_call.rs +++ b/crates/shared/src/bad_token/trace_call.rs @@ -403,7 +403,7 @@ mod tests { }, sources::{BaselineSource, uniswap_v2}, }, - alloy::primitives::address, + alloy::{primitives::address, providers::Provider}, chain::Chain, contracts::alloy::{BalancerV2Vault, GPv2Settlement, IUniswapV3Factory}, ethrpc::Web3, @@ -555,7 +555,7 @@ mod tests { // observe::tracing::initialize("orderbook::bad_token=debug, // shared::transport=debug", tracing::level_filters::LevelFilter::OFF); let web3 = Web3::new_from_env(); - let version = web3.eth().chain_id().await.unwrap().to_string(); + let version = web3.alloy.get_chain_id().await.unwrap().to_string(); let base_tokens = &[ testlib::tokens::WETH, diff --git a/crates/shared/src/event_handling.rs b/crates/shared/src/event_handling.rs index 63e3280215..08c3a7b57b 100644 --- a/crates/shared/src/event_handling.rs +++ b/crates/shared/src/event_handling.rs @@ -774,7 +774,7 @@ mod tests { super::*, alloy::eips::BlockNumberOrTag, contracts::alloy::GPv2Settlement, - ethcontract::{BlockNumber, H256}, + ethcontract::H256, ethrpc::{Web3, block_stream::block_number_to_block_number_hash}, std::str::FromStr, }; @@ -991,20 +991,18 @@ mod tests { .await .unwrap(); let storage = EventStorage { events: vec![] }; - let current_block = web3.eth().block_number().await.unwrap(); + let current_block = web3.alloy.get_block_number().await.unwrap(); const NUMBER_OF_BLOCKS: u64 = 300; //get block in history (current_block - NUMBER_OF_BLOCKS) let block = web3 - .eth() - .block( - BlockNumber::Number(current_block.saturating_sub(NUMBER_OF_BLOCKS.into())).into(), - ) + .alloy + .get_block_by_number(current_block.saturating_sub(NUMBER_OF_BLOCKS).into()) .await .unwrap() .unwrap(); - let block = (block.number.unwrap().as_u64(), block.hash.unwrap()); + let block = (block.number(), block.hash().into_legacy()); let mut event_handler = EventHandler::new( Arc::new(web3.alloy.clone()), AlloyEventRetriever(contract), @@ -1024,20 +1022,18 @@ mod tests { .await .unwrap(); let storage = EventStorage { events: vec![] }; - let current_block = web3.eth().block_number().await.unwrap(); + let current_block = web3.alloy.get_chain_id().await.unwrap(); const NUMBER_OF_BLOCKS: u64 = 300; //get block in history (current_block - NUMBER_OF_BLOCKS) let block = web3 - .eth() - .block( - BlockNumber::Number(current_block.saturating_sub(NUMBER_OF_BLOCKS.into())).into(), - ) + .alloy + .get_block_by_number(current_block.saturating_sub(NUMBER_OF_BLOCKS).into()) .await .unwrap() .unwrap(); - let block = (block.number.unwrap().as_u64(), block.hash.unwrap()); + let block = (block.number(), block.hash().into_legacy()); let mut event_handler = EventHandler::new( Arc::new(web3.alloy.clone()), AlloyEventRetriever(contract), @@ -1058,7 +1054,7 @@ mod tests { .await .unwrap(); - let current_block = web3.eth().block_number().await.unwrap(); + let current_block = web3.alloy.get_chain_id().await.unwrap(); // In this test we query for events multiple times. Newer events might be // included each time we query again for the same events, but we want to // disregard them. @@ -1069,7 +1065,7 @@ mod tests { v.into_iter() .filter(|(_, log)| { // We make the test robust against reorgs by removing events that are too new - log.block_number.unwrap() <= (current_block - MAX_REORG_BLOCK_COUNT).as_u64() + log.block_number.unwrap() <= (current_block - MAX_REORG_BLOCK_COUNT) }) .collect::>() }; @@ -1081,7 +1077,7 @@ mod tests { let storage_empty = EventStorage { events: vec![] }; let event_start = block_number_to_block_number_hash( &web3.alloy, - BlockNumberOrTag::Number((current_block - RANGE_SIZE).as_u64()), + BlockNumberOrTag::Number(current_block - RANGE_SIZE), ) .await .unwrap(); @@ -1103,7 +1099,7 @@ mod tests { let storage_empty = EventStorage { events: vec![] }; let event_start = block_number_to_block_number_hash( &web3.alloy, - BlockNumberOrTag::Number((current_block - RANGE_SIZE).as_u64()), + BlockNumberOrTag::Number(current_block - RANGE_SIZE), ) .await .unwrap(); diff --git a/crates/shared/src/gas_price_estimation/mod.rs b/crates/shared/src/gas_price_estimation/mod.rs index 750c96c5e0..b23955be94 100644 --- a/crates/shared/src/gas_price_estimation/mod.rs +++ b/crates/shared/src/gas_price_estimation/mod.rs @@ -8,6 +8,7 @@ use { gas_price_estimation::alloy::AlloyGasPriceEstimator, http_client::HttpClientFactory, }, + ::alloy::providers::Provider, anyhow::Result, gas_estimation::{ GasPriceEstimating, @@ -49,7 +50,7 @@ pub async fn create_priority_estimator( web3: &Web3, estimator_types: &[GasEstimatorType], ) -> Result> { - let network_id = web3.eth().chain_id().await?.to_string(); + let network_id = web3.alloy.get_chain_id().await?.to_string(); let mut estimators = Vec::>::new(); for estimator_type in estimator_types { diff --git a/crates/shared/src/sources/balancer_v2/pool_fetching/mod.rs b/crates/shared/src/sources/balancer_v2/pool_fetching/mod.rs index 91a37f9be7..c109902be3 100644 --- a/crates/shared/src/sources/balancer_v2/pool_fetching/mod.rs +++ b/crates/shared/src/sources/balancer_v2/pool_fetching/mod.rs @@ -30,7 +30,11 @@ use { recent_block_cache::{Block, CacheConfig}, token_info::TokenInfoFetching, }, - alloy::{primitives::Address, providers::DynProvider}, + alloy::{ + eips::{BlockId, BlockNumberOrTag}, + primitives::{Address, B256}, + providers::{DynProvider, Provider}, + }, anyhow::{Context, Result}, clap::ValueEnum, contracts::alloy::{ @@ -48,8 +52,11 @@ use { BalancerV2WeightedPoolFactoryV3, BalancerV2WeightedPoolFactoryV4, }, - ethcontract::{BlockId, H256}, - ethrpc::block_stream::{BlockRetrieving, CurrentBlockWatcher}, + ethcontract::H256, + ethrpc::{ + alloy::conversions::IntoLegacy, + block_stream::{BlockRetrieving, CurrentBlockWatcher}, + }, model::TokenPair, reqwest::{Client, Url}, std::{ @@ -458,12 +465,11 @@ async fn create_aggregate_pool_fetcher( let registered_pools = pool_initializer.initialize_pools().await?; let fetched_block_number = registered_pools.fetched_block_number; let fetched_block_hash = web3 - .eth() - .block(BlockId::Number(fetched_block_number.into())) + .alloy + .get_block_by_number(BlockNumberOrTag::Number(fetched_block_number)) .await? .context("failed to get block by block number")? - .hash - .context("missing hash from block")?; + .hash(); let mut registered_pools_by_factory = registered_pools.group_by_factory(); macro_rules! registry { @@ -554,7 +560,7 @@ fn create_internal_pool_fetcher( token_infos: Arc, factory_instance: &BalancerFactoryInstance, registered_pools: RegisteredPools, - fetched_block_hash: H256, + fetched_block_hash: B256, ) -> Result> where Factory: FactoryIndexing, @@ -564,7 +570,10 @@ where .iter() .map(|pool| Factory::PoolInfo::from_graph_data(pool, registered_pools.fetched_block_number)) .collect::>()?; - let start_sync_at_block = Some((registered_pools.fetched_block_number, fetched_block_hash)); + let start_sync_at_block = Some(( + registered_pools.fetched_block_number, + fetched_block_hash.into_legacy(), + )); Ok(Box::new(Registry::new( block_retriever, diff --git a/crates/shared/src/sources/swapr.rs b/crates/shared/src/sources/swapr.rs index 28ecc7e4ca..4ec0d57eca 100644 --- a/crates/shared/src/sources/swapr.rs +++ b/crates/shared/src/sources/swapr.rs @@ -58,7 +58,10 @@ mod tests { recent_block_cache::Block, sources::{BaselineSource, uniswap_v2}, }, - alloy::primitives::{Address, address}, + alloy::{ + primitives::{Address, address}, + providers::Provider, + }, ethrpc::alloy::errors::testing_alloy_contract_error, maplit::hashset, }; @@ -108,7 +111,7 @@ mod tests { #[ignore] async fn fetch_swapr_pool() { let web3 = Web3::new_from_env(); - let version = web3.eth().chain_id().await.unwrap().to_string(); + let version = web3.alloy.get_chain_id().await.unwrap().to_string(); let pool_fetcher = uniswap_v2::UniV2BaselineSourceParameters::from_baseline_source( BaselineSource::Swapr, &version, From a23adf2936326859e95edbda6a6533e2b1e11ee6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=CC=81=20Duarte?= Date: Mon, 15 Dec 2025 21:39:03 +0000 Subject: [PATCH 06/24] fix compilation --- crates/e2e/src/setup/onchain_components/mod.rs | 5 +---- crates/e2e/src/setup/services.rs | 1 - crates/refunder/src/lib.rs | 2 +- crates/shared/src/sources/balancer_v2/pool_fetching/mod.rs | 2 +- 4 files changed, 3 insertions(+), 7 deletions(-) diff --git a/crates/e2e/src/setup/onchain_components/mod.rs b/crates/e2e/src/setup/onchain_components/mod.rs index d80f87a370..c8eeba30f8 100644 --- a/crates/e2e/src/setup/onchain_components/mod.rs +++ b/crates/e2e/src/setup/onchain_components/mod.rs @@ -31,10 +31,7 @@ use { secp256k1::SecretKey, shared::ethrpc::Web3, std::{borrow::BorrowMut, ops::Deref}, - web3::{ - Transport, - signing::{self, SecretKeyRef}, - }, + web3::signing::{self, SecretKeyRef}, }; pub mod alloy; diff --git a/crates/e2e/src/setup/services.rs b/crates/e2e/src/setup/services.rs index 344cf92faa..c765fd41d6 100644 --- a/crates/e2e/src/setup/services.rs +++ b/crates/e2e/src/setup/services.rs @@ -31,7 +31,6 @@ use { time::Duration, }, tokio::task::JoinHandle, - web3::Transport, }; pub const API_HOST: &str = "http://127.0.0.1:8080"; diff --git a/crates/refunder/src/lib.rs b/crates/refunder/src/lib.rs index d4137be8c7..910a7e2808 100644 --- a/crates/refunder/src/lib.rs +++ b/crates/refunder/src/lib.rs @@ -4,7 +4,7 @@ pub mod submitter; use { crate::arguments::Arguments, - alloy::signers::local::PrivateKeySigner, + alloy::{providers::Provider, signers::local::PrivateKeySigner}, clap::Parser, contracts::alloy::CoWSwapEthFlow, observe::metrics::LivenessChecking, diff --git a/crates/shared/src/sources/balancer_v2/pool_fetching/mod.rs b/crates/shared/src/sources/balancer_v2/pool_fetching/mod.rs index c109902be3..1edc53cf44 100644 --- a/crates/shared/src/sources/balancer_v2/pool_fetching/mod.rs +++ b/crates/shared/src/sources/balancer_v2/pool_fetching/mod.rs @@ -31,7 +31,7 @@ use { token_info::TokenInfoFetching, }, alloy::{ - eips::{BlockId, BlockNumberOrTag}, + eips::BlockNumberOrTag, primitives::{Address, B256}, providers::{DynProvider, Provider}, }, From e6907060478ff543be8c5bdb74ecbd1151af2071 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=CC=81=20Duarte?= Date: Tue, 16 Dec 2025 09:49:50 +0000 Subject: [PATCH 07/24] fix lint --- crates/driver/src/tests/setup/blockchain.rs | 3 +-- crates/driver/src/tests/setup/mod.rs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/crates/driver/src/tests/setup/blockchain.rs b/crates/driver/src/tests/setup/blockchain.rs index 385fac8679..f811904316 100644 --- a/crates/driver/src/tests/setup/blockchain.rs +++ b/crates/driver/src/tests/setup/blockchain.rs @@ -31,10 +31,9 @@ use { }, futures::Future, secp256k1::SecretKey, - serde_json::json, solvers_dto::solution::Flashloan, std::collections::HashMap, - web3::{Transport, signing::Key}, + web3::signing::Key, }; // TODO Possibly might be a good idea to use an enum for tokens instead of // &'static str diff --git a/crates/driver/src/tests/setup/mod.rs b/crates/driver/src/tests/setup/mod.rs index 80f70578e2..b485cab218 100644 --- a/crates/driver/src/tests/setup/mod.rs +++ b/crates/driver/src/tests/setup/mod.rs @@ -43,7 +43,7 @@ use { }, bigdecimal::{BigDecimal, FromPrimitive}, ethcontract::dyns::DynTransport, - ethrpc::alloy::conversions::{IntoAlloy, IntoLegacy}, + ethrpc::alloy::conversions::IntoAlloy, futures::future::join_all, hyper::StatusCode, model::order::{BuyTokenDestination, SellTokenSource}, From d34d600981eeec0ade8197a842e3dd5ed086ea7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=CC=81=20Duarte?= Date: Tue, 16 Dec 2025 13:07:44 +0000 Subject: [PATCH 08/24] Migrate the AccessList to alloy --- crates/driver/src/domain/eth/mod.rs | 98 +++++++++------ crates/driver/src/domain/mempools.rs | 8 +- crates/driver/src/infra/blockchain/mod.rs | 116 ++++++++++-------- crates/driver/src/infra/mempool/mod.rs | 99 +++++++++------ crates/driver/src/infra/simulator/enso/dto.rs | 32 +---- crates/driver/src/infra/simulator/mod.rs | 2 +- .../src/infra/simulator/tenderly/dto.rs | 33 ++--- crates/solvers-dto/Cargo.toml | 2 +- crates/solvers-dto/src/notification.rs | 6 +- 9 files changed, 206 insertions(+), 190 deletions(-) diff --git a/crates/driver/src/domain/eth/mod.rs b/crates/driver/src/domain/eth/mod.rs index 920b6812dc..079e577b99 100644 --- a/crates/driver/src/domain/eth/mod.rs +++ b/crates/driver/src/domain/eth/mod.rs @@ -1,14 +1,12 @@ use { crate::util::{Bytes, conv::u256::U256Ext}, + alloy::rpc::types::TransactionRequest, derive_more::{From, Into}, - ethrpc::alloy::conversions::{IntoAlloy, IntoLegacy}, - itertools::Itertools, solvers_dto::auction::FlashloanHint, std::{ collections::{HashMap, HashSet}, ops::{Div, Mul, Sub}, }, - web3::types::CallRequest, }; pub mod allowance; @@ -55,18 +53,46 @@ impl AccessList { } } -impl From for AccessList { - fn from(value: web3::types::AccessList) -> Self { +impl IntoIterator for AccessList { + type IntoIter = std::collections::hash_map::IntoIter>; + type Item = (Address, HashSet); + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} + +impl FromIterator<(Address, I)> for AccessList +where + I: IntoIterator, +{ + fn from_iter>(iter: T) -> Self { + Self( + iter.into_iter() + .map(|(address, i)| { + ( + address, + i.into_iter().map(StorageKey).collect::>(), + ) + }) + .collect(), + ) + } +} + +impl From for AccessList { + fn from(value: alloy::eips::eip2930::AccessList) -> Self { Self( value + .0 .into_iter() .map(|item| { ( - item.address.into_alloy(), + item.address, item.storage_keys .into_iter() - .map(|key| key.into_alloy().into()) - .collect(), + .map(StorageKey) + .collect::>(), ) }) .collect(), @@ -74,26 +100,24 @@ impl From for AccessList { } } -impl From for web3::types::AccessList { +impl From for alloy::eips::eip2930::AccessList { fn from(value: AccessList) -> Self { - value - .0 - .into_iter() - .sorted_by_key(|&(address, _)| address) - .map(|(address, storage_keys)| web3::types::AccessListItem { - address: address.into_legacy(), - storage_keys: storage_keys - .into_iter() - .sorted() - .map(|key| key.0.into_legacy()) - .collect(), - }) - .collect() + Self( + value + .into_iter() + .map( + |(address, storage_keys)| alloy::eips::eip2930::AccessListItem { + address, + storage_keys: storage_keys.into_iter().map(|k| k.0).collect(), + }, + ) + .collect(), + ) } } #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Into, From)] -struct StorageKey(pub B256); +pub struct StorageKey(pub B256); // TODO This type should probably use Ethereum::is_contract to verify during // construction that it does indeed point to a contract @@ -348,23 +372,6 @@ pub struct Tx { pub access_list: AccessList, } -impl From for CallRequest { - fn from(value: Tx) -> Self { - Self { - from: Some(value.from.into_legacy()), - to: Some(value.to.into_legacy()), - gas: None, - gas_price: None, - value: Some(value.value.0.into_legacy()), - data: Some(value.input.into()), - transaction_type: None, - access_list: Some(value.access_list.into()), - max_fee_per_gas: None, - max_priority_fee_per_gas: None, - } - } -} - impl std::fmt::Debug for Tx { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("Tx") @@ -377,6 +384,17 @@ impl std::fmt::Debug for Tx { } } +impl From for TransactionRequest { + fn from(value: Tx) -> Self { + TransactionRequest::default() + .from(value.from) + .to(value.to) + .value(value.value.0) + .input(value.input.0.into()) + .access_list(value.access_list.into()) + } +} + impl Tx { pub fn set_access_list(self, access_list: AccessList) -> Self { Self { diff --git a/crates/driver/src/domain/mempools.rs b/crates/driver/src/domain/mempools.rs index 22e961a307..0c4b5c7dd4 100644 --- a/crates/driver/src/domain/mempools.rs +++ b/crates/driver/src/domain/mempools.rs @@ -110,7 +110,7 @@ impl Mempools { // The tx is simulated before submitting the solution to the competition, but a // delay between that and the actual execution can cause the simulation to be // invalid which doesn't make sense to submit to the mempool anymore. - if let Err(err) = self.ethereum.estimate_gas(tx).await { + if let Err(err) = self.ethereum.estimate_gas(tx.clone()).await { if err.is_revert() { tracing::info!( ?err, @@ -222,7 +222,7 @@ impl Mempools { }); } // Check if transaction still simulates - if let Err(err) = self.ethereum.estimate_gas(tx).await { + if let Err(err) = self.ethereum.estimate_gas(tx.clone()).await { if err.is_revert() { tracing::info!( settle_tx_hash = ?hash, @@ -277,7 +277,7 @@ impl Mempools { mempool: &infra::mempool::Mempool, original_tx_gas_price: eth::GasPrice, solver: &Solver, - nonce: eth::U256, + nonce: u64, ) -> Result { let fallback_gas_price = original_tx_gas_price * GAS_PRICE_BUMP; let replacement_gas_price = self @@ -324,7 +324,7 @@ impl Mempools { &self, mempool: &infra::Mempool, solver: &Solver, - nonce: eth::U256, + nonce: u64, ) -> anyhow::Result> { let pending_tx = match mempool .find_pending_tx_in_mempool(solver.address(), nonce) diff --git a/crates/driver/src/infra/blockchain/mod.rs b/crates/driver/src/infra/blockchain/mod.rs index da26855ee6..93f077528d 100644 --- a/crates/driver/src/infra/blockchain/mod.rs +++ b/crates/driver/src/infra/blockchain/mod.rs @@ -3,14 +3,16 @@ use { boundary, domain::{eth, eth::U256}, }, - alloy::{providers::Provider, rpc::types::TransactionReceipt, transports::TransportErrorKind}, + alloy::{ + network::TransactionBuilder, + providers::Provider, + rpc::types::{TransactionReceipt, TransactionRequest}, + transports::TransportErrorKind, + }, + anyhow::anyhow, chain::Chain, ethcontract::errors::ExecutionError, - ethrpc::{ - Web3, - alloy::conversions::{IntoAlloy, IntoLegacy}, - block_stream::CurrentBlockWatcher, - }, + ethrpc::{Web3, alloy::conversions::IntoAlloy, block_stream::CurrentBlockWatcher}, shared::{ account_balances::{BalanceSimulator, SimulationError}, price_estimation::trade_verifier::balance_overrides::{ @@ -22,7 +24,6 @@ use { thiserror::Error, tracing::{Level, instrument}, url::Url, - web3::{Transport, types::CallRequest}, }; pub mod contracts; @@ -184,54 +185,65 @@ impl Ethereum { #[instrument(skip_all)] pub async fn create_access_list(&self, tx: T) -> Result where - CallRequest: From, + T: Into, { - let mut tx: CallRequest = tx.into(); - tx.gas = Some(self.inner.tx_gas_limit.into_legacy()); - tx.gas_price = self - .simulation_gas_price() - .await - .map(IntoLegacy::into_legacy); - - let json = self - .web3 - .transport() - .execute( - "eth_createAccessList", - vec![serde_json::to_value(&tx).unwrap(), "latest".into()], - ) - .await?; - if let Some(err) = json.get("error") { - return Err(Error::AccessList(err.to_owned())); - } - let access_list: web3::types::AccessList = - serde_json::from_value(json.get("accessList").unwrap().to_owned()).unwrap(); - Ok(access_list.into()) + let tx = tx.into(); + + let gas_limit = self.inner.tx_gas_limit.try_into().map_err(|err| { + Error::GasPrice(anyhow!("failed to convert gas_limit to u64: {err:?}")) + })?; + let tx = tx.with_gas_limit(gas_limit); + let tx = match self.simulation_gas_price().await { + Some(gas_price) => { + let gas_price = gas_price.try_into().map_err(|err| { + Error::GasPrice(anyhow!("failed to convert gas_limit to u128: {err:?}")) + })?; + + tx.with_gas_price(gas_price) + } + _ => tx, + }; + + let access_list = self.web3.alloy.create_access_list(&tx).await?; + + Ok(access_list + .ensure_ok() + .map_err(Error::AccessList)? + .access_list + .into()) } /// Estimate gas used by a transaction. - pub async fn estimate_gas(&self, tx: ð::Tx) -> Result { - self.web3 - .eth() - .estimate_gas( - web3::types::CallRequest { - from: Some(tx.from.into_legacy()), - to: Some(tx.to.into_legacy()), - value: Some(tx.value.0.into_legacy()), - data: Some(tx.input.clone().into()), - access_list: Some(tx.access_list.clone().into()), - gas_price: self - .simulation_gas_price() - .await - .map(IntoLegacy::into_legacy), - ..Default::default() - }, - None, - ) - .await - .map(IntoAlloy::into_alloy) - .map(Into::into) - .map_err(Into::into) + pub async fn estimate_gas(&self, tx: eth::Tx) -> Result { + let tx = TransactionRequest::default() + .from(tx.from) + .to(tx.to) + .value(tx.value.0) + .input(tx.input.0.into()) + .access_list(tx.access_list.into()); + + let tx = match self.simulation_gas_price().await { + Some(gas_price) => { + let gas_price = gas_price.try_into().map_err(|err| { + Error::GasPrice(anyhow!("failed to convert gas_limit to u128: {err:?}")) + })?; + + tx.with_gas_price(gas_price) + } + _ => tx, + }; + + tracing::error!("estimating gas"); + + Ok(U256::from( + self.web3 + .alloy + .estimate_gas(tx) + .await + .map_err(anyhow::Error::from) + .map_err(Error::GasPrice)?, + ) + .into()) } /// The gas price is determined based on the deadline by which the @@ -341,7 +353,7 @@ pub enum Error { #[error("gas price estimation error: {0}")] GasPrice(boundary::Error), #[error("access list estimation error: {0:?}")] - AccessList(serde_json::Value), + AccessList(String), } impl Error { diff --git a/crates/driver/src/infra/mempool/mod.rs b/crates/driver/src/infra/mempool/mod.rs index b672071d52..f832cd2c3d 100644 --- a/crates/driver/src/infra/mempool/mod.rs +++ b/crates/driver/src/infra/mempool/mod.rs @@ -4,12 +4,14 @@ use { domain::{eth, mempools}, infra, }, - alloy::{consensus::Transaction, providers::ext::TxPoolApi}, - anyhow::Context, - ethrpc::{ - Web3, - alloy::conversions::{IntoAlloy, IntoLegacy}, + alloy::{ + consensus::Transaction, + network::TransactionBuilder, + providers::{Provider, ext::TxPoolApi}, + rpc::types::TransactionRequest, }, + anyhow::Context, + ethrpc::Web3, }; #[derive(Debug, Clone)] @@ -87,15 +89,21 @@ impl Mempool { /// Fetches the transaction count (nonce) for the given address at the /// specified block number. If no block number is provided in the config, /// uses the web3 lib's default behavior. - pub async fn get_nonce(&self, address: eth::Address) -> Result { - self.transport - .eth() - .transaction_count(address.into_legacy(), self.config.nonce_block_number) - .await - .map(IntoAlloy::into_alloy) - .map_err(|err| { - mempools::Error::Other(anyhow::Error::from(err).context("failed to fetch nonce")) - }) + pub async fn get_nonce(&self, address: eth::Address) -> Result { + let call = self.transport.alloy.get_transaction_count(address); + match self.config.nonce_block_number { + Some(ethcontract::BlockNumber::Latest) => call.latest(), + Some(ethcontract::BlockNumber::Earliest) => call.earliest(), + Some(ethcontract::BlockNumber::Finalized) => call.finalized(), + Some(ethcontract::BlockNumber::Number(number)) => call.number(number.as_u64()), + Some(ethcontract::BlockNumber::Pending) => call.pending(), + Some(ethcontract::BlockNumber::Safe) => call.safe(), + None => call, + } + .await + .map_err(|err| { + mempools::Error::Other(anyhow::Error::from(err).context("failed to fetch nonce")) + }) } /// Submits a transaction to the mempool. Returns optimistically as soon as @@ -106,26 +114,45 @@ impl Mempool { gas_price: eth::GasPrice, gas_limit: eth::Gas, solver: &infra::Solver, - nonce: eth::U256, + nonce: u64, ) -> Result { - let submission = - ethcontract::transaction::TransactionBuilder::new(self.transport.legacy.clone()) - .from(solver.account().clone()) - .to(tx.to.into_legacy()) - .nonce(nonce.into_legacy()) - .gas_price(ethcontract::GasPrice::Eip1559 { - max_fee_per_gas: gas_price.max().0.0.into_legacy(), - max_priority_fee_per_gas: gas_price.tip().0.0.into_legacy(), - }) - .data(tx.input.into()) - .value(tx.value.0.into_legacy()) - .gas(gas_limit.0.into_legacy()) - .access_list(web3::types::AccessList::from(tx.access_list)) - .resolve(ethcontract::transaction::ResolveCondition::Pending) - .send() - .await; - - match submission { + let max_fee_per_gas = gas_price + .max() + .0 + .0 + .try_into() + .map_err(anyhow::Error::from)?; + let max_priority_fee_per_gas = gas_price + .tip() + .0 + .0 + .try_into() + .map_err(anyhow::Error::from)?; + let gas_limit = gas_limit.0.try_into().map_err(anyhow::Error::from)?; + + let tx = TransactionRequest::default() + .from(solver.address()) + .to(tx.to) + .nonce(nonce) + .max_fee_per_gas(max_fee_per_gas) + .max_priority_fee_per_gas(max_priority_fee_per_gas) + .input(tx.input.0.into()) + .value(tx.value.0) + .gas_limit(gas_limit) + .access_list(tx.access_list.into()) + .build(&self.transport.wallet) + .await + .map_err(anyhow::Error::from)?; + + let submission_result = self + .transport + .alloy + .send_tx_envelope(tx) + .await + .map_err(anyhow::Error::from)? + .get_receipt() + .await; + match submission_result { Ok(receipt) => { tracing::debug!( ?nonce, @@ -134,7 +161,7 @@ impl Mempool { solver = ?solver.address(), "successfully submitted tx to mempool" ); - Ok(eth::TxId(receipt.hash().into_alloy())) + Ok(eth::TxId(receipt.transaction_hash)) } Err(err) => { // log pending tx in case we failed to replace a pending tx @@ -161,7 +188,7 @@ impl Mempool { pub async fn find_pending_tx_in_mempool( &self, signer: eth::Address, - nonce: eth::U256, + nonce: u64, ) -> anyhow::Result> { let tx_pool_content = self .transport @@ -175,7 +202,7 @@ impl Mempool { .pending .into_iter() .chain(tx_pool_content.queued) - .find(|(_signer, tx)| eth::U256::from(tx.nonce()) == nonce) + .find(|(_signer, tx)| tx.nonce() == nonce) .map(|(_, tx)| tx); Ok(pending_tx) } diff --git a/crates/driver/src/infra/simulator/enso/dto.rs b/crates/driver/src/infra/simulator/enso/dto.rs index 982ab31ba4..141390a089 100644 --- a/crates/driver/src/infra/simulator/enso/dto.rs +++ b/crates/driver/src/infra/simulator/enso/dto.rs @@ -2,7 +2,7 @@ use { crate::{domain::eth, util::serialize}, - ethrpc::alloy::conversions::IntoAlloy, + alloy::rpc::types::AccessList, serde::{Deserialize, Serialize}, serde_with::serde_as, }; @@ -26,36 +26,6 @@ pub struct Request { pub access_list: Option, } -#[derive(Debug, Serialize)] -#[serde(transparent)] -pub struct AccessList(Vec); - -impl From for AccessList { - fn from(value: eth::AccessList) -> Self { - Self( - web3::types::AccessList::from(value) - .into_iter() - .map(|item| AccessListItem { - address: item.address.into_alloy(), - storage_keys: item - .storage_keys - .into_iter() - .map(IntoAlloy::into_alloy) - .collect(), - }) - .collect(), - ) - } -} - -#[serde_as] -#[derive(Debug, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct AccessListItem { - pub address: eth::Address, - pub storage_keys: Vec, -} - #[serde_as] #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] diff --git a/crates/driver/src/infra/simulator/mod.rs b/crates/driver/src/infra/simulator/mod.rs index 8fa919f31e..137aede036 100644 --- a/crates/driver/src/infra/simulator/mod.rs +++ b/crates/driver/src/infra/simulator/mod.rs @@ -125,7 +125,7 @@ impl Simulator { } Inner::Ethereum => self .eth - .estimate_gas(tx) + .estimate_gas(tx.clone()) .await .map_err(with(tx.clone(), block))?, Inner::Enso(enso) => enso diff --git a/crates/driver/src/infra/simulator/tenderly/dto.rs b/crates/driver/src/infra/simulator/tenderly/dto.rs index 9d97321137..4e8f70ffa8 100644 --- a/crates/driver/src/infra/simulator/tenderly/dto.rs +++ b/crates/driver/src/infra/simulator/tenderly/dto.rs @@ -2,8 +2,6 @@ use { crate::{domain::eth, util::serialize}, - ethrpc::alloy::conversions::{IntoAlloy, IntoLegacy}, - itertools::Itertools, serde::{Deserialize, Serialize}, serde_with::serde_as, }; @@ -54,15 +52,11 @@ struct AccessListItem { impl From for AccessList { fn from(value: eth::AccessList) -> Self { Self( - web3::types::AccessList::from(value) + value .into_iter() - .map(|item| AccessListItem { - address: item.address.into_alloy(), - storage_keys: item - .storage_keys - .into_iter() - .map(IntoAlloy::into_alloy) - .collect(), + .map(|(address, storage_keys)| AccessListItem { + address, + storage_keys: storage_keys.into_iter().map(|k| k.0).collect(), }) .collect(), ) @@ -71,19 +65,12 @@ impl From for AccessList { impl From for eth::AccessList { fn from(value: AccessList) -> Self { - value - .0 - .into_iter() - .map(|item| web3::types::AccessListItem { - address: item.address.into_legacy(), - storage_keys: item - .storage_keys - .into_iter() - .map(IntoLegacy::into_legacy) - .collect(), - }) - .collect_vec() - .into() + Self::from_iter( + value + .0 + .into_iter() + .map(|item| (item.address, item.storage_keys)), + ) } } diff --git a/crates/solvers-dto/Cargo.toml b/crates/solvers-dto/Cargo.toml index 7dbd01af6e..071cb5b452 100644 --- a/crates/solvers-dto/Cargo.toml +++ b/crates/solvers-dto/Cargo.toml @@ -6,7 +6,7 @@ edition = "2024" license = "MIT OR Apache-2.0" [dependencies] -alloy = {workspace = true} +alloy = {workspace = true, features = ["rpc"]} app-data = { workspace = true } bigdecimal = { workspace = true, features = ["serde"] } bytes-hex = { workspace = true } # may get marked as unused but it's used with serde diff --git a/crates/solvers-dto/src/notification.rs b/crates/solvers-dto/src/notification.rs index 5676f07494..b63e2a8fa4 100644 --- a/crates/solvers-dto/src/notification.rs +++ b/crates/solvers-dto/src/notification.rs @@ -1,12 +1,14 @@ use { super::serialize, - alloy::primitives::{Address, B256, U256}, + alloy::{ + primitives::{Address, B256, U256}, + rpc::types::AccessList, + }, chrono::{DateTime, Utc}, number::serialization::HexOrDecimalU256, serde::{Deserialize, Serialize}, serde_with::{DisplayFromStr, serde_as}, std::collections::BTreeSet, - web3::types::AccessList, }; #[serde_as] From 10c97359dd26fb44dba6557a11d954bc28ede7da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=CC=81=20Duarte?= Date: Wed, 17 Dec 2025 09:59:15 +0000 Subject: [PATCH 09/24] wip --- .../src/infra/persistence/dto/order.rs | 8 +-- crates/cow-amm/src/amm.rs | 2 +- crates/cow-amm/src/lib.rs | 4 +- crates/driver/src/tests/boundary.rs | 7 +- crates/driver/src/tests/setup/blockchain.rs | 21 +++--- .../e2e/src/setup/onchain_components/mod.rs | 5 +- crates/e2e/src/setup/solver/solution.rs | 5 +- crates/e2e/tests/e2e/app_data.rs | 7 +- crates/e2e/tests/e2e/app_data_signer.rs | 6 +- crates/e2e/tests/e2e/autopilot_leader.rs | 5 +- crates/e2e/tests/e2e/buffers.rs | 8 +-- crates/e2e/tests/e2e/cow_amm.rs | 9 ++- crates/e2e/tests/e2e/eth_integration.rs | 8 +-- crates/e2e/tests/e2e/ethflow.rs | 17 ++--- crates/e2e/tests/e2e/hooks.rs | 10 ++- crates/e2e/tests/e2e/jit_orders.rs | 8 +-- crates/e2e/tests/e2e/limit_orders.rs | 33 +++++----- crates/e2e/tests/e2e/liquidity.rs | 5 +- .../e2e/liquidity_source_notification.rs | 4 +- crates/e2e/tests/e2e/order_cancellation.rs | 10 ++- crates/e2e/tests/e2e/partial_fill.rs | 6 +- .../tests/e2e/partially_fillable_balance.rs | 6 +- .../e2e/tests/e2e/partially_fillable_pool.rs | 6 +- .../e2e/tests/e2e/place_order_with_quote.rs | 6 +- crates/e2e/tests/e2e/protocol_fee.rs | 16 ++--- crates/e2e/tests/e2e/quoting.rs | 5 +- crates/e2e/tests/e2e/replace_order.rs | 16 ++--- crates/e2e/tests/e2e/solver_competition.rs | 14 ++-- .../tests/e2e/solver_participation_guard.rs | 9 +-- crates/e2e/tests/e2e/submission.rs | 5 +- .../tests/e2e/tracking_insufficient_funds.rs | 7 +- crates/e2e/tests/e2e/uncovered_order.rs | 5 +- crates/e2e/tests/e2e/univ2.rs | 6 +- crates/e2e/tests/e2e/vault_balances.rs | 5 +- crates/e2e/tests/e2e/wrapper.rs | 5 +- crates/model/Cargo.toml | 2 +- crates/model/src/order.rs | 44 +++++-------- crates/model/src/signature.rs | 66 ++++++++++++------- crates/orderbook/src/api/cancel_order.rs | 11 +--- crates/shared/src/order_validation.rs | 18 ++--- crates/shared/src/zeroex_api.rs | 28 ++++---- 41 files changed, 216 insertions(+), 252 deletions(-) diff --git a/crates/autopilot/src/infra/persistence/dto/order.rs b/crates/autopilot/src/infra/persistence/dto/order.rs index 5a68c45482..64c00e61e4 100644 --- a/crates/autopilot/src/infra/persistence/dto/order.rs +++ b/crates/autopilot/src/infra/persistence/dto/order.rs @@ -238,8 +238,8 @@ impl From for domain::auction::order::Signature { impl From for boundary::EcdsaSignature { fn from(signature: domain::auction::order::EcdsaSignature) -> Self { Self { - r: signature.r.0.into(), - s: signature.s.0.into(), + r: signature.r, + s: signature.s, v: signature.v, } } @@ -248,8 +248,8 @@ impl From for boundary::EcdsaSignature { impl From for domain::auction::order::EcdsaSignature { fn from(signature: boundary::EcdsaSignature) -> Self { Self { - r: signature.r.0.into(), - s: signature.s.0.into(), + r: signature.r, + s: signature.s, v: signature.v, } } diff --git a/crates/cow-amm/src/amm.rs b/crates/cow-amm/src/amm.rs index 48685db1f5..0bd42aa195 100644 --- a/crates/cow-amm/src/amm.rs +++ b/crates/cow-amm/src/amm.rs @@ -72,7 +72,7 @@ impl Amm { validator .validate_signature_and_get_additional_gas(SignatureCheck { signer: self.address, - hash, + hash: hash.0, signature: template.signature.to_bytes(), interactions: template.pre_interactions.clone(), balance_override: None, diff --git a/crates/cow-amm/src/lib.rs b/crates/cow-amm/src/lib.rs index f494451017..31925d167c 100644 --- a/crates/cow-amm/src/lib.rs +++ b/crates/cow-amm/src/lib.rs @@ -33,7 +33,7 @@ impl Metrics { pub mod gpv2_order { use { alloy::{ - primitives::{B256, FixedBytes, Keccak256}, + primitives::{B256, Keccak256}, sol_types::{SolStruct, SolValue}, }, contracts::alloy::cow_amm::CowAmm, @@ -98,7 +98,7 @@ pub mod gpv2_order { ) -> InteractionData { let order_hash = eip712_hash_struct(order); let order_hash = hashed_eip712_message(domain_separator, &order_hash); - let calldata = amm.commit(FixedBytes(order_hash)).calldata().clone(); + let calldata = amm.commit(order_hash).calldata().clone(); InteractionData { target: *amm.address(), diff --git a/crates/driver/src/tests/boundary.rs b/crates/driver/src/tests/boundary.rs index 6fec7922b2..44dafaa3de 100644 --- a/crates/driver/src/tests/boundary.rs +++ b/crates/driver/src/tests/boundary.rs @@ -3,9 +3,8 @@ pub use model::{DomainSeparator, order::OrderUid}; use { crate::domain::competition, + alloy::signers::local::PrivateKeySigner, ethrpc::alloy::conversions::IntoAlloy, - secp256k1::SecretKey, - web3::signing::SecretKeyRef, }; /// Order data used for calculating the order UID and signing. @@ -19,7 +18,7 @@ pub struct Order { pub receiver: Option, pub user_fee: ethcontract::U256, pub side: competition::order::Side, - pub secret_key: SecretKey, + pub secret_key: PrivateKeySigner, pub domain_separator: DomainSeparator, pub owner: ethcontract::H160, pub partially_fillable: bool, @@ -53,7 +52,7 @@ impl Order { .sign_with( model::signature::EcdsaSigningScheme::Eip712, &self.domain_separator, - SecretKeyRef::new(&self.secret_key), + &self.secret_key, ) .build() } diff --git a/crates/driver/src/tests/setup/blockchain.rs b/crates/driver/src/tests/setup/blockchain.rs index f811904316..e01ca6186f 100644 --- a/crates/driver/src/tests/setup/blockchain.rs +++ b/crates/driver/src/tests/setup/blockchain.rs @@ -206,7 +206,7 @@ impl QuotedOrder { receiver: self.order.receiver.map(IntoLegacy::into_legacy), user_fee: self.order.fee_amount.into_legacy(), side: self.order.side, - secret_key, + secret_key: PrivateKeySigner::from_bytes((&secret_key.secret_bytes()).into()).unwrap(), domain_separator: blockchain.domain_separator, owner: (&secret_key).address(), partially_fillable: matches!(self.order.partial, Partial::Yes { .. }), @@ -761,22 +761,21 @@ impl Blockchain { let pair = self.find_pair(order); let execution = self.execution(order); + // Register the trader account as a signer + let trader_private_key_signer = + PrivateKeySigner::from_bytes(self.trader_secret_key.as_ref().into()).unwrap(); + let trader_address = trader_private_key_signer.address(); + self.web3.wallet.register_signer(trader_private_key_signer); + // Fund the trader account with tokens needed for the solution. - let trader_account = ethcontract::Account::Offline( - ethcontract::PrivateKey::from_slice(self.trader_secret_key.as_ref()).unwrap(), - None, - ); if order.sell_token == "WETH" { todo!("deposit trader funds into the weth contract, none of the tests do this yet") } else if order.funded { self.tokens .get(order.sell_token) .unwrap() - .mint( - trader_account.address().into_alloy(), - "1e-7".ether().into_wei() * execution.sell, - ) - .from(trader_account.address().into_alloy()) + .mint(trader_address, "1e-7".ether().into_wei() * execution.sell) + .from(trader_address) .send_and_watch() .await .unwrap(); @@ -789,7 +788,7 @@ impl Blockchain { .get(order.sell_token) .unwrap() .approve(vault_relayer, U256::MAX) - .from(trader_account.address().into_alloy()) + .from(trader_address) .send_and_watch() .await .unwrap(); diff --git a/crates/e2e/src/setup/onchain_components/mod.rs b/crates/e2e/src/setup/onchain_components/mod.rs index c8eeba30f8..da909e0cee 100644 --- a/crates/e2e/src/setup/onchain_components/mod.rs +++ b/crates/e2e/src/setup/onchain_components/mod.rs @@ -28,10 +28,9 @@ use { signature::{EcdsaSignature, EcdsaSigningScheme}, }, number::units::EthUnit, - secp256k1::SecretKey, shared::ethrpc::Web3, std::{borrow::BorrowMut, ops::Deref}, - web3::signing::{self, SecretKeyRef}, + web3::signing::{self}, }; pub mod alloy; @@ -65,7 +64,7 @@ impl TestAccount { EcdsaSigningScheme::Eip712, domain_separator, struct_hash, - SecretKeyRef::from(&SecretKey::from_slice(self.private_key()).unwrap()), + &PrivateKeySigner::from_slice(self.private_key()).unwrap(), ) } diff --git a/crates/e2e/src/setup/solver/solution.rs b/crates/e2e/src/setup/solver/solution.rs index 134dd1c41b..f6ce6f34d0 100644 --- a/crates/e2e/src/setup/solver/solution.rs +++ b/crates/e2e/src/setup/solver/solution.rs @@ -1,5 +1,5 @@ use { - alloy::primitives::Address, + alloy::{primitives::Address, signers::local::PrivateKeySigner}, app_data::AppDataHash, model::{ DomainSeparator, @@ -7,7 +7,6 @@ use { signature::EcdsaSigningScheme, }, solvers_dto::solution::{Asset, Kind}, - web3::signing::SecretKeyRef, }; #[derive(Clone, Debug)] @@ -44,7 +43,7 @@ impl JitOrder { self, signing_scheme: EcdsaSigningScheme, domain: &DomainSeparator, - key: SecretKeyRef, + key: &PrivateKeySigner, ) -> (solvers_dto::solution::JitOrder, OrderUid) { let data = self.data(); let signature = model::signature::EcdsaSignature::sign( diff --git a/crates/e2e/tests/e2e/app_data.rs b/crates/e2e/tests/e2e/app_data.rs index effb34dbae..bfdea2c534 100644 --- a/crates/e2e/tests/e2e/app_data.rs +++ b/crates/e2e/tests/e2e/app_data.rs @@ -1,4 +1,5 @@ use { + ::alloy::signers::local::PrivateKeySigner, app_data::{AppDataHash, hash_full_app_data}, e2e::setup::*, ethrpc::alloy::{ @@ -12,10 +13,8 @@ use { }, number::units::EthUnit, reqwest::StatusCode, - secp256k1::SecretKey, shared::ethrpc::Web3, std::str::FromStr, - web3::signing::SecretKeyRef, }; #[tokio::test] @@ -66,7 +65,7 @@ async fn app_data(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); // Adjust valid to make sure we get unique UIDs. valid_to += 1; @@ -231,7 +230,7 @@ async fn app_data_full_format(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); // Adjust valid to make sure we get unique UIDs. valid_to += 1; diff --git a/crates/e2e/tests/e2e/app_data_signer.rs b/crates/e2e/tests/e2e/app_data_signer.rs index 1645ee1e02..7e561ed75f 100644 --- a/crates/e2e/tests/e2e/app_data_signer.rs +++ b/crates/e2e/tests/e2e/app_data_signer.rs @@ -1,5 +1,5 @@ use { - alloy::primitives::Address, + alloy::{primitives::Address, signers::local::PrivateKeySigner}, e2e::setup::{OnchainComponents, Services, TestAccount, run_test, safe::Safe}, ethrpc::alloy::{ CallBuilderExt, @@ -10,9 +10,7 @@ use { signature::EcdsaSigningScheme, }, number::units::EthUnit, - secp256k1::SecretKey, shared::ethrpc::Web3, - web3::signing::SecretKeyRef, }; #[tokio::test] @@ -69,7 +67,7 @@ async fn order_creation_checks_metadata_signer(web3: Web3) { order_creation.sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(signer.private_key()).unwrap()), + &PrivateKeySigner::from_slice(signer.private_key()).unwrap(), ) }; diff --git a/crates/e2e/tests/e2e/autopilot_leader.rs b/crates/e2e/tests/e2e/autopilot_leader.rs index 167c175c4d..9a0bb88b0b 100644 --- a/crates/e2e/tests/e2e/autopilot_leader.rs +++ b/crates/e2e/tests/e2e/autopilot_leader.rs @@ -1,4 +1,5 @@ use { + alloy::signers::local::PrivateKeySigner, autopilot::shutdown_controller::ShutdownController, e2e::setup::{OnchainComponents, Services, TIMEOUT, colocation, run_test, wait_for_condition}, ethrpc::{ @@ -10,9 +11,7 @@ use { }, model::order::{OrderCreation, OrderKind}, number::units::EthUnit, - secp256k1::SecretKey, std::time::Duration, - web3::signing::SecretKeyRef, }; #[tokio::test] @@ -118,7 +117,7 @@ async fn dual_autopilot_only_leader_produces_auctions(web3: Web3) { .sign( model::signature::EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ) }; diff --git a/crates/e2e/tests/e2e/buffers.rs b/crates/e2e/tests/e2e/buffers.rs index ce783c6131..9fa6f4b19c 100644 --- a/crates/e2e/tests/e2e/buffers.rs +++ b/crates/e2e/tests/e2e/buffers.rs @@ -1,5 +1,5 @@ use { - ::alloy::primitives::U256, + ::alloy::{primitives::U256, signers::local::PrivateKeySigner}, e2e::setup::*, ethrpc::alloy::{ CallBuilderExt, @@ -10,9 +10,7 @@ use { signature::EcdsaSigningScheme, }, number::units::EthUnit, - secp256k1::SecretKey, shared::ethrpc::Web3, - web3::signing::SecretKeyRef, }; #[tokio::test] @@ -106,7 +104,7 @@ async fn onchain_settlement_without_liquidity(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); services.create_order(&order).await.unwrap(); @@ -133,7 +131,7 @@ async fn onchain_settlement_without_liquidity(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); services.create_order(&order).await.unwrap(); diff --git a/crates/e2e/tests/e2e/cow_amm.rs b/crates/e2e/tests/e2e/cow_amm.rs index 6d31aeb089..afa785b458 100644 --- a/crates/e2e/tests/e2e/cow_amm.rs +++ b/crates/e2e/tests/e2e/cow_amm.rs @@ -5,6 +5,7 @@ use { Provider, ext::{AnvilApi, ImpersonateConfig}, }, + signers::local::PrivateKeySigner, }, contracts::alloy::{ ERC20, @@ -32,7 +33,6 @@ use { signature::EcdsaSigningScheme, }, number::units::EthUnit, - secp256k1::SecretKey, shared::ethrpc::Web3, solvers_dto::solution::{ BuyTokenBalance, @@ -43,7 +43,6 @@ use { Solution, }, std::collections::{HashMap, HashSet}, - web3::signing::SecretKeyRef, }; #[tokio::test] @@ -307,7 +306,7 @@ async fn cow_amm_jit(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(bob.private_key()).unwrap()), + &PrivateKeySigner::from_slice(bob.private_key()).unwrap(), ); let user_order_id = services.create_order(&user_order).await.unwrap(); @@ -596,7 +595,7 @@ factory = "0xf76c421bAb7df8548604E60deCCcE50477C10462" .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); // Warm up co-located driver by quoting the order (otherwise placing an order @@ -1029,7 +1028,7 @@ async fn cow_amm_opposite_direction(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(bob.private_key()).unwrap()), + &PrivateKeySigner::from_slice(bob.private_key()).unwrap(), ); let user_order_id = services.create_order(&user_order).await.unwrap(); diff --git a/crates/e2e/tests/e2e/eth_integration.rs b/crates/e2e/tests/e2e/eth_integration.rs index 44d98e750e..93434a0adc 100644 --- a/crates/e2e/tests/e2e/eth_integration.rs +++ b/crates/e2e/tests/e2e/eth_integration.rs @@ -1,5 +1,5 @@ use { - ::alloy::providers::Provider, + ::alloy::{providers::Provider, signers::local::PrivateKeySigner}, e2e::setup::*, ethcontract::prelude::Address, ethrpc::alloy::{ @@ -12,9 +12,7 @@ use { signature::EcdsaSigningScheme, }, number::{nonzero::NonZeroU256, units::EthUnit}, - secp256k1::SecretKey, shared::ethrpc::Web3, - web3::signing::SecretKeyRef, }; #[tokio::test] @@ -96,7 +94,7 @@ async fn eth_integration(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader_a.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader_a.private_key()).unwrap(), ); services.create_order(&order_buy_eth_a).await.unwrap(); let order_buy_eth_b = OrderCreation { @@ -111,7 +109,7 @@ async fn eth_integration(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader_b.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader_b.private_key()).unwrap(), ); services.create_order(&order_buy_eth_b).await.unwrap(); diff --git a/crates/e2e/tests/e2e/ethflow.rs b/crates/e2e/tests/e2e/ethflow.rs index 2258aabaf8..47379f5ce2 100644 --- a/crates/e2e/tests/e2e/ethflow.rs +++ b/crates/e2e/tests/e2e/ethflow.rs @@ -1,6 +1,6 @@ use { alloy::{ - primitives::{Address, Bytes, U256}, + primitives::{Address, B256, Bytes, U256}, rpc::types::TransactionReceipt, }, anyhow::bail, @@ -19,7 +19,7 @@ use { run_test, wait_for_condition, }, - ethcontract::{Account, H160, H256}, + ethcontract::{Account, H160}, ethrpc::{ Web3, alloy::{ @@ -711,7 +711,7 @@ impl ExtendedEthFlowOrder { ethflow_contract: &CoWSwapEthFlow::Instance, ) -> EthFlowOrderOnchainStatus { ethflow_contract - .orders(self.hash(contracts, ethflow_contract).await.0.into()) + .orders(self.hash(contracts, ethflow_contract).await) .call() .await .expect("Couldn't fetch order status") @@ -735,10 +735,7 @@ impl ExtendedEthFlowOrder { let result = ethflow_contract .isValidSignature( - self.hash(contracts, ethflow_contract) - .await - .to_fixed_bytes() - .into(), + self.hash(contracts, ethflow_contract).await, Bytes::from(bytes), ) .call() @@ -783,7 +780,7 @@ impl ExtendedEthFlowOrder { &self, contracts: &Contracts, ethflow_contract: &CoWSwapEthFlow::Instance, - ) -> H256 { + ) -> B256 { let domain_separator = DomainSeparator( contracts .gp_settlement @@ -793,13 +790,13 @@ impl ExtendedEthFlowOrder { .expect("Couldn't query domain separator") .0, ); - H256(hashed_eip712_message( + hashed_eip712_message( &domain_separator, &self .to_cow_swap_order(ethflow_contract, &contracts.weth) .data .hash_struct(), - )) + ) } pub async fn uid( diff --git a/crates/e2e/tests/e2e/hooks.rs b/crates/e2e/tests/e2e/hooks.rs index 289c3866ac..510bac73ea 100644 --- a/crates/e2e/tests/e2e/hooks.rs +++ b/crates/e2e/tests/e2e/hooks.rs @@ -1,5 +1,5 @@ use { - alloy::providers::Provider, + alloy::{providers::Provider, signers::local::PrivateKeySigner}, app_data::Hook, e2e::setup::{ OnchainComponents, @@ -21,10 +21,8 @@ use { }, number::{nonzero::NonZeroU256, units::EthUnit}, reqwest::StatusCode, - secp256k1::SecretKey, serde_json::json, shared::ethrpc::Web3, - web3::signing::SecretKeyRef, }; #[tokio::test] @@ -108,7 +106,7 @@ async fn gas_limit(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); let error = services.create_order(&order).await.unwrap_err(); assert_eq!(error.0, StatusCode::BAD_REQUEST); @@ -189,7 +187,7 @@ async fn allowance(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); services.create_order(&order).await.unwrap(); onchain.mint_block().await; @@ -500,7 +498,7 @@ async fn partial_fills(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); services.create_order(&order).await.unwrap(); onchain.mint_block().await; diff --git a/crates/e2e/tests/e2e/jit_orders.rs b/crates/e2e/tests/e2e/jit_orders.rs index 5e5506b752..fe2e26192a 100644 --- a/crates/e2e/tests/e2e/jit_orders.rs +++ b/crates/e2e/tests/e2e/jit_orders.rs @@ -1,5 +1,5 @@ use { - ::alloy::primitives::U256, + ::alloy::{primitives::U256, signers::local::PrivateKeySigner}, e2e::setup::{colocation::SolverEngine, mock::Mock, solution::JitOrder, *}, ethrpc::alloy::{ CallBuilderExt, @@ -10,11 +10,9 @@ use { signature::EcdsaSigningScheme, }, number::units::EthUnit, - secp256k1::SecretKey, shared::ethrpc::Web3, solvers_dto::solution::{Asset, Solution}, std::collections::HashMap, - web3::signing::SecretKeyRef, }; #[tokio::test] @@ -126,7 +124,7 @@ async fn single_limit_order_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); let trader_balance_before = token.balanceOf(trader.address()).call().await.unwrap(); @@ -155,7 +153,7 @@ async fn single_limit_order_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(solver.private_key()).unwrap()), + &PrivateKeySigner::from_slice(solver.private_key()).unwrap(), ); mock_solver.configure_solution(Some(Solution { diff --git a/crates/e2e/tests/e2e/limit_orders.rs b/crates/e2e/tests/e2e/limit_orders.rs index 2d0810c157..62dc540a93 100644 --- a/crates/e2e/tests/e2e/limit_orders.rs +++ b/crates/e2e/tests/e2e/limit_orders.rs @@ -3,6 +3,7 @@ use { ::alloy::{ primitives::{Address, U256, address}, providers::ext::{AnvilApi, ImpersonateConfig}, + signers::local::PrivateKeySigner, }, bigdecimal::BigDecimal, contracts::alloy::ERC20, @@ -20,10 +21,8 @@ use { signature::EcdsaSigningScheme, }, number::{conversions::big_decimal_to_big_uint, units::EthUnit}, - secp256k1::SecretKey, shared::ethrpc::Web3, std::{collections::HashMap, ops::DerefMut}, - web3::signing::SecretKeyRef, }; #[tokio::test] @@ -183,7 +182,7 @@ async fn single_limit_order_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader_a.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader_a.private_key()).unwrap(), ); let balance_before = token_b.balanceOf(trader_a.address()).call().await.unwrap(); let order_id = services.create_order(&order).await.unwrap(); @@ -315,7 +314,7 @@ async fn two_limit_orders_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader_a.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader_a.private_key()).unwrap(), ); let balance_before_a = token_b.balanceOf(trader_a.address()).call().await.unwrap(); @@ -339,7 +338,7 @@ async fn two_limit_orders_test(web3: Web3) { .sign( EcdsaSigningScheme::EthSign, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader_b.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader_b.private_key()).unwrap(), ); let order_id = services.create_order(&order_b).await.unwrap(); @@ -455,7 +454,7 @@ async fn two_limit_orders_multiple_winners_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader_a.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader_a.private_key()).unwrap(), ); let uid_a = services.create_order(&order_a).await.unwrap(); @@ -471,7 +470,7 @@ async fn two_limit_orders_multiple_winners_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader_b.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader_b.private_key()).unwrap(), ); let uid_b = services.create_order(&order_b).await.unwrap(); @@ -666,7 +665,7 @@ async fn too_many_limit_orders_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); services.create_order(&order).await.unwrap(); @@ -684,7 +683,7 @@ async fn too_many_limit_orders_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); let (status, body) = services.create_order(&order).await.unwrap_err(); @@ -765,7 +764,7 @@ async fn limit_does_not_apply_to_in_market_orders_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); assert!(services.create_order(&order).await.is_ok()); @@ -782,7 +781,7 @@ async fn limit_does_not_apply_to_in_market_orders_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); let order_id = services.create_order(&order).await.unwrap(); let limit_order = services.get_order(&order_id).await.unwrap(); @@ -801,7 +800,7 @@ async fn limit_does_not_apply_to_in_market_orders_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); assert!(services.create_order(&order).await.is_ok()); @@ -818,7 +817,7 @@ async fn limit_does_not_apply_to_in_market_orders_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); let (status, body) = services.create_order(&order).await.unwrap_err(); @@ -887,7 +886,7 @@ async fn forked_mainnet_single_limit_order_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); // Warm up co-located driver by quoting the order (otherwise placing an order @@ -985,7 +984,7 @@ async fn forked_gnosis_single_limit_order_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); let sell_token_balance_before = token_usdc.balanceOf(trader.address()).call().await.unwrap(); let buy_token_balance_before = token_wxdai @@ -1084,7 +1083,7 @@ async fn no_liquidity_limit_order(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader_a.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader_a.private_key()).unwrap(), ); let order_id = services.create_order(&order).await.unwrap(); onchain.mint_block().await; @@ -1097,7 +1096,7 @@ async fn no_liquidity_limit_order(web3: Web3) { .create_order(&order.sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader_a.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader_a.private_key()).unwrap(), )) .await .unwrap_err(); diff --git a/crates/e2e/tests/e2e/liquidity.rs b/crates/e2e/tests/e2e/liquidity.rs index c16c736312..018f120dfa 100644 --- a/crates/e2e/tests/e2e/liquidity.rs +++ b/crates/e2e/tests/e2e/liquidity.rs @@ -5,6 +5,7 @@ use { Provider, ext::{AnvilApi, ImpersonateConfig}, }, + signers::local::PrivateKeySigner, }, chrono::{NaiveDateTime, Utc}, contracts::alloy::{ERC20, IZeroex}, @@ -35,8 +36,6 @@ use { signature::EcdsaSigningScheme, }, number::units::EthUnit, - secp256k1::SecretKey, - web3::signing::SecretKeyRef, }; /// The block number from which we will fetch state for the forked tests. @@ -169,7 +168,7 @@ async fn zero_ex_liquidity(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); let chain_id = web3.alloy.get_chain_id().await.unwrap(); diff --git a/crates/e2e/tests/e2e/liquidity_source_notification.rs b/crates/e2e/tests/e2e/liquidity_source_notification.rs index 1c31e0e2e5..b7f447ec24 100644 --- a/crates/e2e/tests/e2e/liquidity_source_notification.rs +++ b/crates/e2e/tests/e2e/liquidity_source_notification.rs @@ -31,10 +31,8 @@ use { signature::EcdsaSigningScheme, }, number::units::EthUnit, - secp256k1::SecretKey, solvers_dto::solution::Solution, std::collections::HashMap, - web3::signing::SecretKeyRef, }; /// The block number from which we will fetch state for the forked tests. @@ -245,7 +243,7 @@ http-timeout = "10s" .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); services.create_order(&order).await.unwrap() }; diff --git a/crates/e2e/tests/e2e/order_cancellation.rs b/crates/e2e/tests/e2e/order_cancellation.rs index b21409b48d..07509aaf60 100644 --- a/crates/e2e/tests/e2e/order_cancellation.rs +++ b/crates/e2e/tests/e2e/order_cancellation.rs @@ -1,5 +1,5 @@ use { - ::alloy::primitives::U256, + ::alloy::{primitives::U256, signers::local::PrivateKeySigner}, database::order_events::OrderEventLabel, e2e::setup::*, ethrpc::alloy::{ @@ -21,10 +21,8 @@ use { signature::{EcdsaSignature, EcdsaSigningScheme}, }, number::{nonzero::NonZeroU256, units::EthUnit}, - secp256k1::SecretKey, serde_json::json, shared::ethrpc::Web3, - web3::signing::SecretKeyRef, }; #[tokio::test] @@ -126,7 +124,7 @@ async fn order_cancellation(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); services.create_order(&order).await.unwrap() } @@ -137,7 +135,7 @@ async fn order_cancellation(web3: Web3) { let cancellation = OrderCancellation::for_order( order_uid, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); async move { @@ -163,7 +161,7 @@ async fn order_cancellation(web3: Web3) { EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, &cancellations.hash_struct(), - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); let signed_cancellations = SignedOrderCancellations { diff --git a/crates/e2e/tests/e2e/partial_fill.rs b/crates/e2e/tests/e2e/partial_fill.rs index 627da48fd0..f4cd65c708 100644 --- a/crates/e2e/tests/e2e/partial_fill.rs +++ b/crates/e2e/tests/e2e/partial_fill.rs @@ -1,5 +1,5 @@ use { - ::alloy::primitives::U256, + ::alloy::{primitives::U256, signers::local::PrivateKeySigner}, e2e::setup::*, ethrpc::alloy::{ CallBuilderExt, @@ -11,9 +11,7 @@ use { }, number::units::EthUnit, orderbook::dto::order::Status, - secp256k1::SecretKey, shared::ethrpc::Web3, - web3::signing::SecretKeyRef, }; #[tokio::test] @@ -72,7 +70,7 @@ async fn test(web3: Web3) { .sign( EcdsaSigningScheme::EthSign, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); let uid = services.create_order(&order).await.unwrap(); diff --git a/crates/e2e/tests/e2e/partially_fillable_balance.rs b/crates/e2e/tests/e2e/partially_fillable_balance.rs index 3066f73931..50e1f846f3 100644 --- a/crates/e2e/tests/e2e/partially_fillable_balance.rs +++ b/crates/e2e/tests/e2e/partially_fillable_balance.rs @@ -1,5 +1,5 @@ use { - ::alloy::primitives::U256, + ::alloy::{primitives::U256, signers::local::PrivateKeySigner}, e2e::setup::*, ethrpc::alloy::{ CallBuilderExt, @@ -10,9 +10,7 @@ use { signature::EcdsaSigningScheme, }, number::units::EthUnit, - secp256k1::SecretKey, shared::ethrpc::Web3, - web3::signing::SecretKeyRef, }; #[tokio::test] @@ -106,7 +104,7 @@ async fn test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader_a.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader_a.private_key()).unwrap(), ); let order_uid = services.create_order(&order_a).await.unwrap(); onchain.mint_block().await; diff --git a/crates/e2e/tests/e2e/partially_fillable_pool.rs b/crates/e2e/tests/e2e/partially_fillable_pool.rs index bb19af4b57..1fccc99cb6 100644 --- a/crates/e2e/tests/e2e/partially_fillable_pool.rs +++ b/crates/e2e/tests/e2e/partially_fillable_pool.rs @@ -1,5 +1,5 @@ use { - ::alloy::primitives::U256, + ::alloy::{primitives::U256, signers::local::PrivateKeySigner}, e2e::setup::*, ethrpc::alloy::{ CallBuilderExt, @@ -10,9 +10,7 @@ use { signature::EcdsaSigningScheme, }, number::units::EthUnit, - secp256k1::SecretKey, shared::ethrpc::Web3, - web3::signing::SecretKeyRef, }; #[tokio::test] #[ignore] @@ -106,7 +104,7 @@ async fn test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader_a.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader_a.private_key()).unwrap(), ); let uid = services.create_order(&order_a).await.unwrap(); let order = services.get_order(&uid).await.unwrap(); diff --git a/crates/e2e/tests/e2e/place_order_with_quote.rs b/crates/e2e/tests/e2e/place_order_with_quote.rs index 7d4c4eacc9..21f99e32da 100644 --- a/crates/e2e/tests/e2e/place_order_with_quote.rs +++ b/crates/e2e/tests/e2e/place_order_with_quote.rs @@ -1,5 +1,5 @@ use { - ::alloy::primitives::U256, + ::alloy::{primitives::U256, signers::local::PrivateKeySigner}, driver::domain::eth::NonZeroU256, e2e::{nodes::local_node::TestNodeApi, setup::*}, ethrpc::alloy::{ @@ -12,10 +12,8 @@ use { signature::EcdsaSigningScheme, }, number::units::EthUnit, - secp256k1::SecretKey, shared::ethrpc::Web3, std::ops::DerefMut, - web3::signing::SecretKeyRef, }; #[tokio::test] @@ -103,7 +101,7 @@ async fn place_order_with_quote(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); let order_uid = services.create_order(&order).await.unwrap(); diff --git a/crates/e2e/tests/e2e/protocol_fee.rs b/crates/e2e/tests/e2e/protocol_fee.rs index b421940860..6e7a2eda58 100644 --- a/crates/e2e/tests/e2e/protocol_fee.rs +++ b/crates/e2e/tests/e2e/protocol_fee.rs @@ -1,5 +1,5 @@ use { - ::alloy::primitives::U256, + ::alloy::{primitives::U256, signers::local::PrivateKeySigner}, driver::domain::eth::NonZeroU256, e2e::{ assert_approximately_eq, @@ -24,10 +24,8 @@ use { }, number::units::EthUnit, reqwest::StatusCode, - secp256k1::SecretKey, serde_json::json, shared::ethrpc::Web3, - web3::signing::SecretKeyRef, }; #[tokio::test] @@ -206,7 +204,7 @@ async fn combined_protocol_fees(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); let limit_surplus_order = OrderCreation { sell_amount: sell_amount.into_alloy(), @@ -217,7 +215,7 @@ async fn combined_protocol_fees(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); let partner_fee_order = OrderCreation { sell_amount: sell_amount.into_alloy(), @@ -229,7 +227,7 @@ async fn combined_protocol_fees(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); tracing::info!("Rebalancing AMM pools for market & limit order."); @@ -542,7 +540,7 @@ async fn surplus_partner_fee(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); let order_uid = services.create_order(&order).await.unwrap(); @@ -797,7 +795,7 @@ async fn volume_fee_buy_order_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); let uid = services.create_order(&order).await.unwrap(); @@ -957,7 +955,7 @@ async fn volume_fee_buy_order_upcoming_future_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); let uid = services.create_order(&order).await.unwrap(); diff --git a/crates/e2e/tests/e2e/quoting.rs b/crates/e2e/tests/e2e/quoting.rs index 7074d2e73a..ad63c6f8c2 100644 --- a/crates/e2e/tests/e2e/quoting.rs +++ b/crates/e2e/tests/e2e/quoting.rs @@ -1,4 +1,5 @@ use { + ::alloy::signers::local::PrivateKeySigner, e2e::setup::{colocation::SolverEngine, mock::Mock, *}, ethrpc::alloy::{ CallBuilderExt, @@ -11,14 +12,12 @@ use { signature::EcdsaSigningScheme, }, number::{nonzero::NonZeroU256, units::EthUnit}, - secp256k1::SecretKey, serde_json::json, shared::ethrpc::Web3, std::{ sync::Arc, time::{Duration, Instant}, }, - web3::signing::SecretKeyRef, }; #[tokio::test] @@ -414,7 +413,7 @@ async fn quote_timeout(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); // order creation requests always use the default quote time diff --git a/crates/e2e/tests/e2e/replace_order.rs b/crates/e2e/tests/e2e/replace_order.rs index 313a577702..b4fc7a1f9a 100644 --- a/crates/e2e/tests/e2e/replace_order.rs +++ b/crates/e2e/tests/e2e/replace_order.rs @@ -1,5 +1,5 @@ use { - ::alloy::primitives::U256, + ::alloy::{primitives::U256, signers::local::PrivateKeySigner}, e2e::{nodes::local_node::TestNodeApi, setup::*}, ethrpc::alloy::{ CallBuilderExt, @@ -15,10 +15,8 @@ use { orderbook::{OrderCancellationError, OrderReplacementError}, }, reqwest::StatusCode, - secp256k1::SecretKey, shared::ethrpc::Web3, warp::reply::Reply, - web3::signing::SecretKeyRef, }; #[tokio::test] @@ -134,7 +132,7 @@ async fn try_replace_unreplaceable_order_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); let balance_before = token_a.balanceOf(trader.address()).call().await.unwrap(); onchain.mint_block().await; @@ -171,7 +169,7 @@ async fn try_replace_unreplaceable_order_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); let response = services.create_order(&new_order).await; let (error_code, error_message) = response.err().unwrap(); @@ -320,7 +318,7 @@ async fn try_replace_someone_else_order_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader_a.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader_a.private_key()).unwrap(), ); let order_id = services.create_order(&order).await.unwrap(); @@ -343,7 +341,7 @@ async fn try_replace_someone_else_order_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader_b.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader_b.private_key()).unwrap(), ); let balance_before = token_a.balanceOf(trader_a.address()).call().await.unwrap(); let response = services.create_order(&new_order).await; @@ -465,7 +463,7 @@ async fn single_replace_order_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); let order_id = services.create_order(&order).await.unwrap(); @@ -498,7 +496,7 @@ async fn single_replace_order_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); let new_order_uid = services.create_order(&new_order).await.unwrap(); diff --git a/crates/e2e/tests/e2e/solver_competition.rs b/crates/e2e/tests/e2e/solver_competition.rs index f468181e5c..a80338c1a8 100644 --- a/crates/e2e/tests/e2e/solver_competition.rs +++ b/crates/e2e/tests/e2e/solver_competition.rs @@ -1,5 +1,5 @@ use { - ::alloy::primitives::U256, + ::alloy::{primitives::U256, signers::local::PrivateKeySigner}, e2e::setup::{colocation::SolverEngine, mock::Mock, *}, ethrpc::alloy::{ CallBuilderExt, @@ -10,11 +10,9 @@ use { signature::EcdsaSigningScheme, }, number::units::EthUnit, - secp256k1::SecretKey, shared::ethrpc::Web3, solvers_dto::solution::Solution, std::collections::HashMap, - web3::signing::SecretKeyRef, }; #[tokio::test] @@ -113,7 +111,7 @@ async fn solver_competition(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); let uid = services.create_order(&order).await.unwrap(); onchain.mint_block().await; @@ -261,7 +259,7 @@ async fn wrong_solution_submission_address(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader_a.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader_a.private_key()).unwrap(), ); let uid_a = services.create_order(&order_a).await.unwrap(); @@ -279,7 +277,7 @@ async fn wrong_solution_submission_address(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader_b.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader_b.private_key()).unwrap(), ); services.create_order(&order_b).await.unwrap(); @@ -415,7 +413,7 @@ async fn store_filtered_solutions(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); let order_ac = OrderCreation { @@ -430,7 +428,7 @@ async fn store_filtered_solutions(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); let order_ab_id = services.create_order(&order_ab).await.unwrap(); diff --git a/crates/e2e/tests/e2e/solver_participation_guard.rs b/crates/e2e/tests/e2e/solver_participation_guard.rs index 8b3ccc3412..1182ec9996 100644 --- a/crates/e2e/tests/e2e/solver_participation_guard.rs +++ b/crates/e2e/tests/e2e/solver_participation_guard.rs @@ -1,5 +1,8 @@ use { - alloy::primitives::{Address, U256}, + alloy::{ + primitives::{Address, U256}, + signers::local::PrivateKeySigner, + }, e2e::setup::{ Db, ExtraServiceArgs, @@ -23,10 +26,8 @@ use { signature::EcdsaSigningScheme, }, number::units::EthUnit, - secp256k1::SecretKey, sqlx::Row, std::time::Instant, - web3::signing::SecretKeyRef, }; #[tokio::test] @@ -348,7 +349,7 @@ async fn execute_order( .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader_a.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader_a.private_key()).unwrap(), ); let balance_before = token_b.balanceOf(trader_a.address()).call().await.unwrap(); let order_id = services.create_order(&order).await.unwrap(); diff --git a/crates/e2e/tests/e2e/submission.rs b/crates/e2e/tests/e2e/submission.rs index 32a75f3f68..08072d53c7 100644 --- a/crates/e2e/tests/e2e/submission.rs +++ b/crates/e2e/tests/e2e/submission.rs @@ -6,6 +6,7 @@ use { client::PollerStream, types::{Transaction, TransactionReceipt}, }, + signers::local::PrivateKeySigner, }, e2e::{nodes::local_node::TestNodeApi, setup::*}, ethrpc::alloy::{ @@ -18,9 +19,7 @@ use { signature::EcdsaSigningScheme, }, number::units::EthUnit, - secp256k1::SecretKey, shared::ethrpc::Web3, - web3::signing::SecretKeyRef, }; #[tokio::test] @@ -85,7 +84,7 @@ async fn test_cancel_on_expiry(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); services.create_order(&order).await.unwrap(); onchain.mint_block().await; diff --git a/crates/e2e/tests/e2e/tracking_insufficient_funds.rs b/crates/e2e/tests/e2e/tracking_insufficient_funds.rs index 963853aa3b..35056cf516 100644 --- a/crates/e2e/tests/e2e/tracking_insufficient_funds.rs +++ b/crates/e2e/tests/e2e/tracking_insufficient_funds.rs @@ -1,4 +1,5 @@ use { + ::alloy::signers::local::PrivateKeySigner, database::order_events::{OrderEvent, OrderEventLabel}, e2e::setup::*, ethrpc::alloy::{ @@ -10,9 +11,7 @@ use { signature::EcdsaSigningScheme, }, number::units::EthUnit, - secp256k1::SecretKey, shared::ethrpc::Web3, - web3::signing::SecretKeyRef, }; #[tokio::test] @@ -86,7 +85,7 @@ async fn test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader_a.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader_a.private_key()).unwrap(), ); let order_b = OrderCreation { sell_token: *onchain.contracts().weth.address(), @@ -100,7 +99,7 @@ async fn test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader_b.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader_b.private_key()).unwrap(), ); let uid_a = services.create_order(&order_a).await.unwrap(); let uid_b = services.create_order(&order_b).await.unwrap(); diff --git a/crates/e2e/tests/e2e/uncovered_order.rs b/crates/e2e/tests/e2e/uncovered_order.rs index 84b56057e4..023a0f22c0 100644 --- a/crates/e2e/tests/e2e/uncovered_order.rs +++ b/crates/e2e/tests/e2e/uncovered_order.rs @@ -1,4 +1,5 @@ use { + ::alloy::signers::local::PrivateKeySigner, e2e::setup::*, ethrpc::alloy::{ CallBuilderExt, @@ -9,9 +10,7 @@ use { signature::EcdsaSigningScheme, }, number::units::EthUnit, - secp256k1::SecretKey, shared::ethrpc::Web3, - web3::signing::SecretKeyRef, }; #[tokio::test] @@ -62,7 +61,7 @@ async fn test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); // This order can't be created because we require the trader // to have at least 1 wei of sell tokens. diff --git a/crates/e2e/tests/e2e/univ2.rs b/crates/e2e/tests/e2e/univ2.rs index 86609eeb00..f92eade158 100644 --- a/crates/e2e/tests/e2e/univ2.rs +++ b/crates/e2e/tests/e2e/univ2.rs @@ -1,5 +1,5 @@ use { - ::alloy::primitives::U256, + ::alloy::{primitives::U256, signers::local::PrivateKeySigner}, contracts::alloy::GPv2Settlement, database::order_events::{OrderEvent, OrderEventLabel}, e2e::setup::*, @@ -12,9 +12,7 @@ use { signature::EcdsaSigningScheme, }, number::units::EthUnit, - secp256k1::SecretKey, shared::ethrpc::Web3, - web3::signing::SecretKeyRef, }; #[tokio::test] @@ -73,7 +71,7 @@ async fn test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); let uid = services.create_order(&order).await.unwrap(); diff --git a/crates/e2e/tests/e2e/vault_balances.rs b/crates/e2e/tests/e2e/vault_balances.rs index b52b38667d..ff82e258ae 100644 --- a/crates/e2e/tests/e2e/vault_balances.rs +++ b/crates/e2e/tests/e2e/vault_balances.rs @@ -1,4 +1,5 @@ use { + ::alloy::signers::local::PrivateKeySigner, e2e::setup::*, ethrpc::alloy::{ CallBuilderExt, @@ -9,9 +10,7 @@ use { signature::EcdsaSigningScheme, }, number::units::EthUnit, - secp256k1::SecretKey, shared::ethrpc::Web3, - web3::signing::SecretKeyRef, }; #[tokio::test] @@ -72,7 +71,7 @@ async fn vault_balances(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); services.create_order(&order).await.unwrap(); onchain.mint_block().await; diff --git a/crates/e2e/tests/e2e/wrapper.rs b/crates/e2e/tests/e2e/wrapper.rs index 5eee690181..3773145aa5 100644 --- a/crates/e2e/tests/e2e/wrapper.rs +++ b/crates/e2e/tests/e2e/wrapper.rs @@ -6,6 +6,7 @@ use { ext::{AnvilApi, DebugApi, ImpersonateConfig}, }, rpc::types::trace::geth::{CallConfig, GethDebugTracingOptions}, + signers::local::PrivateKeySigner, }, app_data::{AppDataHash, hash_full_app_data}, contracts::alloy::ERC20, @@ -20,10 +21,8 @@ use { signature::EcdsaSigningScheme, }, number::units::EthUnit, - secp256k1::SecretKey, serde_json::json, shared::ethrpc::Web3, - web3::signing::SecretKeyRef, }; /// The block number from which we will fetch state for the forked test. @@ -166,7 +165,7 @@ async fn forked_mainnet_wrapper_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()), + &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), ); let sell_token_balance_before = token_weth.balanceOf(trader.address()).call().await.unwrap(); diff --git a/crates/model/Cargo.toml b/crates/model/Cargo.toml index d0005fc1e0..314340e766 100644 --- a/crates/model/Cargo.toml +++ b/crates/model/Cargo.toml @@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0" doctest = false [dependencies] -alloy = { workspace = true, features = ["sol-types"] } +alloy = { workspace = true, features = ["sol-types", "signers", "signer-local"] } anyhow = { workspace = true } app-data = { workspace = true } bigdecimal = { workspace = true } diff --git a/crates/model/src/order.rs b/crates/model/src/order.rs index dc09ebdb51..075c8554c5 100644 --- a/crates/model/src/order.rs +++ b/crates/model/src/order.rs @@ -9,7 +9,10 @@ use { quote::QuoteId, signature::{self, EcdsaSignature, EcdsaSigningScheme, Signature}, }, - alloy::primitives::{Address, B256, U256, U512}, + alloy::{ + primitives::{Address, B256, U256, U512, b256}, + signers::local::PrivateKeySigner, + }, anyhow::{Result, anyhow}, app_data::{AppDataHash, hash_full_app_data}, bigdecimal::BigDecimal, @@ -26,7 +29,7 @@ use { str::FromStr, }, strum::{AsRefStr, EnumString, VariantNames}, - web3::signing::{self, Key, SecretKeyRef}, + web3::signing::{self}, }; /// The flag denoting that an order is buying ETH (or the chain's native token). @@ -158,9 +161,9 @@ impl OrderBuilder { mut self, signing_scheme: EcdsaSigningScheme, domain: &DomainSeparator, - key: SecretKeyRef, + key: &PrivateKeySigner, ) -> Self { - let owner = Address::new(key.address().0); + let owner = key.address(); self.0.metadata.owner = owner; self.0.metadata.uid = self.0.data.uid(domain, owner); self.0.signature = @@ -262,10 +265,7 @@ impl OrderData { pub fn uid(&self, domain: &DomainSeparator, owner: Address) -> OrderUid { OrderUid::from_parts( - B256::new(super::signature::hashed_eip712_message( - domain, - &self.hash_struct(), - )), + super::signature::hashed_eip712_message(domain, &self.hash_struct()), owner, self.valid_to, ) @@ -376,7 +376,7 @@ impl OrderCreation { mut self, signing_scheme: EcdsaSigningScheme, domain: &DomainSeparator, - key: SecretKeyRef, + key: &PrivateKeySigner, ) -> Self { self.signature = EcdsaSignature::sign(signing_scheme, domain, &self.data().hash_struct(), key) @@ -563,12 +563,10 @@ impl Default for OrderCancellation { Self::for_order( OrderUid::default(), &DomainSeparator::default(), - SecretKeyRef::new( - &secp256k1::SecretKey::from_str( - "0000000000000000000000000000000000000000000000000000000000000001", - ) - .unwrap(), - ), + &PrivateKeySigner::from_bytes(&b256!( + "0000000000000000000000000000000000000000000000000000000000000001" + )) + .unwrap(), ) } } @@ -582,7 +580,7 @@ impl OrderCancellation { pub fn for_order( order_uid: OrderUid, domain_separator: &DomainSeparator, - key: SecretKeyRef, + key: &PrivateKeySigner, ) -> Self { let mut result = Self { order_uid, @@ -1063,7 +1061,7 @@ mod tests { use { super::*, crate::signature::{EcdsaSigningScheme, SigningScheme}, - alloy::primitives::address, + alloy::primitives::{address, b256}, chrono::TimeZone, hex_literal::hex, maplit::hashset, @@ -1149,14 +1147,8 @@ mod tests { }, signature: EcdsaSignature { v: 1, - r: B256::from_str( - "0200000000000000000000000000000000000000000000000000000000000003", - ) - .unwrap(), - s: B256::from_str( - "0400000000000000000000000000000000000000000000000000000000000005", - ) - .unwrap(), + r: b256!("0200000000000000000000000000000000000000000000000000000000000003"), + s: b256!("0400000000000000000000000000000000000000000000000000000000000005"), } .to_signature(signing_scheme), interactions: Interactions::default(), @@ -1451,7 +1443,7 @@ mod tests { .sign_with( EcdsaSigningScheme::Eip712, &DomainSeparator::default(), - SecretKeyRef::from(&sk), + &PrivateKeySigner::from_bytes(&PRIVATE_KEY.into()).unwrap(), ) .build(); diff --git a/crates/model/src/signature.rs b/crates/model/src/signature.rs index 4df708ddf6..455faaa6f8 100644 --- a/crates/model/src/signature.rs +++ b/crates/model/src/signature.rs @@ -1,7 +1,11 @@ use { crate::{DomainSeparator, quote::QuoteSigningScheme}, - alloy::primitives::{Address, B256}, + alloy::{ + primitives::{Address, B256}, + signers::{SignerSync, local::PrivateKeySigner}, + }, anyhow::{Context as _, Result, ensure}, + secp256k1::SecretKey, serde::{Deserialize, Serialize, de}, std::{ convert::TryInto as _, @@ -9,7 +13,7 @@ use { }, web3::{ signing::{self, Key, SecretKeyRef}, - types::Recovery, + types::{H256, Recovery}, }, }; @@ -263,24 +267,21 @@ pub struct EcdsaSignature { pub v: u8, } -pub fn hashed_eip712_message( - domain_separator: &DomainSeparator, - struct_hash: &[u8; 32], -) -> [u8; 32] { +pub fn hashed_eip712_message(domain_separator: &DomainSeparator, struct_hash: &[u8; 32]) -> B256 { let mut message = [0u8; 66]; // 0x19 0x01 are the magic prefix bytes for the domain separator // https://eips.ethereum.org/EIPS/eip-712#eth_signTypedData message[0..2].copy_from_slice(&[0x19, 0x01]); message[2..34].copy_from_slice(&domain_separator.0); message[34..66].copy_from_slice(struct_hash); - signing::keccak256(&message) + alloy::primitives::keccak256(message) } -fn hashed_ethsign_message(domain_separator: &DomainSeparator, struct_hash: &[u8; 32]) -> [u8; 32] { +fn hashed_ethsign_message(domain_separator: &DomainSeparator, struct_hash: &[u8; 32]) -> B256 { let mut message = [0u8; 60]; message[..28].copy_from_slice(b"\x19Ethereum Signed Message:\n32"); - message[28..].copy_from_slice(&hashed_eip712_message(domain_separator, struct_hash)); - signing::keccak256(&message) + message[28..].copy_from_slice(hashed_eip712_message(domain_separator, struct_hash).as_slice()); + alloy::primitives::keccak256(message) } /// Orders are always hashed into 32 bytes according to EIP-712. @@ -288,7 +289,7 @@ fn hashed_signing_message( signing_scheme: EcdsaSigningScheme, domain_separator: &DomainSeparator, struct_hash: &[u8; 32], -) -> [u8; 32] { +) -> B256 { match signing_scheme { EcdsaSigningScheme::Eip712 => hashed_eip712_message(domain_separator, struct_hash), EcdsaSigningScheme::EthSign => hashed_ethsign_message(domain_separator, struct_hash), @@ -327,32 +328,49 @@ impl EcdsaSignature { struct_hash: &[u8; 32], ) -> Result { let message = hashed_signing_message(signing_scheme, domain_separator, struct_hash); - let recovery = Recovery::new(message, self.v as u64, self.r.0.into(), self.s.0.into()); + let recovery = Recovery::new( + message.0, + self.v as u64, + H256(B256::from(self.r).0), + H256(B256::from(self.s).0), + ); let (signature, recovery_id) = recovery .as_signature() .context("unexpectedly invalid signature")?; - let signer = Address::new(signing::recover(&message, &signature, recovery_id)?.0); + let signer = Address::new(signing::recover(&message.0, &signature, recovery_id)?.0); - Ok(Recovered { - message: message.into(), - signer, - }) + Ok(Recovered { message, signer }) } pub fn sign( signing_scheme: EcdsaSigningScheme, domain_separator: &DomainSeparator, struct_hash: &[u8; 32], - key: SecretKeyRef, + key: &PrivateKeySigner, ) -> Self { let message = hashed_signing_message(signing_scheme, domain_separator, struct_hash); + let binding = SecretKey::from_slice(key.to_bytes().as_slice()).unwrap(); + let pk = SecretKeyRef::new(&binding); + let s1 = pk.sign(&message.0, None).unwrap(); + + let s1 = Self { + v: s1.v as u8, + r: s1.r.0.into(), + s: s1.s.0.into(), + }; + // Unwrap because the only error is for invalid messages which we don't create. - let signature = key.sign(&message, None).unwrap(); - Self { - v: signature.v as u8, - r: signature.r.0.into(), - s: signature.s.0.into(), - } + let signature = key.sign_hash_sync(&message).unwrap(); + + let s2 = Self { + v: signature.recid().to_byte() + 27, + r: signature.r().into(), + s: signature.s().into(), + }; + + assert_eq!(s1, s2); + + s2 } /// Returns an arbitrary non-zero signature that can be used for recovery diff --git a/crates/orderbook/src/api/cancel_order.rs b/crates/orderbook/src/api/cancel_order.rs index 76556a2565..ae141b299d 100644 --- a/crates/orderbook/src/api/cancel_order.rs +++ b/crates/orderbook/src/api/cancel_order.rs @@ -83,8 +83,7 @@ pub fn cancel_order( mod tests { use { super::*, - alloy::primitives::B256, - hex_literal::hex, + alloy::primitives::b256, model::signature::{EcdsaSignature, EcdsaSigningScheme}, serde_json::json, warp::{Reply, test::request}, @@ -103,12 +102,8 @@ mod tests { .unwrap(), CancellationPayload { signature: EcdsaSignature { - r: B256::new(hex!( - "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" - )), - s: B256::new(hex!( - "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" - )), + r: b256!("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"), + s: b256!("202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"), v: 27, }, signing_scheme: EcdsaSigningScheme::Eip712, diff --git a/crates/shared/src/order_validation.rs b/crates/shared/src/order_validation.rs index ef6230e53f..d1447aa459 100644 --- a/crates/shared/src/order_validation.rs +++ b/crates/shared/src/order_validation.rs @@ -596,7 +596,7 @@ impl OrderValidating for OrderValidator { self.signature_validator .validate_signature_and_get_additional_gas(SignatureCheck { signer: owner, - hash, + hash: hash.0, signature: signature.to_owned(), interactions: app_data.interactions.pre.clone(), balance_override: app_data.inner.protocol.flashloan.as_ref().map(|loan| { @@ -610,7 +610,7 @@ impl OrderValidating for OrderValidator { .await .map_err(|err| match err { SignatureValidationError::Invalid => { - ValidationError::InvalidEip1271Signature(B256::new(hash)) + ValidationError::InvalidEip1271Signature(hash) } SignatureValidationError::Other(err) => ValidationError::Other(err), })? @@ -1020,10 +1020,10 @@ mod tests { signature_validator::MockSignatureValidating, }, alloy::{ - primitives::{Address, U160, address}, + primitives::{Address, U160, address, b256}, providers::{Provider, ProviderBuilder, mock::Asserter}, + signers::local::PrivateKeySigner, }, - ethcontract::web3::signing::SecretKeyRef, futures::FutureExt, maplit::hashset, mockall::predicate::{always, eq}, @@ -1033,7 +1033,6 @@ mod tests { }, number::nonzero::NonZeroU256, serde_json::json, - std::str::FromStr, }; #[test] @@ -1438,7 +1437,7 @@ mod tests { .expect_validate_signature_and_get_additional_gas() .with(eq(SignatureCheck { signer: creation.from.unwrap(), - hash: order_hash, + hash: order_hash.0, signature: vec![1, 2, 3], interactions: pre_interactions.clone(), balance_override: None, @@ -1467,7 +1466,7 @@ mod tests { .expect_validate_signature_and_get_additional_gas() .with(eq(SignatureCheck { signer: creation.from.unwrap(), - hash: order_hash, + hash: order_hash.0, signature: vec![1, 2, 3], interactions: pre_interactions.clone(), balance_override: None, @@ -2050,7 +2049,10 @@ mod tests { order.clone().sign( signing_scheme, &Default::default(), - SecretKeyRef::new(&secp256k1::SecretKey::from_str("0000000000000000000000000000000000000000000000000000000000000001").unwrap()), + &PrivateKeySigner::from_bytes(&b256!( + "0000000000000000000000000000000000000000000000000000000000000001" + )) + .unwrap(), ), &Default::default(), Default::default(), diff --git a/crates/shared/src/zeroex_api.rs b/crates/shared/src/zeroex_api.rs index da4b2e98f8..32e3e8fa4d 100644 --- a/crates/shared/src/zeroex_api.rs +++ b/crates/shared/src/zeroex_api.rs @@ -450,7 +450,7 @@ impl Metrics { mod tests { use { super::*, - alloy::primitives::address, + alloy::primitives::{address, b256}, chrono::{DateTime, NaiveDate}, }; @@ -551,13 +551,11 @@ mod tests { sender: Address::ZERO, signature: ZeroExSignature { signature_type: 3, - r: B256::from_slice( - &const_hex::decode("db60e4fa2b4f2ee073d88eed3502149ba2231d699bc5d92d5627dcd21f915237") - .unwrap() + r: b256!( + "db60e4fa2b4f2ee073d88eed3502149ba2231d699bc5d92d5627dcd21f915237" ), - s: B256::from_slice( - &const_hex::decode("4cb1e9c15788b86d5187b99c0d929ad61d2654c242095c26f9ace17e64aca0fd") - .unwrap() + s: b256!( + "4cb1e9c15788b86d5187b99c0d929ad61d2654c242095c26f9ace17e64aca0fd" ), v: 28u8, }, @@ -568,12 +566,18 @@ mod tests { verifying_contract: address!("def1c0ded9bec7f1a1670819833240f027b25eff"), }, OrderMetadata { - order_hash: - const_hex::decode( - "003427369d4c2a6b0aceeb7b315bb9a6086bc6fc4c887aa51efc73b662c9d127" - ).unwrap(), + order_hash: const_hex::decode( + "003427369d4c2a6b0aceeb7b315bb9a6086bc6fc4c887aa51efc73b662c9d127" + ) + .unwrap(), remaining_fillable_taker_amount: 262467000000000000u128, - created_at: DateTime::from_naive_utc_and_offset(NaiveDate::from_ymd_opt(2022, 2, 26).unwrap().and_hms_nano_opt(6, 59, 0, 440_000_000).unwrap(), Utc), + created_at: DateTime::from_naive_utc_and_offset( + NaiveDate::from_ymd_opt(2022, 2, 26) + .unwrap() + .and_hms_nano_opt(6, 59, 0, 440_000_000) + .unwrap(), + Utc + ), }, )], } From 525129e72f47d7ef5ab03e51701a8e389e301af6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=CC=81=20Duarte?= Date: Wed, 17 Dec 2025 10:12:47 +0000 Subject: [PATCH 10/24] fix wrong migrations --- crates/e2e/tests/e2e/cow_amm.rs | 8 ++------ crates/shared/src/event_handling.rs | 7 ++++--- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/crates/e2e/tests/e2e/cow_amm.rs b/crates/e2e/tests/e2e/cow_amm.rs index dfb1abe227..621c6652cb 100644 --- a/crates/e2e/tests/e2e/cow_amm.rs +++ b/crates/e2e/tests/e2e/cow_amm.rs @@ -206,9 +206,7 @@ async fn cow_amm_jit(web3: Web3) { // the past so the computer's current time is way ahead of the blockchain. let block = web3 .alloy - .get_block(alloy::eips::BlockId::Number( - alloy::eips::BlockNumberOrTag::Latest, - )) + .get_block(alloy::eips::BlockId::latest()) .await .unwrap() .unwrap(); @@ -841,9 +839,7 @@ async fn cow_amm_opposite_direction(web3: Web3) { // Get the current block timestamp let block = web3 .alloy - .get_block(alloy::eips::BlockId::Number( - alloy::eips::BlockNumberOrTag::Latest, - )) + .get_block(alloy::eips::BlockId::latest()) .await .unwrap() .unwrap(); diff --git a/crates/shared/src/event_handling.rs b/crates/shared/src/event_handling.rs index 08c3a7b57b..515b447143 100644 --- a/crates/shared/src/event_handling.rs +++ b/crates/shared/src/event_handling.rs @@ -1021,8 +1021,9 @@ mod tests { let contract = GPv2Settlement::Instance::deployed(&web3.alloy) .await .unwrap(); - let storage = EventStorage { events: vec![] }; - let current_block = web3.alloy.get_chain_id().await.unwrap(); + let storage: EventStorage = + EventStorage { events: vec![] }; + let current_block = web3.alloy.get_block_number().await.unwrap(); const NUMBER_OF_BLOCKS: u64 = 300; @@ -1054,7 +1055,7 @@ mod tests { .await .unwrap(); - let current_block = web3.alloy.get_chain_id().await.unwrap(); + let current_block = web3.alloy.get_block_number().await.unwrap(); // In this test we query for events multiple times. Newer events might be // included each time we query again for the same events, but we want to // disregard them. From 616697c1a88f693b8049aec5ab7de7df2d7bc621 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=CC=81=20Duarte?= Date: Wed, 17 Dec 2025 12:39:12 +0000 Subject: [PATCH 11/24] match signature --- crates/model/src/signature.rs | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/crates/model/src/signature.rs b/crates/model/src/signature.rs index 455faaa6f8..51e9adfbce 100644 --- a/crates/model/src/signature.rs +++ b/crates/model/src/signature.rs @@ -5,14 +5,13 @@ use { signers::{SignerSync, local::PrivateKeySigner}, }, anyhow::{Context as _, Result, ensure}, - secp256k1::SecretKey, serde::{Deserialize, Serialize, de}, std::{ convert::TryInto as _, fmt::{self, Debug, Formatter}, }, web3::{ - signing::{self, Key, SecretKeyRef}, + signing::{self}, types::{H256, Recovery}, }, }; @@ -349,28 +348,17 @@ impl EcdsaSignature { key: &PrivateKeySigner, ) -> Self { let message = hashed_signing_message(signing_scheme, domain_separator, struct_hash); - let binding = SecretKey::from_slice(key.to_bytes().as_slice()).unwrap(); - let pk = SecretKeyRef::new(&binding); - let s1 = pk.sign(&message.0, None).unwrap(); - - let s1 = Self { - v: s1.v as u8, - r: s1.r.0.into(), - s: s1.s.0.into(), - }; - // Unwrap because the only error is for invalid messages which we don't create. let signature = key.sign_hash_sync(&message).unwrap(); - - let s2 = Self { + Self { + // The 27 is slightly magic, it comes from the Electrum notation + // https://github.com/tomusdrw/rust-web3/blob/8d889ae3270508f1e68b6a29bbe51b2bedf7fb1e/src/signing.rs#L107-L113 + // we don't change the number according to the chain id as before the alloy migration + // we were not using chain replay protection v: signature.recid().to_byte() + 27, r: signature.r().into(), s: signature.s().into(), - }; - - assert_eq!(s1, s2); - - s2 + } } /// Returns an arbitrary non-zero signature that can be used for recovery From 3e84f43be7fe553fb54dd1044e81e939dab71a4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=CC=81=20Duarte?= Date: Wed, 17 Dec 2025 12:50:23 +0000 Subject: [PATCH 12/24] clippy --- crates/e2e/tests/e2e/eth_integration.rs | 5 +---- crates/e2e/tests/e2e/submission.rs | 8 ++------ 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/crates/e2e/tests/e2e/eth_integration.rs b/crates/e2e/tests/e2e/eth_integration.rs index 390c27c088..e56bf9bb4b 100644 --- a/crates/e2e/tests/e2e/eth_integration.rs +++ b/crates/e2e/tests/e2e/eth_integration.rs @@ -2,10 +2,7 @@ use { ::alloy::providers::Provider, e2e::setup::*, ethcontract::prelude::Address, - ethrpc::alloy::{ - CallBuilderExt, - conversions::{IntoAlloy, IntoLegacy}, - }, + ethrpc::alloy::{CallBuilderExt, conversions::IntoAlloy}, model::{ order::{BUY_ETH_ADDRESS, OrderCreation, OrderKind}, quote::{OrderQuoteRequest, OrderQuoteSide, SellAmount}, diff --git a/crates/e2e/tests/e2e/submission.rs b/crates/e2e/tests/e2e/submission.rs index dff568a541..44081d3d57 100644 --- a/crates/e2e/tests/e2e/submission.rs +++ b/crates/e2e/tests/e2e/submission.rs @@ -8,12 +8,8 @@ use { }, }, e2e::{nodes::local_node::TestNodeApi, setup::*}, - ethcontract::{BlockId, H160, H256}, - ethrpc::alloy::{ - CallBuilderExt, - conversions::{IntoAlloy, IntoLegacy}, - }, - futures::{Stream, StreamExt}, + ethrpc::alloy::{CallBuilderExt, conversions::IntoAlloy}, + futures::StreamExt, model::{ order::{OrderCreation, OrderKind}, signature::EcdsaSigningScheme, From 663b73205ebc7d03254126461823f623f28052dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=CC=81=20Duarte?= Date: Wed, 17 Dec 2025 18:15:05 +0000 Subject: [PATCH 13/24] Migrate TestAccount to alloy --- Cargo.lock | 126 ++++++----- Cargo.toml | 3 + crates/app-data/src/app_data_hash.rs | 3 +- crates/driver/src/tests/setup/blockchain.rs | 208 ++++++++---------- crates/driver/src/tests/setup/driver.rs | 4 +- crates/driver/src/tests/setup/mod.rs | 30 +-- crates/driver/src/tests/setup/solver.rs | 10 +- crates/e2e/Cargo.toml | 1 + crates/e2e/src/setup/colocation.rs | 2 +- .../e2e/src/setup/onchain_components/mod.rs | 98 ++++----- crates/e2e/tests/e2e/app_data.rs | 5 +- crates/e2e/tests/e2e/app_data_signer.rs | 4 +- crates/e2e/tests/e2e/autopilot_leader.rs | 3 +- crates/e2e/tests/e2e/buffers.rs | 6 +- crates/e2e/tests/e2e/cow_amm.rs | 11 +- crates/e2e/tests/e2e/eth_integration.rs | 6 +- crates/e2e/tests/e2e/ethflow.rs | 37 ++-- crates/e2e/tests/e2e/hooks.rs | 8 +- crates/e2e/tests/e2e/jit_orders.rs | 6 +- crates/e2e/tests/e2e/limit_orders.rs | 33 ++- crates/e2e/tests/e2e/liquidity.rs | 21 +- .../e2e/liquidity_source_notification.rs | 9 +- crates/e2e/tests/e2e/order_cancellation.rs | 8 +- crates/e2e/tests/e2e/partial_fill.rs | 4 +- .../tests/e2e/partially_fillable_balance.rs | 4 +- .../e2e/tests/e2e/partially_fillable_pool.rs | 4 +- .../e2e/tests/e2e/place_order_with_quote.rs | 4 +- crates/e2e/tests/e2e/protocol_fee.rs | 14 +- crates/e2e/tests/e2e/quoting.rs | 3 +- crates/e2e/tests/e2e/refunder.rs | 14 +- crates/e2e/tests/e2e/replace_order.rs | 14 +- crates/e2e/tests/e2e/solver_competition.rs | 12 +- .../tests/e2e/solver_participation_guard.rs | 7 +- crates/e2e/tests/e2e/submission.rs | 7 +- .../tests/e2e/tracking_insufficient_funds.rs | 5 +- crates/e2e/tests/e2e/uncovered_order.rs | 3 +- crates/e2e/tests/e2e/univ2.rs | 4 +- crates/e2e/tests/e2e/vault_balances.rs | 3 +- crates/e2e/tests/e2e/wrapper.rs | 3 +- crates/ethrpc/src/alloy/conversions.rs | 37 ---- crates/shared/Cargo.toml | 2 +- crates/shared/src/bad_token/trace_call.rs | 22 +- 42 files changed, 349 insertions(+), 459 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 532617fd46..4af1040a83 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -212,6 +212,7 @@ dependencies = [ "alloy-primitives", "alloy-sol-type-parser", "alloy-sol-types", + "derive_more 2.0.1", "itoa", "serde", "serde_json", @@ -599,7 +600,9 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9cf0b42ffbf558badfecf1dde0c3c5ed91f29bb7e97876d0bed008c3d5d67171" dependencies = [ + "alloy-dyn-abi", "alloy-primitives", + "alloy-sol-types", "async-trait", "auto_impl", "either", @@ -797,7 +800,7 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd7ce8ed34106acd6e21942022b6a15be6454c2c3ead4d76811d3bdcd63cf771" dependencies = [ - "darling 0.21.3", + "darling", "proc-macro2", "quote", "syn 2.0.108", @@ -2452,38 +2455,14 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "darling" -version = "0.20.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83b2eb4d90d12bdda5ed17de686c2acb4c57914f8f921b8da7e112b5a36f3fe1" -dependencies = [ - "darling_core 0.20.9", - "darling_macro 0.20.9", -] - [[package]] name = "darling" version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" dependencies = [ - "darling_core 0.21.3", - "darling_macro 0.21.3", -] - -[[package]] -name = "darling_core" -version = "0.20.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622687fe0bac72a04e5599029151f5796111b90f1baaa9b544d807a5e31cd120" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 2.0.108", + "darling_core", + "darling_macro", ] [[package]] @@ -2501,24 +2480,13 @@ dependencies = [ "syn 2.0.108", ] -[[package]] -name = "darling_macro" -version = "0.20.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" -dependencies = [ - "darling_core 0.20.9", - "quote", - "syn 2.0.108", -] - [[package]] name = "darling_macro" version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ - "darling_core 0.21.3", + "darling_core", "quote", "syn 2.0.108", ] @@ -2767,11 +2735,18 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" +[[package]] +name = "dyn-clone" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" + [[package]] name = "e2e" version = "1.0.0" dependencies = [ "alloy", + "alloy-signer", "anyhow", "app-data", "autopilot", @@ -4679,9 +4654,9 @@ dependencies = [ [[package]] name = "openssl-probe" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-sys" @@ -5437,6 +5412,26 @@ dependencies = [ "bitflags 2.9.1", ] +[[package]] +name = "ref-cast" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + [[package]] name = "refunder" version = "0.1.0" @@ -5945,6 +5940,30 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "schemars" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "schemars" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9558e172d4e8533736ba97870c4b2cd63f84b382a3d6eb063da41b91cce17289" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + [[package]] name = "scoped-tls" version = "1.0.1" @@ -6042,9 +6061,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.11.0" +version = "2.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" +checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" dependencies = [ "core-foundation-sys", "libc", @@ -6112,13 +6131,15 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.117" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ "itoa", + "memchr", "ryu", "serde", + "serde_core", ] [[package]] @@ -6154,17 +6175,18 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.8.1" +version = "3.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad483d2ab0149d5a5ebcd9972a3852711e0153d863bf5a5d0391d28883c4a20" +checksum = "4fa237f2807440d238e0364a218270b98f767a00d3dada77b1c53ae88940e2e7" dependencies = [ "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", "indexmap 2.10.0", - "serde", - "serde_derive", + "schemars 0.9.0", + "schemars 1.1.0", + "serde_core", "serde_json", "serde_with_macros", "time", @@ -6172,11 +6194,11 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.8.1" +version = "3.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65569b702f41443e8bc8bbb1c5779bd0450bbe723b56198980e80ec45780bce2" +checksum = "52a8e3ca0ca629121f70ab50f95249e5a6f925cc0f6ffe8256c45b728875706c" dependencies = [ - "darling 0.20.9", + "darling", "proc-macro2", "quote", "syn 2.0.108", diff --git a/Cargo.toml b/Cargo.toml index 6d41e5873d..fa95e4a136 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,9 @@ members = ["crates/*"] [workspace.dependencies] alloy = { version = "1.1.0", default-features = false } +# alloy-signer was added because eip712 on the regular alloy crate brings way too much stuff with it +# as such, this is a workaround to force feature unification over alloy to the feature set we want +alloy-signer = { version = "1.1.0", default-features = false} anyhow = "1.0.100" async-trait = "0.1.80" axum = "0.6" diff --git a/crates/app-data/src/app_data_hash.rs b/crates/app-data/src/app_data_hash.rs index 90148e0cf1..91e673e84b 100644 --- a/crates/app-data/src/app_data_hash.rs +++ b/crates/app-data/src/app_data_hash.rs @@ -22,8 +22,7 @@ //! [0]: https://github.com/cowprotocol/services/issues/1465 use { - serde::{Deserializer, Serializer, de}, - serde_with::serde::{Deserialize, Serialize}, + serde::{Deserialize, Deserializer, Serialize, Serializer, de}, std::{ borrow::Cow, fmt::{self, Debug, Formatter}, diff --git a/crates/driver/src/tests/setup/blockchain.rs b/crates/driver/src/tests/setup/blockchain.rs index e01ca6186f..3a28c2103d 100644 --- a/crates/driver/src/tests/setup/blockchain.rs +++ b/crates/driver/src/tests/setup/blockchain.rs @@ -7,6 +7,7 @@ use { alloy::{ primitives::{Address, U256}, providers::{Provider, ext::AnvilApi}, + rpc::types::TransactionRequest, signers::local::{MnemonicBuilder, PrivateKeySigner}, sol_types::SolCall, }, @@ -21,19 +22,13 @@ use { WETH9, support::{Balances, Signatures}, }, - ethcontract::PrivateKey, ethrpc::{ Web3, - alloy::{ - CallBuilderExt, - conversions::{IntoAlloy, IntoLegacy}, - }, + alloy::{CallBuilderExt, ProviderExt, conversions::IntoLegacy}, }, futures::Future, - secp256k1::SecretKey, solvers_dto::solution::Flashloan, std::collections::HashMap, - web3::signing::Key, }; // TODO Possibly might be a good idea to use an enum for tokens instead of // &'static str @@ -48,7 +43,7 @@ pub struct Pair { #[derive(Debug)] pub struct Blockchain { - pub trader_secret_key: SecretKey, + pub trader_secret_key: PrivateKeySigner, pub web3: Web3, pub web3_url: String, pub web3_ws_url: String, @@ -177,13 +172,13 @@ impl QuotedOrder { /// The UID of the order. pub fn order_uid(&self, blockchain: &Blockchain) -> tests::boundary::OrderUid { - self.boundary(blockchain, blockchain.trader_secret_key) + self.boundary(blockchain, blockchain.trader_secret_key.clone()) .uid() } /// The signature of the order. pub fn order_signature(&self, blockchain: &Blockchain) -> Vec { - self.boundary(blockchain, blockchain.trader_secret_key) + self.boundary(blockchain, blockchain.trader_secret_key.clone()) .signature() } @@ -191,12 +186,17 @@ impl QuotedOrder { pub fn order_signature_with_private_key( &self, blockchain: &Blockchain, - private_key: &PrivateKey, + signer: PrivateKeySigner, ) -> Vec { - self.boundary(blockchain, **private_key).signature() + self.boundary(blockchain, signer).signature() } - fn boundary(&self, blockchain: &Blockchain, secret_key: SecretKey) -> tests::boundary::Order { + fn boundary( + &self, + blockchain: &Blockchain, + signer: PrivateKeySigner, + ) -> tests::boundary::Order { + let owner = signer.address().into_legacy(); tests::boundary::Order { sell_token: blockchain.get_token(self.order.sell_token).into_legacy(), buy_token: blockchain.get_token(self.order.buy_token).into_legacy(), @@ -206,9 +206,9 @@ impl QuotedOrder { receiver: self.order.receiver.map(IntoLegacy::into_legacy), user_fee: self.order.fee_amount.into_legacy(), side: self.order.side, - secret_key: PrivateKeySigner::from_bytes((&secret_key.secret_bytes()).into()).unwrap(), + secret_key: signer, domain_separator: blockchain.domain_separator, - owner: (&secret_key).address(), + owner, partially_fillable: matches!(self.order.partial, Partial::Yes { .. }), } } @@ -217,7 +217,7 @@ impl QuotedOrder { pub struct Config { pub pools: Vec, // Main trader secret key (the account deploying the contracts) - pub main_trader_secret_key: SecretKey, + pub main_trader_secret_key: PrivateKeySigner, pub solvers: Vec, pub settlement_address: Option, pub balances_address: Option, @@ -236,77 +236,62 @@ impl Blockchain { let node = Node::new(&config.rpc_args).await; let web3 = Web3::new_from_url(&node.url()); - let private_key = config.main_trader_secret_key.as_ref(); + let main_trader_address = config.main_trader_secret_key.address(); web3.wallet - .register_signer(PrivateKeySigner::from_bytes(private_key.into()).unwrap()); - - let main_trader_account = ethcontract::Account::Offline( - ethcontract::PrivateKey::from_slice(private_key).unwrap(), - None, - ); - let signer = PrivateKeySigner::from_slice(private_key).unwrap(); - web3.wallet.register_signer(signer); - // This account is equivalent to `primary_account`, but due to the wallet + .register_signer(config.main_trader_secret_key.clone()); + // This account is equivalent to the first test account, but due to the wallet // initialization process and the fact that we launch anvil manually, we need to // add it ourselves. // It also must be added after the main_trader because otherwise this will be // used as the default signing account - let anvil_test_account = MnemonicBuilder::english() + let primary_account = MnemonicBuilder::english() .phrase("test test test test test test test test test test test junk") .index(0) .unwrap() .build() .unwrap(); - web3.wallet.register_signer(anvil_test_account); - - let primary_account = primary_account(&web3).await; let primary_address = primary_account.address(); + web3.wallet.register_signer(primary_account); // Use the primary account to fund the trader, cow amm and the solver with ETH. - let balance = web3 - .alloy - .get_balance(primary_address.into_alloy()) - .await - .unwrap(); + let balance = web3.alloy.get_balance(primary_address).await.unwrap(); wait_for( &web3, - web3.eth() - .send_transaction(web3::types::TransactionRequest { - from: primary_address, - to: Some(main_trader_account.address()), - value: Some((balance / alloy::primitives::U256::from(5)).into_legacy()), - ..Default::default() - }), + web3.alloy.send_and_watch( + TransactionRequest::default() + .from(primary_address) + .to(main_trader_address) + .value(balance / alloy::primitives::U256::from(5)), + ), ) .await .unwrap(); let weth = contracts::alloy::WETH9::Instance::deploy_builder(web3.alloy.clone()) - .from(main_trader_account.address().into_alloy()) + .from(main_trader_address) .deploy() .await .unwrap(); let weth = WETH9::WETH9::new(weth, web3.alloy.clone()); wait_for( &web3, - ethcontract::transaction::TransactionBuilder::new(web3.legacy.clone()) - .from(primary_account) - .to(weth.address().into_legacy()) - .value((balance / alloy::primitives::U256::from(5)).into_legacy()) - .send(), + web3.alloy.send_and_watch( + TransactionRequest::default() + .from(primary_address) + .to(*weth.address()) + .value(balance / alloy::primitives::U256::from(5)), + ), ) .await .unwrap(); // Set up the settlement contract and related contracts. - let vault_authorizer = BalancerV2Authorizer::Instance::deploy_builder( - web3.alloy.clone(), - main_trader_account.address().into_alloy(), - ) - .from(main_trader_account.address().into_alloy()) - .deploy() - .await - .unwrap(); + let vault_authorizer = + BalancerV2Authorizer::Instance::deploy_builder(web3.alloy.clone(), main_trader_address) + .from(main_trader_address) + .deploy() + .await + .unwrap(); let vault = BalancerV2Vault::Instance::deploy_builder( web3.alloy.clone(), vault_authorizer, @@ -314,7 +299,7 @@ impl Blockchain { alloy::primitives::U256::ZERO, alloy::primitives::U256::ZERO, ) - .from(main_trader_account.address().into_alloy()) + .from(main_trader_address) .deploy() .await .unwrap(); @@ -367,7 +352,7 @@ impl Blockchain { let balances_address = match config.balances_address { Some(balances_address) => balances_address, None => Balances::Instance::deploy_builder(web3.alloy.clone()) - .from(main_trader_account.address().into_alloy()) + .from(main_trader_address) .deploy() .await .unwrap(), @@ -375,8 +360,8 @@ impl Blockchain { let balances = Balances::Instance::new(balances_address, web3.alloy.clone()); authenticator - .initializeManager(main_trader_account.address().into_alloy()) - .from(main_trader_account.address().into_alloy()) + .initializeManager(main_trader_address) + .from(main_trader_address) .send_and_watch() .await .unwrap(); @@ -385,7 +370,7 @@ impl Blockchain { signatures_address } else { Signatures::Instance::deploy_builder(web3.alloy.clone()) - .from(main_trader_account.address().into_alloy()) + .from(main_trader_address) .deploy() .await .unwrap() @@ -394,44 +379,36 @@ impl Blockchain { let flashloan_router_address = FlashLoanRouter::Instance::deploy_builder(web3.alloy.clone(), *settlement.address()) - .from(main_trader_account.address().into_alloy()) + .from(main_trader_address) .deploy() .await .unwrap(); let flashloan_router = FlashLoanRouter::Instance::new(flashloan_router_address, web3.alloy.clone()); - let mut trader_accounts = Vec::new(); + let mut trader_addresses: Vec
= Vec::new(); for config in config.solvers { authenticator .addSolver(config.address()) - .from(main_trader_account.address().into_alloy()) + .from(main_trader_address) .send_and_watch() .await .unwrap(); wait_for( &web3, - web3.eth() - .send_transaction(web3::types::TransactionRequest { - from: primary_address, - to: Some(config.address().into_legacy()), - value: Some(config.balance.into_legacy()), - ..Default::default() - }), + web3.alloy.send_and_watch( + TransactionRequest::default() + .from(primary_address) + .to(config.address()) + .value(config.balance), + ), ) .await .unwrap(); if !config.balance.is_zero() { - let private_key = config.private_key.as_ref(); - let signer = PrivateKeySigner::from_slice(private_key).unwrap(); - web3.wallet.register_signer(signer); - - let trader_account = ethcontract::Account::Offline( - ethcontract::PrivateKey::from_slice(private_key).unwrap(), - None, - ); - trader_accounts.push(trader_account); + trader_addresses.push(config.signer.address()); + web3.wallet.register_signer(config.signer); } } @@ -457,9 +434,9 @@ impl Blockchain { // Create the uniswap factory. let contract_address = contracts::alloy::UniswapV2Factory::Instance::deploy_builder( web3.alloy.clone(), - main_trader_account.address().into_alloy(), + main_trader_address, ) - .from(main_trader_account.address().into_alloy()) + .from(main_trader_address) .deploy() .await .unwrap(); @@ -483,7 +460,7 @@ impl Blockchain { // Create the pair. uniswap_factory .createPair(token_a, token_b) - .from(main_trader_account.address().into_alloy()) + .from(main_trader_address) .send_and_watch() .await .unwrap(); @@ -504,31 +481,31 @@ impl Blockchain { }); if pool.reserve_a.token == "WETH" { weth.transfer(*pair.address(), pool.reserve_a.amount) - .from(primary_address.into_alloy()) + .from(primary_address) .send_and_watch() .await .unwrap(); weth.transfer(*settlement.address(), pool.reserve_a.amount) - .from(primary_address.into_alloy()) + .from(primary_address) .send_and_watch() .await .unwrap(); - for trader_account in trader_accounts.iter() { - weth.transfer(trader_account.address().into_alloy(), pool.reserve_a.amount) - .from(primary_address.into_alloy()) + for trader_address in trader_addresses.iter().copied() { + weth.transfer(trader_address, pool.reserve_a.amount) + .from(primary_address) .send_and_watch() .await .unwrap(); } } else { - for trader_account in trader_accounts.iter() { + for trader_address in trader_addresses.iter().copied() { let vault_relayer = settlement.vaultRelayer().call().await.unwrap(); tokens .get(pool.reserve_a.token) .unwrap() .approve(vault_relayer, U256::MAX) - .from(trader_account.address().into_alloy()) + .from(trader_address) .send_and_watch() .await .unwrap(); @@ -538,7 +515,7 @@ impl Blockchain { .get(pool.reserve_a.token) .unwrap() .mint(*pair.address(), pool.reserve_a.amount) - .from(main_trader_account.address().into_alloy()) + .from(main_trader_address) .send_and_watch() .await .unwrap(); @@ -547,17 +524,17 @@ impl Blockchain { .get(pool.reserve_a.token) .unwrap() .mint(*settlement.address(), pool.reserve_a.amount) - .from(main_trader_account.address().into_alloy()) + .from(main_trader_address) .send_and_watch() .await .unwrap(); - for trader_account in trader_accounts.iter() { + for trader_address in trader_addresses.iter().copied() { tokens .get(pool.reserve_a.token) .unwrap() - .mint(trader_account.address().into_alloy(), pool.reserve_a.amount) - .from(main_trader_account.address().into_alloy()) + .mint(trader_address, pool.reserve_a.amount) + .from(main_trader_address) .send_and_watch() .await .unwrap(); @@ -565,31 +542,31 @@ impl Blockchain { } if pool.reserve_b.token == "WETH" { weth.transfer(*pair.address(), pool.reserve_b.amount) - .from(primary_address.into_alloy()) + .from(primary_address) .send_and_watch() .await .unwrap(); weth.transfer(*settlement.address(), pool.reserve_b.amount) - .from(primary_address.into_alloy()) + .from(primary_address) .send_and_watch() .await .unwrap(); - for trader_account in trader_accounts.iter() { - weth.transfer(trader_account.address().into_alloy(), pool.reserve_b.amount) - .from(primary_address.into_alloy()) + for trader_address in trader_addresses.iter().copied() { + weth.transfer(trader_address, pool.reserve_b.amount) + .from(primary_address) .send_and_watch() .await .unwrap(); } } else { - for trader_account in trader_accounts.iter() { + for trader_address in trader_addresses.iter().copied() { let vault_relayer = settlement.vaultRelayer().call().await.unwrap(); tokens .get(pool.reserve_b.token) .unwrap() .approve(vault_relayer, U256::MAX) - .from(trader_account.address().into_alloy()) + .from(trader_address) .send_and_watch() .await .unwrap(); @@ -599,7 +576,7 @@ impl Blockchain { .get(pool.reserve_b.token) .unwrap() .mint(*pair.address(), pool.reserve_b.amount) - .from(main_trader_account.address().into_alloy()) + .from(main_trader_address) .send_and_watch() .await .unwrap(); @@ -608,16 +585,16 @@ impl Blockchain { .get(pool.reserve_b.token) .unwrap() .mint(*settlement.address(), pool.reserve_b.amount) - .from(main_trader_account.address().into_alloy()) + .from(main_trader_address) .send_and_watch() .await .unwrap(); - for trader_account in trader_accounts.iter() { + for trader_address in trader_addresses.iter().copied() { tokens .get(pool.reserve_b.token) .unwrap() - .mint(trader_account.address().into_alloy(), pool.reserve_b.amount) - .from(main_trader_account.address().into_alloy()) + .mint(trader_address, pool.reserve_b.amount) + .from(main_trader_address) .send_and_watch() .await .unwrap(); @@ -626,7 +603,7 @@ impl Blockchain { pair.mint(::alloy::primitives::address!( "0x8270bA71b28CF60859B547A2346aCDE824D6ed40" )) - .from(main_trader_account.address().into_alloy()) + .from(main_trader_address) .send_and_watch() .await .unwrap(); @@ -762,10 +739,10 @@ impl Blockchain { let execution = self.execution(order); // Register the trader account as a signer - let trader_private_key_signer = - PrivateKeySigner::from_bytes(self.trader_secret_key.as_ref().into()).unwrap(); - let trader_address = trader_private_key_signer.address(); - self.web3.wallet.register_signer(trader_private_key_signer); + let trader_address = self.trader_secret_key.address(); + self.web3 + .wallet + .register_signer(self.trader_secret_key.clone()); // Fund the trader account with tokens needed for the solution. if order.sell_token == "WETH" { @@ -890,13 +867,6 @@ impl Blockchain { } } -async fn primary_account(web3: &Web3) -> ethcontract::Account { - ethcontract::Account::Local( - web3.alloy.get_accounts().await.unwrap()[0].into_legacy(), - None, - ) -} - /// A blockchain node for development purposes. Dropping this type will /// terminate the node. pub struct Node { diff --git a/crates/driver/src/tests/setup/driver.rs b/crates/driver/src/tests/setup/driver.rs index 315de8676e..bdd69f6fa7 100644 --- a/crates/driver/src/tests/setup/driver.rs +++ b/crates/driver/src/tests/setup/driver.rs @@ -314,7 +314,7 @@ async fn create_config_file( endpoint = "http://{}" absolute-slippage = "{}" relative-slippage = "{}" - account = "0x{}" + account = "{}" solving-share-of-deadline = {} http-time-buffer = "{}ms" fee-handler = {} @@ -328,7 +328,7 @@ async fn create_config_file( .map(|abs| abs.0) .unwrap_or_default(), solver.slippage.relative, - const_hex::encode(solver.private_key.secret_bytes()), + solver.signer.to_bytes(), solver.timeouts.solving_share_of_deadline.get(), solver.timeouts.http_delay.num_milliseconds(), serde_json::to_string(&solver.fee_handler).unwrap(), diff --git a/crates/driver/src/tests/setup/mod.rs b/crates/driver/src/tests/setup/mod.rs index 579b154656..baaffde850 100644 --- a/crates/driver/src/tests/setup/mod.rs +++ b/crates/driver/src/tests/setup/mod.rs @@ -38,17 +38,16 @@ use { }, }, alloy::{ - primitives::{Address, U256, address}, + primitives::{Address, U256, address, b256}, providers::Provider, + signers::local::PrivateKeySigner, }, bigdecimal::{BigDecimal, FromPrimitive}, ethcontract::dyns::DynTransport, - ethrpc::alloy::conversions::IntoAlloy, futures::future::join_all, hyper::StatusCode, model::order::{BuyTokenDestination, SellTokenSource}, number::serialization::HexOrDecimalU256, - secp256k1::SecretKey, serde::{Deserialize, de::IntoDeserializer}, serde_with::serde_as, solvers_dto::solution::Flashloan, @@ -351,7 +350,7 @@ pub struct Solver { /// How much ETH balance should the solver be funded with? 1 ETH by default. balance: eth::U256, /// The private key for this solver. - private_key: ethcontract::PrivateKey, + signer: PrivateKeySigner, /// The slippage for this solver. slippage: Slippage, /// The fraction of time used for solving @@ -373,10 +372,9 @@ pub fn test_solver() -> Solver { Solver { name: solver::NAME.to_owned(), balance: eth::U256::from(10).pow(eth::U256::from(18)), - private_key: ethcontract::PrivateKey::from_slice( - const_hex::decode("a131a35fb8f614b31611f4fe68b6fc538b0febd2f75cd68e1282d8fd45b63326") - .unwrap(), - ) + signer: PrivateKeySigner::from_bytes(&b256!( + "a131a35fb8f614b31611f4fe68b6fc538b0febd2f75cd68e1282d8fd45b63326" + )) .unwrap(), slippage: Slippage { relative: BigDecimal::from_f64(0.3).unwrap(), @@ -393,7 +391,7 @@ pub fn test_solver() -> Solver { impl Solver { pub fn address(&self) -> eth::Address { - self.private_key.public_address().into_alloy() + self.signer.address() } pub fn name(self, name: &str) -> Self { @@ -896,17 +894,13 @@ impl Setup { .. } = self; - // Hardcoded trader account. Don't use this account for anything else!!! - let trader_secret_key = SecretKey::from_slice( - &const_hex::decode("f9f831cee763ef826b8d45557f0f8677b27045e0e011bcd78571a40acc8a6cc3") - .unwrap(), - ) - .unwrap(); - // Create the necessary components for testing. let blockchain = Blockchain::new(blockchain::Config { pools, - main_trader_secret_key: trader_secret_key, + main_trader_secret_key: PrivateKeySigner::from_bytes(&b256!( + "f9f831cee763ef826b8d45557f0f8677b27045e0e011bcd78571a40acc8a6cc3" + )) + .unwrap(), solvers: self.solvers.clone(), settlement_address: self.settlement_address, balances_address: self.balances_address, @@ -964,7 +958,7 @@ impl Setup { deadline: time::Deadline::new(deadline, solver.timeouts), quote: self.quote, fee_handler: solver.fee_handler, - private_key: solver.private_key.clone(), + private_key: solver.signer.clone(), expected_surplus_capturing_jit_order_owners: surplus_capturing_jit_order_owners .clone(), allow_multiple_solve_requests: self.allow_multiple_solve_requests, diff --git a/crates/driver/src/tests/setup/solver.rs b/crates/driver/src/tests/setup/solver.rs index c24f206772..b478868538 100644 --- a/crates/driver/src/tests/setup/solver.rs +++ b/crates/driver/src/tests/setup/solver.rs @@ -13,10 +13,9 @@ use { infra::{self, Ethereum, blockchain::contracts::Addresses, config::file::FeeHandler}, tests::setup::blockchain::Trade, }, - alloy::primitives::Address, + alloy::{primitives::Address, signers::local::PrivateKeySigner}, const_hex::ToHexExt, contracts::alloy::ERC20, - ethrpc::alloy::conversions::IntoAlloy, itertools::Itertools, serde_json::json, solvers_dto::auction::FlashloanHint, @@ -25,7 +24,6 @@ use { net::SocketAddr, sync::{Arc, Mutex}, }, - web3::signing::Key, }; pub const NAME: &str = "test-solver"; @@ -44,7 +42,7 @@ pub struct Config<'a> { /// Is this a test for the /quote endpoint? pub quote: bool, pub fee_handler: FeeHandler, - pub private_key: ethcontract::PrivateKey, + pub private_key: PrivateKeySigner, pub expected_surplus_capturing_jit_order_owners: Vec
, pub allow_multiple_solve_requests: bool, } @@ -351,7 +349,7 @@ impl Solver { jit.quoted_order.order = jit .quoted_order .order - .receiver(Some(config.private_key.address().into_alloy())); + .receiver(Some(config.private_key.address())); let fee_amount = jit.quoted_order.order.solver_fee.unwrap_or_default(); let order = json!({ "sellToken": config.blockchain.get_token(jit.quoted_order.order.sell_token), @@ -367,7 +365,7 @@ impl Solver { }, "sellTokenBalance": jit.quoted_order.order.sell_token_source, "buyTokenBalance": jit.quoted_order.order.buy_token_destination, - "signature": const_hex::encode_prefixed(jit.quoted_order.order_signature_with_private_key(config.blockchain, &config.private_key)), + "signature": const_hex::encode_prefixed(jit.quoted_order.order_signature_with_private_key(config.blockchain, config.private_key.clone())), "signingScheme": if config.quote { "eip1271" } else { "eip712" }, }); trades_json.push(json!({ diff --git a/crates/e2e/Cargo.toml b/crates/e2e/Cargo.toml index 292dc18361..5c6c0ff498 100644 --- a/crates/e2e/Cargo.toml +++ b/crates/e2e/Cargo.toml @@ -10,6 +10,7 @@ license = "MIT OR Apache-2.0" [dependencies] alloy = { workspace = true, default-features = false, features = ["json-rpc", "providers", "rpc-client", "rpc-types", "transports", "reqwest", "signers", "signer-local", "signer-mnemonic", "provider-anvil-api", "provider-debug-api", "sol-types"] } +alloy-signer = {workspace = true, default-features = false, features = ["eip712"]} app-data = { workspace = true } anyhow = { workspace = true } autopilot = { workspace = true } diff --git a/crates/e2e/src/setup/colocation.rs b/crates/e2e/src/setup/colocation.rs index b2cdf38223..01c91be524 100644 --- a/crates/e2e/src/setup/colocation.rs +++ b/crates/e2e/src/setup/colocation.rs @@ -141,7 +141,7 @@ pub fn start_driver_with_config_override( base_tokens: _, merge_solutions, }| { - let account = const_hex::encode(account.private_key()); + let account = account.signer.to_bytes(); format!( r#" [[solver]] diff --git a/crates/e2e/src/setup/onchain_components/mod.rs b/crates/e2e/src/setup/onchain_components/mod.rs index 42a3ddc59a..3f33f7ca02 100644 --- a/crates/e2e/src/setup/onchain_components/mod.rs +++ b/crates/e2e/src/setup/onchain_components/mod.rs @@ -16,7 +16,7 @@ use { GPv2AllowListAuthentication::GPv2AllowListAuthentication, test::CowProtocolToken, }, - ethcontract::{Account, H160, PrivateKey, U256}, + ethcontract::{Account, H160, U256}, ethrpc::alloy::{ CallBuilderExt, ProviderSignerExt, @@ -38,21 +38,12 @@ pub mod safe; #[derive(Clone, Debug)] pub struct TestAccount { - account: Account, - private_key: [u8; 32], + pub signer: PrivateKeySigner, } impl TestAccount { - pub fn account(&self) -> &Account { - &self.account - } - pub fn address(&self) -> Address { - self.account.address().into_alloy() - } - - pub fn private_key(&self) -> &[u8; 32] { - &self.private_key + self.signer.address() } pub fn sign_typed_data( @@ -64,7 +55,7 @@ impl TestAccount { EcdsaSigningScheme::Eip712, domain_separator, struct_hash, - &PrivateKeySigner::from_slice(self.private_key()).unwrap(), + &PrivateKeySigner::from_bytes(&self.signer.to_bytes()).unwrap(), ) } @@ -99,14 +90,11 @@ impl Iterator for AccountGenerator { self.id = self.id.checked_add(1)?; buffer[24..].copy_from_slice(&self.id.to_be_bytes()); - let Ok(pk) = PrivateKey::from_raw(buffer) else { + let Some(signer) = PrivateKeySigner::from_slice(&buffer).ok() else { continue; }; - break Some(TestAccount { - account: Account::Offline(pk, None), - private_key: buffer, - }); + break Some(TestAccount { signer }); } } } @@ -114,14 +102,14 @@ impl Iterator for AccountGenerator { #[derive(Debug)] pub struct MintableToken { contract: ERC20Mintable::Instance, - minter: Account, + minter: Address, } impl MintableToken { pub async fn mint(&self, to: Address, amount: ::alloy::primitives::U256) { self.contract .mint(to, amount) - .from(self.minter.address().into_alloy()) + .from(self.minter) .send_and_watch() .await .unwrap(); @@ -254,9 +242,7 @@ impl OnchainComponents { assert_eq!(res.len(), N); for account in &res { - let signer = PrivateKeySigner::from_slice(account.private_key()).unwrap(); - self.web3.wallet.register_signer(signer); - + self.web3.wallet.register_signer(account.signer.clone()); self.send_wei(account.address(), with_wei).await; } @@ -272,9 +258,7 @@ impl OnchainComponents { let solvers = self.make_accounts::(with_wei).await; for solver in &solvers { - self.web3 - .wallet - .register_signer(PrivateKeySigner::from_slice(solver.private_key()).unwrap()); + self.web3.wallet.register_signer(solver.signer.clone()); self.contracts .gp_authenticator @@ -360,22 +344,19 @@ impl OnchainComponents { } /// Deploy `N` tokens without any onchain liquidity - pub async fn deploy_tokens(&self, minter: &Account) -> [MintableToken; N] { + pub async fn deploy_tokens(&self, minter: Address) -> [MintableToken; N] { let mut res = Vec::with_capacity(N); for _ in 0..N { let contract_address = ERC20Mintable::Instance::deploy_builder(self.web3.alloy.clone()) // We can't escape the .from here because we need to ensure Minter permissions later on - .from(minter.address().into_alloy()) + .from(minter) .deploy() .await .expect("ERC20Mintable deployment failed"); let contract = ERC20Mintable::Instance::new(contract_address, self.web3.alloy.clone()); - res.push(MintableToken { - contract, - minter: minter.clone(), - }); + res.push(MintableToken { contract, minter }); } res.try_into().unwrap() @@ -387,16 +368,13 @@ impl OnchainComponents { token_amount: ::alloy::primitives::U256, weth_amount: ::alloy::primitives::U256, ) -> [MintableToken; N] { - let minter = Account::Local( - self.web3 - .alloy - .get_accounts() - .await - .expect("getting accounts failed")[0] - .into_legacy(), - None, - ); - let tokens = self.deploy_tokens::(&minter).await; + let minter = self + .web3 + .alloy + .get_accounts() + .await + .expect("getting accounts failed")[0]; + let tokens = self.deploy_tokens::(minter).await; self.seed_weth_uni_v2_pools(tokens.iter(), token_amount, weth_amount) .await; tokens @@ -410,8 +388,8 @@ impl OnchainComponents { ) { for MintableToken { contract, minter } in tokens { contract - .mint(minter.address().into_alloy(), token_amount) - .from(minter.address().into_alloy()) + .mint(*minter, token_amount) + .from(*minter) .send_and_watch() .await .unwrap(); @@ -420,7 +398,7 @@ impl OnchainComponents { .weth .deposit() .value(weth_amount) - .from(minter.address().into_alloy()) + .from(*minter) .send_and_watch() .await .unwrap(); @@ -428,14 +406,14 @@ impl OnchainComponents { self.contracts .uniswap_v2_factory .createPair(*contract.address(), *self.contracts.weth.address()) - .from(minter.address().into_alloy()) + .from(*minter) .send_and_watch() .await .unwrap(); contract .approve(*self.contracts.uniswap_v2_router.address(), token_amount) - .from(minter.address().into_alloy()) + .from(*minter) .send_and_watch() .await .unwrap(); @@ -443,7 +421,7 @@ impl OnchainComponents { self.contracts .weth .approve(*self.contracts.uniswap_v2_router.address(), weth_amount) - .from(minter.address().into_alloy()) + .from(*minter) .send_and_watch() .await .unwrap(); @@ -457,10 +435,10 @@ impl OnchainComponents { weth_amount, ::alloy::primitives::U256::ZERO, ::alloy::primitives::U256::ZERO, - minter.address().into_alloy(), + *minter, ::alloy::primitives::U256::MAX, ) - .from(minter.address().into_alloy()) + .from(*minter) .send_and_watch() .await .unwrap(); @@ -472,14 +450,14 @@ impl OnchainComponents { asset_a: (&MintableToken, ::alloy::primitives::U256), asset_b: (&MintableToken, ::alloy::primitives::U256), ) { - let lp = &asset_a.0.minter; - asset_a.0.mint(lp.address().into_alloy(), asset_a.1).await; - asset_b.0.mint(lp.address().into_alloy(), asset_b.1).await; + let lp = asset_a.0.minter; + asset_a.0.mint(lp, asset_a.1).await; + asset_b.0.mint(lp, asset_b.1).await; self.contracts .uniswap_v2_factory .createPair(*asset_a.0.address(), *asset_b.0.address()) - .from(lp.address().into_alloy()) + .from(lp) .send_and_watch() .await .unwrap(); @@ -487,7 +465,7 @@ impl OnchainComponents { asset_a .0 .approve(*self.contracts.uniswap_v2_router.address(), asset_a.1) - .from(lp.address().into_alloy()) + .from(lp) .send_and_watch() .await .unwrap(); @@ -495,7 +473,7 @@ impl OnchainComponents { asset_b .0 .approve(*self.contracts.uniswap_v2_router.address(), asset_b.1) - .from(lp.address().into_alloy()) + .from(lp) .send_and_watch() .await .unwrap(); @@ -508,10 +486,10 @@ impl OnchainComponents { asset_b.1, ::alloy::primitives::U256::ZERO, ::alloy::primitives::U256::ZERO, - lp.address().into_alloy(), + lp, ::alloy::primitives::U256::MAX, ) - .from(lp.address().into_alloy()) + .from(lp) .send_and_watch() .await .unwrap(); @@ -549,10 +527,10 @@ impl OnchainComponents { pair.swap( ::alloy::primitives::U256::from(out0), ::alloy::primitives::U256::from(out1), - token.minter.address().into_alloy(), + token.minter, Default::default(), ) - .from(token.minter.address().into_alloy()) + .from(token.minter) .send_and_watch() .await .expect("Uniswap V2 pair couldn't mint"); diff --git a/crates/e2e/tests/e2e/app_data.rs b/crates/e2e/tests/e2e/app_data.rs index 9a02e82cf3..c56f1521bb 100644 --- a/crates/e2e/tests/e2e/app_data.rs +++ b/crates/e2e/tests/e2e/app_data.rs @@ -1,5 +1,4 @@ use { - ::alloy::signers::local::PrivateKeySigner, app_data::{AppDataHash, hash_full_app_data}, e2e::setup::*, ethrpc::alloy::{CallBuilderExt, conversions::IntoAlloy}, @@ -59,7 +58,7 @@ async fn app_data(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); // Adjust valid to make sure we get unique UIDs. valid_to += 1; @@ -221,7 +220,7 @@ async fn app_data_full_format(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); // Adjust valid to make sure we get unique UIDs. valid_to += 1; diff --git a/crates/e2e/tests/e2e/app_data_signer.rs b/crates/e2e/tests/e2e/app_data_signer.rs index 1ee06b2ce4..35095f9bd6 100644 --- a/crates/e2e/tests/e2e/app_data_signer.rs +++ b/crates/e2e/tests/e2e/app_data_signer.rs @@ -1,5 +1,5 @@ use { - alloy::{primitives::Address, signers::local::PrivateKeySigner}, + alloy::primitives::Address, e2e::setup::{OnchainComponents, Services, TestAccount, run_test, safe::Safe}, ethrpc::alloy::{CallBuilderExt, conversions::IntoAlloy}, model::{ @@ -61,7 +61,7 @@ async fn order_creation_checks_metadata_signer(web3: Web3) { order_creation.sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(signer.private_key()).unwrap(), + &signer.signer, ) }; diff --git a/crates/e2e/tests/e2e/autopilot_leader.rs b/crates/e2e/tests/e2e/autopilot_leader.rs index b8f6f5d6af..505c3f86db 100644 --- a/crates/e2e/tests/e2e/autopilot_leader.rs +++ b/crates/e2e/tests/e2e/autopilot_leader.rs @@ -1,5 +1,4 @@ use { - alloy::signers::local::PrivateKeySigner, autopilot::shutdown_controller::ShutdownController, e2e::setup::{OnchainComponents, Services, TIMEOUT, colocation, run_test, wait_for_condition}, ethrpc::{ @@ -114,7 +113,7 @@ async fn dual_autopilot_only_leader_produces_auctions(web3: Web3) { .sign( model::signature::EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ) }; diff --git a/crates/e2e/tests/e2e/buffers.rs b/crates/e2e/tests/e2e/buffers.rs index fa7ff27814..cfed844a7d 100644 --- a/crates/e2e/tests/e2e/buffers.rs +++ b/crates/e2e/tests/e2e/buffers.rs @@ -1,5 +1,5 @@ use { - ::alloy::{primitives::U256, signers::local::PrivateKeySigner}, + ::alloy::primitives::U256, e2e::setup::*, ethrpc::alloy::{CallBuilderExt, conversions::IntoAlloy}, model::{ @@ -98,7 +98,7 @@ async fn onchain_settlement_without_liquidity(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); services.create_order(&order).await.unwrap(); @@ -125,7 +125,7 @@ async fn onchain_settlement_without_liquidity(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); services.create_order(&order).await.unwrap(); diff --git a/crates/e2e/tests/e2e/cow_amm.rs b/crates/e2e/tests/e2e/cow_amm.rs index fb6c650c6e..e30022e4b6 100644 --- a/crates/e2e/tests/e2e/cow_amm.rs +++ b/crates/e2e/tests/e2e/cow_amm.rs @@ -5,7 +5,6 @@ use { Provider, ext::{AnvilApi, ImpersonateConfig}, }, - signers::local::PrivateKeySigner, }, contracts::alloy::{ ERC20, @@ -146,7 +145,7 @@ async fn cow_amm_jit(web3: Web3) { Bytes::copy_from_slice(&oracle_data), FixedBytes(APP_DATA), ) - .from(cow_amm_owner.account().address().into_alloy()) + .from(cow_amm_owner.address()) .send_and_watch() .await .unwrap(); @@ -301,7 +300,7 @@ async fn cow_amm_jit(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(bob.private_key()).unwrap(), + &bob.signer, ); let user_order_id = services.create_order(&user_order).await.unwrap(); @@ -590,7 +589,7 @@ factory = "0xf76c421bAb7df8548604E60deCCcE50477C10462" .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); // Warm up co-located driver by quoting the order (otherwise placing an order @@ -782,7 +781,7 @@ async fn cow_amm_opposite_direction(web3: Web3) { Bytes::copy_from_slice(&oracle_data), FixedBytes(APP_DATA), ) - .from(cow_amm_owner.account().address().into_alloy()) + .from(cow_amm_owner.address()) .send_and_watch() .await .unwrap(); @@ -1018,7 +1017,7 @@ async fn cow_amm_opposite_direction(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(bob.private_key()).unwrap(), + &bob.signer, ); let user_order_id = services.create_order(&user_order).await.unwrap(); diff --git a/crates/e2e/tests/e2e/eth_integration.rs b/crates/e2e/tests/e2e/eth_integration.rs index 937213a49f..ca5606f1bf 100644 --- a/crates/e2e/tests/e2e/eth_integration.rs +++ b/crates/e2e/tests/e2e/eth_integration.rs @@ -1,5 +1,5 @@ use { - ::alloy::{providers::Provider, signers::local::PrivateKeySigner}, + ::alloy::providers::Provider, e2e::setup::*, ethcontract::prelude::Address, ethrpc::alloy::{CallBuilderExt, conversions::IntoAlloy}, @@ -88,7 +88,7 @@ async fn eth_integration(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader_a.private_key()).unwrap(), + &trader_a.signer, ); services.create_order(&order_buy_eth_a).await.unwrap(); let order_buy_eth_b = OrderCreation { @@ -103,7 +103,7 @@ async fn eth_integration(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader_b.private_key()).unwrap(), + &trader_b.signer, ); services.create_order(&order_buy_eth_b).await.unwrap(); diff --git a/crates/e2e/tests/e2e/ethflow.rs b/crates/e2e/tests/e2e/ethflow.rs index f7664d45b5..6624861247 100644 --- a/crates/e2e/tests/e2e/ethflow.rs +++ b/crates/e2e/tests/e2e/ethflow.rs @@ -19,7 +19,7 @@ use { run_test, wait_for_condition, }, - ethcontract::{Account, H160}, + ethcontract::H160, ethrpc::{ Web3, alloy::{ @@ -154,10 +154,7 @@ async fn eth_flow_tx(web3: Web3) { app_data: OrderCreationAppData::Hash { hash: app_data::AppDataHash(const_hex::decode(&hash[2..]).unwrap().try_into().unwrap()), }, - ..intent.to_quote_request( - trader.account().address().into_alloy(), - &onchain.contracts().weth, - ) + ..intent.to_quote_request(trader.address(), &onchain.contracts().weth) }; let quote: OrderQuoteResponse = test_submit_quote(&services, "e_request).await; @@ -173,7 +170,7 @@ async fn eth_flow_tx(web3: Web3) { let ethflow_contract = onchain.contracts().ethflows.first().unwrap(); submit_order( ðflow_order, - trader.account(), + trader.address(), onchain.contracts(), ethflow_contract, ) @@ -290,7 +287,7 @@ async fn eth_flow_without_quote(web3: Web3) { let ethflow_contract = onchain.contracts().ethflows.first().unwrap(); submit_order( ðflow_order, - trader.account(), + trader.address(), onchain.contracts(), ethflow_contract, ) @@ -334,10 +331,7 @@ async fn eth_flow_indexing_after_refund(web3: Web3) { buy_token: *dai.address(), receiver: Address::repeat_byte(42), }) - .to_quote_request( - dummy_trader.account().address().into_alloy(), - &onchain.contracts().weth, - ), + .to_quote_request(dummy_trader.address(), &onchain.contracts().weth), ) .await, valid_to, @@ -346,7 +340,7 @@ async fn eth_flow_indexing_after_refund(web3: Web3) { let ethflow_contract = onchain.contracts().ethflows.first().unwrap(); submit_order( &dummy_order, - dummy_trader.account(), + dummy_trader.address(), onchain.contracts(), ethflow_contract, ) @@ -374,10 +368,7 @@ async fn eth_flow_indexing_after_refund(web3: Web3) { buy_token, receiver, }) - .to_quote_request( - trader.account().address().into_alloy(), - &onchain.contracts().weth, - ), + .to_quote_request(trader.address(), &onchain.contracts().weth), ) .await, valid_to, @@ -385,7 +376,7 @@ async fn eth_flow_indexing_after_refund(web3: Web3) { .include_slippage_bps(300); submit_order( ðflow_order, - trader.account(), + trader.address(), onchain.contracts(), ethflow_contract, ) @@ -435,7 +426,7 @@ async fn test_submit_quote( async fn submit_order( ethflow_order: &ExtendedEthFlowOrder, - user: &Account, + user: Address, contracts: &Contracts, ethflow_contract: &CoWSwapEthFlow::Instance, ) { @@ -445,12 +436,12 @@ async fn submit_order( ); let result = ethflow_order - .mine_order_creation(user.address().into_alloy(), ethflow_contract) + .mine_order_creation(user, ethflow_contract) .await; assert!(result.status()); // success assert_eq!( ethflow_order.status(contracts, ethflow_contract).await, - EthFlowOrderOnchainStatus::Created(user.address(), ethflow_order.0.validTo) + EthFlowOrderOnchainStatus::Created(user, ethflow_order.0.validTo) ); } @@ -813,7 +804,7 @@ impl ExtendedEthFlowOrder { #[derive(Debug, PartialEq, Eq)] pub enum EthFlowOrderOnchainStatus { Invalidated, - Created(H160, u32), + Created(Address, u32), Free, } @@ -822,7 +813,7 @@ impl From for EthFlowOrderOnchainS match value.owner { owner if owner == NO_OWNER => Self::Free, owner if owner == INVALIDATED_OWNER => Self::Invalidated, - _ => Self::Created(value.owner.into_legacy(), value.validTo), + _ => Self::Created(value.owner, value.validTo), } } } @@ -896,7 +887,7 @@ async fn eth_flow_zero_buy_amount(web3: Web3) { let ethflow_contract = onchain.contracts().ethflows.first().unwrap(); submit_order( ðflow_order, - trader.account(), + trader.address(), onchain.contracts(), ethflow_contract, ) diff --git a/crates/e2e/tests/e2e/hooks.rs b/crates/e2e/tests/e2e/hooks.rs index 6dffc178ad..bc8d5eeb14 100644 --- a/crates/e2e/tests/e2e/hooks.rs +++ b/crates/e2e/tests/e2e/hooks.rs @@ -1,5 +1,5 @@ use { - alloy::{providers::Provider, signers::local::PrivateKeySigner}, + alloy::providers::Provider, app_data::Hook, e2e::setup::{ OnchainComponents, @@ -106,7 +106,7 @@ async fn gas_limit(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); let error = services.create_order(&order).await.unwrap_err(); assert_eq!(error.0, StatusCode::BAD_REQUEST); @@ -187,7 +187,7 @@ async fn allowance(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); services.create_order(&order).await.unwrap(); onchain.mint_block().await; @@ -492,7 +492,7 @@ async fn partial_fills(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); services.create_order(&order).await.unwrap(); onchain.mint_block().await; diff --git a/crates/e2e/tests/e2e/jit_orders.rs b/crates/e2e/tests/e2e/jit_orders.rs index 98c2913ce9..cfc205105b 100644 --- a/crates/e2e/tests/e2e/jit_orders.rs +++ b/crates/e2e/tests/e2e/jit_orders.rs @@ -1,5 +1,5 @@ use { - ::alloy::{primitives::U256, signers::local::PrivateKeySigner}, + ::alloy::primitives::U256, e2e::setup::{colocation::SolverEngine, mock::Mock, solution::JitOrder, *}, ethrpc::alloy::{ CallBuilderExt, @@ -121,7 +121,7 @@ async fn single_limit_order_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); let trader_balance_before = token.balanceOf(trader.address()).call().await.unwrap(); @@ -150,7 +150,7 @@ async fn single_limit_order_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(solver.private_key()).unwrap(), + &solver.signer, ); mock_solver.configure_solution(Some(Solution { diff --git a/crates/e2e/tests/e2e/limit_orders.rs b/crates/e2e/tests/e2e/limit_orders.rs index 01db095568..06cdcde564 100644 --- a/crates/e2e/tests/e2e/limit_orders.rs +++ b/crates/e2e/tests/e2e/limit_orders.rs @@ -3,7 +3,6 @@ use { ::alloy::{ primitives::{Address, U256, address}, providers::ext::{AnvilApi, ImpersonateConfig}, - signers::local::PrivateKeySigner, }, bigdecimal::BigDecimal, contracts::alloy::ERC20, @@ -179,7 +178,7 @@ async fn single_limit_order_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader_a.private_key()).unwrap(), + &trader_a.signer, ); let balance_before = token_b.balanceOf(trader_a.address()).call().await.unwrap(); let order_id = services.create_order(&order).await.unwrap(); @@ -308,7 +307,7 @@ async fn two_limit_orders_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader_a.private_key()).unwrap(), + &trader_a.signer, ); let balance_before_a = token_b.balanceOf(trader_a.address()).call().await.unwrap(); @@ -332,7 +331,7 @@ async fn two_limit_orders_test(web3: Web3) { .sign( EcdsaSigningScheme::EthSign, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader_b.private_key()).unwrap(), + &trader_b.signer, ); let order_id = services.create_order(&order_b).await.unwrap(); @@ -442,7 +441,7 @@ async fn two_limit_orders_multiple_winners_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader_a.private_key()).unwrap(), + &trader_a.signer, ); let uid_a = services.create_order(&order_a).await.unwrap(); @@ -458,7 +457,7 @@ async fn two_limit_orders_multiple_winners_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader_b.private_key()).unwrap(), + &trader_b.signer, ); let uid_b = services.create_order(&order_b).await.unwrap(); @@ -650,7 +649,7 @@ async fn too_many_limit_orders_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); services.create_order(&order).await.unwrap(); @@ -668,7 +667,7 @@ async fn too_many_limit_orders_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); let (status, body) = services.create_order(&order).await.unwrap_err(); @@ -746,7 +745,7 @@ async fn limit_does_not_apply_to_in_market_orders_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); assert!(services.create_order(&order).await.is_ok()); @@ -763,7 +762,7 @@ async fn limit_does_not_apply_to_in_market_orders_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); let order_id = services.create_order(&order).await.unwrap(); let limit_order = services.get_order(&order_id).await.unwrap(); @@ -782,7 +781,7 @@ async fn limit_does_not_apply_to_in_market_orders_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); assert!(services.create_order(&order).await.is_ok()); @@ -799,7 +798,7 @@ async fn limit_does_not_apply_to_in_market_orders_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); let (status, body) = services.create_order(&order).await.unwrap_err(); @@ -868,7 +867,7 @@ async fn forked_mainnet_single_limit_order_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); // Warm up co-located driver by quoting the order (otherwise placing an order @@ -966,7 +965,7 @@ async fn forked_gnosis_single_limit_order_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); let sell_token_balance_before = token_usdc.balanceOf(trader.address()).call().await.unwrap(); let buy_token_balance_before = token_wxdai @@ -1001,7 +1000,7 @@ async fn no_liquidity_limit_order(web3: Web3) { let [solver] = onchain.make_solvers(10_000u64.eth()).await; let [trader_a] = onchain.make_accounts(1u64.eth()).await; - let [token_a, unsupported] = onchain.deploy_tokens(solver.account()).await; + let [token_a, unsupported] = onchain.deploy_tokens(solver.address()).await; // Fund trader accounts token_a.mint(trader_a.address(), 10u64.eth()).await; @@ -1065,7 +1064,7 @@ async fn no_liquidity_limit_order(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader_a.private_key()).unwrap(), + &trader_a.signer, ); let order_id = services.create_order(&order).await.unwrap(); onchain.mint_block().await; @@ -1078,7 +1077,7 @@ async fn no_liquidity_limit_order(web3: Web3) { .create_order(&order.sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader_a.private_key()).unwrap(), + &trader_a.signer, )) .await .unwrap_err(); diff --git a/crates/e2e/tests/e2e/liquidity.rs b/crates/e2e/tests/e2e/liquidity.rs index 018f120dfa..401f9f6720 100644 --- a/crates/e2e/tests/e2e/liquidity.rs +++ b/crates/e2e/tests/e2e/liquidity.rs @@ -5,7 +5,6 @@ use { Provider, ext::{AnvilApi, ImpersonateConfig}, }, - signers::local::PrivateKeySigner, }, chrono::{NaiveDateTime, Utc}, contracts::alloy::{ERC20, IZeroex}, @@ -22,13 +21,12 @@ use { wait_for_condition, }, }, - ethcontract::{Account, H256}, + ethcontract::H256, ethrpc::{ Web3, alloy::{ CallBuilderExt, - ProviderSignerExt, - conversions::{IntoAlloy, IntoLegacy, TryIntoAlloyAsync}, + conversions::{IntoAlloy, IntoLegacy}, }, }, model::{ @@ -71,11 +69,8 @@ async fn zero_ex_liquidity(web3: Web3) { web3.alloy.clone(), ); - let zeroex_provider = { - let signer = solver.account().clone().try_into_alloy().await.unwrap(); - web3.alloy.with_signer(signer) - }; - let zeroex = IZeroex::Instance::deployed(&zeroex_provider).await.unwrap(); + web3.wallet.register_signer(solver.signer.clone()); + let zeroex = IZeroex::Instance::deployed(&web3.alloy).await.unwrap(); let amount = 500u64.matom(); @@ -168,7 +163,7 @@ async fn zero_ex_liquidity(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); let chain_id = web3.alloy.get_chain_id().await.unwrap(); @@ -282,7 +277,7 @@ async fn zero_ex_liquidity(web3: Web3) { salt: alloy::primitives::U256::from(Utc::now().timestamp()), } .to_order_record(chain_id, *zeroex.address(), zeroex_maker); - fill_or_kill_zeroex_limit_order(&zeroex, &zeroex_order, solver.account().clone()) + fill_or_kill_zeroex_limit_order(&zeroex, &zeroex_order, solver.address()) .await .unwrap(); let zeroex_order_amounts = get_zeroex_order_amounts(&zeroex, &zeroex_order) @@ -410,7 +405,7 @@ async fn get_zeroex_order_amounts( async fn fill_or_kill_zeroex_limit_order( zeroex: &IZeroex::Instance, zeroex_order: &shared::zeroex_api::OrderRecord, - from_account: Account, + from: Address, ) -> anyhow::Result { let order = zeroex_order.order(); let tx_hash = zeroex @@ -437,7 +432,7 @@ async fn fill_or_kill_zeroex_limit_order( }, zeroex_order.order().taker_amount, ) - .from(from_account.address().into_alloy()) + .from(from) .send() .await? .watch() diff --git a/crates/e2e/tests/e2e/liquidity_source_notification.rs b/crates/e2e/tests/e2e/liquidity_source_notification.rs index b7f447ec24..179884a8d7 100644 --- a/crates/e2e/tests/e2e/liquidity_source_notification.rs +++ b/crates/e2e/tests/e2e/liquidity_source_notification.rs @@ -2,7 +2,7 @@ use { alloy::{ primitives::{Address, Bytes, U256, address}, providers::ext::{AnvilApi, ImpersonateConfig}, - signers::{SignerSync, local::PrivateKeySigner}, + signers::SignerSync, }, chrono::Utc, contracts::alloy::{ERC20, LiquoriceSettlement}, @@ -243,7 +243,7 @@ http-timeout = "10s" .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); services.create_order(&order).await.unwrap() }; @@ -274,13 +274,14 @@ http-timeout = "10s" .unwrap(); // Create Liquorice order signature - let signer = PrivateKeySigner::from_slice(liquorice_maker.private_key()).unwrap(); + let liquorice_maker_address = liquorice_maker.address(); + let signer = liquorice_maker.signer; let liquorice_order_signature = signer.sign_hash_sync(&liquorice_order_hash).unwrap(); // Create Liquorice settlement calldata liquorice_settlement .settleSingle( - liquorice_maker.address(), + liquorice_maker_address, liquorice_order.clone(), LiquoriceSettlement::Signature::TypedSignature { signatureType: 3, // EIP712 diff --git a/crates/e2e/tests/e2e/order_cancellation.rs b/crates/e2e/tests/e2e/order_cancellation.rs index b3ad336286..622f446101 100644 --- a/crates/e2e/tests/e2e/order_cancellation.rs +++ b/crates/e2e/tests/e2e/order_cancellation.rs @@ -1,5 +1,5 @@ use { - ::alloy::{primitives::U256, signers::local::PrivateKeySigner}, + ::alloy::primitives::U256, database::order_events::OrderEventLabel, e2e::setup::*, ethrpc::alloy::{CallBuilderExt, conversions::IntoAlloy}, @@ -118,7 +118,7 @@ async fn order_cancellation(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); services.create_order(&order).await.unwrap() } @@ -129,7 +129,7 @@ async fn order_cancellation(web3: Web3) { let cancellation = OrderCancellation::for_order( order_uid, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); async move { @@ -155,7 +155,7 @@ async fn order_cancellation(web3: Web3) { EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, &cancellations.hash_struct(), - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); let signed_cancellations = SignedOrderCancellations { diff --git a/crates/e2e/tests/e2e/partial_fill.rs b/crates/e2e/tests/e2e/partial_fill.rs index 2520a8ac9d..710e950e92 100644 --- a/crates/e2e/tests/e2e/partial_fill.rs +++ b/crates/e2e/tests/e2e/partial_fill.rs @@ -1,5 +1,5 @@ use { - ::alloy::{primitives::U256, signers::local::PrivateKeySigner}, + ::alloy::primitives::U256, e2e::setup::*, ethrpc::alloy::{ CallBuilderExt, @@ -70,7 +70,7 @@ async fn test(web3: Web3) { .sign( EcdsaSigningScheme::EthSign, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); let uid = services.create_order(&order).await.unwrap(); diff --git a/crates/e2e/tests/e2e/partially_fillable_balance.rs b/crates/e2e/tests/e2e/partially_fillable_balance.rs index 6ea97f3ac0..81e8dc77bf 100644 --- a/crates/e2e/tests/e2e/partially_fillable_balance.rs +++ b/crates/e2e/tests/e2e/partially_fillable_balance.rs @@ -1,5 +1,5 @@ use { - ::alloy::{primitives::U256, signers::local::PrivateKeySigner}, + ::alloy::primitives::U256, e2e::setup::*, ethrpc::alloy::{CallBuilderExt, conversions::IntoAlloy}, model::{ @@ -98,7 +98,7 @@ async fn test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader_a.private_key()).unwrap(), + &trader_a.signer, ); let order_uid = services.create_order(&order_a).await.unwrap(); onchain.mint_block().await; diff --git a/crates/e2e/tests/e2e/partially_fillable_pool.rs b/crates/e2e/tests/e2e/partially_fillable_pool.rs index 4e55a57b32..35942cdf3c 100644 --- a/crates/e2e/tests/e2e/partially_fillable_pool.rs +++ b/crates/e2e/tests/e2e/partially_fillable_pool.rs @@ -1,5 +1,5 @@ use { - ::alloy::{primitives::U256, signers::local::PrivateKeySigner}, + ::alloy::primitives::U256, e2e::setup::*, ethrpc::alloy::{CallBuilderExt, conversions::IntoAlloy}, model::{ @@ -98,7 +98,7 @@ async fn test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader_a.private_key()).unwrap(), + &trader_a.signer, ); let uid = services.create_order(&order_a).await.unwrap(); let order = services.get_order(&uid).await.unwrap(); diff --git a/crates/e2e/tests/e2e/place_order_with_quote.rs b/crates/e2e/tests/e2e/place_order_with_quote.rs index 797412c8c3..2f4cd384ab 100644 --- a/crates/e2e/tests/e2e/place_order_with_quote.rs +++ b/crates/e2e/tests/e2e/place_order_with_quote.rs @@ -1,5 +1,5 @@ use { - ::alloy::{primitives::U256, signers::local::PrivateKeySigner}, + ::alloy::primitives::U256, driver::domain::eth::NonZeroU256, e2e::{nodes::local_node::TestNodeApi, setup::*}, ethrpc::alloy::{CallBuilderExt, conversions::IntoAlloy}, @@ -101,7 +101,7 @@ async fn place_order_with_quote(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); let order_uid = services.create_order(&order).await.unwrap(); diff --git a/crates/e2e/tests/e2e/protocol_fee.rs b/crates/e2e/tests/e2e/protocol_fee.rs index c309bba9ec..b05f0ef39b 100644 --- a/crates/e2e/tests/e2e/protocol_fee.rs +++ b/crates/e2e/tests/e2e/protocol_fee.rs @@ -1,5 +1,5 @@ use { - ::alloy::{primitives::U256, signers::local::PrivateKeySigner}, + ::alloy::primitives::U256, driver::domain::eth::NonZeroU256, e2e::{ assert_approximately_eq, @@ -204,7 +204,7 @@ async fn combined_protocol_fees(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); let limit_surplus_order = OrderCreation { sell_amount: sell_amount.into_alloy(), @@ -215,7 +215,7 @@ async fn combined_protocol_fees(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); let partner_fee_order = OrderCreation { sell_amount: sell_amount.into_alloy(), @@ -227,7 +227,7 @@ async fn combined_protocol_fees(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); tracing::info!("Rebalancing AMM pools for market & limit order."); @@ -540,7 +540,7 @@ async fn surplus_partner_fee(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); let order_uid = services.create_order(&order).await.unwrap(); @@ -792,7 +792,7 @@ async fn volume_fee_buy_order_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); let uid = services.create_order(&order).await.unwrap(); @@ -949,7 +949,7 @@ async fn volume_fee_buy_order_upcoming_future_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); let uid = services.create_order(&order).await.unwrap(); diff --git a/crates/e2e/tests/e2e/quoting.rs b/crates/e2e/tests/e2e/quoting.rs index ce6d5134cd..753d193687 100644 --- a/crates/e2e/tests/e2e/quoting.rs +++ b/crates/e2e/tests/e2e/quoting.rs @@ -1,5 +1,4 @@ use { - ::alloy::signers::local::PrivateKeySigner, e2e::setup::{colocation::SolverEngine, mock::Mock, *}, ethrpc::alloy::{CallBuilderExt, conversions::IntoAlloy}, futures::FutureExt, @@ -401,7 +400,7 @@ async fn quote_timeout(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); // order creation requests always use the default quote time diff --git a/crates/e2e/tests/e2e/refunder.rs b/crates/e2e/tests/e2e/refunder.rs index d839c7c0b6..8ce2eadffa 100644 --- a/crates/e2e/tests/e2e/refunder.rs +++ b/crates/e2e/tests/e2e/refunder.rs @@ -3,11 +3,7 @@ use { ::alloy::primitives::Address, chrono::{TimeZone, Utc}, e2e::{nodes::local_node::TestNodeApi, setup::*}, - ethrpc::{ - Web3, - alloy::conversions::TryIntoAlloyAsync, - block_stream::timestamp_of_current_block_in_seconds, - }, + ethrpc::{Web3, block_stream::timestamp_of_current_block_in_seconds}, model::quote::{OrderQuoteRequest, OrderQuoteSide, QuoteSigningScheme, Validity}, number::{nonzero::NonZeroU256, units::EthUnit}, refunder::refund_service::RefundService, @@ -125,19 +121,13 @@ async fn refunder_tx(web3: Web3) { // Create the refund service and execute the refund tx let pg_pool = PgPool::connect_lazy("postgresql://").expect("failed to create database"); - let refunder_signer = { - match refunder.account().clone().try_into_alloy().await.unwrap() { - ethrpc::alloy::Account::Signer(signer) => signer, - _ => panic!("Refunder account must be a signer"), - } - }; let mut refunder = RefundService::new( pg_pool, web3, vec![ethflow_contract.clone(), ethflow_contract_2.clone()], validity_duration as i64 / 2, 10i64, - refunder_signer, + Box::new(refunder.signer), 2_000_000_000_000, // max_gas_price: 2000 Gwei 30_000_000_000, // start_priority_fee_tip: 30 Gwei ); diff --git a/crates/e2e/tests/e2e/replace_order.rs b/crates/e2e/tests/e2e/replace_order.rs index 68f8f27b1e..be8d98bb36 100644 --- a/crates/e2e/tests/e2e/replace_order.rs +++ b/crates/e2e/tests/e2e/replace_order.rs @@ -1,5 +1,5 @@ use { - ::alloy::{primitives::U256, signers::local::PrivateKeySigner}, + ::alloy::primitives::U256, e2e::{nodes::local_node::TestNodeApi, setup::*}, ethrpc::alloy::{CallBuilderExt, conversions::IntoAlloy}, model::{ @@ -126,7 +126,7 @@ async fn try_replace_unreplaceable_order_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); let balance_before = token_a.balanceOf(trader.address()).call().await.unwrap(); onchain.mint_block().await; @@ -163,7 +163,7 @@ async fn try_replace_unreplaceable_order_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); let response = services.create_order(&new_order).await; let (error_code, error_message) = response.err().unwrap(); @@ -309,7 +309,7 @@ async fn try_replace_someone_else_order_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader_a.private_key()).unwrap(), + &trader_a.signer, ); let order_id = services.create_order(&order).await.unwrap(); @@ -332,7 +332,7 @@ async fn try_replace_someone_else_order_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader_b.private_key()).unwrap(), + &trader_b.signer, ); let balance_before = token_a.balanceOf(trader_a.address()).call().await.unwrap(); let response = services.create_order(&new_order).await; @@ -451,7 +451,7 @@ async fn single_replace_order_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); let order_id = services.create_order(&order).await.unwrap(); @@ -484,7 +484,7 @@ async fn single_replace_order_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); let new_order_uid = services.create_order(&new_order).await.unwrap(); diff --git a/crates/e2e/tests/e2e/solver_competition.rs b/crates/e2e/tests/e2e/solver_competition.rs index aa10ca2529..b24a958a33 100644 --- a/crates/e2e/tests/e2e/solver_competition.rs +++ b/crates/e2e/tests/e2e/solver_competition.rs @@ -1,5 +1,5 @@ use { - ::alloy::{primitives::U256, signers::local::PrivateKeySigner}, + ::alloy::primitives::U256, e2e::setup::{colocation::SolverEngine, mock::Mock, *}, ethrpc::alloy::{ CallBuilderExt, @@ -108,7 +108,7 @@ async fn solver_competition(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); let uid = services.create_order(&order).await.unwrap(); onchain.mint_block().await; @@ -250,7 +250,7 @@ async fn wrong_solution_submission_address(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader_a.private_key()).unwrap(), + &trader_a.signer, ); let uid_a = services.create_order(&order_a).await.unwrap(); @@ -268,7 +268,7 @@ async fn wrong_solution_submission_address(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader_b.private_key()).unwrap(), + &trader_b.signer, ); services.create_order(&order_b).await.unwrap(); @@ -401,7 +401,7 @@ async fn store_filtered_solutions(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); let order_ac = OrderCreation { @@ -416,7 +416,7 @@ async fn store_filtered_solutions(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); let order_ab_id = services.create_order(&order_ab).await.unwrap(); diff --git a/crates/e2e/tests/e2e/solver_participation_guard.rs b/crates/e2e/tests/e2e/solver_participation_guard.rs index 98f421cde8..5723fa47df 100644 --- a/crates/e2e/tests/e2e/solver_participation_guard.rs +++ b/crates/e2e/tests/e2e/solver_participation_guard.rs @@ -1,8 +1,5 @@ use { - alloy::{ - primitives::{Address, U256}, - signers::local::PrivateKeySigner, - }, + alloy::primitives::{Address, U256}, e2e::setup::{ Db, ExtraServiceArgs, @@ -343,7 +340,7 @@ async fn execute_order( .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader_a.private_key()).unwrap(), + &trader_a.signer, ); let balance_before = token_b.balanceOf(trader_a.address()).call().await.unwrap(); let order_id = services.create_order(&order).await.unwrap(); diff --git a/crates/e2e/tests/e2e/submission.rs b/crates/e2e/tests/e2e/submission.rs index de9cf2c234..094441dd06 100644 --- a/crates/e2e/tests/e2e/submission.rs +++ b/crates/e2e/tests/e2e/submission.rs @@ -6,7 +6,6 @@ use { client::PollerStream, types::{Transaction, TransactionReceipt}, }, - signers::local::PrivateKeySigner, }, e2e::{nodes::local_node::TestNodeApi, setup::*}, ethrpc::alloy::{CallBuilderExt, conversions::IntoAlloy}, @@ -92,7 +91,7 @@ async fn test_cancel_on_expiry(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); services.create_order(&order).await.unwrap(); onchain.mint_block().await; @@ -192,7 +191,7 @@ async fn test_submit_same_sell_and_buy_token_order_without_quote(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_bytes(trader.private_key().into()).unwrap(), + &trader.signer, ); services.create_order(&order).await.unwrap(); // Start tracking confirmed blocks so we can find the transaction later @@ -325,7 +324,7 @@ async fn test_execute_same_sell_and_buy_token(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_bytes(trader.private_key().into()).unwrap(), + &trader.signer, ); assert!(services.create_order(&order).await.is_ok()); diff --git a/crates/e2e/tests/e2e/tracking_insufficient_funds.rs b/crates/e2e/tests/e2e/tracking_insufficient_funds.rs index bb7b66cb7b..36192c7163 100644 --- a/crates/e2e/tests/e2e/tracking_insufficient_funds.rs +++ b/crates/e2e/tests/e2e/tracking_insufficient_funds.rs @@ -1,5 +1,4 @@ use { - ::alloy::signers::local::PrivateKeySigner, database::order_events::{OrderEvent, OrderEventLabel}, e2e::setup::*, ethrpc::alloy::{CallBuilderExt, conversions::IntoAlloy}, @@ -79,7 +78,7 @@ async fn test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader_a.private_key()).unwrap(), + &trader_a.signer, ); let order_b = OrderCreation { sell_token: *onchain.contracts().weth.address(), @@ -93,7 +92,7 @@ async fn test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader_b.private_key()).unwrap(), + &trader_b.signer, ); let uid_a = services.create_order(&order_a).await.unwrap(); let uid_b = services.create_order(&order_b).await.unwrap(); diff --git a/crates/e2e/tests/e2e/uncovered_order.rs b/crates/e2e/tests/e2e/uncovered_order.rs index d04fb66bb0..1110ee96ec 100644 --- a/crates/e2e/tests/e2e/uncovered_order.rs +++ b/crates/e2e/tests/e2e/uncovered_order.rs @@ -1,5 +1,4 @@ use { - ::alloy::signers::local::PrivateKeySigner, e2e::setup::*, ethrpc::alloy::{CallBuilderExt, conversions::IntoAlloy}, model::{ @@ -55,7 +54,7 @@ async fn test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); // This order can't be created because we require the trader // to have at least 1 wei of sell tokens. diff --git a/crates/e2e/tests/e2e/univ2.rs b/crates/e2e/tests/e2e/univ2.rs index d0e6fe066b..0590e498c6 100644 --- a/crates/e2e/tests/e2e/univ2.rs +++ b/crates/e2e/tests/e2e/univ2.rs @@ -1,5 +1,5 @@ use { - ::alloy::{primitives::U256, signers::local::PrivateKeySigner}, + ::alloy::primitives::U256, contracts::alloy::GPv2Settlement, database::order_events::{OrderEvent, OrderEventLabel}, e2e::setup::*, @@ -65,7 +65,7 @@ async fn test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); let uid = services.create_order(&order).await.unwrap(); diff --git a/crates/e2e/tests/e2e/vault_balances.rs b/crates/e2e/tests/e2e/vault_balances.rs index c7dab394f9..f4e9ece300 100644 --- a/crates/e2e/tests/e2e/vault_balances.rs +++ b/crates/e2e/tests/e2e/vault_balances.rs @@ -1,5 +1,4 @@ use { - ::alloy::signers::local::PrivateKeySigner, e2e::setup::*, ethrpc::alloy::{CallBuilderExt, conversions::IntoAlloy}, model::{ @@ -65,7 +64,7 @@ async fn vault_balances(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); services.create_order(&order).await.unwrap(); onchain.mint_block().await; diff --git a/crates/e2e/tests/e2e/wrapper.rs b/crates/e2e/tests/e2e/wrapper.rs index 3773145aa5..c56bf93ef9 100644 --- a/crates/e2e/tests/e2e/wrapper.rs +++ b/crates/e2e/tests/e2e/wrapper.rs @@ -6,7 +6,6 @@ use { ext::{AnvilApi, DebugApi, ImpersonateConfig}, }, rpc::types::trace::geth::{CallConfig, GethDebugTracingOptions}, - signers::local::PrivateKeySigner, }, app_data::{AppDataHash, hash_full_app_data}, contracts::alloy::ERC20, @@ -165,7 +164,7 @@ async fn forked_mainnet_wrapper_test(web3: Web3) { .sign( EcdsaSigningScheme::Eip712, &onchain.contracts().domain_separator, - &PrivateKeySigner::from_slice(trader.private_key()).unwrap(), + &trader.signer, ); let sell_token_balance_before = token_weth.balanceOf(trader.address()).call().await.unwrap(); diff --git a/crates/ethrpc/src/alloy/conversions.rs b/crates/ethrpc/src/alloy/conversions.rs index ff6d7ebc31..01e5cad35c 100644 --- a/crates/ethrpc/src/alloy/conversions.rs +++ b/crates/ethrpc/src/alloy/conversions.rs @@ -1,6 +1,5 @@ use { alloy::{network::TxSigner, signers::Signature}, - anyhow::Context, std::collections::HashMap, }; @@ -157,42 +156,6 @@ pub enum Account { Signer(Box + Send + Sync + 'static>), } -#[async_trait::async_trait] -pub trait TryIntoAlloyAsync { - type Into; - - async fn try_into_alloy(self) -> anyhow::Result; -} - -#[async_trait::async_trait] -impl TryIntoAlloyAsync for ethcontract::Account { - type Into = Account; - - async fn try_into_alloy(self) -> anyhow::Result { - match self { - ethcontract::Account::Offline(pk, _) => { - let signer = - alloy::signers::local::PrivateKeySigner::from_slice(&pk.secret_bytes()) - .context("invalid private key bytes")?; - Ok(Account::Signer(Box::new(signer))) - } - ethcontract::Account::Kms(account, chain_id) => { - let signer = alloy::signers::aws::AwsSigner::new( - account.client().clone(), - account.key_id().to_string(), - chain_id, - ) - .await?; - Ok(Account::Signer(Box::new(signer))) - } - ethcontract::Account::Local(address, _) => Ok(Account::Address(address.into_alloy())), - ethcontract::Account::Locked(_, _, _) => { - anyhow::bail!("Locked accounts are not currently supported") - } - } - } -} - ////////////////////////////////// // Conversions to the legacy types ////////////////////////////////// diff --git a/crates/shared/Cargo.toml b/crates/shared/Cargo.toml index 7bbfcaa060..611cc7e35e 100644 --- a/crates/shared/Cargo.toml +++ b/crates/shared/Cargo.toml @@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0" doctest = false [dependencies] -alloy = { workspace = true, features = ["sol-types"] } +alloy = { workspace = true, features = ["sol-types", "signer-local"] } anyhow = { workspace = true } app-data = { workspace = true } bytes-hex = { workspace = true } diff --git a/crates/shared/src/bad_token/trace_call.rs b/crates/shared/src/bad_token/trace_call.rs index 77b768272b..41502dcf84 100644 --- a/crates/shared/src/bad_token/trace_call.rs +++ b/crates/shared/src/bad_token/trace_call.rs @@ -1,10 +1,14 @@ use { super::{BadTokenDetecting, TokenQuality, token_owner_finder::TokenOwnerFinding}, crate::{ethrpc::Web3, trace_many}, - alloy::{primitives::Address, sol_types::SolCall}, + alloy::{ + primitives::{Address, keccak256}, + signers::local::PrivateKeySigner, + sol_types::SolCall, + }, anyhow::{Context, Result, bail, ensure}, contracts::alloy::ERC20, - ethcontract::{PrivateKey, jsonrpc::ErrorCode}, + ethcontract::jsonrpc::ErrorCode, ethrpc::alloy::conversions::{IntoAlloy, IntoLegacy}, model::interaction::InteractionData, primitive_types::{H160, U256}, @@ -12,7 +16,6 @@ use { tracing::instrument, web3::{ error::TransportError, - signing::keccak256, types::{BlockTrace, Bytes, CallRequest, Res}, }, }; @@ -154,10 +157,10 @@ impl TraceCallDetectorRaw { // For the out transfer we use an arbitrary address without balance to detect // tokens that usually apply fees but not if the the sender or receiver is // specifically exempt like their own uniswap pools. - fn arbitrary_recipient() -> H160 { - PrivateKey::from_raw(keccak256(b"moo")) + fn arbitrary_recipient() -> Address { + PrivateKeySigner::from_bytes(&keccak256(b"moo")) .unwrap() - .public_address() + .address() } fn create_trace_request( @@ -167,7 +170,7 @@ impl TraceCallDetectorRaw { take_from: Address, ) -> Vec { let mut requests = Vec::new(); - let recipient = Self::arbitrary_recipient().into_alloy(); + let recipient = Self::arbitrary_recipient(); let settlement_contract = self.settlement_contract; // 0 @@ -543,11 +546,6 @@ mod tests { assert_eq!(result, expected); } - #[test] - fn arbitrary_recipient_() { - println!("{:?}", TraceCallDetectorRaw::arbitrary_recipient()); - } - // cargo test -p shared mainnet_tokens -- --nocapture --ignored #[tokio::test] #[ignore] From db595fa00f5f027d3c7fb324c8315d91f4b72629 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=CC=81=20Duarte?= Date: Thu, 18 Dec 2025 14:56:34 +0000 Subject: [PATCH 14/24] migrate solver accounts to alloy --- crates/driver/src/domain/competition/mod.rs | 3 +- .../src/domain/competition/solution/mod.rs | 1 + crates/driver/src/domain/eth/mod.rs | 77 +++++++++++++++- crates/driver/src/domain/mempools.rs | 4 +- crates/driver/src/infra/config/file/load.rs | 33 +++---- crates/driver/src/infra/config/file/mod.rs | 4 - crates/driver/src/infra/mempool/mod.rs | 89 +++++++++++-------- crates/driver/src/infra/solver/mod.rs | 51 ++++++++++- crates/driver/src/run.rs | 18 +++- crates/e2e/tests/e2e/submission.rs | 12 ++- crates/ethrpc/src/alloy/mod.rs | 22 ----- 11 files changed, 224 insertions(+), 90 deletions(-) diff --git a/crates/driver/src/domain/competition/mod.rs b/crates/driver/src/domain/competition/mod.rs index b93fb98977..0246748529 100644 --- a/crates/driver/src/domain/competition/mod.rs +++ b/crates/driver/src/domain/competition/mod.rs @@ -21,7 +21,6 @@ use { }, util::{Bytes, math}, }, - ethrpc::alloy::conversions::IntoAlloy, futures::{StreamExt, future::Either, stream::FuturesUnordered}, itertools::Itertools, std::{ @@ -128,7 +127,7 @@ impl Competition { let mut auction = Arc::unwrap_or_clone(tasks.auction.await); let settlement_contract = *self.eth.contracts().settlement().address(); - let solver_address = self.solver.account().address().into_alloy(); + let solver_address = self.solver.address(); let order_sorting_strategies = self.order_sorting_strategies.clone(); // Add the CoW AMM orders to the auction diff --git a/crates/driver/src/domain/competition/solution/mod.rs b/crates/driver/src/domain/competition/solution/mod.rs index 565bb9e637..a76e7187be 100644 --- a/crates/driver/src/domain/competition/solution/mod.rs +++ b/crates/driver/src/domain/competition/solution/mod.rs @@ -15,6 +15,7 @@ use { solver::{ManageNativeToken, Solver}, }, }, + alloy::network::TxSigner, chrono::Utc, futures::future::try_join_all, itertools::Itertools, diff --git a/crates/driver/src/domain/eth/mod.rs b/crates/driver/src/domain/eth/mod.rs index 920b6812dc..bebbda6c46 100644 --- a/crates/driver/src/domain/eth/mod.rs +++ b/crates/driver/src/domain/eth/mod.rs @@ -1,5 +1,6 @@ use { crate::util::{Bytes, conv::u256::U256Ext}, + alloy::rpc::types::TransactionRequest, derive_more::{From, Into}, ethrpc::alloy::conversions::{IntoAlloy, IntoLegacy}, itertools::Itertools, @@ -92,8 +93,71 @@ impl From for web3::types::AccessList { } } +impl IntoIterator for AccessList { + type IntoIter = std::collections::hash_map::IntoIter>; + type Item = (Address, HashSet); + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} + +impl FromIterator<(Address, I)> for AccessList +where + I: IntoIterator, +{ + fn from_iter>(iter: T) -> Self { + Self( + iter.into_iter() + .map(|(address, i)| { + ( + address, + i.into_iter().map(StorageKey).collect::>(), + ) + }) + .collect(), + ) + } +} + +impl From for AccessList { + fn from(value: alloy::eips::eip2930::AccessList) -> Self { + Self( + value + .0 + .into_iter() + .map(|item| { + ( + item.address, + item.storage_keys + .into_iter() + .map(StorageKey) + .collect::>(), + ) + }) + .collect(), + ) + } +} + +impl From for alloy::eips::eip2930::AccessList { + fn from(value: AccessList) -> Self { + Self( + value + .into_iter() + .map( + |(address, storage_keys)| alloy::eips::eip2930::AccessListItem { + address, + storage_keys: storage_keys.into_iter().map(|k| k.0).collect(), + }, + ) + .collect(), + ) + } +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Into, From)] -struct StorageKey(pub B256); +pub struct StorageKey(pub B256); // TODO This type should probably use Ethereum::is_contract to verify during // construction that it does indeed point to a contract @@ -377,6 +441,17 @@ impl std::fmt::Debug for Tx { } } +impl From for TransactionRequest { + fn from(value: Tx) -> Self { + TransactionRequest::default() + .from(value.from) + .to(value.to) + .value(value.value.0) + .input(value.input.0.into()) + .access_list(value.access_list.into()) + } +} + impl Tx { pub fn set_access_list(self, access_list: AccessList) -> Self { Self { diff --git a/crates/driver/src/domain/mempools.rs b/crates/driver/src/domain/mempools.rs index 2803b043ed..7ce4718109 100644 --- a/crates/driver/src/domain/mempools.rs +++ b/crates/driver/src/domain/mempools.rs @@ -272,7 +272,7 @@ impl Mempools { mempool: &infra::mempool::Mempool, original_tx_gas_price: eth::GasPrice, solver: &Solver, - nonce: eth::U256, + nonce: u64, ) -> Result { let fallback_gas_price = original_tx_gas_price * GAS_PRICE_BUMP; let replacement_gas_price = self @@ -319,7 +319,7 @@ impl Mempools { &self, mempool: &infra::Mempool, solver: &Solver, - nonce: eth::U256, + nonce: u64, ) -> anyhow::Result> { let pending_tx = match mempool .find_pending_tx_in_mempool(solver.address(), nonce) diff --git a/crates/driver/src/infra/config/file/load.rs b/crates/driver/src/infra/config/file/load.rs index c766492bb7..58d5ee1ec9 100644 --- a/crates/driver/src/infra/config/file/load.rs +++ b/crates/driver/src/infra/config/file/load.rs @@ -9,11 +9,11 @@ use { mempool, notify, simulator, - solver::{self, BadTokenDetection, SolutionMerging}, + solver::{self, Account, BadTokenDetection, SolutionMerging}, }, }, + alloy::signers::{aws::AwsSigner, local::PrivateKeySigner}, chain::Chain, - ethrpc::alloy::conversions::IntoLegacy, futures::future::join_all, number::conversions::big_decimal_to_big_rational, std::path::Path, @@ -52,21 +52,22 @@ pub async fn load(chain: Chain, path: &Path) -> infra::Config { ); infra::Config { solvers: join_all(config.solvers.into_iter().map(|solver_config| async move { - let account = match solver_config.account { - file::Account::PrivateKey(private_key) => ethcontract::Account::Offline( - ethcontract::PrivateKey::from_raw(private_key.0).unwrap(), - None, - ), - file::Account::Kms(key_id) => { - let config = ethcontract::aws_config::load_from_env().await; - let account = - ethcontract::transaction::kms::Account::new((&config).into(), &key_id.0) - .await - .unwrap_or_else(|_| panic!("Unable to load KMS account {key_id:?}")); - ethcontract::Account::Kms(account, None) + let account: Account = match solver_config.account { + file::Account::PrivateKey(private_key) => { + PrivateKeySigner::from_bytes(&private_key) + .expect( + "private key should + be valid", + ) + .into() } - file::Account::Address(address) => { - ethcontract::Account::Local(address.into_legacy(), None) + file::Account::Kms(arn) => { + let sdk_config = alloy::signers::aws::aws_config::load_from_env().await; + let client = alloy::signers::aws::aws_sdk_kms::Client::new(&sdk_config); + AwsSigner::new(client, arn.0, config.chain_id.map(Into::into)) + .await + .expect("unable to load kms account {arn:?}") + .into() } }; solver::Config { diff --git a/crates/driver/src/infra/config/file/mod.rs b/crates/driver/src/infra/config/file/mod.rs index 0ccae1db7c..830ba5e5a2 100644 --- a/crates/driver/src/infra/config/file/mod.rs +++ b/crates/driver/src/infra/config/file/mod.rs @@ -343,10 +343,6 @@ enum Account { PrivateKey(eth::B256), /// AWS KMS is used to sign transactions. Expects the key identifier. Kms(#[serde_as(as = "serde_with::DisplayFromStr")] Arn), - /// An address is used to identify the account for signing, relying on the - /// connected node's account management features. This can also be used to - /// start the driver in a dry-run mode. - Address(eth::Address), } #[serde_as] diff --git a/crates/driver/src/infra/mempool/mod.rs b/crates/driver/src/infra/mempool/mod.rs index 46291dfa9f..0181013a26 100644 --- a/crates/driver/src/infra/mempool/mod.rs +++ b/crates/driver/src/infra/mempool/mod.rs @@ -2,14 +2,15 @@ use { crate::{ boundary::unbuffered_web3_client, domain::{eth, mempools}, - infra, + infra::{self, solver::Account}, }, - alloy::{consensus::Transaction, providers::ext::TxPoolApi}, - anyhow::Context, - ethrpc::{ - Web3, - alloy::conversions::{IntoAlloy, IntoLegacy}, + alloy::{ + consensus::Transaction, + providers::{Provider, ext::TxPoolApi}, + rpc::types::TransactionRequest, }, + anyhow::Context, + ethrpc::Web3, }; #[derive(Debug, Clone)] @@ -53,22 +54,22 @@ impl std::fmt::Display for Mempool { } impl Mempool { - pub fn new(config: Config) -> Self { - Self { - transport: unbuffered_web3_client(&config.url), - config, + pub fn new(config: Config, solver_accounts: Vec) -> Self { + let transport = unbuffered_web3_client(&config.url); + for account in solver_accounts { + transport.wallet.register_signer(account); } + Self { transport, config } } /// Fetches the transaction count (nonce) for the given address at the /// specified block number. If no block number is provided in the config, /// uses the web3 lib's default behavior. - pub async fn get_nonce(&self, address: eth::Address) -> Result { + pub async fn get_nonce(&self, address: eth::Address) -> Result { self.transport - .eth() - .transaction_count(address.into_legacy(), self.config.nonce_block_number) + .alloy + .get_transaction_count(address) .await - .map(IntoAlloy::into_alloy) .map_err(|err| { mempools::Error::Other(anyhow::Error::from(err).context("failed to fetch nonce")) }) @@ -82,27 +83,45 @@ impl Mempool { gas_price: eth::GasPrice, gas_limit: eth::Gas, solver: &infra::Solver, - nonce: eth::U256, + nonce: u64, ) -> Result { - let submission = - ethcontract::transaction::TransactionBuilder::new(self.transport.legacy.clone()) - .from(solver.account().clone()) - .to(tx.to.into_legacy()) - .nonce(nonce.into_legacy()) - .gas_price(ethcontract::GasPrice::Eip1559 { - max_fee_per_gas: gas_price.max().0.0.into_legacy(), - max_priority_fee_per_gas: gas_price.tip().0.0.into_legacy(), - }) - .data(tx.input.into()) - .value(tx.value.0.into_legacy()) - .gas(gas_limit.0.into_legacy()) - .access_list(web3::types::AccessList::from(tx.access_list)) - .resolve(ethcontract::transaction::ResolveCondition::Pending) - .send() - .await; + let max_fee_per_gas = gas_price + .max() + .0 + .0 + .try_into() + .map_err(anyhow::Error::from)?; + let max_priority_fee_per_gas = gas_price + .tip() + .0 + .0 + .try_into() + .map_err(anyhow::Error::from)?; + let gas_limit = gas_limit.0.try_into().map_err(anyhow::Error::from)?; + + let tx_request = TransactionRequest::default() + .from(solver.address()) + .to(tx.to) + .nonce(nonce) + .max_fee_per_gas(max_fee_per_gas) + .max_priority_fee_per_gas(max_priority_fee_per_gas) + .gas_limit(gas_limit) + .input(tx.input.0.into()) + .value(tx.value.0) + .access_list(tx.access_list.into()); + + let submission = self + .transport + .alloy + .send_transaction(tx_request) + .await + .map_err(|err| { + tracing::error!(?err, ">>> failed to submit send tx"); + anyhow::Error::from(err) + }); match submission { - Ok(receipt) => { + Ok(tx) => { tracing::debug!( ?nonce, ?gas_price, @@ -110,7 +129,7 @@ impl Mempool { solver = ?solver.address(), "successfully submitted tx to mempool" ); - Ok(eth::TxId(receipt.hash().into_alloy())) + Ok(eth::TxId(*tx.tx_hash())) } Err(err) => { // log pending tx in case we failed to replace a pending tx @@ -137,7 +156,7 @@ impl Mempool { pub async fn find_pending_tx_in_mempool( &self, signer: eth::Address, - nonce: eth::U256, + nonce: u64, ) -> anyhow::Result> { let tx_pool_content = self .transport @@ -151,7 +170,7 @@ impl Mempool { .pending .into_iter() .chain(tx_pool_content.queued) - .find(|(_signer, tx)| eth::U256::from(tx.nonce()) == nonce) + .find(|(_signer, tx)| tx.nonce() == nonce) .map(|(_, tx)| tx); Ok(pending_tx) } diff --git a/crates/driver/src/infra/solver/mod.rs b/crates/driver/src/infra/solver/mod.rs index dbfbddcfd3..e4819e8b70 100644 --- a/crates/driver/src/infra/solver/mod.rs +++ b/crates/driver/src/infra/solver/mod.rs @@ -20,9 +20,14 @@ use { }, util, }, + alloy::{ + consensus::SignableTransaction, + network::TxSigner, + primitives::Address, + signers::{Signature, aws::AwsSigner, local::PrivateKeySigner}, + }, anyhow::Result, derive_more::{From, Into}, - ethrpc::alloy::conversions::IntoAlloy, num::BigRational, observe::tracing::tracing_headers, reqwest::header::HeaderName, @@ -101,6 +106,44 @@ pub struct Solver { persistence: Persistence, } +#[derive(Debug, Clone)] +pub enum Account { + PrivateKey(PrivateKeySigner), + Kms(AwsSigner), +} + +#[async_trait::async_trait] +impl TxSigner for Account { + fn address(&self) -> Address { + match self { + Account::PrivateKey(local_signer) => local_signer.address(), + Account::Kms(aws_signer) => aws_signer.address(), + } + } + + async fn sign_transaction( + &self, + tx: &mut dyn SignableTransaction, + ) -> alloy::signers::Result { + match self { + Account::PrivateKey(local_signer) => local_signer.sign_transaction(tx).await, + Account::Kms(aws_signer) => aws_signer.sign_transaction(tx).await, + } + } +} + +impl From for Account { + fn from(value: PrivateKeySigner) -> Self { + Self::PrivateKey(value) + } +} + +impl From for Account { + fn from(value: AwsSigner) -> Self { + Self::Kms(value) + } +} + #[derive(Debug, Clone)] pub struct Config { /// The endpoint of the solver, including the path (commonly "/solve"). @@ -111,7 +154,7 @@ pub struct Config { /// Whether or not liquidity is used by this solver. pub liquidity: Liquidity, /// The private key of this solver, used for settlement submission. - pub account: ethcontract::Account, + pub account: Account, /// How much time to spend for each step of the solving and competition. pub timeouts: Timeouts, /// HTTP headers that should be added to every request. @@ -190,11 +233,11 @@ impl Solver { /// The blockchain address of this solver. pub fn address(&self) -> eth::Address { - self.config.account.address().into_alloy() + self.config.account.address() } /// The account which should be used to sign settlements for this solver. - pub fn account(&self) -> ethcontract::Account { + pub fn account(&self) -> Account { self.config.account.clone() } diff --git a/crates/driver/src/run.rs b/crates/driver/src/run.rs index fed4b33f8a..ee9b524da9 100644 --- a/crates/driver/src/run.rs +++ b/crates/driver/src/run.rs @@ -16,6 +16,7 @@ use { solver::Solver, }, }, + alloy::network::TxSigner, clap::Parser, futures::future::join_all, shared::arguments::tracing_config, @@ -79,7 +80,16 @@ async fn run_with(args: cli::Args, addr_sender: Option>> registering signer for {}", solver.account.address()); + ethrpc.web3().wallet.register_signer(solver.account.clone()); + } + Ethereum::new( ethrpc, config.contracts.clone(), diff --git a/crates/e2e/tests/e2e/submission.rs b/crates/e2e/tests/e2e/submission.rs index 094441dd06..39c07916c5 100644 --- a/crates/e2e/tests/e2e/submission.rs +++ b/crates/e2e/tests/e2e/submission.rs @@ -121,10 +121,16 @@ async fn test_cancel_on_expiry(web3: Web3) { .await .expect("Must be able to set mining interval"); + tracing::error!(">>> solver addr {}", solver.address()); + // Wait for cancellation tx to appear - wait_for_condition(TIMEOUT, || async { solver.nonce(&web3).await == nonce + 1 }) - .await - .unwrap(); + wait_for_condition(TIMEOUT, || async { + let n = solver.nonce(&web3).await; + tracing::error!(">>> got {}, expected {}", n, nonce + 1); + n == nonce + 1 + }) + .await + .unwrap(); // Check that it's actually a cancellation let tx = tokio::time::timeout( diff --git a/crates/ethrpc/src/alloy/mod.rs b/crates/ethrpc/src/alloy/mod.rs index 914e7e3251..abbd613a2c 100644 --- a/crates/ethrpc/src/alloy/mod.rs +++ b/crates/ethrpc/src/alloy/mod.rs @@ -7,7 +7,6 @@ mod wallet; use { crate::{AlloyProvider, Config}, alloy::{ - network::EthereumWallet, providers::{Provider, ProviderBuilder}, rpc::client::{ClientBuilder, RpcClient}, }, @@ -102,9 +101,6 @@ impl RpcClientRandomIdExt for RpcClient { } pub trait ProviderSignerExt { - /// Creates a new provider with the given signer. - fn with_signer(&self, signer: Account) -> Self; - /// Creates a new provider without any signers. /// This is only ever useful if you configured /// anvil to impersonate some account and want @@ -114,24 +110,6 @@ pub trait ProviderSignerExt { } impl ProviderSignerExt for AlloyProvider { - fn with_signer(&self, signer: Account) -> Self { - let Account::Signer(signer) = signer else { - // Otherwise an unlocked account is used, not need to change anything. - return self.clone(); - }; - - let is_local = self.client().is_local(); - let transport = self.client().transport().clone(); - let wallet = EthereumWallet::new(signer); - let client = RpcClient::with_random_id(transport, is_local); - - ProviderBuilder::new() - .wallet(wallet) - .with_simple_nonce_management() - .connect_client(client) - .erased() - } - fn without_wallet(&self) -> Self { let is_local = self.client().is_local(); let transport = self.client().transport().clone(); From 2634602ee6cf1a03da49642ac68020483c7f490f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=CC=81=20Duarte?= Date: Thu, 18 Dec 2025 15:32:29 +0000 Subject: [PATCH 15/24] wip --- crates/driver/Cargo.toml | 2 +- crates/driver/src/domain/eth/mod.rs | 63 ----------------------------- 2 files changed, 1 insertion(+), 64 deletions(-) diff --git a/crates/driver/Cargo.toml b/crates/driver/Cargo.toml index b49abdebfb..c4ce469e8c 100644 --- a/crates/driver/Cargo.toml +++ b/crates/driver/Cargo.toml @@ -15,7 +15,7 @@ name = "driver" path = "src/main.rs" [dependencies] -alloy = { workspace = true, features = ["sol-types", "provider-txpool-api", "rand", "provider-anvil-api", "json-rpc"] } +alloy = { workspace = true, features = ["sol-types", "provider-txpool-api", "rand", "provider-anvil-api", "json-rpc", "rpc-types"] } app-data = { workspace = true } async-trait = { workspace = true } axum = { workspace = true } diff --git a/crates/driver/src/domain/eth/mod.rs b/crates/driver/src/domain/eth/mod.rs index 6549fdad07..079e577b99 100644 --- a/crates/driver/src/domain/eth/mod.rs +++ b/crates/driver/src/domain/eth/mod.rs @@ -116,69 +116,6 @@ impl From for alloy::eips::eip2930::AccessList { } } -impl IntoIterator for AccessList { - type IntoIter = std::collections::hash_map::IntoIter>; - type Item = (Address, HashSet); - - fn into_iter(self) -> Self::IntoIter { - self.0.into_iter() - } -} - -impl FromIterator<(Address, I)> for AccessList -where - I: IntoIterator, -{ - fn from_iter>(iter: T) -> Self { - Self( - iter.into_iter() - .map(|(address, i)| { - ( - address, - i.into_iter().map(StorageKey).collect::>(), - ) - }) - .collect(), - ) - } -} - -impl From for AccessList { - fn from(value: alloy::eips::eip2930::AccessList) -> Self { - Self( - value - .0 - .into_iter() - .map(|item| { - ( - item.address, - item.storage_keys - .into_iter() - .map(StorageKey) - .collect::>(), - ) - }) - .collect(), - ) - } -} - -impl From for alloy::eips::eip2930::AccessList { - fn from(value: AccessList) -> Self { - Self( - value - .into_iter() - .map( - |(address, storage_keys)| alloy::eips::eip2930::AccessListItem { - address, - storage_keys: storage_keys.into_iter().map(|k| k.0).collect(), - }, - ) - .collect(), - ) - } -} - #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Into, From)] pub struct StorageKey(pub B256); From 0e6210e6a3fb40d8eb9a1091d42385eb0ae08859 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=CC=81=20Duarte?= Date: Thu, 18 Dec 2025 14:56:34 +0000 Subject: [PATCH 16/24] migrate solver accounts to alloy --- crates/driver/src/domain/competition/mod.rs | 3 +- .../src/domain/competition/solution/mod.rs | 1 + crates/driver/src/domain/eth/mod.rs | 77 +++++++++++++++- crates/driver/src/domain/mempools.rs | 4 +- crates/driver/src/infra/config/file/load.rs | 33 +++---- crates/driver/src/infra/config/file/mod.rs | 4 - crates/driver/src/infra/mempool/mod.rs | 87 +++++++++++-------- crates/driver/src/infra/solver/mod.rs | 51 ++++++++++- crates/driver/src/run.rs | 12 ++- crates/ethrpc/src/alloy/mod.rs | 22 ----- 10 files changed, 207 insertions(+), 87 deletions(-) diff --git a/crates/driver/src/domain/competition/mod.rs b/crates/driver/src/domain/competition/mod.rs index b93fb98977..0246748529 100644 --- a/crates/driver/src/domain/competition/mod.rs +++ b/crates/driver/src/domain/competition/mod.rs @@ -21,7 +21,6 @@ use { }, util::{Bytes, math}, }, - ethrpc::alloy::conversions::IntoAlloy, futures::{StreamExt, future::Either, stream::FuturesUnordered}, itertools::Itertools, std::{ @@ -128,7 +127,7 @@ impl Competition { let mut auction = Arc::unwrap_or_clone(tasks.auction.await); let settlement_contract = *self.eth.contracts().settlement().address(); - let solver_address = self.solver.account().address().into_alloy(); + let solver_address = self.solver.address(); let order_sorting_strategies = self.order_sorting_strategies.clone(); // Add the CoW AMM orders to the auction diff --git a/crates/driver/src/domain/competition/solution/mod.rs b/crates/driver/src/domain/competition/solution/mod.rs index 565bb9e637..a76e7187be 100644 --- a/crates/driver/src/domain/competition/solution/mod.rs +++ b/crates/driver/src/domain/competition/solution/mod.rs @@ -15,6 +15,7 @@ use { solver::{ManageNativeToken, Solver}, }, }, + alloy::network::TxSigner, chrono::Utc, futures::future::try_join_all, itertools::Itertools, diff --git a/crates/driver/src/domain/eth/mod.rs b/crates/driver/src/domain/eth/mod.rs index 920b6812dc..bebbda6c46 100644 --- a/crates/driver/src/domain/eth/mod.rs +++ b/crates/driver/src/domain/eth/mod.rs @@ -1,5 +1,6 @@ use { crate::util::{Bytes, conv::u256::U256Ext}, + alloy::rpc::types::TransactionRequest, derive_more::{From, Into}, ethrpc::alloy::conversions::{IntoAlloy, IntoLegacy}, itertools::Itertools, @@ -92,8 +93,71 @@ impl From for web3::types::AccessList { } } +impl IntoIterator for AccessList { + type IntoIter = std::collections::hash_map::IntoIter>; + type Item = (Address, HashSet); + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} + +impl FromIterator<(Address, I)> for AccessList +where + I: IntoIterator, +{ + fn from_iter>(iter: T) -> Self { + Self( + iter.into_iter() + .map(|(address, i)| { + ( + address, + i.into_iter().map(StorageKey).collect::>(), + ) + }) + .collect(), + ) + } +} + +impl From for AccessList { + fn from(value: alloy::eips::eip2930::AccessList) -> Self { + Self( + value + .0 + .into_iter() + .map(|item| { + ( + item.address, + item.storage_keys + .into_iter() + .map(StorageKey) + .collect::>(), + ) + }) + .collect(), + ) + } +} + +impl From for alloy::eips::eip2930::AccessList { + fn from(value: AccessList) -> Self { + Self( + value + .into_iter() + .map( + |(address, storage_keys)| alloy::eips::eip2930::AccessListItem { + address, + storage_keys: storage_keys.into_iter().map(|k| k.0).collect(), + }, + ) + .collect(), + ) + } +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Into, From)] -struct StorageKey(pub B256); +pub struct StorageKey(pub B256); // TODO This type should probably use Ethereum::is_contract to verify during // construction that it does indeed point to a contract @@ -377,6 +441,17 @@ impl std::fmt::Debug for Tx { } } +impl From for TransactionRequest { + fn from(value: Tx) -> Self { + TransactionRequest::default() + .from(value.from) + .to(value.to) + .value(value.value.0) + .input(value.input.0.into()) + .access_list(value.access_list.into()) + } +} + impl Tx { pub fn set_access_list(self, access_list: AccessList) -> Self { Self { diff --git a/crates/driver/src/domain/mempools.rs b/crates/driver/src/domain/mempools.rs index 2803b043ed..7ce4718109 100644 --- a/crates/driver/src/domain/mempools.rs +++ b/crates/driver/src/domain/mempools.rs @@ -272,7 +272,7 @@ impl Mempools { mempool: &infra::mempool::Mempool, original_tx_gas_price: eth::GasPrice, solver: &Solver, - nonce: eth::U256, + nonce: u64, ) -> Result { let fallback_gas_price = original_tx_gas_price * GAS_PRICE_BUMP; let replacement_gas_price = self @@ -319,7 +319,7 @@ impl Mempools { &self, mempool: &infra::Mempool, solver: &Solver, - nonce: eth::U256, + nonce: u64, ) -> anyhow::Result> { let pending_tx = match mempool .find_pending_tx_in_mempool(solver.address(), nonce) diff --git a/crates/driver/src/infra/config/file/load.rs b/crates/driver/src/infra/config/file/load.rs index c766492bb7..58d5ee1ec9 100644 --- a/crates/driver/src/infra/config/file/load.rs +++ b/crates/driver/src/infra/config/file/load.rs @@ -9,11 +9,11 @@ use { mempool, notify, simulator, - solver::{self, BadTokenDetection, SolutionMerging}, + solver::{self, Account, BadTokenDetection, SolutionMerging}, }, }, + alloy::signers::{aws::AwsSigner, local::PrivateKeySigner}, chain::Chain, - ethrpc::alloy::conversions::IntoLegacy, futures::future::join_all, number::conversions::big_decimal_to_big_rational, std::path::Path, @@ -52,21 +52,22 @@ pub async fn load(chain: Chain, path: &Path) -> infra::Config { ); infra::Config { solvers: join_all(config.solvers.into_iter().map(|solver_config| async move { - let account = match solver_config.account { - file::Account::PrivateKey(private_key) => ethcontract::Account::Offline( - ethcontract::PrivateKey::from_raw(private_key.0).unwrap(), - None, - ), - file::Account::Kms(key_id) => { - let config = ethcontract::aws_config::load_from_env().await; - let account = - ethcontract::transaction::kms::Account::new((&config).into(), &key_id.0) - .await - .unwrap_or_else(|_| panic!("Unable to load KMS account {key_id:?}")); - ethcontract::Account::Kms(account, None) + let account: Account = match solver_config.account { + file::Account::PrivateKey(private_key) => { + PrivateKeySigner::from_bytes(&private_key) + .expect( + "private key should + be valid", + ) + .into() } - file::Account::Address(address) => { - ethcontract::Account::Local(address.into_legacy(), None) + file::Account::Kms(arn) => { + let sdk_config = alloy::signers::aws::aws_config::load_from_env().await; + let client = alloy::signers::aws::aws_sdk_kms::Client::new(&sdk_config); + AwsSigner::new(client, arn.0, config.chain_id.map(Into::into)) + .await + .expect("unable to load kms account {arn:?}") + .into() } }; solver::Config { diff --git a/crates/driver/src/infra/config/file/mod.rs b/crates/driver/src/infra/config/file/mod.rs index 0ccae1db7c..830ba5e5a2 100644 --- a/crates/driver/src/infra/config/file/mod.rs +++ b/crates/driver/src/infra/config/file/mod.rs @@ -343,10 +343,6 @@ enum Account { PrivateKey(eth::B256), /// AWS KMS is used to sign transactions. Expects the key identifier. Kms(#[serde_as(as = "serde_with::DisplayFromStr")] Arn), - /// An address is used to identify the account for signing, relying on the - /// connected node's account management features. This can also be used to - /// start the driver in a dry-run mode. - Address(eth::Address), } #[serde_as] diff --git a/crates/driver/src/infra/mempool/mod.rs b/crates/driver/src/infra/mempool/mod.rs index 46291dfa9f..80180fdfc8 100644 --- a/crates/driver/src/infra/mempool/mod.rs +++ b/crates/driver/src/infra/mempool/mod.rs @@ -2,14 +2,15 @@ use { crate::{ boundary::unbuffered_web3_client, domain::{eth, mempools}, - infra, + infra::{self, solver::Account}, }, - alloy::{consensus::Transaction, providers::ext::TxPoolApi}, - anyhow::Context, - ethrpc::{ - Web3, - alloy::conversions::{IntoAlloy, IntoLegacy}, + alloy::{ + consensus::Transaction, + providers::{Provider, ext::TxPoolApi}, + rpc::types::TransactionRequest, }, + anyhow::Context, + ethrpc::Web3, }; #[derive(Debug, Clone)] @@ -53,22 +54,23 @@ impl std::fmt::Display for Mempool { } impl Mempool { - pub fn new(config: Config) -> Self { - Self { - transport: unbuffered_web3_client(&config.url), - config, + pub fn new(config: Config, solver_accounts: Vec) -> Self { + let transport = unbuffered_web3_client(&config.url); + // Register the solver accounts into the wallet to submit txs on their behalf + for account in solver_accounts { + transport.wallet.register_signer(account); } + Self { transport, config } } /// Fetches the transaction count (nonce) for the given address at the /// specified block number. If no block number is provided in the config, /// uses the web3 lib's default behavior. - pub async fn get_nonce(&self, address: eth::Address) -> Result { + pub async fn get_nonce(&self, address: eth::Address) -> Result { self.transport - .eth() - .transaction_count(address.into_legacy(), self.config.nonce_block_number) + .alloy + .get_transaction_count(address) .await - .map(IntoAlloy::into_alloy) .map_err(|err| { mempools::Error::Other(anyhow::Error::from(err).context("failed to fetch nonce")) }) @@ -82,27 +84,42 @@ impl Mempool { gas_price: eth::GasPrice, gas_limit: eth::Gas, solver: &infra::Solver, - nonce: eth::U256, + nonce: u64, ) -> Result { - let submission = - ethcontract::transaction::TransactionBuilder::new(self.transport.legacy.clone()) - .from(solver.account().clone()) - .to(tx.to.into_legacy()) - .nonce(nonce.into_legacy()) - .gas_price(ethcontract::GasPrice::Eip1559 { - max_fee_per_gas: gas_price.max().0.0.into_legacy(), - max_priority_fee_per_gas: gas_price.tip().0.0.into_legacy(), - }) - .data(tx.input.into()) - .value(tx.value.0.into_legacy()) - .gas(gas_limit.0.into_legacy()) - .access_list(web3::types::AccessList::from(tx.access_list)) - .resolve(ethcontract::transaction::ResolveCondition::Pending) - .send() - .await; + let max_fee_per_gas = gas_price + .max() + .0 + .0 + .try_into() + .map_err(anyhow::Error::from)?; + let max_priority_fee_per_gas = gas_price + .tip() + .0 + .0 + .try_into() + .map_err(anyhow::Error::from)?; + let gas_limit = gas_limit.0.try_into().map_err(anyhow::Error::from)?; + + let tx_request = TransactionRequest::default() + .from(solver.address()) + .to(tx.to) + .nonce(nonce) + .max_fee_per_gas(max_fee_per_gas) + .max_priority_fee_per_gas(max_priority_fee_per_gas) + .gas_limit(gas_limit) + .input(tx.input.0.into()) + .value(tx.value.0) + .access_list(tx.access_list.into()); + + let submission = self + .transport + .alloy + .send_transaction(tx_request) + .await + .map_err(anyhow::Error::from); match submission { - Ok(receipt) => { + Ok(tx) => { tracing::debug!( ?nonce, ?gas_price, @@ -110,7 +127,7 @@ impl Mempool { solver = ?solver.address(), "successfully submitted tx to mempool" ); - Ok(eth::TxId(receipt.hash().into_alloy())) + Ok(eth::TxId(*tx.tx_hash())) } Err(err) => { // log pending tx in case we failed to replace a pending tx @@ -137,7 +154,7 @@ impl Mempool { pub async fn find_pending_tx_in_mempool( &self, signer: eth::Address, - nonce: eth::U256, + nonce: u64, ) -> anyhow::Result> { let tx_pool_content = self .transport @@ -151,7 +168,7 @@ impl Mempool { .pending .into_iter() .chain(tx_pool_content.queued) - .find(|(_signer, tx)| eth::U256::from(tx.nonce()) == nonce) + .find(|(_signer, tx)| tx.nonce() == nonce) .map(|(_, tx)| tx); Ok(pending_tx) } diff --git a/crates/driver/src/infra/solver/mod.rs b/crates/driver/src/infra/solver/mod.rs index dbfbddcfd3..e4819e8b70 100644 --- a/crates/driver/src/infra/solver/mod.rs +++ b/crates/driver/src/infra/solver/mod.rs @@ -20,9 +20,14 @@ use { }, util, }, + alloy::{ + consensus::SignableTransaction, + network::TxSigner, + primitives::Address, + signers::{Signature, aws::AwsSigner, local::PrivateKeySigner}, + }, anyhow::Result, derive_more::{From, Into}, - ethrpc::alloy::conversions::IntoAlloy, num::BigRational, observe::tracing::tracing_headers, reqwest::header::HeaderName, @@ -101,6 +106,44 @@ pub struct Solver { persistence: Persistence, } +#[derive(Debug, Clone)] +pub enum Account { + PrivateKey(PrivateKeySigner), + Kms(AwsSigner), +} + +#[async_trait::async_trait] +impl TxSigner for Account { + fn address(&self) -> Address { + match self { + Account::PrivateKey(local_signer) => local_signer.address(), + Account::Kms(aws_signer) => aws_signer.address(), + } + } + + async fn sign_transaction( + &self, + tx: &mut dyn SignableTransaction, + ) -> alloy::signers::Result { + match self { + Account::PrivateKey(local_signer) => local_signer.sign_transaction(tx).await, + Account::Kms(aws_signer) => aws_signer.sign_transaction(tx).await, + } + } +} + +impl From for Account { + fn from(value: PrivateKeySigner) -> Self { + Self::PrivateKey(value) + } +} + +impl From for Account { + fn from(value: AwsSigner) -> Self { + Self::Kms(value) + } +} + #[derive(Debug, Clone)] pub struct Config { /// The endpoint of the solver, including the path (commonly "/solve"). @@ -111,7 +154,7 @@ pub struct Config { /// Whether or not liquidity is used by this solver. pub liquidity: Liquidity, /// The private key of this solver, used for settlement submission. - pub account: ethcontract::Account, + pub account: Account, /// How much time to spend for each step of the solving and competition. pub timeouts: Timeouts, /// HTTP headers that should be added to every request. @@ -190,11 +233,11 @@ impl Solver { /// The blockchain address of this solver. pub fn address(&self) -> eth::Address { - self.config.account.address().into_alloy() + self.config.account.address() } /// The account which should be used to sign settlements for this solver. - pub fn account(&self) -> ethcontract::Account { + pub fn account(&self) -> Account { self.config.account.clone() } diff --git a/crates/driver/src/run.rs b/crates/driver/src/run.rs index fed4b33f8a..4a95fb557e 100644 --- a/crates/driver/src/run.rs +++ b/crates/driver/src/run.rs @@ -16,6 +16,7 @@ use { solver::Solver, }, }, + alloy::network::TxSigner, clap::Parser, futures::future::join_all, shared::arguments::tracing_config, @@ -79,7 +80,16 @@ async fn run_with(args: cli::Args, addr_sender: Option Self; - /// Creates a new provider without any signers. /// This is only ever useful if you configured /// anvil to impersonate some account and want @@ -114,24 +110,6 @@ pub trait ProviderSignerExt { } impl ProviderSignerExt for AlloyProvider { - fn with_signer(&self, signer: Account) -> Self { - let Account::Signer(signer) = signer else { - // Otherwise an unlocked account is used, not need to change anything. - return self.clone(); - }; - - let is_local = self.client().is_local(); - let transport = self.client().transport().clone(); - let wallet = EthereumWallet::new(signer); - let client = RpcClient::with_random_id(transport, is_local); - - ProviderBuilder::new() - .wallet(wallet) - .with_simple_nonce_management() - .connect_client(client) - .erased() - } - fn without_wallet(&self) -> Self { let is_local = self.client().is_local(); let transport = self.client().transport().clone(); From 0d5c47dc4f3e414c37657435ba66550d7f34bfd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=CC=81=20Duarte?= Date: Fri, 19 Dec 2025 09:54:09 +0000 Subject: [PATCH 17/24] lints --- crates/driver/src/infra/config/file/load.rs | 2 +- crates/driver/src/infra/mempool/mod.rs | 2 +- crates/driver/src/run.rs | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/crates/driver/src/infra/config/file/load.rs b/crates/driver/src/infra/config/file/load.rs index 58d5ee1ec9..aabe755e5a 100644 --- a/crates/driver/src/infra/config/file/load.rs +++ b/crates/driver/src/infra/config/file/load.rs @@ -64,7 +64,7 @@ pub async fn load(chain: Chain, path: &Path) -> infra::Config { file::Account::Kms(arn) => { let sdk_config = alloy::signers::aws::aws_config::load_from_env().await; let client = alloy::signers::aws::aws_sdk_kms::Client::new(&sdk_config); - AwsSigner::new(client, arn.0, config.chain_id.map(Into::into)) + AwsSigner::new(client, arn.0, config.chain_id) .await .expect("unable to load kms account {arn:?}") .into() diff --git a/crates/driver/src/infra/mempool/mod.rs b/crates/driver/src/infra/mempool/mod.rs index 80180fdfc8..6468695022 100644 --- a/crates/driver/src/infra/mempool/mod.rs +++ b/crates/driver/src/infra/mempool/mod.rs @@ -144,7 +144,7 @@ impl Mempool { solver = ?solver.address(), "failed to submit tx to mempool" ); - Err(mempools::Error::Other(err.into())) + Err(mempools::Error::Other(err)) } } } diff --git a/crates/driver/src/run.rs b/crates/driver/src/run.rs index 4a95fb557e..85dfbc88d2 100644 --- a/crates/driver/src/run.rs +++ b/crates/driver/src/run.rs @@ -16,7 +16,6 @@ use { solver::Solver, }, }, - alloy::network::TxSigner, clap::Parser, futures::future::join_all, shared::arguments::tracing_config, From ab57d1b4cd58f0ae4c6677078ed09b563941f842 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=CC=81=20Duarte?= Date: Fri, 19 Dec 2025 10:46:22 +0000 Subject: [PATCH 18/24] Fix nonce --- crates/driver/src/infra/config/file/mod.rs | 12 +++++++++- crates/driver/src/infra/mempool/mod.rs | 26 ++++++++++++++-------- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/crates/driver/src/infra/config/file/mod.rs b/crates/driver/src/infra/config/file/mod.rs index 4a9e0dc81b..f9f1586f1c 100644 --- a/crates/driver/src/infra/config/file/mod.rs +++ b/crates/driver/src/infra/config/file/mod.rs @@ -1,7 +1,7 @@ pub use load::load; use { crate::{domain::eth, infra, util::serialize}, - alloy::primitives::Address, + alloy::{eips::BlockNumberOrTag, primitives::Address}, number::serialization::HexOrDecimalU256, reqwest::Url, serde::{Deserialize, Deserializer, Serialize}, @@ -144,6 +144,16 @@ impl From for web3::types::BlockNumber { } } +impl From for BlockNumberOrTag { + fn from(value: BlockNumber) -> Self { + match value { + BlockNumber::Pending => Self::Pending, + BlockNumber::Latest => Self::Latest, + BlockNumber::Earliest => Self::Earliest, + } + } +} + #[serde_as] #[derive(Debug, Deserialize)] #[serde(rename_all = "kebab-case")] diff --git a/crates/driver/src/infra/mempool/mod.rs b/crates/driver/src/infra/mempool/mod.rs index 2f4832da99..035f933a2f 100644 --- a/crates/driver/src/infra/mempool/mod.rs +++ b/crates/driver/src/infra/mempool/mod.rs @@ -6,6 +6,7 @@ use { }, alloy::{ consensus::Transaction, + eips::BlockNumberOrTag, providers::{Provider, ext::TxPoolApi}, rpc::types::TransactionRequest, }, @@ -21,7 +22,7 @@ pub struct Config { pub retry_interval: std::time::Duration, /// Optional block number to use when fetching nonces. If None, uses the /// web3 lib's default behavior, which is `latest`. - pub nonce_block_number: Option, + pub nonce_block_number: Option, pub url: reqwest::Url, pub name: String, pub revert_protection: RevertProtection, @@ -64,15 +65,22 @@ impl Mempool { /// Fetches the transaction count (nonce) for the given address at the /// specified block number. If no block number is provided in the config, - /// uses the web3 lib's default behavior. + /// uses the alloy's default behavior. pub async fn get_nonce(&self, address: eth::Address) -> Result { - self.transport - .alloy - .get_transaction_count(address) - .await - .map_err(|err| { - mempools::Error::Other(anyhow::Error::from(err).context("failed to fetch nonce")) - }) + let call = self.transport.alloy.get_transaction_count(address); + match self.config.nonce_block_number { + Some(BlockNumberOrTag::Latest) => call.latest(), + Some(BlockNumberOrTag::Earliest) => call.earliest(), + Some(BlockNumberOrTag::Finalized) => call.finalized(), + Some(BlockNumberOrTag::Number(number)) => call.number(number), + Some(BlockNumberOrTag::Pending) => call.pending(), + Some(BlockNumberOrTag::Safe) => call.safe(), + None => call, + } + .await + .map_err(|err| { + mempools::Error::Other(anyhow::Error::from(err).context("failed to fetch nonce")) + }) } /// Submits a transaction to the mempool. Returns optimistically as soon as From fdb2ce802393ceabadbf708758f3e162abfb3ed9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=CC=81=20Duarte?= Date: Fri, 19 Dec 2025 10:58:34 +0000 Subject: [PATCH 19/24] address comment --- crates/driver/src/infra/config/file/load.rs | 1 + crates/driver/src/infra/config/file/mod.rs | 4 ++++ crates/driver/src/infra/solver/mod.rs | 6 ++++++ 3 files changed, 11 insertions(+) diff --git a/crates/driver/src/infra/config/file/load.rs b/crates/driver/src/infra/config/file/load.rs index 1ba6ec37e5..c85b4d5c20 100644 --- a/crates/driver/src/infra/config/file/load.rs +++ b/crates/driver/src/infra/config/file/load.rs @@ -69,6 +69,7 @@ pub async fn load(chain: Chain, path: &Path) -> infra::Config { .expect("unable to load kms account {arn:?}") .into() } + file::Account::Address(address) => Account::Address(address), }; solver::Config { endpoint: solver_config.endpoint, diff --git a/crates/driver/src/infra/config/file/mod.rs b/crates/driver/src/infra/config/file/mod.rs index f9f1586f1c..7dfc6894f5 100644 --- a/crates/driver/src/infra/config/file/mod.rs +++ b/crates/driver/src/infra/config/file/mod.rs @@ -342,6 +342,10 @@ enum Account { PrivateKey(eth::B256), /// AWS KMS is used to sign transactions. Expects the key identifier. Kms(#[serde_as(as = "serde_with::DisplayFromStr")] Arn), + /// Used to start the driver in the dry-run mode. This account type is + /// *unable* to sign transactions as alloy does not support *implicit* + /// node-side signing. + Address(eth::Address), } #[serde_as] diff --git a/crates/driver/src/infra/solver/mod.rs b/crates/driver/src/infra/solver/mod.rs index e4819e8b70..5fba87ecbc 100644 --- a/crates/driver/src/infra/solver/mod.rs +++ b/crates/driver/src/infra/solver/mod.rs @@ -110,6 +110,7 @@ pub struct Solver { pub enum Account { PrivateKey(PrivateKeySigner), Kms(AwsSigner), + Address(Address), } #[async_trait::async_trait] @@ -118,6 +119,7 @@ impl TxSigner for Account { match self { Account::PrivateKey(local_signer) => local_signer.address(), Account::Kms(aws_signer) => aws_signer.address(), + Account::Address(address) => *address, } } @@ -128,6 +130,10 @@ impl TxSigner for Account { match self { Account::PrivateKey(local_signer) => local_signer.sign_transaction(tx).await, Account::Kms(aws_signer) => aws_signer.sign_transaction(tx).await, + // The address actually can't sign anything but for TxSigner only the Tx matters + Account::Address(_) => Err(alloy::signers::Error::UnsupportedOperation( + alloy::signers::UnsupportedSignerOperation::SignHash, + )), } } } From 6b9d8bd433aaa38778b922beb7743389d030cfc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=CC=81=20Duarte?= Date: Fri, 19 Dec 2025 11:38:29 +0000 Subject: [PATCH 20/24] fix bad local merge --- crates/driver/src/run.rs | 7 ------- crates/e2e/tests/e2e/submission.rs | 12 +++--------- 2 files changed, 3 insertions(+), 16 deletions(-) diff --git a/crates/driver/src/run.rs b/crates/driver/src/run.rs index ee9b524da9..85dfbc88d2 100644 --- a/crates/driver/src/run.rs +++ b/crates/driver/src/run.rs @@ -16,7 +16,6 @@ use { solver::Solver, }, }, - alloy::network::TxSigner, clap::Parser, futures::future::join_all, shared::arguments::tracing_config, @@ -177,12 +176,6 @@ async fn ethereum( .await .expect("initialize gas price estimator"), ); - - for solver in &config.solvers { - tracing::error!(">>> registering signer for {}", solver.account.address()); - ethrpc.web3().wallet.register_signer(solver.account.clone()); - } - Ethereum::new( ethrpc, config.contracts.clone(), diff --git a/crates/e2e/tests/e2e/submission.rs b/crates/e2e/tests/e2e/submission.rs index 3d0227fb41..0848e06214 100644 --- a/crates/e2e/tests/e2e/submission.rs +++ b/crates/e2e/tests/e2e/submission.rs @@ -121,16 +121,10 @@ async fn test_cancel_on_expiry(web3: Web3) { .await .expect("Must be able to set mining interval"); - tracing::error!(">>> solver addr {}", solver.address()); - // Wait for cancellation tx to appear - wait_for_condition(TIMEOUT, || async { - let n = solver.nonce(&web3).await; - tracing::error!(">>> got {}, expected {}", n, nonce + 1); - n == nonce + 1 - }) - .await - .unwrap(); + wait_for_condition(TIMEOUT, || async { solver.nonce(&web3).await == nonce + 1 }) + .await + .unwrap(); // Check that it's actually a cancellation let tx = tokio::time::timeout( From b1d3c0cbc87edbb6668bd644112253ba0243224c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=CC=81=20Duarte?= Date: Fri, 19 Dec 2025 11:55:41 +0000 Subject: [PATCH 21/24] fix merge --- crates/driver/src/domain/eth/mod.rs | 63 ----------------------------- 1 file changed, 63 deletions(-) diff --git a/crates/driver/src/domain/eth/mod.rs b/crates/driver/src/domain/eth/mod.rs index 6549fdad07..079e577b99 100644 --- a/crates/driver/src/domain/eth/mod.rs +++ b/crates/driver/src/domain/eth/mod.rs @@ -116,69 +116,6 @@ impl From for alloy::eips::eip2930::AccessList { } } -impl IntoIterator for AccessList { - type IntoIter = std::collections::hash_map::IntoIter>; - type Item = (Address, HashSet); - - fn into_iter(self) -> Self::IntoIter { - self.0.into_iter() - } -} - -impl FromIterator<(Address, I)> for AccessList -where - I: IntoIterator, -{ - fn from_iter>(iter: T) -> Self { - Self( - iter.into_iter() - .map(|(address, i)| { - ( - address, - i.into_iter().map(StorageKey).collect::>(), - ) - }) - .collect(), - ) - } -} - -impl From for AccessList { - fn from(value: alloy::eips::eip2930::AccessList) -> Self { - Self( - value - .0 - .into_iter() - .map(|item| { - ( - item.address, - item.storage_keys - .into_iter() - .map(StorageKey) - .collect::>(), - ) - }) - .collect(), - ) - } -} - -impl From for alloy::eips::eip2930::AccessList { - fn from(value: AccessList) -> Self { - Self( - value - .into_iter() - .map( - |(address, storage_keys)| alloy::eips::eip2930::AccessListItem { - address, - storage_keys: storage_keys.into_iter().map(|k| k.0).collect(), - }, - ) - .collect(), - ) - } -} - #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Into, From)] pub struct StorageKey(pub B256); From a2ae8ee90c855d614211f3eee7209963c033fca9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=CC=81=20Duarte?= Date: Fri, 19 Dec 2025 13:49:21 +0000 Subject: [PATCH 22/24] address comment --- crates/driver/src/infra/blockchain/mod.rs | 51 +++++++++++------------ 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/crates/driver/src/infra/blockchain/mod.rs b/crates/driver/src/infra/blockchain/mod.rs index 0420f4f181..058e20406e 100644 --- a/crates/driver/src/infra/blockchain/mod.rs +++ b/crates/driver/src/infra/blockchain/mod.rs @@ -194,13 +194,7 @@ impl Ethereum { })?; let tx = tx.with_gas_limit(gas_limit); let tx = match self.simulation_gas_price().await { - Some(gas_price) => { - let gas_price = gas_price.try_into().map_err(|err| { - Error::GasPrice(anyhow!("failed to convert gas_limit to u128: {err:?}")) - })?; - - tx.with_gas_price(gas_price) - } + Some(gas_price) => tx.with_gas_price(gas_price), _ => tx, }; @@ -223,28 +217,21 @@ impl Ethereum { .access_list(tx.access_list.into()); let tx = match self.simulation_gas_price().await { - Some(gas_price) => { - let gas_price = gas_price.try_into().map_err(|err| { - Error::GasPrice(anyhow!("failed to convert gas_limit to u128: {err:?}")) - })?; - - tx.with_gas_price(gas_price) - } + Some(gas_price) => tx.with_gas_price(gas_price), _ => tx, }; - tracing::error!("estimating gas"); - - Ok(U256::from( - self.web3 - .alloy - .estimate_gas(tx) - .pending() - .await - .map_err(anyhow::Error::from) - .map_err(Error::GasPrice)?, - ) - .into()) + let estimated_gas = self + .web3 + .alloy + .estimate_gas(tx) + .pending() + .await + .map_err(anyhow::Error::from) + .map_err(Error::GasPrice)? + .into(); + + Ok(estimated_gas) } /// The gas price is determined based on the deadline by which the @@ -309,7 +296,7 @@ impl Ethereum { } #[instrument(skip(self), ret(level = Level::DEBUG))] - pub(super) async fn simulation_gas_price(&self) -> Option { + pub(super) async fn simulation_gas_price(&self) -> Option { // Some nodes don't pick a reasonable default value when you don't specify a gas // price and default to 0. Additionally some sneaky tokens have special code // paths that detect that case to try to behave differently during simulations @@ -323,6 +310,16 @@ impl Ethereum { .await .ok() .map(|gas| gas.effective().0.0) + .and_then(|gas| { + u128::try_from(gas) + .inspect_err(|err| { + tracing::debug!( + ?err, + "failed to convert gas estimate to u128, returning None" + ); + }) + .ok() + }) } pub fn web3(&self) -> &Web3 { From f7a1e70b8e1a81e4a0f2d6252e03114d0cc5c290 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=CC=81=20Duarte?= Date: Mon, 22 Dec 2025 09:09:08 +0000 Subject: [PATCH 23/24] address comment --- crates/driver/src/infra/blockchain/mod.rs | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/crates/driver/src/infra/blockchain/mod.rs b/crates/driver/src/infra/blockchain/mod.rs index 058e20406e..029060a711 100644 --- a/crates/driver/src/infra/blockchain/mod.rs +++ b/crates/driver/src/infra/blockchain/mod.rs @@ -304,22 +304,15 @@ impl Ethereum { // default value we estimate the current gas price upfront. But because it's // extremely rare that tokens behave that way we are fine with falling back to // the node specific fallback value instead of failing the whole call. - self.inner - .gas - .estimate() - .await - .ok() - .map(|gas| gas.effective().0.0) - .and_then(|gas| { - u128::try_from(gas) - .inspect_err(|err| { - tracing::debug!( - ?err, - "failed to convert gas estimate to u128, returning None" - ); - }) - .ok() + let gas_price = self.inner.gas.estimate().await.ok()?.gas.effective().0.0; + u128::try_from(gas_price) + .inspect_err(|err| { + tracing::debug!( + ?err, + "failed to convert gas estimate to u128, returning None" + ); }) + .ok() } pub fn web3(&self) -> &Web3 { From 384be5edf804ea712763c218713ad54aa030cbaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=CC=81=20Duarte?= Date: Mon, 22 Dec 2025 09:09:30 +0000 Subject: [PATCH 24/24] fix comp --- crates/driver/src/infra/blockchain/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/driver/src/infra/blockchain/mod.rs b/crates/driver/src/infra/blockchain/mod.rs index 029060a711..8f44b030da 100644 --- a/crates/driver/src/infra/blockchain/mod.rs +++ b/crates/driver/src/infra/blockchain/mod.rs @@ -304,7 +304,7 @@ impl Ethereum { // default value we estimate the current gas price upfront. But because it's // extremely rare that tokens behave that way we are fine with falling back to // the node specific fallback value instead of failing the whole call. - let gas_price = self.inner.gas.estimate().await.ok()?.gas.effective().0.0; + let gas_price = self.inner.gas.estimate().await.ok()?.effective().0.0; u128::try_from(gas_price) .inspect_err(|err| { tracing::debug!(