From 9fc092ef5a3655e95e9b0c6885df5fe7e15b7713 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Tue, 9 Dec 2025 09:24:20 +0000 Subject: [PATCH 1/6] Migrate ethereum related DTOs and downstream usages --- Cargo.lock | 1 + crates/autopilot/src/boundary/order.rs | 12 +- crates/autopilot/src/database/competition.rs | 2 +- crates/autopilot/src/domain/auction/mod.rs | 4 +- .../domain/competition/winner_selection.rs | 19 +-- crates/autopilot/src/domain/eth/mod.rs | 21 ++- crates/autopilot/src/domain/fee/mod.rs | 19 ++- crates/autopilot/src/domain/quote/mod.rs | 7 +- crates/autopilot/src/domain/settlement/mod.rs | 58 +++----- .../src/domain/settlement/trade/math.rs | 25 ++-- .../src/domain/settlement/transaction/mod.rs | 20 +-- .../src/infra/blockchain/contracts.rs | 4 +- crates/autopilot/src/infra/blockchain/mod.rs | 14 +- .../src/infra/persistence/dto/auction.rs | 5 +- .../src/infra/persistence/dto/fee_policy.rs | 7 +- .../src/infra/persistence/dto/order.rs | 31 ++-- .../src/infra/persistence/dto/quote.rs | 9 +- crates/autopilot/src/infra/persistence/mod.rs | 68 +++++---- .../autopilot/src/infra/solvers/dto/solve.rs | 23 +-- crates/autopilot/src/run.rs | 14 +- crates/autopilot/src/run_loop.rs | 19 +-- crates/autopilot/src/shadow.rs | 2 +- crates/autopilot/src/solvable_orders.rs | 3 +- crates/autopilot/src/util/conv.rs | 6 +- crates/driver/Cargo.toml | 2 +- .../src/boundary/liquidity/balancer/v2/mod.rs | 27 ++-- .../boundary/liquidity/balancer/v2/stable.rs | 22 +-- .../liquidity/balancer/v2/weighted.rs | 20 +-- crates/driver/src/boundary/liquidity/mod.rs | 7 +- .../src/boundary/liquidity/uniswap/v2.rs | 37 ++--- .../src/boundary/liquidity/uniswap/v3.rs | 39 ++--- .../driver/src/domain/competition/auction.rs | 4 +- .../domain/competition/bad_tokens/metrics.rs | 6 +- .../competition/bad_tokens/simulation.rs | 10 +- crates/driver/src/domain/competition/mod.rs | 29 ++-- .../src/domain/competition/order/mod.rs | 36 ++--- .../src/domain/competition/pre_processing.rs | 45 +++--- .../domain/competition/solution/encoding.rs | 136 ++++++++---------- .../src/domain/competition/solution/fee.rs | 2 +- .../competition/solution/interaction.rs | 21 ++- .../src/domain/competition/solution/mod.rs | 20 ++- .../domain/competition/solution/scoring.rs | 45 +++--- .../domain/competition/solution/settlement.rs | 6 +- .../domain/competition/solution/slippage.rs | 89 ++++++------ .../src/domain/competition/solution/trade.rs | 6 +- .../driver/src/domain/competition/sorting.rs | 16 +-- crates/driver/src/domain/cow_amm.rs | 10 +- crates/driver/src/domain/eth/gas.rs | 11 +- crates/driver/src/domain/eth/mod.rs | 64 ++++----- .../src/domain/liquidity/balancer/v2/mod.rs | 2 +- .../domain/liquidity/balancer/v2/weighted.rs | 2 +- crates/driver/src/domain/liquidity/zeroex.rs | 4 +- crates/driver/src/domain/quote.rs | 19 ++- .../src/infra/api/routes/quote/dto/order.rs | 4 +- .../src/infra/api/routes/quote/dto/quote.rs | 28 ++-- .../api/routes/solve/dto/solve_request.rs | 33 +++-- .../api/routes/solve/dto/solve_response.rs | 10 +- .../driver/src/infra/blockchain/contracts.rs | 28 ++-- crates/driver/src/infra/blockchain/gas.rs | 12 +- crates/driver/src/infra/blockchain/mod.rs | 46 ++++-- crates/driver/src/infra/blockchain/token.rs | 23 +-- crates/driver/src/infra/config/file/load.rs | 7 +- crates/driver/src/infra/config/file/mod.rs | 34 ++--- crates/driver/src/infra/liquidity/config.rs | 43 +++--- crates/driver/src/infra/mempool/mod.rs | 20 +-- .../liquidity_sources/liquorice/notifier.rs | 18 ++- crates/driver/src/infra/simulator/enso/dto.rs | 9 +- crates/driver/src/infra/simulator/enso/mod.rs | 4 +- .../src/infra/simulator/tenderly/dto.rs | 11 +- .../src/infra/simulator/tenderly/mod.rs | 9 +- crates/driver/src/infra/solver/dto/auction.rs | 49 +++---- .../src/infra/solver/dto/notification.rs | 24 ++-- .../driver/src/infra/solver/dto/solution.rs | 30 ++-- crates/driver/src/infra/solver/mod.rs | 16 +-- crates/driver/src/infra/tokens.rs | 23 +-- .../driver/src/tests/cases/example_config.rs | 8 +- crates/driver/src/tests/cases/fees.rs | 4 +- .../driver/src/tests/cases/flashloan_hints.rs | 20 ++- crates/driver/src/tests/cases/jit_orders.rs | 4 +- .../src/tests/cases/order_prioritization.rs | 3 +- .../driver/src/tests/cases/protocol_fees.rs | 4 +- .../driver/src/tests/cases/solver_balance.rs | 4 +- crates/driver/src/tests/mod.rs | 4 - crates/driver/src/tests/setup/blockchain.rs | 114 +++++++-------- crates/driver/src/tests/setup/driver.rs | 12 +- crates/driver/src/tests/setup/fee.rs | 2 +- crates/driver/src/tests/setup/mod.rs | 76 +++++----- crates/driver/src/tests/setup/solver.rs | 65 ++++----- crates/driver/src/util/conv/u256.rs | 15 +- crates/driver/src/util/serialize/u256.rs | 10 +- crates/e2e/src/setup/solver/solution.rs | 21 ++- crates/e2e/tests/e2e/cow_amm.rs | 89 +++++------- crates/e2e/tests/e2e/jit_orders.rs | 20 +-- .../e2e/liquidity_source_notification.rs | 34 +++-- crates/e2e/tests/e2e/solver_competition.rs | 23 ++- .../tests/e2e/solver_participation_guard.rs | 16 +-- crates/shared/src/baseline_solver.rs | 33 +++-- .../src/sources/balancer_v2/swap/mod.rs | 93 +++++++----- .../src/sources/uniswap_v2/pool_fetching.rs | 21 +-- crates/solver/src/solver.rs | 3 +- crates/solvers-dto/Cargo.toml | 1 + crates/solvers-dto/src/auction.rs | 56 ++++---- crates/solvers-dto/src/solution.rs | 36 ++--- .../src/api/routes/solve/dto/auction.rs | 6 +- .../src/api/routes/solve/dto/solution.rs | 8 +- crates/solvers/src/boundary/baseline.rs | 58 ++++---- .../src/boundary/liquidity/concentrated.rs | 13 +- .../boundary/liquidity/constant_product.rs | 29 ++-- .../src/boundary/liquidity/limit_order.rs | 41 +++--- .../solvers/src/boundary/liquidity/stable.rs | 12 +- .../boundary/liquidity/weighted_product.rs | 20 +-- crates/solvers/src/domain/auction.rs | 9 +- crates/solvers/src/domain/eth/mod.rs | 20 ++- .../src/domain/liquidity/constant_product.rs | 2 +- .../src/domain/liquidity/limit_order.rs | 4 +- crates/solvers/src/domain/liquidity/mod.rs | 6 +- crates/solvers/src/domain/notification.rs | 2 +- crates/solvers/src/domain/order.rs | 6 +- crates/solvers/src/domain/solution.rs | 4 +- crates/solvers/src/domain/solver.rs | 22 +-- crates/solvers/src/infra/config.rs | 9 +- crates/solvers/src/infra/contracts.rs | 10 +- crates/solvers/src/util/conv.rs | 16 +-- crates/solvers/src/util/mod.rs | 1 - crates/solvers/src/util/serialize/mod.rs | 3 - crates/solvers/src/util/serialize/u256.rs | 19 --- 126 files changed, 1302 insertions(+), 1420 deletions(-) delete mode 100644 crates/solvers/src/util/serialize/mod.rs delete mode 100644 crates/solvers/src/util/serialize/u256.rs diff --git a/Cargo.lock b/Cargo.lock index 566699c907..4b01d2c733 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6544,6 +6544,7 @@ dependencies = [ name = "solvers-dto" version = "0.1.0" dependencies = [ + "alloy", "app-data", "bigdecimal", "bytes-hex", diff --git a/crates/autopilot/src/boundary/order.rs b/crates/autopilot/src/boundary/order.rs index 906e211074..95c8841dcc 100644 --- a/crates/autopilot/src/boundary/order.rs +++ b/crates/autopilot/src/boundary/order.rs @@ -1,6 +1,6 @@ use { crate::domain::{self, eth}, - ethrpc::alloy::conversions::IntoLegacy, + ethrpc::alloy::conversions::IntoAlloy, shared::remaining_amounts, }; @@ -15,12 +15,12 @@ pub fn to_domain( domain::Order { uid: order.metadata.uid.into(), sell: eth::Asset { - token: order.data.sell_token.into_legacy().into(), - amount: order.data.sell_amount.into_legacy().into(), + token: order.data.sell_token.into(), + amount: order.data.sell_amount.into(), }, buy: eth::Asset { - token: order.data.buy_token.into_legacy().into(), - amount: order.data.buy_amount.into_legacy().into(), + token: order.data.buy_token.into(), + amount: order.data.buy_amount.into(), }, protocol_fees, created: u32::try_from(order.metadata.creation_date.timestamp()).unwrap_or(u32::MIN), @@ -29,7 +29,7 @@ pub fn to_domain( receiver: order.data.receiver, owner: order.metadata.owner, partially_fillable: order.data.partially_fillable, - executed: remaining_order.executed_amount.into(), + executed: remaining_order.executed_amount.into_alloy().into(), pre_interactions: if order_is_untouched { order.interactions.pre.into_iter().map(Into::into).collect() } else { diff --git a/crates/autopilot/src/database/competition.rs b/crates/autopilot/src/database/competition.rs index 0ce7909abd..ddc7923d58 100644 --- a/crates/autopilot/src/database/competition.rs +++ b/crates/autopilot/src/database/competition.rs @@ -52,7 +52,7 @@ impl super::Postgres { .map(|(solver, score)| database::reference_scores::Score { auction_id: competition.auction_id, solver: ByteArray(solver.0.0), - reference_score: u256_to_big_decimal(&score.get().0), + reference_score: number::conversions::alloy::u256_to_big_decimal(&score.get().0), }) .collect(); diff --git a/crates/autopilot/src/domain/auction/mod.rs b/crates/autopilot/src/domain/auction/mod.rs index fb6fdb8e62..e4c3bc6a50 100644 --- a/crates/autopilot/src/domain/auction/mod.rs +++ b/crates/autopilot/src/domain/auction/mod.rs @@ -1,6 +1,6 @@ use { super::{Order, eth}, - alloy::primitives::Address, + alloy::primitives::{Address, U256}, std::collections::HashMap, }; @@ -77,7 +77,7 @@ impl Price { /// assert_eq!(eth, eth::Ether::from(eth::U256::exp10(15))); /// ``` pub fn in_eth(self, amount: eth::TokenAmount) -> eth::Ether { - (amount.0 * self.0.0 / Self::BASE).into() + (amount.0 * self.0.0 / U256::from(Self::BASE)).into() } } diff --git a/crates/autopilot/src/domain/competition/winner_selection.rs b/crates/autopilot/src/domain/competition/winner_selection.rs index 44737ae01e..86fdfc045b 100644 --- a/crates/autopilot/src/domain/competition/winner_selection.rs +++ b/crates/autopilot/src/domain/competition/winner_selection.rs @@ -476,6 +476,7 @@ mod tests { }, infra::Driver, }, + alloy::primitives::{U256, address}, ethcontract::H160, ethrpc::alloy::conversions::{IntoAlloy, IntoLegacy}, hex_literal::hex, @@ -1157,7 +1158,7 @@ mod tests { prices .iter() .map(|(token_id, price)| { - let token_address = TokenAddress(*token_map.get(token_id).unwrap()); + let token_address = token_map.get(token_id).unwrap().into_alloy().into(); let price = create_price(*price); (token_address, price) }) @@ -1274,7 +1275,7 @@ mod tests { fn create_test_arbitrator() -> super::Arbitrator { super::Arbitrator { max_winners: 10, - weth: H160::from_slice(&hex!("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2")).into(), + weth: address!("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2").into(), } } @@ -1294,18 +1295,18 @@ mod tests { uid: create_order_uid(uid), sell: eth::Asset { amount: sell_amount.into(), - token: sell_token.into(), + token: sell_token.into_alloy().into(), }, buy: eth::Asset { amount: buy_amount.into(), - token: buy_token.into(), + token: buy_token.into_alloy().into(), }, protocol_fees: vec![], side, receiver: None, owner: Default::default(), partially_fillable: false, - executed: eth::U256::zero().into(), + executed: eth::U256::ZERO.into(), pre_interactions: vec![], post_interactions: vec![], sell_token_balance: order::SellTokenSource::Erc20, @@ -1338,7 +1339,7 @@ mod tests { ) -> Auction { // Initialize the prices of the tokens if they are not specified let prices = prices.unwrap_or({ - let default_price = create_price(DEFAULT_TOKEN_PRICE.into()); + let default_price = create_price(U256::from(DEFAULT_TOKEN_PRICE)); let mut res = HashMap::new(); for order in &orders { res.insert(order.buy.token, default_price); @@ -1381,8 +1382,8 @@ mod tests { let prices = prices.unwrap_or({ let mut res = HashMap::new(); for (_, trade) in &trades { - res.insert(trade.buy.token, create_price(eth::U256::one())); - res.insert(trade.sell.token, create_price(eth::U256::one())); + res.insert(trade.buy.token, create_price(eth::U256::ONE)); + res.insert(trade.sell.token, create_price(eth::U256::ONE)); } res }); @@ -1394,7 +1395,7 @@ mod tests { solution_id, solver_address, // provided score does not matter as it's computed automatically by the arbitrator - Score(eth::Ether(eth::U256::zero())), + Score(eth::Ether(eth::U256::ZERO)), trade_order_map, prices, ); diff --git a/crates/autopilot/src/domain/eth/mod.rs b/crates/autopilot/src/domain/eth/mod.rs index 3bc638c20b..23862cdbe7 100644 --- a/crates/autopilot/src/domain/eth/mod.rs +++ b/crates/autopilot/src/domain/eth/mod.rs @@ -1,18 +1,15 @@ +pub use alloy::primitives::{Address, B256, U256}; use { crate::{domain, util::conv::U256Ext}, derive_more::{Display, From, Into}, }; -pub use { - alloy::primitives::Address, - primitive_types::{H160, H256, U256}, -}; /// ERC20 token address for ETH. In reality, ETH is not an ERC20 token because /// it does not implement the ERC20 interface, but this address is used by /// convention across the Ethereum ecosystem whenever ETH is treated like an /// ERC20 token. /// Same address is also used for XDAI on Gnosis Chain. -pub const NATIVE_TOKEN: TokenAddress = TokenAddress(H160([0xee; 20])); +pub const NATIVE_TOKEN: TokenAddress = TokenAddress(Address::repeat_byte(0xee)); /// Block number. #[derive(Debug, Copy, Clone, From, PartialEq, PartialOrd, Default)] @@ -29,13 +26,13 @@ impl std::ops::Add for BlockNo { /// A transaction ID, AKA transaction hash. #[derive(Debug, Copy, Clone, From, Default)] -pub struct TxId(pub H256); +pub struct TxId(pub B256); /// An ERC20 token address. /// /// https://eips.ethereum.org/EIPS/eip-20 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, From, Into)] -pub struct TokenAddress(pub H160); +pub struct TokenAddress(pub Address); impl TokenAddress { /// If the token is ETH/XDAI, return WETH/WXDAI, thereby converting it to @@ -54,8 +51,8 @@ impl TokenAddress { #[derive(Debug, Clone, Copy, From, Into)] pub struct WrappedNativeToken(TokenAddress); -impl From for WrappedNativeToken { - fn from(value: H160) -> Self { +impl From
for WrappedNativeToken { + fn from(value: Address) -> Self { WrappedNativeToken(value.into()) } } @@ -106,7 +103,7 @@ impl std::ops::Add for SellTokenAmount { impl num::Zero for SellTokenAmount { fn zero() -> Self { - Self(U256::zero()) + Self(U256::ZERO) } fn is_zero(&self) -> bool { @@ -232,7 +229,7 @@ impl std::ops::AddAssign for TokenAmount { impl num::Zero for TokenAmount { fn zero() -> Self { - Self(U256::zero()) + Self(U256::ZERO) } fn is_zero(&self) -> bool { @@ -284,7 +281,7 @@ impl num::CheckedSub for Ether { impl num::Zero for Ether { fn zero() -> Self { - Self(U256::zero()) + Self(U256::ZERO) } fn is_zero(&self) -> bool { diff --git a/crates/autopilot/src/domain/fee/mod.rs b/crates/autopilot/src/domain/fee/mod.rs index 77f6c48d56..6bca0bd74d 100644 --- a/crates/autopilot/src/domain/fee/mod.rs +++ b/crates/autopilot/src/domain/fee/mod.rs @@ -16,7 +16,6 @@ use { app_data::Validator, chrono::{DateTime, Utc}, derive_more::Into, - ethrpc::alloy::conversions::{IntoAlloy, IntoLegacy}, primitive_types::H160, rust_decimal::Decimal, std::{collections::HashSet, str::FromStr}, @@ -207,9 +206,9 @@ impl ProtocolFees { factor, max_volume_factor, quote: Quote { - sell_amount: quote.sell_amount.0.into_alloy(), - buy_amount: quote.buy_amount.0.into_alloy(), - fee: quote.fee.0.into_alloy(), + sell_amount: quote.sell_amount.0, + buy_amount: quote.buy_amount.0, + fee: quote.fee.0, solver: quote.solver, }, } @@ -231,9 +230,9 @@ impl ProtocolFees { // being considered out of market price. let reference_quote = quote.clone().unwrap_or(domain::Quote { order_uid: order.metadata.uid.into(), - sell_amount: order.data.sell_amount.into_legacy().into(), - buy_amount: U256::ZERO.into_legacy().into(), - fee: order.data.fee_amount.into_legacy().into(), + sell_amount: order.data.sell_amount.into(), + buy_amount: U256::ZERO.into(), + fee: order.data.fee_amount.into(), solver: Address::ZERO, }); @@ -372,9 +371,9 @@ pub struct Quote { impl Quote { fn from_domain(value: &domain::Quote) -> Self { Self { - sell_amount: value.sell_amount.0.into_alloy(), - buy_amount: value.buy_amount.0.into_alloy(), - fee: value.fee.0.into_alloy(), + sell_amount: value.sell_amount.0, + buy_amount: value.buy_amount.0, + fee: value.fee.0, solver: value.solver, } } diff --git a/crates/autopilot/src/domain/quote/mod.rs b/crates/autopilot/src/domain/quote/mod.rs index 12efff2fa1..9f8aa301e9 100644 --- a/crates/autopilot/src/domain/quote/mod.rs +++ b/crates/autopilot/src/domain/quote/mod.rs @@ -2,7 +2,6 @@ use { super::OrderUid, crate::{boundary::Amounts, domain::eth}, alloy::primitives::Address, - ethrpc::alloy::conversions::IntoAlloy, }; #[derive(Clone, Debug, PartialEq)] @@ -17,9 +16,9 @@ pub struct Quote { impl From<&Quote> for Amounts { fn from(quote: &Quote) -> Self { Self { - sell: quote.sell_amount.0.into_alloy(), - buy: quote.buy_amount.0.into_alloy(), - fee: quote.fee.0.into_alloy(), + sell: quote.sell_amount.0, + buy: quote.buy_amount.0, + fee: quote.fee.0, } } } diff --git a/crates/autopilot/src/domain/settlement/mod.rs b/crates/autopilot/src/domain/settlement/mod.rs index f0976949c0..0bdedd6430 100644 --- a/crates/autopilot/src/domain/settlement/mod.rs +++ b/crates/autopilot/src/domain/settlement/mod.rs @@ -19,7 +19,6 @@ use { chrono::{DateTime, Utc}, database::{orders::OrderKind, solver_competition_v2::Solution}, futures::TryFutureExt, - number::conversions::big_decimal_to_u256, std::collections::{HashMap, HashSet}, }; @@ -242,12 +241,16 @@ fn order_to_key(order: &database::solver_competition_v2::Order) -> OrderMatchKey OrderMatchKey { uid: OrderUid(order.uid.0), token: match order.side { - OrderKind::Sell => eth::H160(order.sell_token.0).into(), - OrderKind::Buy => eth::H160(order.buy_token.0).into(), + OrderKind::Sell => eth::Address::new(order.sell_token.0).into(), + OrderKind::Buy => eth::Address::new(order.buy_token.0).into(), }, executed: match order.side { - OrderKind::Sell => big_decimal_to_u256(&order.executed_sell).unwrap_or_default(), - OrderKind::Buy => big_decimal_to_u256(&order.executed_buy).unwrap_or_default(), + OrderKind::Sell => { + number::conversions::alloy::big_decimal_to_u256(&order.executed_sell) + .unwrap_or_default() + } + OrderKind::Buy => number::conversions::alloy::big_decimal_to_u256(&order.executed_buy) + .unwrap_or_default(), }, } } @@ -717,16 +720,12 @@ mod tests { // prices read from https://solver-instances.s3.eu-central-1.amazonaws.com/prod/mainnet/legacy/8655372.json prices: auction::Prices::from([ ( - eth::TokenAddress(eth::H160::from_slice(&hex!( - "c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" - ))), + eth::TokenAddress(address!("c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2")), auction::Price::try_new(eth::U256::from(1000000000000000000u128).into()) .unwrap(), ), ( - eth::TokenAddress(eth::H160::from_slice(&hex!( - "c52fafdc900cb92ae01e6e4f8979af7f436e2eb2" - ))), + eth::TokenAddress(address!("c52fafdc900cb92ae01e6e4f8979af7f436e2eb2")), auction::Price::try_new(eth::U256::from(537359915436704u128).into()).unwrap(), ), ]), @@ -856,16 +855,12 @@ mod tests { let prices: auction::Prices = From::from([ ( - eth::TokenAddress(eth::H160::from_slice(&hex!( - "dac17f958d2ee523a2206206994597c13d831ec7" - ))), + eth::TokenAddress(address!("dac17f958d2ee523a2206206994597c13d831ec7")), auction::Price::try_new(eth::U256::from(321341140475275961528483840u128).into()) .unwrap(), ), ( - eth::TokenAddress(eth::H160::from_slice(&hex!( - "056fd409e1d7a124bd7017459dfea2f387b6d5cd" - ))), + eth::TokenAddress(address!("056fd409e1d7a124bd7017459dfea2f387b6d5cd")), auction::Price::try_new( eth::U256::from(3177764302250520038326415654912u128).into(), ) @@ -1033,16 +1028,12 @@ mod tests { let prices: auction::Prices = From::from([ ( - eth::TokenAddress(eth::H160::from_slice(&hex!( - "a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" - ))), + eth::TokenAddress(address!("a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48")), auction::Price::try_new(eth::U256::from(374263465721452989998170112u128).into()) .unwrap(), ), ( - eth::TokenAddress(eth::H160::from_slice(&hex!( - "c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" - ))), + eth::TokenAddress(address!("c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2")), auction::Price::try_new(eth::U256::from(1000000000000000000u128).into()).unwrap(), ), ]); @@ -1215,21 +1206,15 @@ mod tests { let prices: auction::Prices = From::from([ ( - eth::TokenAddress(eth::H160::from_slice(&hex!( - "812Ba41e071C7b7fA4EBcFB62dF5F45f6fA853Ee" - ))), + eth::TokenAddress(address!("812Ba41e071C7b7fA4EBcFB62dF5F45f6fA853Ee")), auction::Price::try_new(eth::U256::from(400373909534592401408u128).into()).unwrap(), ), ( - eth::TokenAddress(eth::H160::from_slice(&hex!( - "a21Af1050F7B26e0cfF45ee51548254C41ED6b5c" - ))), + eth::TokenAddress(address!("a21Af1050F7B26e0cfF45ee51548254C41ED6b5c")), auction::Price::try_new(eth::U256::from(127910593u128).into()).unwrap(), ), ( - eth::TokenAddress(eth::H160::from_slice(&hex!( - "c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" - ))), + eth::TokenAddress(address!("c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2")), auction::Price::try_new(eth::U256::from(1000000000000000000u128).into()).unwrap(), ), ]); @@ -1248,11 +1233,14 @@ mod tests { )]), }; let jit_trade = super::trade::Trade::new(transaction.trades[1].clone(), &auction, 0); - assert_eq!(jit_trade.fee_in_ether(&auction.prices).unwrap().0, 0.into()); - assert_eq!(jit_trade.score(&auction).unwrap().0, 0.into()); + assert_eq!( + jit_trade.fee_in_ether(&auction.prices).unwrap().0, + eth::U256::ZERO + ); + assert_eq!(jit_trade.score(&auction).unwrap().0, eth::U256::ZERO); assert_eq!( jit_trade.fee_breakdown(&auction).unwrap().total.amount.0, - 0.into() + eth::U256::ZERO ); assert!( jit_trade diff --git a/crates/autopilot/src/domain/settlement/trade/math.rs b/crates/autopilot/src/domain/settlement/trade/math.rs index c8635850da..e22e823127 100644 --- a/crates/autopilot/src/domain/settlement/trade/math.rs +++ b/crates/autopilot/src/domain/settlement/trade/math.rs @@ -15,8 +15,8 @@ use { }, util::conv::U256Ext, }, + alloy::primitives::{U512, ruint::UintTryFrom}, error::Math, - ethrpc::alloy::conversions::IntoLegacy, num::{CheckedAdd, CheckedDiv, CheckedMul, CheckedSub}, std::collections::HashMap, }; @@ -55,7 +55,7 @@ impl Trade { let surplus_in_surplus_token = { let user_surplus = self.surplus_over_limit_price()?.0; let fees: eth::U256 = self.protocol_fees(fee_policies)?.into_iter().try_fold( - eth::U256::zero(), + eth::U256::ZERO, |acc, i| { acc.checked_add(i.fee.amount.0) .ok_or(Error::Math(Math::Overflow)) @@ -79,12 +79,13 @@ impl Trade { // to avoid loss of precision because we work with integers we first multiply // and then divide: // buy_amount = surplus * buy_price / sell_price - let surplus_in_buy_tokens: eth::U256 = surplus_in_surplus_token - .full_mul(self.buy.amount.0) - .checked_div(self.sell.amount.0.into()) - .ok_or(Error::Math(Math::DivisionByZero))? - .try_into() - .map_err(|_| Error::Math(Math::Overflow))?; + let surplus_in_buy_tokens = surplus_in_surplus_token + .widening_mul(self.buy.amount.0) + .checked_div(U512::from(self.sell.amount.0)) + .ok_or(Error::Math(Math::DivisionByZero))?; + let surplus_in_buy_tokens: eth::U256 = + eth::U256::uint_try_from(surplus_in_buy_tokens) + .map_err(|_| Error::Math(Math::Overflow))?; // Afterwards we convert the buy token surplus to the native token. native_price_buy.in_eth(surplus_in_buy_tokens.into()) @@ -348,7 +349,7 @@ impl Trade { // negative surplus is not error in this case, as solutions often have no // improvement over quote which results in negative surplus if let Err(error::Math::Negative) = surplus { - return Ok(eth::SurplusTokenAmount(0.into())); + return Ok(eth::SurplusTokenAmount(eth::U256::ZERO)); } Ok(surplus?) } @@ -384,9 +385,9 @@ impl Trade { side: self.side, }, Quote { - sell: quote.sell_amount.into_legacy().into(), - buy: quote.buy_amount.into_legacy().into(), - fee: quote.fee.into_legacy().into(), + sell: quote.sell_amount.into(), + buy: quote.buy_amount.into(), + fee: quote.fee.into(), }, )?; self.surplus_over(&self.prices.custom, quote) diff --git a/crates/autopilot/src/domain/settlement/transaction/mod.rs b/crates/autopilot/src/domain/settlement/transaction/mod.rs index 01185f5733..bb1f377c6f 100644 --- a/crates/autopilot/src/domain/settlement/transaction/mod.rs +++ b/crates/autopilot/src/domain/settlement/transaction/mod.rs @@ -138,18 +138,18 @@ impl Transaction { uid: tokenized::order_uid(&trade, &tokens, domain_separator) .map_err(Error::OrderUidRecover)?, sell: eth::Asset { - token: sell_token.into_legacy().into(), - amount: trade.sellAmount.into_legacy().into(), + token: sell_token.into(), + amount: trade.sellAmount.into(), }, buy: eth::Asset { - token: buy_token.into_legacy().into(), - amount: trade.buyAmount.into_legacy().into(), + token: buy_token.into(), + amount: trade.buyAmount.into(), }, side: flags.side(), receiver: trade.receiver, valid_to: trade.validTo, app_data: domain::auction::order::AppDataHash(trade.appData.into()), - fee_amount: trade.feeAmount.into_legacy().into(), + fee_amount: trade.feeAmount.into(), sell_token_balance: flags.sell_token_balance().into(), buy_token_balance: flags.buy_token_balance().into(), partially_fillable: flags.partially_fillable(), @@ -159,15 +159,15 @@ impl Transaction { ) .map_err(Error::SignatureRecover)?) .into(), - executed: trade.executedAmount.into_legacy().into(), + executed: trade.executedAmount.into(), prices: Prices { uniform: ClearingPrices { - sell: clearing_prices[uniform_sell_token_index].into_legacy(), - buy: clearing_prices[uniform_buy_token_index].into_legacy(), + sell: clearing_prices[uniform_sell_token_index], + buy: clearing_prices[uniform_buy_token_index], }, custom: ClearingPrices { - sell: clearing_prices[sell_token_index].into_legacy(), - buy: clearing_prices[buy_token_index].into_legacy(), + sell: clearing_prices[sell_token_index], + buy: clearing_prices[buy_token_index], }, }, }) diff --git a/crates/autopilot/src/infra/blockchain/contracts.rs b/crates/autopilot/src/infra/blockchain/contracts.rs index a6eb92a1ae..afbebbea14 100644 --- a/crates/autopilot/src/infra/blockchain/contracts.rs +++ b/crates/autopilot/src/infra/blockchain/contracts.rs @@ -10,7 +10,7 @@ use { WETH9, support::Balances, }, - ethrpc::{Web3, alloy::conversions::IntoLegacy}, + ethrpc::Web3, }; #[derive(Debug, Clone)] @@ -145,7 +145,7 @@ impl Contracts { /// Wrapped version of the native token (e.g. WETH for Ethereum, WXDAI for /// Gnosis Chain) pub fn wrapped_native_token(&self) -> domain::eth::WrappedNativeToken { - self.weth.address().into_legacy().into() + (*self.weth.address()).into() } pub fn authenticator(&self) -> &GPv2AllowListAuthentication::Instance { diff --git a/crates/autopilot/src/infra/blockchain/mod.rs b/crates/autopilot/src/infra/blockchain/mod.rs index 3b2fa38be2..0b8a9b9624 100644 --- a/crates/autopilot/src/infra/blockchain/mod.rs +++ b/crates/autopilot/src/infra/blockchain/mod.rs @@ -5,7 +5,7 @@ use { chain::Chain, ethrpc::{ Web3, - alloy::conversions::IntoAlloy, + alloy::conversions::{IntoAlloy, IntoLegacy}, block_stream::CurrentBlockWatcher, extensions::DebugNamespace, }, @@ -112,11 +112,13 @@ 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()), - self.web3.eth().transaction_receipt(hash.0), + self.web3.eth().transaction(hash.0.into_legacy().into()), + self.web3.eth().transaction_receipt(hash.0.into_legacy()), // Use unbuffered transport for the Debug API since not all providers support // batched debug calls. - self.unbuffered_web3.debug().transaction(hash.0), + self.unbuffered_web3 + .debug() + .transaction(hash.0.into_legacy()), )?; let transaction = transaction.ok_or(Error::TransactionNotFound)?; let receipt = receipt.ok_or(Error::TransactionNotFound)?; @@ -144,7 +146,7 @@ fn into_domain( timestamp: U256, ) -> anyhow::Result { Ok(eth::Transaction { - hash: transaction.hash.into(), + hash: transaction.hash.into_alloy().into(), from: transaction .from .map(IntoAlloy::into_alloy) @@ -157,10 +159,12 @@ fn into_domain( 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(), timestamp: timestamp.as_u32(), trace_calls: trace_calls.into(), diff --git a/crates/autopilot/src/infra/persistence/dto/auction.rs b/crates/autopilot/src/infra/persistence/dto/auction.rs index 0755ec033a..3fbd168416 100644 --- a/crates/autopilot/src/infra/persistence/dto/auction.rs +++ b/crates/autopilot/src/infra/persistence/dto/auction.rs @@ -20,7 +20,7 @@ pub fn from_domain(auction: domain::RawAuctionData) -> RawAuctionData { prices: auction .prices .into_iter() - .map(|(key, value)| (key.into(), value.get().into())) + .map(|(key, value)| (key.0.into_legacy(), value.get().0.into_legacy())) .collect(), surplus_capturing_jit_order_owners: auction .surplus_capturing_jit_order_owners @@ -69,7 +69,8 @@ impl Auction { .prices .into_iter() .map(|(key, value)| { - Price::try_new(value.into()).map(|price| (eth::TokenAddress(key), price)) + Price::try_new(value.into_alloy().into()) + .map(|price| (eth::TokenAddress(key.into_alloy()), price)) }) .collect::>()?, surplus_capturing_jit_order_owners: self diff --git a/crates/autopilot/src/infra/persistence/dto/fee_policy.rs b/crates/autopilot/src/infra/persistence/dto/fee_policy.rs index b6700777bc..d82a019c36 100644 --- a/crates/autopilot/src/infra/persistence/dto/fee_policy.rs +++ b/crates/autopilot/src/infra/persistence/dto/fee_policy.rs @@ -2,7 +2,6 @@ use { crate::{boundary, domain}, anyhow::Context, database::fee_policies::{FeePolicy, FeePolicyKind}, - ethrpc::alloy::conversions::IntoAlloy, }; pub fn from_domain( @@ -84,9 +83,9 @@ pub fn try_into_domain( quote: { let quote = quote.ok_or(Error::MissingQuote)?; domain::fee::Quote { - sell_amount: quote.sell_amount.0.into_alloy(), - buy_amount: quote.buy_amount.0.into_alloy(), - fee: quote.fee.0.into_alloy(), + sell_amount: quote.sell_amount.0, + buy_amount: quote.buy_amount.0, + fee: quote.fee.0, solver: quote.solver, } }, diff --git a/crates/autopilot/src/infra/persistence/dto/order.rs b/crates/autopilot/src/infra/persistence/dto/order.rs index 88fd4662c3..241e199c74 100644 --- a/crates/autopilot/src/infra/persistence/dto/order.rs +++ b/crates/autopilot/src/infra/persistence/dto/order.rs @@ -3,11 +3,10 @@ use { boundary::{self}, domain::{self, OrderUid, eth, fee::FeeFactor}, }, - alloy::primitives::Address, + alloy::primitives::{Address, U256}, app_data::AppDataHash, ethrpc::alloy::conversions::{IntoAlloy, IntoLegacy}, number::serialization::HexOrDecimalU256, - primitive_types::{H160, U256}, serde::{Deserialize, Serialize}, serde_with::serde_as, }; @@ -17,8 +16,8 @@ use { #[serde(rename_all = "camelCase")] pub struct Order { pub uid: boundary::OrderUid, - pub sell_token: H160, - pub buy_token: H160, + pub sell_token: Address, + pub buy_token: Address, #[serde_as(as = "HexOrDecimalU256")] pub sell_amount: U256, #[serde_as(as = "HexOrDecimalU256")] @@ -27,8 +26,8 @@ pub struct Order { pub created: u32, pub valid_to: u32, pub kind: boundary::OrderKind, - pub receiver: Option, - pub owner: H160, + pub receiver: Option
, + pub owner: Address, pub partially_fillable: bool, #[serde_as(as = "HexOrDecimalU256")] pub executed: U256, @@ -59,8 +58,8 @@ pub fn from_domain(order: domain::Order) -> Order { created: order.created, valid_to: order.valid_to, kind: order.side.into(), - receiver: order.receiver.map(IntoLegacy::into_legacy), - owner: order.owner.into_legacy(), + receiver: order.receiver, + owner: order.owner, partially_fillable: order.partially_fillable, executed: order.executed.into(), pre_interactions: order.pre_interactions.into_iter().map(Into::into).collect(), @@ -97,8 +96,8 @@ pub fn to_domain(order: Order) -> domain::Order { created: order.created, valid_to: order.valid_to, side: order.kind.into(), - receiver: order.receiver.map(|h160| eth::Address::from(h160.0)), - owner: eth::Address::from(order.owner.0), + receiver: order.receiver, + owner: order.owner, partially_fillable: order.partially_fillable, executed: order.executed.into(), pre_interactions: order.pre_interactions.into_iter().map(Into::into).collect(), @@ -348,9 +347,9 @@ pub struct Quote { impl Quote { fn from_domain(quote: domain::Quote) -> Self { Quote { - sell_amount: quote.sell_amount.0.into_alloy(), - buy_amount: quote.buy_amount.0.into_alloy(), - fee: quote.fee.0.into_alloy(), + sell_amount: quote.sell_amount.0, + buy_amount: quote.buy_amount.0, + fee: quote.fee.0, solver: quote.solver, } } @@ -358,9 +357,9 @@ impl Quote { pub fn to_domain(&self, order_uid: OrderUid) -> domain::Quote { domain::Quote { order_uid, - sell_amount: self.sell_amount.into_legacy().into(), - buy_amount: self.buy_amount.into_legacy().into(), - fee: self.fee.into_legacy().into(), + sell_amount: self.sell_amount.into(), + buy_amount: self.buy_amount.into(), + fee: self.fee.into(), solver: self.solver, } } diff --git a/crates/autopilot/src/infra/persistence/dto/quote.rs b/crates/autopilot/src/infra/persistence/dto/quote.rs index d3216d024e..79f108a51c 100644 --- a/crates/autopilot/src/infra/persistence/dto/quote.rs +++ b/crates/autopilot/src/infra/persistence/dto/quote.rs @@ -8,8 +8,9 @@ use { FromPrimitive, num_traits::{CheckedDiv, CheckedMul}, }, + ethrpc::alloy::conversions::IntoAlloy, num::BigRational, - number::conversions::{big_decimal_to_u256, big_rational_to_u256}, + number::conversions::big_rational_to_u256, }; pub fn into_domain(quote: boundary::database::orders::Quote) -> Result { @@ -27,13 +28,13 @@ pub fn into_domain(quote: boundary::database::orders::Quote) -> Result(solution) @@ -344,7 +356,7 @@ impl Persistence { ByteArray(solver.0.0), ) .await? - .map(|hash| H256(hash.0).into())) + .map(|hash| B256::new(hash.0).into())) } /// Save auction related data to the database. @@ -374,12 +386,12 @@ impl Persistence { price_tokens: auction .prices .keys() - .map(|token| ByteArray(token.0.0)) + .map(|token| ByteArray(token.0.0.0)) .collect(), price_values: auction .prices .values() - .map(|price| u256_to_big_decimal(&price.get().0)) + .map(|price| number::conversions::alloy::u256_to_big_decimal(&price.get().0)) .collect(), surplus_capturing_jit_order_owners: auction .surplus_capturing_jit_order_owners @@ -425,8 +437,8 @@ impl Persistence { .map_err(error::Auction::DatabaseError)? .into_iter() .map(|price| { - let token = eth::H160(price.token.0).into(); - let price = big_decimal_to_u256(&price.price) + let token = eth::Address::new(price.token.0).into(); + let price = number::conversions::alloy::big_decimal_to_u256(&price.price) .ok_or(domain::auction::InvalidPrice) .and_then(|p| domain::auction::Price::try_new(p.into())) .map_err(|_err| error::Auction::InvalidPrice(token)); @@ -678,7 +690,7 @@ impl Persistence { .context("negative block")? .into(), log_index: u64::try_from(event.log_index).context("negative log index")?, - transaction: eth::TxId(H256(event.tx_hash.0)), + transaction: eth::TxId(B256::new(event.tx_hash.0)), }; Ok::<_, DatabaseError>(event) }) @@ -790,15 +802,19 @@ impl Persistence { auction_id, block_number, Asset { - token: ByteArray(order_fee.total.token.0.0), - amount: u256_to_big_decimal(&order_fee.total.amount.0), + token: ByteArray(order_fee.total.token.0.0.0), + amount: number::conversions::alloy::u256_to_big_decimal( + &order_fee.total.amount.0, + ), }, &order_fee .protocol .into_iter() .map(|executed| Asset { - token: ByteArray(executed.fee.token.0.0), - amount: u256_to_big_decimal(&executed.fee.amount.0), + token: ByteArray(executed.fee.token.0.0.0), + amount: number::conversions::alloy::u256_to_big_decimal( + &executed.fee.amount.0, + ), }) .collect::>(), ) @@ -830,13 +846,13 @@ impl Persistence { 0, ) .unwrap_or_default(), - sell_token: ByteArray(jit_order.sell.token.0.0), - buy_token: ByteArray(jit_order.buy.token.0.0), - sell_amount: u256_to_big_decimal(&jit_order.sell.amount.0), - buy_amount: u256_to_big_decimal(&jit_order.buy.amount.0), + sell_token: ByteArray(jit_order.sell.token.0.0.0), + buy_token: ByteArray(jit_order.buy.token.0.0.0), + sell_amount: number::conversions::alloy::u256_to_big_decimal(&jit_order.sell.amount.0), + buy_amount: number::conversions::alloy::u256_to_big_decimal(&jit_order.buy.amount.0), valid_to: i64::from(jit_order.valid_to), app_data: ByteArray(jit_order.app_data.0), - fee_amount: u256_to_big_decimal(&jit_order.fee_amount.0), + fee_amount: number::conversions::alloy::u256_to_big_decimal(&jit_order.fee_amount.0), kind: jit_order.side.into(), partially_fillable: jit_order.partially_fillable, signature: jit_order.signature.to_bytes(), diff --git a/crates/autopilot/src/infra/solvers/dto/solve.rs b/crates/autopilot/src/infra/solvers/dto/solve.rs index 330bf6150a..f0fadc88d1 100644 --- a/crates/autopilot/src/infra/solvers/dto/solve.rs +++ b/crates/autopilot/src/infra/solvers/dto/solve.rs @@ -51,9 +51,9 @@ impl Request { .prices .iter() .map(|(address, price)| Token { - address: address.to_owned().into(), - price: Some(price.get().into()), - trusted: trusted_tokens.contains(&(address.0)), + address: address.to_owned().0.into_legacy(), + price: Some(price.get().0.into_legacy()), + trusted: trusted_tokens.contains(&(address.0.into_legacy())), }) .chain(trusted_tokens.iter().map(|&address| Token { address, @@ -116,7 +116,7 @@ impl Solution { Ok(domain::competition::Solution::new( self.solution_id, self.submission_address.into_alloy(), - domain::competition::Score::try_new(self.score.into())?, + domain::competition::Score::try_new(self.score.into_alloy().into())?, self.orders .into_iter() .map(|(o, amounts)| (o.into(), amounts.into_domain())) @@ -124,7 +124,8 @@ impl Solution { self.clearing_prices .into_iter() .map(|(token, price)| { - domain::auction::Price::try_new(price.into()).map(|price| (token.into(), price)) + domain::auction::Price::try_new(price.into_alloy().into()) + .map(|price| (token.into_alloy().into(), price)) }) .collect::>()?, )) @@ -160,19 +161,19 @@ impl TradedOrder { pub fn into_domain(self) -> domain::competition::TradedOrder { domain::competition::TradedOrder { sell: eth::Asset { - token: self.sell_token.into(), - amount: self.limit_sell.into(), + token: self.sell_token.into_alloy().into(), + amount: self.limit_sell.into_alloy().into(), }, buy: eth::Asset { - token: self.buy_token.into(), - amount: self.limit_buy.into(), + token: self.buy_token.into_alloy().into(), + amount: self.limit_buy.into_alloy().into(), }, side: match self.side { Side::Buy => domain::auction::order::Side::Buy, Side::Sell => domain::auction::order::Side::Sell, }, - executed_sell: self.executed_sell.into(), - executed_buy: self.executed_buy.into(), + executed_sell: self.executed_sell.into_alloy().into(), + executed_buy: self.executed_buy.into_alloy().into(), } } } diff --git a/crates/autopilot/src/run.rs b/crates/autopilot/src/run.rs index 5823554e7b..3ea7f470fe 100644 --- a/crates/autopilot/src/run.rs +++ b/crates/autopilot/src/run.rs @@ -31,7 +31,7 @@ use { ethcontract::H160, ethrpc::{ Web3, - alloy::conversions::IntoLegacy, + alloy::conversions::{IntoAlloy, IntoLegacy}, block_stream::block_number_to_block_number_hash, }, futures::StreamExt, @@ -658,7 +658,10 @@ pub async fn run(args: Arguments, shutdown_controller: ShutdownController) { infra::Driver::try_new( driver.url, driver.name.clone(), - driver.fairness_threshold.map(Into::into), + driver + .fairness_threshold + .map(IntoAlloy::into_alloy) + .map(Into::into), driver.submission_account, driver.requested_timeout_on_problems, ) @@ -715,7 +718,10 @@ async fn shadow_mode(args: Arguments) -> ! { infra::Driver::try_new( driver.url, driver.name.clone(), - driver.fairness_threshold.map(Into::into), + driver + .fairness_threshold + .map(IntoAlloy::into_alloy) + .map(Into::into), // HACK: the auction logic expects all drivers // to use a different submission address. But // in the shadow environment all drivers use @@ -795,7 +801,7 @@ async fn shadow_mode(args: Arguments) -> ! { liveness.clone(), current_block, args.max_winners_per_auction, - weth.address().into_legacy().into(), + (*weth.address()).into(), ); shadow.run_forever().await; } diff --git a/crates/autopilot/src/run_loop.rs b/crates/autopilot/src/run_loop.rs index dafe902d63..570e63c8a5 100644 --- a/crates/autopilot/src/run_loop.rs +++ b/crates/autopilot/src/run_loop.rs @@ -29,10 +29,7 @@ use { ::observe::metrics, anyhow::{Context, Result}, database::order_events::OrderEventLabel, - ethrpc::{ - alloy::conversions::{IntoAlloy, IntoLegacy}, - block_stream::BlockInfo, - }, + ethrpc::{alloy::conversions::IntoLegacy, block_stream::BlockInfo}, futures::{FutureExt, TryFutureExt}, itertools::Itertools, model::solver_competition::{ @@ -497,9 +494,7 @@ impl RunLoop { .map(|(index, participant)| SolverSettlement { solver: participant.driver().name.clone(), solver_address: participant.solution().solver(), - score: Some(Score::Solver( - participant.solution().score().get().0.into_alloy(), - )), + score: Some(Score::Solver(participant.solution().score().get().0)), ranking: index + 1, orders: participant .solution() @@ -507,15 +502,15 @@ impl RunLoop { .iter() .map(|(id, order)| Order::Colocated { id: (*id).into(), - sell_amount: order.executed_sell.0.into_alloy(), - buy_amount: order.executed_buy.0.into_alloy(), + sell_amount: order.executed_sell.0, + buy_amount: order.executed_buy.0, }) .collect(), clearing_prices: participant .solution() .prices() .iter() - .map(|(token, price)| (token.0.into_alloy(), price.get().0.into_alloy())) + .map(|(token, price)| (token.0, price.get().0)) .collect(), is_winner: participant.is_winner(), filtered_out: participant.filtered_out(), @@ -537,7 +532,7 @@ impl RunLoop { prices: auction .prices .iter() - .map(|(key, value)| (key.0.into_alloy(), value.get().0.into_alloy())) + .map(|(key, value)| (key.0, value.get().0)) .collect(), }, solutions, @@ -550,7 +545,7 @@ impl RunLoop { .prices .clone() .into_iter() - .map(|(key, value)| (key.into(), value.get().into())) + .map(|(key, value)| (key.0.into_legacy(), value.get().0.into_legacy())) .collect(), block_deadline, competition_simulation_block, diff --git a/crates/autopilot/src/shadow.rs b/crates/autopilot/src/shadow.rs index e0a5b67e4a..9e99d83609 100644 --- a/crates/autopilot/src/shadow.rs +++ b/crates/autopilot/src/shadow.rs @@ -167,7 +167,7 @@ impl RunLoop { Metrics::get() .performance_rewards .with_label_values(&[&driver.name]) - .inc_by(reward.get().0.to_f64_lossy()); + .inc_by(f64::from(reward.get().0)); Metrics::get() .wins .with_label_values(&[&driver.name]) diff --git a/crates/autopilot/src/solvable_orders.rs b/crates/autopilot/src/solvable_orders.rs index 84995a913b..bd8b411c40 100644 --- a/crates/autopilot/src/solvable_orders.rs +++ b/crates/autopilot/src/solvable_orders.rs @@ -310,8 +310,7 @@ impl SolvableOrdersCache { prices: prices .into_iter() .map(|(key, value)| { - Price::try_new(value.into_legacy().into()) - .map(|price| (eth::TokenAddress(key.into_legacy()), price)) + Price::try_new(value.into()).map(|price| (eth::TokenAddress(key), price)) }) .collect::>()?, surplus_capturing_jit_order_owners, diff --git a/crates/autopilot/src/util/conv.rs b/crates/autopilot/src/util/conv.rs index d3fa44f96a..11629fdc44 100644 --- a/crates/autopilot/src/util/conv.rs +++ b/crates/autopilot/src/util/conv.rs @@ -7,7 +7,7 @@ pub trait U256Ext: Sized { impl U256Ext for eth::U256 { fn checked_ceil_div(&self, other: &Self) -> Option { - self.checked_add(other.checked_sub(1.into())?)? + self.checked_add(other.checked_sub(Self::ONE)?)? .checked_div(*other) } @@ -22,8 +22,8 @@ impl U256Ext for eth::U256 { // that requires to double check and adjust a few tests due to tiny // changes in rounding. const CONVERSION_FACTOR: f64 = 1_000_000_000_000_000_000.; - let multiplied = self.checked_mul(Self::from_f64_lossy(factor * CONVERSION_FACTOR))? - / Self::from_f64_lossy(CONVERSION_FACTOR); + let multiplied = self.checked_mul(Self::from(factor * CONVERSION_FACTOR))? + / Self::from(CONVERSION_FACTOR); Some(multiplied) } } diff --git a/crates/driver/Cargo.toml b/crates/driver/Cargo.toml index 89f59e8e53..b7af7e7128 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"] } +alloy = { workspace = true, features = ["sol-types", "rand"] } app-data = { workspace = true } async-trait = { workspace = true } axum = { workspace = true } diff --git a/crates/driver/src/boundary/liquidity/balancer/v2/mod.rs b/crates/driver/src/boundary/liquidity/balancer/v2/mod.rs index 99f2c48270..d0a837776f 100644 --- a/crates/driver/src/boundary/liquidity/balancer/v2/mod.rs +++ b/crates/driver/src/boundary/liquidity/balancer/v2/mod.rs @@ -16,10 +16,7 @@ use { BalancerV2WeightedPoolFactory, BalancerV2WeightedPoolFactoryV3, }, - ethrpc::{ - alloy::conversions::{IntoAlloy, IntoLegacy}, - block_stream::{BlockRetrieving, CurrentBlockWatcher}, - }, + ethrpc::block_stream::{BlockRetrieving, CurrentBlockWatcher}, shared::{ http_solver::model::TokenAmount, sources::balancer_v2::{ @@ -55,27 +52,21 @@ fn to_interaction( // Note that this code assumes `receiver == sender`. This assumption is // also baked into the Balancer V2 logic in the `shared` crate, so to // change this assumption, we would need to change it there as well. - receiver.0.into_alloy(), - pool.vault.0.into_alloy(), - Allowances::empty(receiver.0.into_alloy()), + *receiver, + pool.vault.0, + Allowances::empty(*receiver), ); let interaction = handler.swap( - TokenAmount::new( - input.0.token.0.0.into_alloy(), - input.0.amount.0.into_alloy(), - ), - TokenAmount::new( - output.0.token.0.0.into_alloy(), - output.0.amount.0.into_alloy(), - ), + TokenAmount::new(input.0.token.0.0, input.0.amount.0), + TokenAmount::new(output.0.token.0.0, output.0.amount.0), ); let (target, value, call_data) = interaction.encode_swap(); eth::Interaction { - target: target.into_legacy().into(), - value: value.into_legacy().into(), + target, + value: value.into(), call_data: call_data.0.to_vec().into(), } } @@ -113,7 +104,7 @@ async fn init_liquidity( ) -> Result> { let web3 = eth.web3().clone(); let contracts = BalancerContracts { - vault: BalancerV2Vault::Instance::new(config.vault.0.into_alloy(), web3.alloy.clone()), + vault: BalancerV2Vault::Instance::new(config.vault.0, web3.alloy.clone()), factories: [ config .weighted diff --git a/crates/driver/src/boundary/liquidity/balancer/v2/stable.rs b/crates/driver/src/boundary/liquidity/balancer/v2/stable.rs index 0a9eb482ea..03b21b48f4 100644 --- a/crates/driver/src/boundary/liquidity/balancer/v2/stable.rs +++ b/crates/driver/src/boundary/liquidity/balancer/v2/stable.rs @@ -6,7 +6,7 @@ use { liquidity::{self, balancer}, }, }, - ethrpc::alloy::conversions::IntoLegacy, + ethrpc::alloy::conversions::IntoAlloy, solver::liquidity::{StablePoolOrder, balancer_v2}, }; @@ -27,33 +27,33 @@ pub fn to_domain(id: liquidity::Id, pool: StablePoolOrder) -> Result>()?, )?, amplification_parameter: balancer::v2::stable::AmplificationParameter::new( - pool.amplification_parameter.factor(), - pool.amplification_parameter.precision(), + pool.amplification_parameter.factor().into_alloy(), + pool.amplification_parameter.precision().into_alloy(), )?, - fee: balancer::v2::Fee::from_raw(pool.fee.as_uint256()), + fee: balancer::v2::Fee::from_raw(pool.fee.as_uint256().into_alloy()), }), }) } fn vault(pool: &StablePoolOrder) -> eth::ContractAddress { - pool.settlement_handling + (*pool + .settlement_handling .as_any() .downcast_ref::() .expect("downcast balancer settlement handler") - .vault() - .into_legacy() - .into() + .vault()) + .into() } fn pool_id(pool: &StablePoolOrder) -> balancer::v2::Id { diff --git a/crates/driver/src/boundary/liquidity/balancer/v2/weighted.rs b/crates/driver/src/boundary/liquidity/balancer/v2/weighted.rs index f0e75b24c2..4ddba4063c 100644 --- a/crates/driver/src/boundary/liquidity/balancer/v2/weighted.rs +++ b/crates/driver/src/boundary/liquidity/balancer/v2/weighted.rs @@ -6,7 +6,7 @@ use { liquidity::{self, balancer}, }, }, - ethrpc::alloy::conversions::IntoLegacy, + ethrpc::alloy::conversions::IntoAlloy, shared::sources::balancer_v2::pool_fetching::WeightedPoolVersion, solver::liquidity::{WeightedProductOrder, balancer_v2}, }; @@ -28,20 +28,20 @@ pub fn to_domain(id: liquidity::Id, pool: WeightedProductOrder) -> Result>()?, )?, - fee: balancer::v2::Fee::from_raw(pool.fee.as_uint256()), + fee: balancer::v2::Fee::from_raw(pool.fee.as_uint256().into_alloy()), version: match pool.version { WeightedPoolVersion::V0 => balancer::v2::weighted::Version::V0, WeightedPoolVersion::V3Plus => balancer::v2::weighted::Version::V3Plus, @@ -51,13 +51,13 @@ pub fn to_domain(id: liquidity::Id, pool: WeightedProductOrder) -> Result eth::ContractAddress { - pool.settlement_handling + (*pool + .settlement_handling .as_any() .downcast_ref::() .expect("downcast balancer settlement handler") - .vault() - .into_legacy() - .into() + .vault()) + .into() } fn pool_id(pool: &WeightedProductOrder) -> balancer::v2::Id { diff --git a/crates/driver/src/boundary/liquidity/mod.rs b/crates/driver/src/boundary/liquidity/mod.rs index a06e8ae772..545fd8d51a 100644 --- a/crates/driver/src/boundary/liquidity/mod.rs +++ b/crates/driver/src/boundary/liquidity/mod.rs @@ -4,7 +4,7 @@ use { infra::{self, blockchain::Ethereum}, }, anyhow::Result, - ethrpc::{alloy::conversions::IntoAlloy, block_stream::CurrentBlockWatcher}, + ethrpc::block_stream::CurrentBlockWatcher, futures::future, model::TokenPair, shared::{ @@ -104,7 +104,8 @@ impl Fetcher { &config .base_tokens .iter() - .map(|t| t.0.0.into_alloy()) + .cloned() + .map(Into::into) .collect::>(), ); @@ -131,7 +132,7 @@ impl Fetcher { .iter() .map(|pair| { let (a, b) = pair.get(); - TokenPair::new(a.0.0.into_alloy(), b.0.0.into_alloy()).expect("a != b") + TokenPair::new(a.0.0, b.0.0).expect("a != b") }) .collect(); diff --git a/crates/driver/src/boundary/liquidity/uniswap/v2.rs b/crates/driver/src/boundary/liquidity/uniswap/v2.rs index 8bf9b979cc..6c2d33d9a6 100644 --- a/crates/driver/src/boundary/liquidity/uniswap/v2.rs +++ b/crates/driver/src/boundary/liquidity/uniswap/v2.rs @@ -10,11 +10,7 @@ use { alloy::primitives::Address, async_trait::async_trait, contracts::alloy::IUniswapLikeRouter, - ethrpc::{ - Web3, - alloy::conversions::{IntoAlloy, IntoLegacy}, - block_stream::CurrentBlockWatcher, - }, + ethrpc::{Web3, block_stream::CurrentBlockWatcher}, shared::{ http_solver::model::TokenAmount, sources::uniswap_v2::{ @@ -61,7 +57,7 @@ pub fn router(pool: &ConstantProductOrder) -> eth::ContractAddress { .downcast_ref::() .expect("downcast uniswap settlement handler") .router(); - eth::ContractAddress::from(address.into_legacy()) + eth::ContractAddress::from(address) } pub(in crate::boundary::liquidity) fn to_domain_pool( @@ -76,15 +72,15 @@ pub(in crate::boundary::liquidity) fn to_domain_pool( ); Ok(liquidity::uniswap::v2::Pool { - address: pool.address.into_legacy().into(), + address: pool.address, router: router(&pool), reserves: liquidity::uniswap::v2::Reserves::try_new( eth::Asset { - token: pool.tokens.get().0.into_legacy().into(), + token: pool.tokens.get().0.into(), amount: pool.reserves.0.into(), }, eth::Asset { - token: pool.tokens.get().1.into_legacy().into(), + token: pool.tokens.get().1.into(), amount: pool.reserves.1.into(), }, ) @@ -99,27 +95,21 @@ pub fn to_interaction( receiver: ð::Address, ) -> eth::Interaction { let handler = uniswap_v2::Inner::new( - pool.router.0.into_alloy(), - receiver.0.into_alloy(), - Mutex::new(Allowances::empty(receiver.0.into_alloy())), + pool.router.0, + *receiver, + Mutex::new(Allowances::empty(*receiver)), ); let (_, interaction) = handler.settle( - TokenAmount::new( - input.0.token.0.0.into_alloy(), - input.0.amount.0.into_alloy(), - ), - TokenAmount::new( - output.0.token.0.0.into_alloy(), - output.0.amount.0.into_alloy(), - ), + TokenAmount::new(input.0.token.into(), input.0.amount), + TokenAmount::new(output.0.token.into(), output.0.amount), ); let (target, value, call_data) = interaction.encode_swap(); eth::Interaction { - target: target.into_legacy().into(), - value: value.into_legacy().into(), + target, + value: value.into(), call_data: call_data.0.to_vec().into(), } } @@ -143,8 +133,7 @@ where R: PoolReading + Send + Sync + 'static, F: FnOnce(Web3, PairProvider) -> R, { - let router = - IUniswapLikeRouter::Instance::new(config.router.0.into_alloy(), eth.web3().alloy.clone()); + let router = IUniswapLikeRouter::Instance::new(config.router.0, eth.web3().alloy.clone()); let settlement = eth.contracts().settlement().clone(); let pool_fetcher = { let factory = router.factory().call().await?; diff --git a/crates/driver/src/boundary/liquidity/uniswap/v3.rs b/crates/driver/src/boundary/liquidity/uniswap/v3.rs index 6ac59e305a..b68358ea05 100644 --- a/crates/driver/src/boundary/liquidity/uniswap/v3.rs +++ b/crates/driver/src/boundary/liquidity/uniswap/v3.rs @@ -11,10 +11,7 @@ use { infra::{self, blockchain::Ethereum}, }, anyhow::Context, - ethrpc::{ - alloy::conversions::{IntoAlloy, IntoLegacy}, - block_stream::BlockRetrieving, - }, + ethrpc::{alloy::conversions::IntoAlloy, block_stream::BlockRetrieving}, shared::{ http_solver::model::TokenAmount, interaction::Interaction, @@ -49,15 +46,15 @@ pub fn to_domain(id: liquidity::Id, pool: ConcentratedLiquidity) -> Result eth::Interaction { let handler = UniswapV3SettlementHandler::new( - pool.router.0.into_alloy(), - receiver.0.into_alloy(), - Mutex::new(Allowances::empty(receiver.0.into_alloy())), + pool.router.into(), + *receiver, + Mutex::new(Allowances::empty(*receiver)), pool.fee.0, ); let (_, interaction) = handler.settle( - TokenAmount::new( - input.0.token.0.0.into_alloy(), - input.0.amount.0.into_alloy(), - ), - TokenAmount::new( - output.0.token.0.0.into_alloy(), - output.0.amount.0.into_alloy(), - ), + TokenAmount::new(input.0.token.into(), input.0.amount), + TokenAmount::new(output.0.token.into(), output.0.amount), ); let encoded = interaction.encode(); eth::Interaction { - target: eth::Address(encoded.0.into_legacy()), - value: eth::Ether(encoded.1.into_legacy()), + target: encoded.0, + value: encoded.1.into(), call_data: crate::util::Bytes(encoded.2.0.to_vec()), } } @@ -154,7 +145,7 @@ async fn init_liquidity( tokio::task::spawn(update_task); Ok(UniswapV3Liquidity::new( - config.router.0.into_alloy(), + config.router.into(), *eth.contracts().settlement().address(), web3, pool_fetcher, diff --git a/crates/driver/src/domain/competition/auction.rs b/crates/driver/src/domain/competition/auction.rs index f29fcbe4ad..b111b2e664 100644 --- a/crates/driver/src/domain/competition/auction.rs +++ b/crates/driver/src/domain/competition/auction.rs @@ -111,7 +111,7 @@ impl Auction { .filter_map(|(address, token)| token.price.map(|price| (*address, price))) .chain(std::iter::once(( eth::ETH_TOKEN, - eth::U256::exp10(18).into(), + eth::U256::from(10).pow(eth::U256::from(18)).into(), ))) .collect() } @@ -180,7 +180,7 @@ impl Price { /// assert_eq!(eth, eth::Ether::from(eth::U256::exp10(15))); /// ``` pub fn in_eth(self, amount: eth::TokenAmount) -> eth::Ether { - (amount.0 * self.0.0 / Self::BASE).into() + (amount.0 * self.0.0 / eth::U256::from(Self::BASE)).into() } /// Convert an amount of ETH into a token amount using this price. diff --git a/crates/driver/src/domain/competition/bad_tokens/metrics.rs b/crates/driver/src/domain/competition/bad_tokens/metrics.rs index a0444169b9..3d00cc776d 100644 --- a/crates/driver/src/domain/competition/bad_tokens/metrics.rs +++ b/crates/driver/src/domain/competition/bad_tokens/metrics.rs @@ -136,7 +136,7 @@ impl Detector { #[cfg(test)] mod tests { - use {super::*, ethcontract::H160}; + use {super::*, alloy::primitives::Address}; /// Tests that a token only gets marked temporarily as unsupported. /// After the freeze period it will be allowed again. @@ -151,8 +151,8 @@ mod tests { solver::Name("mysolver".to_string()), ); - let token_a = eth::TokenAddress(eth::ContractAddress(H160([1; 20]))); - let token_b = eth::TokenAddress(eth::ContractAddress(H160([2; 20]))); + let token_a = eth::TokenAddress(eth::ContractAddress(Address::repeat_byte(1))); + let token_b = eth::TokenAddress(eth::ContractAddress(Address::repeat_byte(2))); let token_quality = || detector.get_quality(&token_a, Instant::now()); // token is reported as unknown while we don't have enough measurements diff --git a/crates/driver/src/domain/competition/bad_tokens/simulation.rs b/crates/driver/src/domain/competition/bad_tokens/simulation.rs index 0568af3c94..110ac047e6 100644 --- a/crates/driver/src/domain/competition/bad_tokens/simulation.rs +++ b/crates/driver/src/domain/competition/bad_tokens/simulation.rs @@ -7,7 +7,7 @@ use { }, infra::{self, observe::metrics}, }, - ethrpc::alloy::conversions::IntoAlloy, + ethrpc::alloy::conversions::IntoLegacy, futures::FutureExt, model::interaction::InteractionData, shared::{ @@ -69,12 +69,12 @@ impl Detector { .pre_interactions .iter() .map(|i| InteractionData { - target: i.target.0.into_alloy(), - value: i.value.0.into_alloy(), + target: i.target, + value: i.value.0, call_data: i.call_data.0.clone(), }) .collect(); - let trader = order.trader().0.0.into_alloy(); + let trader = order.trader().0; let sell_amount = match order.partial { order::Partial::Yes { available } => available.0, order::Partial::No => order.sell.amount.0, @@ -83,7 +83,7 @@ impl Detector { async move { let result = inner .detector - .test_transfer(trader, sell_token.0.0.into_alloy(), sell_amount, &pre_interactions) + .test_transfer(trader, sell_token.0.0, sell_amount.into_legacy(), &pre_interactions) .await; match result { Err(err) => { diff --git a/crates/driver/src/domain/competition/mod.rs b/crates/driver/src/domain/competition/mod.rs index 1fb751b9ca..350475f1f6 100644 --- a/crates/driver/src/domain/competition/mod.rs +++ b/crates/driver/src/domain/competition/mod.rs @@ -21,7 +21,7 @@ use { }, util::{Bytes, math}, }, - ethrpc::alloy::conversions::{IntoAlloy, IntoLegacy}, + ethrpc::alloy::conversions::IntoAlloy, futures::{StreamExt, future::Either, stream::FuturesUnordered}, itertools::Itertools, num::Zero, @@ -128,15 +128,15 @@ 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(); + let settlement_contract = *self.eth.contracts().settlement().address(); + let solver_address = self.solver.account().address().into_alloy(); let order_sorting_strategies = self.order_sorting_strategies.clone(); // Add the CoW AMM orders to the auction let cow_amm_orders = tasks.cow_amm_orders.await; auction.orders.extend(cow_amm_orders.iter().cloned()); - let settlement = settlement_contract.into_legacy(); + let settlement = settlement_contract; let sort_orders_future = Self::run_blocking_with_timer("sort_orders", move || { // Use spawn_blocking() because a lot of CPU bound computations are happening // and we don't want to block the runtime for too long. @@ -156,13 +156,7 @@ impl Competition { // Same as before with sort_orders, we use spawn_blocking() because a lot of CPU // bound computations are happening and we want to avoid blocking // the runtime. - Self::update_orders( - auction, - balances, - app_data, - cow_amm_orders, - ð::Address(settlement), - ) + Self::update_orders(auction, balances, app_data, cow_amm_orders, &settlement) }) .await; @@ -399,9 +393,9 @@ impl Competition { // we allocate balances for the most relevants first. fn sort_orders( mut auction: Auction, - solver: eth::H160, + solver: eth::Address, order_sorting_strategies: Vec>, - _settlement_contract: eth::H160, + _settlement_contract: eth::Address, ) -> Auction { sorting::sort_orders( &mut auction.orders, @@ -500,13 +494,8 @@ impl Competition { // following: `available + (fee * available / sell) <= allocated_balance` if let order::Partial::Yes { available } = &mut order.partial { *available = order::TargetAmount( - math::mul_ratio( - available.0.into_alloy(), - allocated_balance.0.into_alloy(), - max_sell.0.into_alloy(), - ) - .unwrap_or_default() - .into_legacy(), + math::mul_ratio(available.0, allocated_balance.0, max_sell.0) + .unwrap_or_default(), ); } if order.available().is_zero() { diff --git a/crates/driver/src/domain/competition/order/mod.rs b/crates/driver/src/domain/competition/order/mod.rs index 8a53dff4ad..99154f6e3d 100644 --- a/crates/driver/src/domain/competition/order/mod.rs +++ b/crates/driver/src/domain/competition/order/mod.rs @@ -5,7 +5,6 @@ use { util::{self, Bytes}, }, derive_more::{From, Into}, - ethrpc::alloy::conversions::{IntoAlloy, IntoLegacy}, model::order::{BuyTokenDestination, SellTokenSource}, }; pub use {fees::FeePolicy, signature::Signature}; @@ -150,23 +149,14 @@ impl Order { }; let target = self.target(); - amounts.sell.amount = util::math::mul_ratio( - amounts.sell.amount.0.into_alloy(), - available.0.into_alloy(), - target.0.into_alloy(), - ) - .unwrap_or_default() - .into_legacy() - .into(); - - amounts.buy.amount = util::math::mul_ratio_ceil( - amounts.buy.amount.0.into_alloy(), - available.0.into_alloy(), - target.0.into_alloy(), - ) - .unwrap_or_default() - .into_legacy() - .into(); + amounts.sell.amount = util::math::mul_ratio(amounts.sell.amount.0, available.0, target.0) + .unwrap_or_default() + .into(); + + amounts.buy.amount = + util::math::mul_ratio_ceil(amounts.buy.amount.0, available.0, target.0) + .unwrap_or_default() + .into(); amounts } @@ -219,14 +209,14 @@ impl From<&solvers_dto::solution::OrderUid> for Uid { impl Uid { pub fn owner(&self) -> eth::Address { - self.parts().1.into() + self.parts().1 } /// Splits an order UID into its parts. - fn parts(&self) -> (eth::H256, eth::H160, u32) { + fn parts(&self) -> (eth::H256, eth::Address, u32) { ( eth::H256::from_slice(&self.0.0[0..32]), - eth::H160::from_slice(&self.0.0[32..52]), + eth::Address::from_slice(&self.0.0[32..52]), u32::from_le_bytes(self.0.0[52..].try_into().unwrap()), ) } @@ -417,11 +407,11 @@ mod tests { #[test] fn order_scaling() { let sell = |amount: u64| eth::Asset { - token: eth::H160::from_low_u64_be(0x5e11).into(), + token: eth::Address::left_padding_from(0x5e11_u64.to_be_bytes().as_slice()).into(), amount: eth::U256::from(amount).into(), }; let buy = |amount: u64| eth::Asset { - token: eth::H160::from_low_u64_be(0xbbbb).into(), + token: eth::Address::left_padding_from(0xbbbb_u64.to_be_bytes().as_slice()).into(), amount: eth::U256::from(amount).into(), }; diff --git a/crates/driver/src/domain/competition/pre_processing.rs b/crates/driver/src/domain/competition/pre_processing.rs index 1630051ee8..b155a2a3bc 100644 --- a/crates/driver/src/domain/competition/pre_processing.rs +++ b/crates/driver/src/domain/competition/pre_processing.rs @@ -127,7 +127,7 @@ impl DataAggregator { eth.web3(), shared::signature_validator::Contracts { settlement: eth.contracts().settlement().clone(), - vault_relayer: eth.contracts().vault_relayer().0, + vault_relayer: eth.contracts().vault_relayer().0.into_legacy(), signatures: eth.contracts().signatures().clone(), }, eth.balance_overrider(), @@ -137,7 +137,7 @@ impl DataAggregator { .contracts() .cow_amm_helper_by_factory() .iter() - .map(|(factory, helper)| (factory.0.into_alloy(), helper.0.into_alloy())) + .map(|(factory, helper)| (factory.0, helper.0)) .collect(); let cow_amm_cache = cow_amm::Cache::new(eth.web3().alloy.clone(), cow_amm_helper_by_factory); @@ -273,8 +273,8 @@ impl Utilities { && order.app_data.flashloan() == first.app_data.flashloan() }); Query { - owner: trader.0.0.into_alloy(), - token: token.0.0.into_alloy(), + owner: trader.0, + token: token.0.0, source: match source { SellTokenBalance::Erc20 => SellTokenSource::Erc20, SellTokenBalance::Internal => SellTokenSource::Internal, @@ -285,8 +285,8 @@ impl Utilities { .pre_interactions .iter() .map(|i| InteractionData { - target: i.target.0.into_alloy(), - value: i.value.0.into_alloy(), + target: i.target, + value: i.value.0, call_data: i.call_data.0.clone(), }) .collect() @@ -315,11 +315,11 @@ impl Utilities { .into_iter() .zip(balances) .filter_map(|(query, balance)| { - let balance = balance.ok()?; + let balance = balance.ok()?.into_alloy(); Some(( ( - order::Trader(query.owner.into_legacy().into()), - query.token.into_legacy().into(), + order::Trader(query.owner), + query.token.into(), match query.source { SellTokenSource::Erc20 => SellTokenBalance::Erc20, SellTokenSource::Internal => SellTokenBalance::Internal, @@ -420,9 +420,9 @@ impl Utilities { .iter() .map(|t| { auction.tokens - .get(ð::TokenAddress(eth::ContractAddress(t.into_legacy()))) + .get(ð::TokenAddress(eth::ContractAddress(*t))) .and_then(|token| token.price) - .map(|price| price.0.0.into_alloy()) + .map(|price| price.0.0) }) .collect::>>()?; Some((amm, prices)) @@ -449,21 +449,18 @@ impl Utilities { .uid(&domain_separator, &amm.into_legacy()) .0 .into(), - receiver: template - .order - .receiver - .map(|addr| addr.into_legacy().into()), + receiver: template.order.receiver, created: u32::try_from(Utc::now().timestamp()) .unwrap_or(u32::MIN) .into(), valid_to: template.order.valid_to.into(), buy: eth::Asset { - amount: template.order.buy_amount.into_legacy().into(), - token: template.order.buy_token.into_legacy().into(), + amount: template.order.buy_amount.into(), + token: template.order.buy_token.into(), }, sell: eth::Asset { - amount: template.order.sell_amount.into_legacy().into(), - token: template.order.sell_token.into_legacy().into(), + amount: template.order.sell_amount.into(), + token: template.order.sell_token.into(), }, kind: order::Kind::Limit, side: template.order.kind.into(), @@ -473,12 +470,8 @@ impl Utilities { partial: match template.order.partially_fillable { true => order::Partial::Yes { available: match template.order.kind { - OrderKind::Sell => { - order::TargetAmount(template.order.sell_amount.into_legacy()) - } - OrderKind::Buy => { - order::TargetAmount(template.order.buy_amount.into_legacy()) - } + OrderKind::Sell => order::TargetAmount(template.order.sell_amount), + OrderKind::Buy => order::TargetAmount(template.order.buy_amount), }, }, false => order::Partial::No, @@ -497,7 +490,7 @@ impl Utilities { Signature::Eip1271(bytes) => order::Signature { scheme: order::signature::Scheme::Eip1271, data: Bytes(bytes), - signer: amm.into_legacy().into(), + signer: amm, }, _ => { tracing::warn!( diff --git a/crates/driver/src/domain/competition/solution/encoding.rs b/crates/driver/src/domain/competition/solution/encoding.rs index fb4357d02a..5ac39b6037 100644 --- a/crates/driver/src/domain/competition/solution/encoding.rs +++ b/crates/driver/src/domain/competition/solution/encoding.rs @@ -13,11 +13,13 @@ use { util::Bytes, }, allowance::Allowance, - alloy::sol_types::SolCall, + alloy::{ + primitives::{Address, U256}, + sol_types::SolCall, + }, contracts::alloy::{FlashLoanRouter::LoanRequest, WETH9}, - ethcontract::H160, - ethrpc::alloy::conversions::{IntoAlloy, IntoLegacy}, itertools::Itertools, + num::Zero, }; #[derive(Debug, thiserror::Error)] @@ -53,7 +55,7 @@ pub fn tx( let mut interactions = Vec::with_capacity(approvals.size_hint().0 + solution.interactions().len()); let mut post_interactions = solution.post_interactions.clone(); - let mut native_unwrap = eth::TokenAmount(eth::U256::zero()); + let mut native_unwrap = eth::TokenAmount(eth::U256::ZERO); // Encode uniform clearing price vector for (token, amount) in solution @@ -61,8 +63,8 @@ pub fn tx( .into_iter() .sorted_by_cached_key(|(token, _amount)| *token) { - tokens.push(token.0.0.into_alloy()); - clearing_prices.push(amount.into_alloy()); + tokens.push(token.into()); + clearing_prices.push(amount); } // Encode trades with custom clearing prices @@ -98,12 +100,12 @@ pub fn tx( // indices are set below sell_token_index: Default::default(), buy_token_index: Default::default(), - receiver: trade.order().receiver.unwrap_or_default().into(), + receiver: trade.order().receiver.unwrap_or_default(), sell_amount: trade.order().sell.amount.into(), buy_amount: trade.order().buy.amount.into(), valid_to: trade.order().valid_to.into(), app_data: trade.order().app_data.hash().0.0.into(), - fee_amount: eth::U256::zero(), + fee_amount: eth::U256::ZERO, flags: Flags { side: trade.order().side, partially_fillable: matches!( @@ -136,12 +138,12 @@ pub fn tx( // indices are set below sell_token_index: Default::default(), buy_token_index: Default::default(), - receiver: trade.order().receiver.into(), + receiver: trade.order().receiver, sell_amount: trade.order().sell.amount.into(), buy_amount: trade.order().buy.amount.into(), valid_to: trade.order().valid_to.into(), app_data: trade.order().app_data.0.0.into(), - fee_amount: eth::U256::zero(), + fee_amount: eth::U256::ZERO, flags: Flags { side: trade.order().side, partially_fillable: matches!( @@ -158,13 +160,13 @@ pub fn tx( ) } }; - tokens.push(price.sell_token.into_alloy()); - tokens.push(price.buy_token.into_alloy()); - clearing_prices.push(price.sell_price.into_alloy()); - clearing_prices.push(price.buy_price.into_alloy()); + tokens.push(price.sell_token); + tokens.push(price.buy_token); + clearing_prices.push(price.sell_price); + clearing_prices.push(price.buy_price); - trade.sell_token_index = (tokens.len() - 2).into(); - trade.buy_token_index = (tokens.len() - 1).into(); + trade.sell_token_index = U256::from(tokens.len() - 2); + trade.buy_token_index = U256::from(tokens.len() - 1); trades.push(trade); } @@ -196,11 +198,9 @@ pub fn tx( target: interaction.target.into(), call_data: interaction.call_data.clone(), }, - competition::solution::Interaction::Liquidity(liquidity) => liquidity_interaction( - liquidity, - &slippage, - contracts.settlement().address().into_legacy(), - )?, + competition::solution::Interaction::Liquidity(liquidity) => { + liquidity_interaction(liquidity, &slippage, contracts.settlement().address())? + } }) } @@ -238,17 +238,14 @@ pub fn tx( } else if has_wrappers { encode_wrapper_settlement(solution, settle_calldata) } else { - ( - contracts.settlement().address().into_legacy().into(), - settle_calldata, - ) + (*contracts.settlement().address(), settle_calldata) }; Ok(eth::Tx { from: solution.solver().address(), to, input: calldata.into(), - value: Ether(0.into()), + value: Ether::zero(), access_list: Default::default(), }) } @@ -274,10 +271,10 @@ fn encode_flashloan_settlement( .flashloans .values() .map(|flashloan| LoanRequest::Data { - amount: flashloan.amount.0.into_alloy(), - borrower: flashloan.protocol_adapter.0.into_alloy(), - lender: flashloan.liquidity_provider.0.into_alloy(), - token: flashloan.token.0.0.into_alloy(), + amount: flashloan.amount.0, + borrower: flashloan.protocol_adapter.0, + lender: flashloan.liquidity_provider.0, + token: flashloan.token.0.0, }) .collect(); @@ -287,7 +284,7 @@ fn encode_flashloan_settlement( .calldata() .to_vec(); - Ok((router.address().into_legacy().into(), calldata)) + Ok((*router.address(), calldata)) } /// Encodes a settlement transaction that uses wrapper contracts. @@ -331,7 +328,7 @@ fn encode_wrapper_data(wrappers: &[super::WrapperCall]) -> Vec { for (index, w) in wrappers.iter().enumerate() { // Skip first wrapper's address (it's the transaction target) if index != 0 { - wrapper_data.extend(w.address.0.as_bytes()); + wrapper_data.extend(w.address.as_slice()); } // Encode data length as u16 in native endian, then the data itself @@ -345,7 +342,7 @@ fn encode_wrapper_data(wrappers: &[super::WrapperCall]) -> Vec { pub fn liquidity_interaction( liquidity: &Liquidity, slippage: &slippage::Parameters, - settlement_contract: H160, + settlement_contract: &Address, ) -> Result { let (input, output) = slippage.apply_to(&slippage::Interaction { input: liquidity.input, @@ -353,21 +350,15 @@ pub fn liquidity_interaction( })?; match liquidity.liquidity.kind.clone() { - liquidity::Kind::UniswapV2(pool) => { - pool.swap(&input, &output, &settlement_contract.into()).ok() - } - liquidity::Kind::UniswapV3(pool) => { - pool.swap(&input, &output, &settlement_contract.into()).ok() - } + liquidity::Kind::UniswapV2(pool) => pool.swap(&input, &output, settlement_contract).ok(), + liquidity::Kind::UniswapV3(pool) => pool.swap(&input, &output, settlement_contract).ok(), liquidity::Kind::BalancerV2Stable(pool) => { - pool.swap(&input, &output, &settlement_contract.into()).ok() + pool.swap(&input, &output, settlement_contract).ok() } liquidity::Kind::BalancerV2Weighted(pool) => { - pool.swap(&input, &output, &settlement_contract.into()).ok() - } - liquidity::Kind::Swapr(pool) => { - pool.swap(&input, &output, &settlement_contract.into()).ok() + pool.swap(&input, &output, settlement_contract).ok() } + liquidity::Kind::Swapr(pool) => pool.swap(&input, &output, settlement_contract).ok(), liquidity::Kind::ZeroEx(limit_order) => limit_order.to_interaction(&input).ok(), } .ok_or(Error::InvalidInteractionExecution(Box::new( @@ -380,12 +371,12 @@ pub fn approve(allowance: &Allowance) -> eth::Interaction { let amount: [_; 32] = allowance.amount.to_be_bytes(); eth::Interaction { target: allowance.token.0.into(), - value: eth::U256::zero().into(), + value: Ether::zero(), // selector (4 bytes) + spender (20 byte address padded to 32 bytes) + amount (32 bytes) call_data: [ selector.as_slice(), [0; 12].as_slice(), - allowance.spender.0.as_bytes(), + allowance.spender.as_slice(), &amount, ] .concat() @@ -395,16 +386,16 @@ pub fn approve(allowance: &Allowance) -> eth::Interaction { fn unwrap(amount: eth::TokenAmount, weth: &WETH9::Instance) -> eth::Interaction { eth::Interaction { - target: weth.address().into_legacy().into(), - value: Ether(0.into()), - call_data: Bytes(weth.withdraw(amount.0.into_alloy()).calldata().to_vec()), + target: *weth.address(), + value: Ether::zero(), + call_data: weth.withdraw(amount.0).calldata().to_vec().into(), } } struct Trade { sell_token_index: eth::U256, buy_token_index: eth::U256, - receiver: eth::H160, + receiver: eth::Address, sell_amount: eth::U256, buy_amount: eth::U256, valid_to: u32, @@ -416,9 +407,9 @@ struct Trade { } struct Price { - sell_token: eth::H160, + sell_token: eth::Address, sell_price: eth::U256, - buy_token: eth::H160, + buy_token: eth::Address, buy_price: eth::U256, } @@ -433,22 +424,22 @@ struct Flags { pub mod codec { use { crate::domain::{competition::order, eth}, + alloy::primitives::U256, contracts::alloy::GPv2Settlement, - ethrpc::alloy::conversions::IntoAlloy, }; pub(super) fn trade(trade: &super::Trade) -> GPv2Settlement::GPv2Trade::Data { GPv2Settlement::GPv2Trade::Data { - sellTokenIndex: trade.sell_token_index.into_alloy(), - buyTokenIndex: trade.buy_token_index.into_alloy(), - receiver: trade.receiver.into_alloy(), - sellAmount: trade.sell_amount.into_alloy(), - buyAmount: trade.buy_amount.into_alloy(), + sellTokenIndex: trade.sell_token_index, + buyTokenIndex: trade.buy_token_index, + receiver: trade.receiver, + sellAmount: trade.sell_amount, + buyAmount: trade.buy_amount, validTo: trade.valid_to, appData: trade.app_data.0.into(), - feeAmount: trade.fee_amount.into_alloy(), - flags: flags(&trade.flags).into_alloy(), - executedAmount: trade.executed_amount.into_alloy(), + feeAmount: trade.fee_amount, + flags: flags(&trade.flags), + executedAmount: trade.executed_amount, signature: trade.signature.0.clone().into(), } } @@ -481,15 +472,15 @@ pub mod codec { order::signature::Scheme::Eip1271 => 0b10, order::signature::Scheme::PreSign => 0b11, } << 5; - result.into() + U256::from(result) } pub(super) fn interaction( interaction: ð::Interaction, ) -> GPv2Settlement::GPv2Interaction::Data { GPv2Settlement::GPv2Interaction::Data { - target: interaction.target.0.into_alloy(), - value: interaction.value.0.into_alloy(), + target: interaction.target, + value: interaction.value.0, callData: interaction.call_data.0.clone().into(), } } @@ -500,31 +491,30 @@ pub mod codec { signature.data.clone() } order::signature::Scheme::Eip1271 => { - super::Bytes([signature.signer.0.as_bytes(), signature.data.0.as_slice()].concat()) - } - order::signature::Scheme::PreSign => { - super::Bytes(signature.signer.0.as_bytes().to_vec()) + [signature.signer.as_slice(), signature.data.0.as_slice()] + .concat() + .into() } + order::signature::Scheme::PreSign => signature.signer.to_vec().into(), } } } #[cfg(test)] mod test { - use {super::*, hex_literal::hex}; + use {super::*, alloy::primitives::address, hex_literal::hex}; #[test] fn test_approve() { let allowance = Allowance { - token: eth::H160::from_slice(&hex!("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2")).into(), - spender: eth::H160::from_slice(&hex!("000000000022D473030F116dDEE9F6B43aC78BA3")) - .into(), + token: address!("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2").into(), + spender: address!("000000000022D473030F116dDEE9F6B43aC78BA3"), amount: alloy::primitives::U256::MAX, }; let interaction = approve(&allowance); assert_eq!( interaction.target, - eth::H160::from_slice(&hex!("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2")).into(), + address!("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"), ); assert_eq!( interaction.call_data.0.as_slice(), diff --git a/crates/driver/src/domain/competition/solution/fee.rs b/crates/driver/src/domain/competition/solution/fee.rs index a6b4d0cdc2..dd1329a6ec 100644 --- a/crates/driver/src/domain/competition/solution/fee.rs +++ b/crates/driver/src/domain/competition/solution/fee.rs @@ -418,6 +418,6 @@ mod tests { } pub fn to_wei(base: u32) -> eth::U256 { - eth::U256::from(base) * eth::U256::exp10(18) + eth::U256::from(base) * eth::U256::from(10).pow(eth::U256::from(18)) } } diff --git a/crates/driver/src/domain/competition/solution/interaction.rs b/crates/driver/src/domain/competition/solution/interaction.rs index b2b285f9af..b7fc594c78 100644 --- a/crates/driver/src/domain/competition/solution/interaction.rs +++ b/crates/driver/src/domain/competition/solution/interaction.rs @@ -1,9 +1,6 @@ -use { - crate::{ - domain::{self, eth, liquidity}, - util::Bytes, - }, - ethrpc::alloy::conversions::IntoLegacy, +use crate::{ + domain::{self, eth, liquidity}, + util::Bytes, }; /// Interaction with a smart contract which is needed to execute this solution @@ -40,12 +37,12 @@ impl Interaction { Interaction::Custom(interaction) => interaction.allowances.clone(), Interaction::Liquidity(interaction) => { let address = match &interaction.liquidity.kind { - liquidity::Kind::UniswapV2(pool) => pool.router.into(), - liquidity::Kind::UniswapV3(pool) => pool.router.into(), - liquidity::Kind::BalancerV2Stable(pool) => pool.vault.into(), - liquidity::Kind::BalancerV2Weighted(pool) => pool.vault.into(), - liquidity::Kind::Swapr(pool) => pool.base.router.into(), - liquidity::Kind::ZeroEx(pool) => pool.zeroex.address().into_legacy(), + liquidity::Kind::UniswapV2(pool) => pool.router, + liquidity::Kind::UniswapV3(pool) => pool.router, + liquidity::Kind::BalancerV2Stable(pool) => pool.vault, + liquidity::Kind::BalancerV2Weighted(pool) => pool.vault, + liquidity::Kind::Swapr(pool) => pool.base.router, + liquidity::Kind::ZeroEx(pool) => (*pool.zeroex.address()).into(), }; // As a gas optimization, we always approve the max amount possible. This // minimizes the number of approvals necessary, and therefore diff --git a/crates/driver/src/domain/competition/solution/mod.rs b/crates/driver/src/domain/competition/solution/mod.rs index 327dfcc808..565bb9e637 100644 --- a/crates/driver/src/domain/competition/solution/mod.rs +++ b/crates/driver/src/domain/competition/solution/mod.rs @@ -16,7 +16,6 @@ use { }, }, chrono::Utc, - ethrpc::alloy::conversions::{IntoAlloy, IntoLegacy}, futures::future::try_join_all, itertools::Itertools, num::{BigRational, One}, @@ -283,10 +282,7 @@ impl Solution { let allowances = try_join_all(self.allowances(internalization).map(|required| async move { eth.erc20(required.0.token) - .allowance( - settlement_contract.address().into_legacy().into(), - required.0.spender, - ) + .allowance(*settlement_contract.address(), required.0.spender) .await .map(|existing| (required, existing)) })) @@ -342,8 +338,8 @@ impl Solution { // Scale prices let mut prices = self.prices.clone(); for (token, price) in other.prices.iter() { - let scaled = number::conversions::big_rational_to_u256( - &(number::conversions::u256_to_big_rational(price) * &factor), + let scaled = number::conversions::alloy::big_rational_to_u256( + &(number::conversions::alloy::u256_to_big_rational(price) * &factor), ) .map_err(error::Merge::Math)?; match prices.entry(*token) { @@ -425,8 +421,8 @@ impl Solution { for allowance in allowances { let amount = normalized .entry((allowance.0.token, allowance.0.spender)) - .or_insert(eth::U256::zero()); - *amount = amount.saturating_add(allowance.0.amount.into_legacy()); + .or_insert(eth::U256::ZERO); + *amount = amount.saturating_add(allowance.0.amount); } normalized .into_iter() @@ -434,7 +430,7 @@ impl Solution { eth::Allowance { token, spender, - amount: amount.into_alloy(), + amount, } .into() }) @@ -547,8 +543,8 @@ fn scaling_factor(first: &Prices, second: &Prices) -> Option { let first_price = first[token]; let second_price = second[token]; BigRational::new( - number::conversions::u256_to_big_int(&first_price), - number::conversions::u256_to_big_int(&second_price), + number::conversions::alloy::u256_to_big_int(&first_price), + number::conversions::alloy::u256_to_big_int(&second_price), ) }) .collect(); diff --git a/crates/driver/src/domain/competition/solution/scoring.rs b/crates/driver/src/domain/competition/solution/scoring.rs index 8191411624..89b25da344 100644 --- a/crates/driver/src/domain/competition/solution/scoring.rs +++ b/crates/driver/src/domain/competition/solution/scoring.rs @@ -27,6 +27,7 @@ use { }, util::conv::u256::U256Ext, }, + alloy::primitives::ruint::UintTryFrom, }; pub fn compute_score( @@ -108,12 +109,13 @@ impl Trade { // to avoid loss of precision because we work with integers we first multiply // and then divide: // buy_amount = surplus * buy_price / sell_price - let surplus_in_buy_tokens: eth::U256 = surplus_in_surplus_token - .full_mul(self.signed_buy.amount.0) - .checked_div(self.signed_sell.amount.0.into()) - .ok_or(Error::Math(Math::DivisionByZero))? - .try_into() - .map_err(|_| Error::Math(Math::Overflow))?; + let surplus_in_buy_tokens = surplus_in_surplus_token + .widening_mul(self.signed_buy.amount.0) + .checked_div(alloy::primitives::U512::from(self.signed_sell.amount.0)) + .ok_or(Error::Math(Math::DivisionByZero))?; + let surplus_in_buy_tokens: eth::U256 = + eth::U256::uint_try_from(surplus_in_buy_tokens) + .map_err(|_| Error::Math(Math::Overflow))?; // Afterwards we convert the buy token surplus to the native token. native_price_buy.in_eth(surplus_in_buy_tokens.into()) @@ -296,7 +298,7 @@ impl Trade { // negative surplus is not error in this case, as solutions often have no // improvement over quote which results in negative surplus if let Err(Math::Negative) = surplus { - return Ok(eth::SurplusTokenAmount(0.into())); + return Ok(eth::SurplusTokenAmount(eth::U256::ZERO)); } Ok(surplus?) } @@ -400,7 +402,12 @@ pub enum Error { #[cfg(test)] mod tests { - use {super::*, auction::Price, shared::addr, std::collections::HashMap}; + use { + super::*, + alloy::primitives::{Address, U256, address}, + auction::Price, + std::collections::HashMap, + }; /// Tests that the new score computation limits the score of certain /// buy orders to a reasonable amount. @@ -408,40 +415,40 @@ mod tests { /// [auction](https://api.cow.fi/base/api/v1/solver_competition/by_tx_hash/0xe3ef02493255f17c0abd2ff88c34682d35f0de4f4875a4653104e3453473d8d9). #[test] fn score_problematic_buy_order() { - let weth = addr!("4200000000000000000000000000000000000006"); - let bnkr = addr!("22af33fe49fd1fa80c7149773dde5890d3c76f3b"); + const WETH: Address = address!("4200000000000000000000000000000000000006"); + const BNKR: Address = address!("22af33fe49fd1fa80c7149773dde5890d3c76f3b"); // Buy order which results in an unreasonably high score // using the original scoring mechanism. let trade = Trade { signed_sell: eth::Asset { - token: weth.into(), + token: WETH.into(), amount: 9865986634773384514560000000000000u128.into(), }, signed_buy: eth::Asset { - token: bnkr.into(), + token: BNKR.into(), amount: 4025333872768468868566822740u128.into(), }, side: Side::Buy, - executed: order::TargetAmount(8050667745u128.into()), + executed: order::TargetAmount(U256::from(8050667745u128)), custom_price: CustomClearingPrices { - sell: 874045870u128.into(), - buy: 8050667745u128.into(), + sell: U256::from(874045870u128), + buy: U256::from(8050667745u128), }, policies: vec![], }; let native_prices: HashMap<_, _> = [ ( - weth.into(), - Price(eth::Ether(1000000000000000000u128.into())), + WETH.into(), + Price(eth::Ether(U256::from(1000000000000000000u128))), ), - (bnkr.into(), Price(eth::Ether(113181296327u128.into()))), + (BNKR.into(), Price(eth::Ether(U256::from(113181296327u128)))), ] .into_iter() .collect(); let score = trade.score(&native_prices).unwrap(); - assert_eq!(score.0, 911.into()); + assert_eq!(score.0, U256::from(911)); } } diff --git a/crates/driver/src/domain/competition/solution/settlement.rs b/crates/driver/src/domain/competition/solution/settlement.rs index 9c8358b5ff..afbdd882c7 100644 --- a/crates/driver/src/domain/competition/solution/settlement.rs +++ b/crates/driver/src/domain/competition/solution/settlement.rs @@ -380,7 +380,7 @@ impl Gas { // will not exceed the remaining space in the block next and ignore transactions // whose gas limit exceed the remaining space (without simulating the actual // gas required). - let max_gas = eth::Gas(block_limit.0 / 2); + let max_gas = eth::Gas(block_limit.0 / eth::U256::from(2)); if estimate > max_gas { return Err(solution::Error::GasLimitExceeded(estimate, max_gas)); } @@ -392,9 +392,7 @@ impl Gas { // the end of execution, so we want to increase gas limit enough so // those solutions don't revert with out of gas error. const GAS_LIMIT_FACTOR: f64 = 2.0; - let estimate_with_buffer = - eth::U256::from_f64_lossy(eth::U256::to_f64_lossy(estimate.into()) * GAS_LIMIT_FACTOR) - .into(); + let estimate_with_buffer = eth::U256::from(f64::from(estimate.0) * GAS_LIMIT_FACTOR).into(); Ok(Self { estimate, diff --git a/crates/driver/src/domain/competition/solution/slippage.rs b/crates/driver/src/domain/competition/solution/slippage.rs index cf12a7c22b..82b0fe7d57 100644 --- a/crates/driver/src/domain/competition/solution/slippage.rs +++ b/crates/driver/src/domain/competition/solution/slippage.rs @@ -4,9 +4,7 @@ use { eth, liquidity::{ExactOutput, MaxInput}, }, - ethcontract::U256, num::{BigRational, CheckedDiv, CheckedMul}, - number::conversions::big_rational_to_u256, shared::conversions::U256Ext, }; @@ -44,14 +42,13 @@ impl Parameters { let slippage = if let Some(price) = self.prices.get(&interaction.input.token) { let amount = price.in_eth(interaction.input.amount); let relative = amount.0.to_big_rational() * &self.relative; - let relative = - big_rational_to_u256(&relative).map_err(|_| super::error::Math::DivisionByZero)?; + let relative = number::conversions::alloy::big_rational_to_u256(&relative) + .map_err(|_| super::error::Math::DivisionByZero)?; // Final slippage considers min/max caps - let slippage = num::clamp( - relative, + let slippage = relative.clamp( self.min.unwrap_or_default(), - self.max.unwrap_or(U256::max_value()), + self.max.unwrap_or(eth::U256::MAX), ); tracing::debug!( @@ -66,14 +63,13 @@ impl Parameters { } else if let Some(price) = self.prices.get(&interaction.output.token) { let amount = price.in_eth(interaction.output.amount); let relative = amount.0.to_big_rational() * &self.relative; - let relative = - big_rational_to_u256(&relative).map_err(|_| super::error::Math::DivisionByZero)?; + let relative = number::conversions::alloy::big_rational_to_u256(&relative) + .map_err(|_| super::error::Math::DivisionByZero)?; // Final slippage considers min/max caps - let slippage = num::clamp( - relative, + let slippage = relative.clamp( self.min.unwrap_or_default(), - self.max.unwrap_or(U256::max_value()), + self.max.unwrap_or(alloy::primitives::U256::MAX), ); tracing::debug!( @@ -97,7 +93,7 @@ impl Parameters { "unable to compute capped slippage; falling back to relative slippage", ); let relative = interaction.input.amount.0.to_big_rational() * &self.relative; - big_rational_to_u256(&relative) + number::conversions::alloy::big_rational_to_u256(&relative) .map_err(|_| super::error::Math::DivisionByZero)? .into() }; @@ -115,15 +111,10 @@ impl Parameters { #[cfg(test)] mod tests { - use {super::*, crate::domain::eth::Asset, num::rational::Ratio}; + use {super::*, crate::domain::eth::Asset, alloy::primitives::address, num::rational::Ratio}; - const GNO: eth::H160 = eth::H160(hex_literal::hex!( - "6810e776880c02933d47db1b9fc05908e5386b96" - )); - - const USDC: eth::H160 = eth::H160(hex_literal::hex!( - "A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" - )); + const GNO: eth::Address = address!("6810e776880c02933d47db1b9fc05908e5386b96"); + const USDC: eth::Address = address!("A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"); #[test] fn test_input_price() { @@ -131,17 +122,17 @@ mod tests { input: Asset { token: GNO.into(), // 1GNO - amount: eth::U256::exp10(18).into(), + amount: eth::U256::from(10).pow(eth::U256::from(18)).into(), }, output: Asset { token: USDC.into(), // 200 USDC - amount: (U256::from(200) * eth::U256::exp10(6)).into(), + amount: (eth::U256::from(200) * eth::U256::from(10).pow(eth::U256::from(6))).into(), }, }; let prices = maplit::hashmap! { // 0.1 ETH - GNO.into() => eth::U256::exp10(17).into(), + GNO.into() => eth::U256::from(10).pow(eth::U256::from(17)).into(), }; // no cap @@ -154,33 +145,39 @@ mod tests { let (max_input, exact_output) = slippage.apply_to(&interaction).unwrap(); assert_eq!( max_input.0.amount, - (eth::U256::exp10(18) + eth::U256::exp10(17)).into() + (eth::U256::from(10).pow(eth::U256::from(18)) + + eth::U256::from(10).pow(eth::U256::from(17))) + .into() ); assert_eq!(exact_output.0.amount, interaction.output.amount); // min cap let min_cap = Parameters { // 0.1 ETH (1 GNO) - min: Some(eth::U256::exp10(17)), + min: Some(eth::U256::from(10).pow(eth::U256::from(17))), ..slippage.clone() }; let (max_input, _) = min_cap.apply_to(&interaction).unwrap(); assert_eq!( max_input.0.amount, - (eth::U256::exp10(18) + eth::U256::exp10(18)).into() + (eth::U256::from(10).pow(eth::U256::from(18)) + + eth::U256::from(10).pow(eth::U256::from(18))) + .into() ); assert_eq!(exact_output.0.amount, interaction.output.amount); // max cap let max_cap = Parameters { // 0.001 ETH (0.01 GNO) - max: Some(eth::U256::exp10(15)), + max: Some(eth::U256::from(10).pow(eth::U256::from(15))), ..slippage }; let (max_input, _) = max_cap.apply_to(&interaction).unwrap(); assert_eq!( max_input.0.amount, - (eth::U256::exp10(18) + eth::U256::exp10(16)).into() + (eth::U256::from(10).pow(eth::U256::from(18)) + + eth::U256::from(10).pow(eth::U256::from(16))) + .into() ); assert_eq!(exact_output.0.amount, interaction.output.amount); } @@ -191,17 +188,17 @@ mod tests { input: Asset { token: GNO.into(), // 1GNO - amount: eth::U256::exp10(18).into(), + amount: eth::U256::from(10).pow(eth::U256::from(18)).into(), }, output: Asset { token: USDC.into(), // 200 USDC - amount: (U256::from(200) * eth::U256::exp10(6)).into(), + amount: (eth::U256::from(200) * eth::U256::from(10).pow(eth::U256::from(6))).into(), }, }; let prices = maplit::hashmap! { // $4000 per ETH (1 USD = 0.0005 ETH), 6 decimals - USDC.into() => (U256::from(5) * eth::U256::exp10(26)).into(), + USDC.into() => (eth::U256::from(5) * eth::U256::from(10).pow(eth::U256::from(26))).into(), }; // no cap @@ -214,33 +211,39 @@ mod tests { let (max_input, exact_output) = slippage.apply_to(&interaction).unwrap(); assert_eq!( max_input.0.amount, - (eth::U256::exp10(18) + eth::U256::exp10(17)).into() + (eth::U256::from(10).pow(eth::U256::from(18)) + + eth::U256::from(10).pow(eth::U256::from(17))) + .into() ); assert_eq!(exact_output.0.amount, interaction.output.amount); // min cap let min_cap = Parameters { // 0.1 ETH (1 GNO) - min: Some(eth::U256::exp10(17)), + min: Some(eth::U256::from(10).pow(eth::U256::from(17))), ..slippage.clone() }; let (max_input, _) = min_cap.apply_to(&interaction).unwrap(); assert_eq!( max_input.0.amount, - (eth::U256::exp10(18) + eth::U256::exp10(18)).into() + (eth::U256::from(10).pow(eth::U256::from(18)) + + eth::U256::from(10).pow(eth::U256::from(18))) + .into() ); assert_eq!(exact_output.0.amount, interaction.output.amount); // max cap let max_cap = Parameters { // 0.001 ETH (0.01 GNO) - max: Some(eth::U256::exp10(15)), + max: Some(eth::U256::from(10).pow(eth::U256::from(15))), ..slippage }; let (max_input, _) = max_cap.apply_to(&interaction).unwrap(); assert_eq!( max_input.0.amount, - (eth::U256::exp10(18) + eth::U256::exp10(16)).into() + (eth::U256::from(10).pow(eth::U256::from(18)) + + eth::U256::from(10).pow(eth::U256::from(16))) + .into() ); assert_eq!(exact_output.0.amount, interaction.output.amount); } @@ -249,20 +252,20 @@ mod tests { fn test_no_price() { let slippage = Parameters { relative: Ratio::from_float(1.).unwrap(), - max: Some(eth::U256::exp10(16)), - min: Some(eth::U256::exp10(18)), + max: Some(eth::U256::from(10).pow(eth::U256::from(16))), + min: Some(eth::U256::from(10).pow(eth::U256::from(18))), prices: Default::default(), }; let interaction = Interaction { input: Asset { token: GNO.into(), // 1GNO - amount: eth::U256::exp10(18).into(), + amount: eth::U256::from(10).pow(eth::U256::from(18)).into(), }, output: Asset { token: USDC.into(), // 200 USDC - amount: (U256::from(200) * eth::U256::exp10(6)).into(), + amount: (eth::U256::from(200) * eth::U256::from(10).pow(eth::U256::from(6))).into(), }, }; @@ -270,7 +273,9 @@ mod tests { let (max_input, exact_output) = slippage.apply_to(&interaction).unwrap(); assert_eq!( max_input.0.amount, - (eth::U256::exp10(18) + eth::U256::exp10(18)).into() + (eth::U256::from(10).pow(eth::U256::from(18)) + + eth::U256::from(10).pow(eth::U256::from(18))) + .into() ); assert_eq!(exact_output.0.amount, interaction.output.amount); } diff --git a/crates/driver/src/domain/competition/solution/trade.rs b/crates/driver/src/domain/competition/solution/trade.rs index 3aefc566e4..38df39533b 100644 --- a/crates/driver/src/domain/competition/solution/trade.rs +++ b/crates/driver/src/domain/competition/solution/trade.rs @@ -201,7 +201,7 @@ impl Fulfillment { // Orders with static fees are no longer used, except for quoting purposes, when // the static fee is set to 0. This is expected to be resolved with https://github.com/cowprotocol/services/issues/2543 // Once resolved, this code will be simplified as part of https://github.com/cowprotocol/services/issues/2507 - order::SellAmount(0.into()) + order::SellAmount(eth::U256::ZERO) } Fee::Dynamic(fee) => fee, } @@ -303,7 +303,7 @@ impl Fulfillment { // be caught by simulation limit_sell_amount .checked_sub(executed_sell_amount_with_fee) - .unwrap_or(eth::U256::zero()) + .unwrap_or(eth::U256::ZERO) } Side::Sell => { // Scale to support partially fillable orders @@ -328,7 +328,7 @@ impl Fulfillment { // be caught by simulation executed_buy_amount .checked_sub(limit_buy_amount) - .unwrap_or(eth::U256::zero()) + .unwrap_or(eth::U256::ZERO) } }; Ok(surplus.into()) diff --git a/crates/driver/src/domain/competition/sorting.rs b/crates/driver/src/domain/competition/sorting.rs index 83d0a667af..c06b95fd2d 100644 --- a/crates/driver/src/domain/competition/sorting.rs +++ b/crates/driver/src/domain/competition/sorting.rs @@ -22,7 +22,7 @@ pub trait SortingStrategy: Send + Sync + Debug { &self, order: &order::Order, tokens: &Tokens, - solver: ð::H160, + solver: ð::Address, now: chrono::DateTime, ) -> SortingKey; } @@ -37,7 +37,7 @@ impl SortingStrategy for ExternalPrice { &self, order: &order::Order, tokens: &Tokens, - _solver: ð::H160, + _solver: ð::Address, _now: chrono::DateTime, ) -> SortingKey { // The likelihood that this order will be fulfilled, based on token prices. @@ -48,8 +48,8 @@ impl SortingStrategy for ExternalPrice { tokens.get(&order.sell.token).and_then(|token| token.price), ) { (Some(buy_price), Some(sell_price)) => { - let buy = buy_price.in_eth(order.buy.amount).0.to_f64_lossy(); - let sell = sell_price.in_eth(order.sell.amount).0.to_f64_lossy(); + let buy = f64::from(buy_price.in_eth(order.buy.amount).0); + let sell = f64::from(sell_price.in_eth(order.sell.amount).0); if buy.is_subnormal() { 0. } else { sell / buy } } _ => 0., @@ -91,7 +91,7 @@ impl SortingStrategy for CreationTimestamp { &self, order: &order::Order, _tokens: &Tokens, - _solver: ð::H160, + _solver: ð::Address, now: chrono::DateTime, ) -> SortingKey { SortingKey::Timestamp(match self.max_order_age { @@ -116,7 +116,7 @@ impl SortingStrategy for OwnQuotes { &self, order: &order::Order, _tokens: &Tokens, - solver: ð::H160, + solver: ð::Address, now: chrono::DateTime, ) -> SortingKey { let is_order_outdated = self.max_order_age.is_some_and(|max_order_age| { @@ -124,7 +124,7 @@ impl SortingStrategy for OwnQuotes { u32::try_from((now - max_order_age).timestamp()).unwrap_or(u32::MAX); order.created.0 < earliest_allowed_creation }); - let is_own_quote = order.quote.as_ref().is_some_and(|q| &q.solver.0 == solver); + let is_own_quote = order.quote.as_ref().is_some_and(|q| &q.solver == solver); SortingKey::Bool(!is_order_outdated && is_own_quote) } @@ -135,7 +135,7 @@ impl SortingStrategy for OwnQuotes { pub fn sort_orders( orders: &mut [order::Order], tokens: &Tokens, - solver: ð::H160, + solver: ð::Address, order_comparators: &[Arc], ) { let now = chrono::Utc::now(); diff --git a/crates/driver/src/domain/cow_amm.rs b/crates/driver/src/domain/cow_amm.rs index d384a30153..f28eb97ee0 100644 --- a/crates/driver/src/domain/cow_amm.rs +++ b/crates/driver/src/domain/cow_amm.rs @@ -3,7 +3,6 @@ use { alloy::{primitives::Address, providers::DynProvider}, contracts::alloy::cow_amm::CowAmmLegacyHelper, cow_amm::Amm, - ethrpc::alloy::conversions::IntoAlloy, itertools::{ Either::{Left, Right}, Itertools, @@ -55,12 +54,9 @@ impl Cache { let cache = self.inner.read().await; surplus_capturing_jit_order_owners .iter() - .partition_map(|&address| { - let address = address.0.into_alloy(); - match cache.get(&address) { - Some(amm) => Left(amm.clone()), - None => Right(address), - } + .partition_map(|&address| match cache.get(&address) { + Some(amm) => Left(amm.clone()), + None => Right(address), }) }; diff --git a/crates/driver/src/domain/eth/gas.rs b/crates/driver/src/domain/eth/gas.rs index 8c69e0dcbd..62d03b620e 100644 --- a/crates/driver/src/domain/eth/gas.rs +++ b/crates/driver/src/domain/eth/gas.rs @@ -13,7 +13,7 @@ pub struct Gas(pub U256); impl From for Gas { fn from(value: u64) -> Self { - Self(value.into()) + Self(U256::from(value)) } } @@ -43,9 +43,10 @@ pub struct GasPrice { impl GasPrice { /// Returns the estimated [`EffectiveGasPrice`] for the gas price estimate. pub fn effective(&self) -> EffectiveGasPrice { - U256::from(self.max) - .min(U256::from(self.base).saturating_add(self.tip.into())) - .into() + let max = self.max.0.0; + let base = self.base.0.0; + let tip = self.tip.0.0; + max.min(base.saturating_add(tip)).into() } pub fn max(&self) -> FeePerGas { @@ -113,7 +114,7 @@ pub struct FeePerGas(pub Ether); impl FeePerGas { /// Multiplies this fee by the given floating point number, rounding up. fn mul_ceil(self, rhs: f64) -> Self { - U256::from_f64_lossy((self.0.0.to_f64_lossy() * rhs).ceil()).into() + U256::from((f64::from(self.0.0) * rhs).ceil()).into() } } diff --git a/crates/driver/src/domain/eth/mod.rs b/crates/driver/src/domain/eth/mod.rs index 6c02781fbc..792a006e9c 100644 --- a/crates/driver/src/domain/eth/mod.rs +++ b/crates/driver/src/domain/eth/mod.rs @@ -17,10 +17,11 @@ mod gas; pub use { allowance::Allowance, + alloy::primitives::{Address, U256}, eip712::DomainSeparator, gas::{EffectiveGasPrice, FeePerGas, Gas, GasPrice}, number::nonzero::U256 as NonZeroU256, - primitive_types::{H160, H256, U256, U512}, + primitive_types::{H256, U512}, }; // TODO This module is getting a little hectic with all kinds of different @@ -30,7 +31,7 @@ pub use { /// it does not implement the ERC20 interface, but this address is used by /// convention across the Ethereum ecosystem whenever ETH is treated like an /// ERC20 token. -pub const ETH_TOKEN: TokenAddress = TokenAddress(ContractAddress(H160([0xee; 20]))); +pub const ETH_TOKEN: TokenAddress = TokenAddress(ContractAddress(Address::repeat_byte(0xee))); /// An EIP-2930 access list. This type ensures that the addresses and storage /// keys are not repeated, and that the ordering is deterministic. @@ -62,7 +63,7 @@ impl From for AccessList { .into_iter() .map(|item| { ( - item.address.into(), + item.address.into_alloy(), item.storage_keys .into_iter() .map(|key| key.into()) @@ -81,7 +82,7 @@ impl From for web3::types::AccessList { .into_iter() .sorted_by_key(|&(address, _)| address) .map(|(address, storage_keys)| web3::types::AccessListItem { - address: address.into(), + address: address.into_legacy(), storage_keys: storage_keys.into_iter().sorted().map(|key| key.0).collect(), }) .collect() @@ -91,21 +92,11 @@ impl From for web3::types::AccessList { #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Into, From)] struct StorageKey(pub H256); -/// An address. Can be an EOA or a smart contract address. -#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, From, Into)] -pub struct Address(pub H160); - // TODO This type should probably use Ethereum::is_contract to verify during // construction that it does indeed point to a contract /// A smart contract address. #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Into, From)] -pub struct ContractAddress(pub H160); - -impl From for Address { - fn from(value: ContractAddress) -> Self { - value.0.into() - } -} +pub struct ContractAddress(pub Address); /// An ERC20 token address. /// @@ -188,7 +179,7 @@ impl num::CheckedDiv for TokenAmount { impl From for TokenAmount { fn from(value: u128) -> Self { - Self(value.into()) + Self(U256::from(value)) } } @@ -208,7 +199,7 @@ impl std::ops::AddAssign for TokenAmount { impl num::Zero for TokenAmount { fn zero() -> Self { - Self(U256::zero()) + Self(U256::ZERO) } fn is_zero(&self) -> bool { @@ -226,19 +217,19 @@ impl std::fmt::Display for TokenAmount { #[derive(Debug, Clone, Copy, From, Into)] pub struct WethAddress(pub TokenAddress); -impl From for WethAddress { - fn from(value: H160) -> Self { +impl From
for WethAddress { + fn from(value: Address) -> Self { WethAddress(value.into()) } } -impl From for TokenAddress { - fn from(value: H160) -> Self { +impl From
for TokenAddress { + fn from(value: Address) -> Self { Self(value.into()) } } -impl From for H160 { +impl From for Address { fn from(value: TokenAddress) -> Self { value.0.into() } @@ -264,15 +255,14 @@ pub struct Ether(pub U256); impl From for num::BigInt { fn from(value: Ether) -> Self { - let mut bytes = [0; 32]; - value.0.to_big_endian(&mut bytes); - num::BigUint::from_bytes_be(&bytes).into() + num::BigUint::from_bytes_be(value.0.to_be_bytes::<32>().as_slice()).into() } } +// TODO: check if actually needed impl From for Ether { fn from(value: i32) -> Self { - Self(value.into()) + Self(U256::from(value)) } } @@ -286,7 +276,7 @@ impl std::ops::Add for Ether { impl num::Zero for Ether { fn zero() -> Self { - Self(U256::zero()) + Self(U256::ZERO) } fn is_zero(&self) -> bool { @@ -315,8 +305,8 @@ pub struct Interaction { impl From for model::interaction::InteractionData { fn from(interaction: Interaction) -> Self { Self { - target: interaction.target.0.into_alloy(), - value: interaction.value.0.into_alloy(), + target: interaction.target, + value: interaction.value.0, call_data: interaction.call_data.0, } } @@ -325,8 +315,8 @@ impl From for model::interaction::InteractionData { impl From for Interaction { fn from(interaction: model::interaction::InteractionData) -> Self { Self { - target: interaction.target.into_legacy().into(), - value: interaction.value.into_legacy().into(), + target: interaction.target, + value: interaction.value.into(), call_data: interaction.call_data.into(), } } @@ -358,11 +348,11 @@ pub struct Tx { impl From for CallRequest { fn from(value: Tx) -> Self { Self { - from: Some(value.from.into()), - to: Some(value.to.into()), + from: Some(value.from.into_legacy()), + to: Some(value.to.into_legacy()), gas: None, gas_price: None, - value: Some(value.value.into()), + value: Some(value.value.0.into_legacy()), data: Some(value.input.into()), transaction_type: None, access_list: Some(value.access_list.into()), @@ -438,7 +428,7 @@ impl From<&solvers_dto::solution::Flashloan> for Flashloan { Self { liquidity_provider: value.liquidity_provider.into(), protocol_adapter: value.protocol_adapter.into(), - receiver: value.receiver.into(), + receiver: value.receiver, token: value.token.into(), amount: value.amount.into(), } @@ -451,8 +441,8 @@ impl Into for &Flashloan { FlashloanHint { liquidity_provider: self.liquidity_provider.into(), protocol_adapter: self.protocol_adapter.into(), - receiver: self.receiver.into(), - token: self.token.into(), + receiver: self.receiver, + token: self.token.0.into(), amount: self.amount.into(), } } diff --git a/crates/driver/src/domain/liquidity/balancer/v2/mod.rs b/crates/driver/src/domain/liquidity/balancer/v2/mod.rs index 302fbea332..b5d4a87605 100644 --- a/crates/driver/src/domain/liquidity/balancer/v2/mod.rs +++ b/crates/driver/src/domain/liquidity/balancer/v2/mod.rs @@ -18,7 +18,7 @@ pub struct Id(pub eth::H256); impl Id { /// Extracts the pool address configured in the ID. pub fn address(&self) -> eth::ContractAddress { - eth::H160::from_slice(&self.0[..20]).into() + eth::Address::from_slice(&self.0[..20]).into() } } diff --git a/crates/driver/src/domain/liquidity/balancer/v2/weighted.rs b/crates/driver/src/domain/liquidity/balancer/v2/weighted.rs index 53da2a6ac8..24f4fa55ca 100644 --- a/crates/driver/src/domain/liquidity/balancer/v2/weighted.rs +++ b/crates/driver/src/domain/liquidity/balancer/v2/weighted.rs @@ -123,7 +123,7 @@ impl Weight { } fn base() -> eth::U256 { - eth::U256::exp10(18) + eth::U256::from(10).pow(eth::U256::from(18)) } } diff --git a/crates/driver/src/domain/liquidity/zeroex.rs b/crates/driver/src/domain/liquidity/zeroex.rs index b0dbc193a1..6e3fa34096 100644 --- a/crates/driver/src/domain/liquidity/zeroex.rs +++ b/crates/driver/src/domain/liquidity/zeroex.rs @@ -3,7 +3,7 @@ use { alloy::primitives::{Address, B256}, anyhow::anyhow, contracts::alloy::IZeroex, - ethrpc::alloy::conversions::{IntoAlloy, IntoLegacy}, + ethrpc::alloy::conversions::IntoAlloy, primitive_types::U256, std::sync::Arc, }; @@ -81,7 +81,7 @@ impl LimitOrder { let calldata = method.calldata(); Ok(eth::Interaction { - target: self.zeroex.address().into_legacy().into(), + target: *self.zeroex.address(), value: 0.into(), call_data: calldata.to_vec().into(), }) diff --git a/crates/driver/src/domain/quote.rs b/crates/driver/src/domain/quote.rs index 0fd50b101a..73015a7ff7 100644 --- a/crates/driver/src/domain/quote.rs +++ b/crates/driver/src/domain/quote.rs @@ -16,7 +16,6 @@ use { util, }, chrono::Utc, - ethrpc::alloy::conversions::IntoLegacy, std::{ collections::{HashMap, HashSet}, iter, @@ -26,7 +25,7 @@ use { /// A quote describing the expected outcome of an order. #[derive(Debug)] pub struct Quote { - pub clearing_prices: HashMap, + pub clearing_prices: HashMap, pub pre_interactions: Vec, pub interactions: Vec, pub solver: eth::Address, @@ -48,9 +47,7 @@ impl Quote { interactions: solution .interactions() .iter() - .map(|i| { - encode::interaction(i, eth.contracts().settlement().address().into_legacy()) - }) + .map(|i| encode::interaction(i, eth.contracts().settlement().address())) .collect::, _>>()? .into_iter() .flatten() @@ -191,7 +188,7 @@ impl Order { fn buy(&self) -> eth::Asset { match self.side { order::Side::Sell => eth::Asset { - amount: eth::U256::one().into(), + amount: eth::U256::ONE.into(), token: self.tokens.buy, }, order::Side::Buy => eth::Asset { @@ -219,7 +216,9 @@ impl Order { // contract level. Requiring to trade more than `type(uint112).max` // is unlikely and would not work with Uniswap V2 anyway. order::Side::Buy => eth::Asset { - amount: (eth::U256::one() << 144).into(), + // NOTE: the saturating strategy here is slightly irrelevant since we know that 1 << + // 144 fits within U256 + amount: (eth::U256::ONE.saturating_shl(144)).into(), token: self.tokens.sell, }, } @@ -269,7 +268,7 @@ mod encode { allowance::{Approval, Required}, }, }, - ethcontract::H160, + alloy::primitives::Address, num::rational::Ratio, }; @@ -277,7 +276,7 @@ mod encode { pub(super) fn interaction( interaction: &solution::Interaction, - settlement: H160, + settlement: &Address, ) -> Result, solution::encoding::Error> { let slippage = solution::slippage::Parameters { relative: Ratio::new_raw(DEFAULT_QUOTE_SLIPPAGE_BPS.into(), 10_000.into()), @@ -289,7 +288,7 @@ mod encode { let encoded = match interaction { solution::Interaction::Custom(interaction) => eth::Interaction { value: interaction.value, - target: interaction.target.0.into(), + target: interaction.target.0, call_data: interaction.call_data.clone(), }, solution::Interaction::Liquidity(liquidity) => { diff --git a/crates/driver/src/infra/api/routes/quote/dto/order.rs b/crates/driver/src/infra/api/routes/quote/dto/order.rs index 9d7e4a4f95..b157954bf0 100644 --- a/crates/driver/src/infra/api/routes/quote/dto/order.rs +++ b/crates/driver/src/infra/api/routes/quote/dto/order.rs @@ -26,8 +26,8 @@ impl Order { #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Order { - sell_token: eth::H160, - buy_token: eth::H160, + sell_token: eth::Address, + buy_token: eth::Address, #[serde_as(as = "serialize::U256")] amount: eth::U256, kind: Kind, diff --git a/crates/driver/src/infra/api/routes/quote/dto/quote.rs b/crates/driver/src/infra/api/routes/quote/dto/quote.rs index 6cc519855e..ebc82de552 100644 --- a/crates/driver/src/infra/api/routes/quote/dto/quote.rs +++ b/crates/driver/src/infra/api/routes/quote/dto/quote.rs @@ -18,9 +18,13 @@ impl Quote { clearing_prices: quote.clearing_prices, pre_interactions: quote.pre_interactions.into_iter().map(Into::into).collect(), interactions: quote.interactions.into_iter().map(Into::into).collect(), - solver: quote.solver.0, - gas: quote.gas.map(|gas| gas.0.as_u64()), - tx_origin: quote.tx_origin.map(|addr| addr.0), + solver: quote.solver, + gas: quote.gas.map(|gas| { + gas.0 + .try_into() + .expect("value should be lower than u64::MAX") + }), + tx_origin: quote.tx_origin, jit_orders: quote.jit_orders.into_iter().map(Into::into).collect(), } } @@ -31,14 +35,14 @@ impl Quote { #[serde(rename_all = "camelCase")] pub struct Quote { #[serde_as(as = "HashMap<_, serialize::U256>")] - clearing_prices: HashMap, + clearing_prices: HashMap, pre_interactions: Vec, interactions: Vec, - solver: eth::H160, + solver: eth::Address, #[serde(skip_serializing_if = "Option::is_none")] gas: Option, #[serde(skip_serializing_if = "Option::is_none")] - tx_origin: Option, + tx_origin: Option, jit_orders: Vec, } @@ -46,7 +50,7 @@ pub struct Quote { #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] struct Interaction { - target: eth::H160, + target: eth::Address, #[serde_as(as = "serialize::U256")] value: eth::U256, #[serde_as(as = "serialize::Hex")] @@ -56,7 +60,7 @@ struct Interaction { impl From for Interaction { fn from(interaction: eth::Interaction) -> Self { Self { - target: interaction.target.into(), + target: interaction.target, value: interaction.value.into(), call_data: interaction.call_data.into(), } @@ -67,15 +71,15 @@ impl From for Interaction { #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase", deny_unknown_fields)] struct JitOrder { - buy_token: eth::H160, - sell_token: eth::H160, + buy_token: eth::Address, + sell_token: eth::Address, #[serde_as(as = "serialize::U256")] sell_amount: eth::U256, #[serde_as(as = "serialize::U256")] buy_amount: eth::U256, #[serde_as(as = "serialize::U256")] executed_amount: eth::U256, - receiver: eth::H160, + receiver: eth::Address, partially_fillable: bool, valid_to: u32, #[serde_as(as = "serialize::Hex")] @@ -96,7 +100,7 @@ impl From for JitOrder { sell_amount: jit.order().sell.amount.into(), buy_amount: jit.order().buy.amount.into(), executed_amount: jit.executed().into(), - receiver: jit.order().receiver.into(), + receiver: jit.order().receiver, partially_fillable: jit.order().partially_fillable, valid_to: jit.order().valid_to.into(), app_data: jit.order().app_data.into(), diff --git a/crates/driver/src/infra/api/routes/solve/dto/solve_request.rs b/crates/driver/src/infra/api/routes/solve/dto/solve_request.rs index 509b9fb4d5..5d534e6cd4 100644 --- a/crates/driver/src/infra/api/routes/solve/dto/solve_request.rs +++ b/crates/driver/src/infra/api/routes/solve/dto/solve_request.rs @@ -44,7 +44,7 @@ impl SolveRequest { .into_iter() .map(|order| competition::Order { uid: order.uid.into(), - receiver: order.receiver.map(Into::into), + receiver: order.receiver, created: order.created.into(), valid_to: order.valid_to.into(), buy: eth::Asset { @@ -83,7 +83,7 @@ impl SolveRequest { .pre_interactions .into_iter() .map(|interaction| eth::Interaction { - target: interaction.target.into(), + target: interaction.target, value: interaction.value.into(), call_data: interaction.call_data.into(), }) @@ -92,7 +92,7 @@ impl SolveRequest { .post_interactions .into_iter() .map(|interaction| eth::Interaction { - target: interaction.target.into(), + target: interaction.target, value: interaction.value.into(), call_data: interaction.call_data.into(), }) @@ -124,7 +124,7 @@ impl SolveRequest { } }, data: order.signature.into(), - signer: order.owner.into(), + signer: order.owner, }, protocol_fees: order .protocol_fees @@ -171,7 +171,6 @@ impl SolveRequest { eth, self.surplus_capturing_jit_order_owners .into_iter() - .map(Into::into) .collect::>(), ) .await @@ -217,7 +216,7 @@ pub struct SolveRequest { orders: Vec, deadline: chrono::DateTime, #[serde(default)] - surplus_capturing_jit_order_owners: Vec, + surplus_capturing_jit_order_owners: Vec, } impl SolveRequest { @@ -230,7 +229,7 @@ impl SolveRequest { #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] struct Token { - pub address: eth::H160, + pub address: eth::Address, #[serde_as(as = "Option")] pub price: Option, pub trusted: bool, @@ -242,8 +241,8 @@ struct Token { struct Order { #[serde_as(as = "serialize::Hex")] uid: [u8; order::UID_LEN], - sell_token: eth::H160, - buy_token: eth::H160, + sell_token: eth::Address, + buy_token: eth::Address, #[serde_as(as = "serialize::U256")] sell_amount: eth::U256, #[serde_as(as = "serialize::U256")] @@ -252,8 +251,8 @@ struct Order { created: u32, valid_to: u32, kind: Kind, - receiver: Option, - owner: eth::H160, + receiver: Option, + owner: eth::Address, partially_fillable: bool, /// Always zero if the order is not partially fillable. #[serde_as(as = "serialize::U256")] @@ -284,7 +283,7 @@ enum Kind { #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] struct Interaction { - target: eth::H160, + target: eth::Address, #[serde_as(as = "serialize::U256")] value: eth::U256, #[serde_as(as = "serialize::Hex")] @@ -349,11 +348,15 @@ pub struct Quote { pub buy_amount: eth::U256, #[serde_as(as = "serialize::U256")] pub fee: eth::U256, - pub solver: eth::H160, + pub solver: eth::Address, } impl Quote { - fn into_domain(self, sell_token: eth::H160, buy_token: eth::H160) -> competition::order::Quote { + fn into_domain( + self, + sell_token: eth::Address, + buy_token: eth::Address, + ) -> competition::order::Quote { competition::order::Quote { sell: eth::Asset { amount: self.sell_amount.into(), @@ -367,7 +370,7 @@ impl Quote { amount: self.fee.into(), token: sell_token.into(), }, - solver: self.solver.into(), + solver: self.solver, } } } diff --git a/crates/driver/src/infra/api/routes/solve/dto/solve_response.rs b/crates/driver/src/infra/api/routes/solve/dto/solve_response.rs index 892810f5f1..3c57936481 100644 --- a/crates/driver/src/infra/api/routes/solve/dto/solve_response.rs +++ b/crates/driver/src/infra/api/routes/solve/dto/solve_response.rs @@ -31,7 +31,7 @@ impl Solution { Self { solution_id, score: solved.score.0, - submission_address: solver.address().into(), + submission_address: solver.address(), orders: solved .trades .into_iter() @@ -73,11 +73,11 @@ pub struct Solution { solution_id: u64, #[serde_as(as = "serialize::U256")] score: eth::U256, - submission_address: eth::H160, + submission_address: eth::Address, #[serde_as(as = "HashMap")] orders: HashMap, #[serde_as(as = "HashMap<_, serialize::U256>")] - clearing_prices: HashMap, + clearing_prices: HashMap, } #[serde_as] @@ -85,8 +85,8 @@ pub struct Solution { #[serde(rename_all = "camelCase")] pub struct TradedOrder { pub side: Side, - pub sell_token: eth::H160, - pub buy_token: eth::H160, + pub sell_token: eth::Address, + pub buy_token: eth::Address, #[serde_as(as = "serialize::U256")] /// Sell limit order amount. pub limit_sell: eth::U256, diff --git a/crates/driver/src/infra/blockchain/contracts.rs b/crates/driver/src/infra/blockchain/contracts.rs index d89a39b294..e602ee42e2 100644 --- a/crates/driver/src/infra/blockchain/contracts.rs +++ b/crates/driver/src/infra/blockchain/contracts.rs @@ -8,10 +8,7 @@ use { WETH9, support::Balances, }, - ethrpc::{ - Web3, - alloy::conversions::{IntoAlloy, IntoLegacy}, - }, + ethrpc::{Web3, alloy::conversions::IntoAlloy}, std::collections::HashMap, thiserror::Error, }; @@ -58,7 +55,7 @@ impl Contracts { let settlement = GPv2Settlement::Instance::new( addresses .settlement - .map(|addr| addr.0.into_alloy()) + .map(Into::into) .or_else(|| GPv2Settlement::deployment_address(&chain.id())) .unwrap(), web3.alloy.clone(), @@ -69,7 +66,7 @@ impl Contracts { let balance_helper = Balances::Instance::new( addresses .balances - .map(|addr| addr.0.into_alloy()) + .map(Into::into) .or_else(|| Balances::deployment_address(&chain.id())) .unwrap(), web3.alloy.clone(), @@ -77,7 +74,7 @@ impl Contracts { let signatures = contracts::alloy::support::Signatures::Instance::new( addresses .signatures - .map(|addr| addr.0.into_alloy()) + .map(Into::into) .or_else(|| contracts::alloy::support::Signatures::deployment_address(&chain.id())) .unwrap(), web3.alloy.clone(), @@ -86,7 +83,7 @@ impl Contracts { let weth = WETH9::Instance::new( addresses .weth - .map(|addr| addr.0.into_alloy()) + .map(Into::into) .or_else(|| WETH9::deployment_address(&chain.id())) .unwrap(), web3.alloy.clone(), @@ -104,18 +101,12 @@ impl Contracts { // TODO: use `address_for()` once contracts are deployed let flashloan_router = addresses .flashloan_router - .or_else(|| { - FlashLoanRouter::deployment_address(&chain.id()).map(|deployment_address| { - eth::ContractAddress(deployment_address.into_legacy()) - }) - }) - .map(|address| { - FlashLoanRouter::Instance::new(address.0.into_alloy(), web3.alloy.clone()) - }); + .or_else(|| FlashLoanRouter::deployment_address(&chain.id()).map(eth::ContractAddress)) + .map(|address| FlashLoanRouter::Instance::new(address.0, web3.alloy.clone())); Ok(Self { settlement, - vault_relayer: vault_relayer.into_legacy().into(), + vault_relayer: vault_relayer.into(), vault, signatures, weth, @@ -148,7 +139,7 @@ impl Contracts { } pub fn weth_address(&self) -> eth::WethAddress { - self.weth.address().into_legacy().into() + (*self.weth.address()).into() } pub fn settlement_domain_separator(&self) -> ð::DomainSeparator { @@ -185,6 +176,7 @@ pub fn deployment_address( .networks .get(&chain.id().to_string())? .address + .into_alloy() .into(), ) } diff --git a/crates/driver/src/infra/blockchain/gas.rs b/crates/driver/src/infra/blockchain/gas.rs index 76ed302dac..9c2491aae4 100644 --- a/crates/driver/src/infra/blockchain/gas.rs +++ b/crates/driver/src/infra/blockchain/gas.rs @@ -72,7 +72,7 @@ impl GasPriceEstimator { } => (max_additional_tip, additional_tip_percentage), }) .next() - .unwrap_or((eth::U256::zero(), 0.)); + .unwrap_or((eth::U256::ZERO, 0.)); // Use the lowest max_fee_per_gas of all mempools as the max_fee_per_gas let max_fee_per_gas = mempools .iter() @@ -104,19 +104,17 @@ impl GasPriceEstimator { .await .map(|estimate| { let (max, percentage) = self.additional_tip; - let additional_tip = max - .to_f64_lossy() - .min(estimate.max_fee_per_gas * percentage); + let additional_tip = f64::from(max).min(estimate.max_fee_per_gas * percentage); let tip = std::cmp::max( - self.min_priority_fee + eth::U256::from_f64_lossy(additional_tip), - eth::U256::from_f64_lossy(estimate.max_priority_fee_per_gas + additional_tip), + self.min_priority_fee + eth::U256::from(additional_tip), + eth::U256::from(estimate.max_priority_fee_per_gas + additional_tip), ); eth::GasPrice::new( self.max_fee_per_gas.into(), tip.into(), - eth::U256::from_f64_lossy(estimate.base_fee_per_gas).into(), + eth::U256::from(estimate.base_fee_per_gas).into(), ) }) .map_err(Error::GasPrice) diff --git a/crates/driver/src/infra/blockchain/mod.rs b/crates/driver/src/infra/blockchain/mod.rs index 25c109ca61..d1a73a7574 100644 --- a/crates/driver/src/infra/blockchain/mod.rs +++ b/crates/driver/src/infra/blockchain/mod.rs @@ -1,9 +1,16 @@ use { - crate::{boundary, domain::eth}, + crate::{ + boundary, + domain::{eth, eth::U256}, + }, alloy::providers::Provider, chain::Chain, - ethcontract::{U256, errors::ExecutionError}, - ethrpc::{Web3, alloy::conversions::IntoLegacy, block_stream::CurrentBlockWatcher}, + ethcontract::errors::ExecutionError, + ethrpc::{ + Web3, + alloy::conversions::{IntoAlloy, IntoLegacy}, + block_stream::CurrentBlockWatcher, + }, shared::{ account_balances::{BalanceSimulator, SimulationError}, price_estimation::trade_verifier::balance_overrides::{ @@ -116,7 +123,7 @@ impl Ethereum { let balance_simulator = BalanceSimulator::new( contracts.settlement().clone(), contracts.balance_helper().clone(), - contracts.vault_relayer().0, + contracts.vault_relayer().0.into_legacy(), Some(contracts.vault().address().into_legacy()), balance_overrider.clone(), ); @@ -163,7 +170,7 @@ 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(), None).await?; + let code = self.web3.eth().code(address.into_legacy(), None).await?; Ok(!code.0.is_empty()) } @@ -180,8 +187,11 @@ impl Ethereum { CallRequest: From, { let mut tx: CallRequest = tx.into(); - tx.gas = Some(self.inner.tx_gas_limit); - tx.gas_price = self.simulation_gas_price().await; + 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 @@ -205,17 +215,21 @@ impl Ethereum { .eth() .estimate_gas( web3::types::CallRequest { - from: Some(tx.from.into()), - to: Some(tx.to.into()), - value: Some(tx.value.into()), + 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, + 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) } @@ -228,15 +242,21 @@ impl Ethereum { } pub fn block_gas_limit(&self) -> eth::Gas { - self.inner.current_block.borrow().gas_limit.into() + self.inner + .current_block + .borrow() + .gas_limit + .into_alloy() + .into() } /// 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(), None) + .balance(address.into_legacy(), None) .await + .map(IntoAlloy::into_alloy) .map(Into::into) .map_err(Into::into) } diff --git a/crates/driver/src/infra/blockchain/token.rs b/crates/driver/src/infra/blockchain/token.rs index 70744f035b..dfa27f223b 100644 --- a/crates/driver/src/infra/blockchain/token.rs +++ b/crates/driver/src/infra/blockchain/token.rs @@ -1,10 +1,7 @@ use { super::{Error, Ethereum}, crate::domain::eth, - ethrpc::alloy::{ - conversions::{IntoAlloy, IntoLegacy}, - errors::ContractErrorExt, - }, + ethrpc::alloy::errors::ContractErrorExt, }; /// An ERC-20 token. @@ -17,16 +14,13 @@ pub struct Erc20 { impl Erc20 { pub(super) fn new(eth: &Ethereum, address: eth::TokenAddress) -> Self { Self { - token: contracts::alloy::ERC20::Instance::new( - address.0.0.into_alloy(), - eth.web3.alloy.clone(), - ), + token: contracts::alloy::ERC20::Instance::new(address.0.0, eth.web3.alloy.clone()), } } /// Returns the [`eth::TokenAddress`] of the ERC20. pub fn address(&self) -> eth::TokenAddress { - self.token.address().into_legacy().into() + (*self.token.address()).into() } /// Fetch the ERC20 allowance for the spender. See the allowance method in @@ -38,13 +32,9 @@ impl Erc20 { owner: eth::Address, spender: eth::Address, ) -> Result { - let amount = self - .token - .allowance(owner.0.into_alloy(), spender.0.into_alloy()) - .call() - .await?; + let amount = self.token.allowance(owner, spender).call().await?; Ok(eth::Allowance { - token: self.token.address().into_legacy().into(), + token: (*self.token.address()).into(), spender, amount, } @@ -81,10 +71,9 @@ impl Erc20 { /// https://eips.ethereum.org/EIPS/eip-20#balanceof pub async fn balance(&self, holder: eth::Address) -> Result { self.token - .balanceOf(holder.0.into_alloy()) + .balanceOf(holder) .call() .await - .map(IntoLegacy::into_legacy) .map(Into::into) .map_err(Into::into) } diff --git a/crates/driver/src/infra/config/file/load.rs b/crates/driver/src/infra/config/file/load.rs index ffd20f214e..27fcd6986c 100644 --- a/crates/driver/src/infra/config/file/load.rs +++ b/crates/driver/src/infra/config/file/load.rs @@ -13,6 +13,7 @@ use { }, }, chain::Chain, + ethrpc::alloy::conversions::IntoLegacy, futures::future::join_all, number::conversions::big_decimal_to_big_rational, std::path::Path, @@ -64,7 +65,9 @@ pub async fn load(chain: Chain, path: &Path) -> infra::Config { .unwrap_or_else(|_| panic!("Unable to load KMS account {key_id:?}")); ethcontract::Account::Kms(account, None) } - file::Account::Address(address) => ethcontract::Account::Local(address, None), + file::Account::Address(address) => { + ethcontract::Account::Local(address.into_legacy(), None) + } }; solver::Config { endpoint: solver_config.endpoint, @@ -100,7 +103,7 @@ pub async fn load(chain: Chain, path: &Path) -> infra::Config { }, s3: solver_config.s3.map(Into::into), solver_native_token: solver_config.manage_native_token.to_domain(), - quote_tx_origin: solver_config.quote_tx_origin.map(eth::Address), + quote_tx_origin: solver_config.quote_tx_origin, response_size_limit_max_bytes: solver_config.response_size_limit_max_bytes, bad_token_detection: BadTokenDetection { tokens_supported: solver_config diff --git a/crates/driver/src/infra/config/file/mod.rs b/crates/driver/src/infra/config/file/mod.rs index 109113f6d1..2276787960 100644 --- a/crates/driver/src/infra/config/file/mod.rs +++ b/crates/driver/src/infra/config/file/mod.rs @@ -219,7 +219,7 @@ fn default_additional_tip_percentage() -> f64 { /// 1000 gwei fn default_gas_price_cap() -> eth::U256 { - eth::U256::from(1000) * eth::U256::exp10(9) + eth::U256::from(1000) * eth::U256::from(10).pow(eth::U256::from(9)) } fn default_target_confirm_time() -> Duration { @@ -232,7 +232,7 @@ fn default_retry_interval() -> Duration { /// 3 gwei fn default_max_additional_tip() -> eth::U256 { - eth::U256::from(3) * eth::U256::exp10(9) + eth::U256::from(3) * eth::U256::from(10).pow(eth::U256::from(9)) } fn default_soft_cancellations_flag() -> bool { @@ -304,7 +304,7 @@ struct SolverConfig { /// Which `tx.origin` is required to make a quote simulation pass. #[serde(default)] - quote_tx_origin: Option, + quote_tx_origin: Option, /// Maximum HTTP response size the driver will accept in bytes. #[serde(default = "default_response_size_limit_max_bytes")] @@ -351,7 +351,7 @@ enum Account { /// 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::H160), + Address(eth::Address), } #[serde_as] @@ -390,16 +390,16 @@ struct Slippage { #[serde(rename_all = "kebab-case", deny_unknown_fields)] struct ContractsConfig { /// Override the default address of the GPv2Settlement contract. - gp_v2_settlement: Option, + gp_v2_settlement: Option, /// Override the default address of the WETH contract. - weth: Option, + weth: Option, /// Override the default address of the Balances contract. - balances: Option, + balances: Option, /// Override the default address of the Signatures contract. - signatures: Option, + signatures: Option, /// List of all cow amm factories with the corresponding helper contract. #[serde(default)] @@ -407,16 +407,16 @@ struct ContractsConfig { /// Flashloan router to support taking out multiple flashloans /// in the same settlement. - flashloan_router: Option, + flashloan_router: Option, } #[derive(Debug, Clone, Deserialize)] #[serde(rename_all = "kebab-case", deny_unknown_fields)] pub struct CowAmmConfig { /// CoW AMM factory address. - pub factory: eth::H160, + pub factory: eth::Address, /// Which helper contract to use for interfacing with CoW AMMs. - pub helper: eth::H160, + pub helper: eth::Address, } #[derive(Debug, Deserialize)] @@ -459,7 +459,7 @@ struct LiquidityConfig { /// Additional tokens for which liquidity is always fetched, regardless of /// whether or not the token appears in the auction. #[serde(default)] - base_tokens: Vec, + base_tokens: Vec, /// Liquidity provided by a Uniswap V2 compatible contract. #[serde(default)] @@ -496,7 +496,7 @@ enum UniswapV2Config { #[serde(rename_all = "kebab-case")] Manual { /// The address of the Uniswap V2 compatible router contract. - router: eth::H160, + router: eth::Address, /// The digest of the pool initialization code. pool_code: eth::H256, @@ -529,7 +529,7 @@ enum SwaprConfig { #[serde(rename_all = "kebab-case")] Manual { /// The address of the Swapr compatible router contract. - router: eth::H160, + router: eth::Address, /// The digest of the pool initialization code. pool_code: eth::H256, @@ -576,7 +576,7 @@ enum UniswapV3Config { #[serde(rename_all = "kebab-case")] Manual { /// Addresses of Uniswap V3 compatible router contracts. - router: eth::H160, + router: eth::Address, /// How many pools to initialize during start up. #[serde(default = "uniswap_v3::default_max_pools_to_initialize")] @@ -637,7 +637,7 @@ enum BalancerV2Config { #[serde(rename_all = "kebab-case")] Manual { /// Addresses of Balancer V2 compatible vault contract. - vault: eth::H160, + vault: eth::Address, /// The weighted pool factory contract addresses. #[serde(default)] @@ -838,7 +838,7 @@ fn default_simulation_bad_token_max_age() -> Duration { pub struct BadTokenDetectionConfig { /// Which tokens are explicitly supported or unsupported by the solver. #[serde(default)] - pub token_supported: HashMap, + pub token_supported: HashMap, /// Whether the solver opted into detecting unsupported /// tokens with `trace_callMany` based simulation. diff --git a/crates/driver/src/infra/liquidity/config.rs b/crates/driver/src/infra/liquidity/config.rs index b2f64faa63..d4e62ae9fb 100644 --- a/crates/driver/src/infra/liquidity/config.rs +++ b/crates/driver/src/infra/liquidity/config.rs @@ -4,7 +4,6 @@ use { chain::Chain, contracts::alloy::BalancerV2Vault, derive_more::Debug, - ethrpc::alloy::conversions::IntoLegacy, hex_literal::hex, reqwest::Url, shared::sources::uniswap_v2::{ @@ -63,9 +62,9 @@ impl UniswapV2 { #[expect(clippy::self_named_constructors)] pub fn uniswap_v2(chain: Chain) -> Option { Some(Self { - router: ContractAddress::from( - contracts::alloy::UniswapV2Router02::deployment_address(&chain.id())?.into_legacy(), - ), + router: ContractAddress::from(contracts::alloy::UniswapV2Router02::deployment_address( + &chain.id(), + )?), pool_code: UNISWAP_INIT.into(), missing_pool_cache_time: Duration::from_secs(60 * 60), }) @@ -74,9 +73,9 @@ impl UniswapV2 { /// Returns the liquidity configuration for SushiSwap. pub fn sushi_swap(chain: Chain) -> Option { Some(Self { - router: ContractAddress::from( - contracts::alloy::SushiSwapRouter::deployment_address(&chain.id())?.into_legacy(), - ), + router: ContractAddress::from(contracts::alloy::SushiSwapRouter::deployment_address( + &chain.id(), + )?), pool_code: SUSHISWAP_INIT.into(), missing_pool_cache_time: Duration::from_secs(60 * 60), }) @@ -85,9 +84,9 @@ impl UniswapV2 { /// Returns the liquidity configuration for Honeyswap. pub fn honeyswap(chain: Chain) -> Option { Some(Self { - router: ContractAddress::from( - contracts::alloy::BaoswapRouter::deployment_address(&chain.id())?.into_legacy(), - ), + router: ContractAddress::from(contracts::alloy::BaoswapRouter::deployment_address( + &chain.id(), + )?), pool_code: HONEYSWAP_INIT.into(), missing_pool_cache_time: Duration::from_secs(60 * 60), }) @@ -96,9 +95,9 @@ impl UniswapV2 { /// Returns the liquidity configuration for Baoswap. pub fn baoswap(chain: Chain) -> Option { Some(Self { - router: ContractAddress::from( - contracts::alloy::BaoswapRouter::deployment_address(&chain.id())?.into_legacy(), - ), + router: ContractAddress::from(contracts::alloy::BaoswapRouter::deployment_address( + &chain.id(), + )?), pool_code: BAOSWAP_INIT.into(), missing_pool_cache_time: Duration::from_secs(60 * 60), }) @@ -112,9 +111,9 @@ impl UniswapV2 { } .into(); Some(Self { - router: ContractAddress::from( - contracts::alloy::PancakeRouter::deployment_address(&chain.id())?.into_legacy(), - ), + router: ContractAddress::from(contracts::alloy::PancakeRouter::deployment_address( + &chain.id(), + )?), pool_code, missing_pool_cache_time: Duration::from_secs(60 * 60), }) @@ -125,8 +124,7 @@ impl UniswapV2 { pub fn testnet_uniswapv2(chain: Chain) -> Option { Some(Self { router: ContractAddress::from( - contracts::alloy::TestnetUniswapV2Router02::deployment_address(&chain.id())? - .into_legacy(), + contracts::alloy::TestnetUniswapV2Router02::deployment_address(&chain.id())?, ), pool_code: TESTNET_UNISWAP_INIT.into(), missing_pool_cache_time: Duration::from_secs(60 * 60), @@ -152,9 +150,9 @@ impl Swapr { #[expect(clippy::self_named_constructors)] pub fn swapr(chain: Chain) -> Option { Some(Self { - router: ContractAddress::from( - contracts::alloy::SwaprRouter::deployment_address(&chain.id())?.into_legacy(), - ), + router: ContractAddress::from(contracts::alloy::SwaprRouter::deployment_address( + &chain.id(), + )?), pool_code: SWAPR_INIT.into(), missing_pool_cache_time: Duration::from_secs(60 * 60), }) @@ -193,7 +191,6 @@ impl UniswapV3 { ) -> Option { Some(Self { router: contracts::alloy::UniswapV3SwapRouterV2::deployment_address(&chain.id())? - .into_legacy() .into(), max_pools_to_initialize: 100, graph_url: graph_url.clone(), @@ -255,7 +252,7 @@ impl BalancerV2 { } Some(Self { - vault: ContractAddress(BalancerV2Vault::deployment_address(&chain.id())?.into_legacy()), + vault: ContractAddress(BalancerV2Vault::deployment_address(&chain.id())?), weighted: address_for!( chain, [ diff --git a/crates/driver/src/infra/mempool/mod.rs b/crates/driver/src/infra/mempool/mod.rs index c89413e9b4..e9d684a7c6 100644 --- a/crates/driver/src/infra/mempool/mod.rs +++ b/crates/driver/src/infra/mempool/mod.rs @@ -4,7 +4,10 @@ use { domain::{competition, eth, mempools}, infra, }, - ethrpc::Web3, + ethrpc::{ + Web3, + alloy::conversions::{IntoAlloy, IntoLegacy}, + }, }; #[derive(Debug, Clone)] @@ -85,8 +88,9 @@ impl Mempool { pub async fn get_nonce(&self, address: eth::Address) -> Result { self.transport .eth() - .transaction_count(address.into(), self.config.nonce_block_number) + .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")) }) @@ -103,15 +107,15 @@ impl Mempool { ) -> Result { ethcontract::transaction::TransactionBuilder::new(self.transport.legacy.clone()) .from(solver.account().clone()) - .to(tx.to.into()) - .nonce(nonce) + .to(tx.to.into_legacy()) + .nonce(nonce.into_legacy()) .gas_price(ethcontract::GasPrice::Eip1559 { - max_fee_per_gas: gas.price.max().into(), - max_priority_fee_per_gas: gas.price.tip().into(), + 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) - .gas(gas.limit.0) + .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() diff --git a/crates/driver/src/infra/notify/liquidity_sources/liquorice/notifier.rs b/crates/driver/src/infra/notify/liquidity_sources/liquorice/notifier.rs index f951392ddf..9818d2d366 100644 --- a/crates/driver/src/infra/notify/liquidity_sources/liquorice/notifier.rs +++ b/crates/driver/src/infra/notify/liquidity_sources/liquorice/notifier.rs @@ -90,7 +90,6 @@ mod utils { }, alloy::{primitives::Address, sol_types::SolCall}, contracts::alloy::LiquoriceSettlement, - ethrpc::alloy::conversions::IntoAlloy, std::collections::HashSet, }; @@ -145,7 +144,7 @@ mod utils { interaction: ð::Interaction, liquorice_settlement_contract_address: Address, ) -> Option { - if interaction.target.0.into_alloy() != liquorice_settlement_contract_address { + if interaction.target != liquorice_settlement_contract_address { return None; } @@ -166,22 +165,21 @@ mod utils { infra::notify::liquidity_sources::liquorice::notifier::utils::extract_rfq_id_from_interaction, util::Bytes, }, - ethrpc::alloy::conversions::IntoAlloy, - primitive_types::H160, + alloy::primitives::Address, }; #[test] fn test_extract_rfq_id_from_valid_settle_single_call() { let calldata = const_hex::decode("9935c868000000000000000000000000b10b9c690a681b6285c2e2df7734f9d729c5c4d500000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000001dcd65000000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009008d19f58aabd9ed0d60971565aa8510560ab410000000000000000000000009008d19f58aabd9ed0d60971565aa8510560ab41000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7000000000000000000000000000000000000000000000000000000001dcd6500000000000000000000000000000000000000000000000000000000001dcd650000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000068a76fd0000000000000000000000000b10b9c690a681b6285c2e2df7734f9d729c5c4d5000000000000000000000000000000000000000000000000000000000000002463393964326533662d373032622d343963392d386262382d343337373537373066326633000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000041d44f6881d24cd3ad94561d1aad5e220929181cf728f89620629e0efbe3daa9833b9f2967bf37381f56b41266327a3804c92204f30a2d660cae8b42cd6f7d9b701c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000041000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap(); - let liquorice_settlement_address = H160::random().into(); + let liquorice_settlement_address = Address::random(); let rfq_id = extract_rfq_id_from_interaction( ð::Interaction { target: liquorice_settlement_address, call_data: Bytes(calldata), value: 0.into(), }, - liquorice_settlement_address.0.into_alloy(), + liquorice_settlement_address, ) .unwrap(); assert_eq!(rfq_id, "c99d2e3f-702b-49c9-8bb8-43775770f2f3".to_string()); @@ -189,14 +187,14 @@ mod utils { #[test] fn test_returns_none_for_arbitrary_call() { - let liquorice_settlement_address = H160::random().into(); + let liquorice_settlement_address = Address::random(); let rfq_id = extract_rfq_id_from_interaction( ð::Interaction { target: liquorice_settlement_address, call_data: Bytes(vec![]), value: 0.into(), }, - liquorice_settlement_address.0.into_alloy(), + liquorice_settlement_address, ); assert!(rfq_id.is_none()); @@ -206,11 +204,11 @@ mod utils { fn test_returns_none_for_different_target() { let rfq_id = extract_rfq_id_from_interaction( ð::Interaction { - target: H160::random().into(), + target: Address::random(), call_data: Bytes(vec![]), value: 0.into(), }, - H160::random().into_alloy(), + Address::random(), ); assert!(rfq_id.is_none()); diff --git a/crates/driver/src/infra/simulator/enso/dto.rs b/crates/driver/src/infra/simulator/enso/dto.rs index 065bcf03a4..6291d8924d 100644 --- a/crates/driver/src/infra/simulator/enso/dto.rs +++ b/crates/driver/src/infra/simulator/enso/dto.rs @@ -2,6 +2,7 @@ use { crate::{domain::eth, util::serialize}, + ethrpc::alloy::conversions::IntoAlloy, serde::{Deserialize, Serialize}, serde_with::serde_as, }; @@ -11,8 +12,8 @@ use { #[serde(rename_all = "camelCase")] pub struct Request { pub chain_id: u64, - pub from: eth::H160, - pub to: eth::H160, + pub from: eth::Address, + pub to: eth::Address, #[serde_as(as = "serialize::Hex")] pub data: Vec, pub value: eth::U256, @@ -35,7 +36,7 @@ impl From for AccessList { web3::types::AccessList::from(value) .into_iter() .map(|item| AccessListItem { - address: item.address, + address: item.address.into_alloy(), storage_keys: item.storage_keys, }) .collect(), @@ -47,7 +48,7 @@ impl From for AccessList { #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] pub struct AccessListItem { - pub address: eth::H160, + pub address: eth::Address, pub storage_keys: Vec, } diff --git a/crates/driver/src/infra/simulator/enso/mod.rs b/crates/driver/src/infra/simulator/enso/mod.rs index e7f30948ef..29dcc2d2db 100644 --- a/crates/driver/src/infra/simulator/enso/mod.rs +++ b/crates/driver/src/infra/simulator/enso/mod.rs @@ -59,8 +59,8 @@ impl Enso { .post(self.url.clone()) .json(&dto::Request { chain_id: self.chain.id(), - from: tx.from.into(), - to: tx.to.into(), + from: tx.from, + to: tx.to, data: tx.input.into(), value: tx.value.into(), gas_limit: GAS_LIMIT, diff --git a/crates/driver/src/infra/simulator/tenderly/dto.rs b/crates/driver/src/infra/simulator/tenderly/dto.rs index 14a691e073..286e8b0efd 100644 --- a/crates/driver/src/infra/simulator/tenderly/dto.rs +++ b/crates/driver/src/infra/simulator/tenderly/dto.rs @@ -2,6 +2,7 @@ use { crate::{domain::eth, util::serialize}, + ethrpc::alloy::conversions::{IntoAlloy, IntoLegacy}, itertools::Itertools, serde::{Deserialize, Serialize}, serde_with::serde_as, @@ -11,8 +12,8 @@ use { #[derive(Debug, Serialize)] pub struct Request { pub network_id: String, - pub from: eth::H160, - pub to: eth::H160, + pub from: eth::Address, + pub to: eth::Address, #[serde_as(as = "serialize::Hex")] pub input: Vec, pub value: eth::U256, @@ -45,7 +46,7 @@ pub struct AccessList(Vec); #[derive(Debug, Deserialize, Serialize)] struct AccessListItem { - address: eth::H160, + address: eth::Address, #[serde(default)] storage_keys: Vec, } @@ -56,7 +57,7 @@ impl From for AccessList { web3::types::AccessList::from(value) .into_iter() .map(|item| AccessListItem { - address: item.address, + address: item.address.into_alloy(), storage_keys: item.storage_keys, }) .collect(), @@ -70,7 +71,7 @@ impl From for eth::AccessList { .0 .into_iter() .map(|item| web3::types::AccessListItem { - address: item.address, + address: item.address.into_legacy(), storage_keys: item.storage_keys, }) .collect_vec() diff --git a/crates/driver/src/infra/simulator/tenderly/mod.rs b/crates/driver/src/infra/simulator/tenderly/mod.rs index 793290bb04..601ec876d1 100644 --- a/crates/driver/src/infra/simulator/tenderly/mod.rs +++ b/crates/driver/src/infra/simulator/tenderly/mod.rs @@ -76,8 +76,8 @@ impl Tenderly { .post(self.endpoint.clone()) .json(&dto::Request { network_id: self.eth.chain().id().to_string(), - from: tx.from.into(), - to: tx.to.into(), + from: tx.from, + to: tx.to, input: tx.input.clone().into(), value: tx.value.into(), save: self.config.save, @@ -88,7 +88,10 @@ impl Tenderly { } else { Some(tx.access_list.clone().into()) }, - gas_price: gas_price.unwrap_or_default().as_u64(), + gas_price: gas_price + .unwrap_or_default() + .try_into() + .expect("value should be lower than u64::MAX"), }) .send() .await? diff --git a/crates/driver/src/infra/solver/dto/auction.rs b/crates/driver/src/infra/solver/dto/auction.rs index 84ce51d7f2..5af1ef96d5 100644 --- a/crates/driver/src/infra/solver/dto/auction.rs +++ b/crates/driver/src/infra/solver/dto/auction.rs @@ -12,7 +12,7 @@ use { util::conv::{rational_to_big_decimal, u256::U256Ext}, }, app_data::AppDataHash, - ethrpc::alloy::conversions::IntoLegacy, + ethrpc::alloy::conversions::IntoAlloy, model::order::{BuyTokenDestination, SellTokenSource}, std::collections::HashMap, }; @@ -30,7 +30,7 @@ pub fn new( wrappers: &WrapperCalls, deadline: chrono::DateTime, ) -> solvers_dto::auction::Auction { - let mut tokens: HashMap = auction + let mut tokens: HashMap = auction .tokens() .iter() .map(|token| { @@ -59,8 +59,8 @@ pub fn new( liquidity::Kind::Swapr(pool) => pool.base.reserves.iter().map(|r| r.token).collect(), liquidity::Kind::ZeroEx(limit_order) => { vec![ - limit_order.order.maker_token.into_legacy().into(), - limit_order.order.taker_token.into_legacy().into(), + limit_order.order.maker_token.into(), + limit_order.order.taker_token.into(), ] } }) @@ -113,8 +113,8 @@ pub fn new( } solvers_dto::auction::Order { uid: order.uid.into(), - sell_token: available.sell.token.into(), - buy_token: available.buy.token.into(), + sell_token: available.sell.token.0.0, + buy_token: available.buy.token.0.0, sell_amount: available.sell.amount.into(), buy_amount: available.buy.amount.into(), full_sell_amount: order.sell.amount.into(), @@ -123,8 +123,8 @@ pub fn new( Side::Buy => solvers_dto::auction::Kind::Buy, Side::Sell => solvers_dto::auction::Kind::Sell, }, - receiver: order.receiver.map(Into::into), - owner: order.signature.signer.into(), + receiver: order.receiver, + owner: order.signature.signer, partially_fillable: order.is_partial(), class: match order.kind { order::Kind::Market => solvers_dto::auction::Class::Market, @@ -182,15 +182,15 @@ pub fn new( solvers_dto::auction::Liquidity::ConstantProduct( solvers_dto::auction::ConstantProductPool { id: liquidity.id.0.to_string(), - address: pool.address.into(), - router: pool.router.into(), + address: pool.address, + router: pool.router.0, gas_estimate: liquidity.gas.into(), tokens: pool .reserves .iter() .map(|asset| { ( - asset.token.into(), + asset.token.0.0, solvers_dto::auction::ConstantProductReserve { balance: asset.amount.into(), }, @@ -206,9 +206,9 @@ pub fn new( solvers_dto::auction::ConcentratedLiquidityPool { id: liquidity.id.0.to_string(), address: pool.address.0, - router: pool.router.into(), + router: pool.router.0, gas_estimate: liquidity.gas.0, - tokens: vec![pool.tokens.get().0.into(), pool.tokens.get().1.into()], + tokens: vec![pool.tokens.get().0.0.0, pool.tokens.get().1.0.0], sqrt_price: pool.sqrt_price.0, liquidity: pool.liquidity.0, tick: pool.tick.0, @@ -225,7 +225,7 @@ pub fn new( solvers_dto::auction::Liquidity::Stable(solvers_dto::auction::StablePool { id: liquidity.id.0.to_string(), address: pool.id.address().into(), - balancer_pool_id: pool.id.into(), + balancer_pool_id: pool.id.0.into_alloy(), gas_estimate: liquidity.gas.into(), tokens: pool .reserves @@ -252,7 +252,7 @@ pub fn new( solvers_dto::auction::WeightedProductPool { id: liquidity.id.0.to_string(), address: pool.id.address().into(), - balancer_pool_id: pool.id.into(), + balancer_pool_id: pool.id.0.into_alloy(), gas_estimate: liquidity.gas.into(), tokens: pool .reserves @@ -283,7 +283,7 @@ pub fn new( liquidity::Kind::Swapr(pool) => solvers_dto::auction::Liquidity::ConstantProduct( solvers_dto::auction::ConstantProductPool { id: liquidity.id.0.to_string(), - address: pool.base.address.into(), + address: pool.base.address, router: pool.base.router.into(), gas_estimate: liquidity.gas.into(), tokens: pool @@ -306,14 +306,16 @@ pub fn new( solvers_dto::auction::Liquidity::LimitOrder( solvers_dto::auction::ForeignLimitOrder { id: liquidity.id.0.to_string(), - address: limit_order.zeroex.address().into_legacy(), + address: *limit_order.zeroex.address(), gas_estimate: liquidity.gas.into(), hash: Default::default(), - maker_token: limit_order.order.maker_token.into_legacy(), - taker_token: limit_order.order.taker_token.into_legacy(), - maker_amount: limit_order.fillable.maker.into(), - taker_amount: limit_order.fillable.taker.into(), - taker_token_fee_amount: limit_order.order.taker_token_fee_amount.into(), + maker_token: limit_order.order.maker_token, + taker_token: limit_order.order.taker_token, + maker_amount: eth::U256::from(limit_order.fillable.maker), + taker_amount: eth::U256::from(limit_order.fillable.taker), + taker_token_fee_amount: eth::U256::from( + limit_order.order.taker_token_fee_amount, + ), }, ) } @@ -326,7 +328,6 @@ pub fn new( .surplus_capturing_jit_order_owners() .iter() .cloned() - .map(Into::into) .collect::>(), } } @@ -359,7 +360,7 @@ fn fee_policy_from_domain(value: fees::FeePolicy) -> solvers_dto::auction::FeePo fn interaction_from_domain(value: eth::Interaction) -> solvers_dto::auction::InteractionData { solvers_dto::auction::InteractionData { - target: value.target.0, + target: value.target, value: value.value.0, call_data: value.call_data.0, } diff --git a/crates/driver/src/infra/solver/dto/notification.rs b/crates/driver/src/infra/solver/dto/notification.rs index 587d5c5c38..eef98a3a9b 100644 --- a/crates/driver/src/infra/solver/dto/notification.rs +++ b/crates/driver/src/infra/solver/dto/notification.rs @@ -1,6 +1,9 @@ -use crate::{ - domain::competition::{auction, solution}, - infra::notify, +use { + crate::{ + domain::competition::{auction, solution}, + infra::notify, + }, + ethrpc::alloy::conversions::IntoLegacy, }; pub fn new( @@ -18,10 +21,10 @@ pub fn new( solvers_dto::notification::Kind::SimulationFailed { block: block.0, tx: solvers_dto::notification::Tx { - from: tx.from.into(), - to: tx.to.into(), + from: tx.from.into_legacy(), + to: tx.to.into_legacy(), input: tx.input.into(), - value: tx.value.into(), + value: tx.value.0.into_legacy(), access_list: tx.access_list.into(), }, succeeded_once, @@ -30,12 +33,15 @@ pub fn new( notify::Kind::ScoringFailed(scoring) => scoring.into(), notify::Kind::NonBufferableTokensUsed(tokens) => { solvers_dto::notification::Kind::NonBufferableTokensUsed { - tokens: tokens.into_iter().map(|token| token.0.0).collect(), + tokens: tokens + .into_iter() + .map(|token| token.0.0.into_legacy()) + .collect(), } } notify::Kind::SolverAccountInsufficientBalance(required) => { solvers_dto::notification::Kind::SolverAccountInsufficientBalance { - required: required.0, + required: required.0.into_legacy(), } } notify::Kind::DuplicatedSolutionId => { @@ -94,7 +100,7 @@ impl From for solvers_dto::notification::Kind { } notify::ScoreKind::MissingPrice(token_address) => { solvers_dto::notification::Kind::MissingPrice { - token_address: token_address.into(), + token_address: token_address.0.0.into_legacy(), } } } diff --git a/crates/driver/src/infra/solver/dto/solution.rs b/crates/driver/src/infra/solver/dto/solution.rs index 691e25cc46..86b589e0f5 100644 --- a/crates/driver/src/infra/solver/dto/solution.rs +++ b/crates/driver/src/infra/solver/dto/solution.rs @@ -9,7 +9,7 @@ use { util::Bytes, }, app_data::AppDataHash, - ethrpc::alloy::conversions::{IntoAlloy, IntoLegacy}, + ethrpc::alloy::conversions::IntoLegacy, itertools::Itertools, model::{ DomainSeparator, @@ -79,7 +79,7 @@ impl Solutions { amount: jit_order.0.buy_amount.into(), token: jit_order.0.buy_token.into(), }, - receiver: jit_order.0.receiver.into(), + receiver: jit_order.0.receiver, partially_fillable: jit_order.0.partially_fillable, valid_to: jit_order.0.valid_to.into(), app_data: jit_order.0.app_data.into(), @@ -126,7 +126,7 @@ impl Solutions { .pre_interactions .into_iter() .map(|interaction| eth::Interaction { - target: interaction.target.into(), + target: interaction.target, value: interaction.value.into(), call_data: Bytes(interaction.calldata), }) @@ -147,8 +147,8 @@ impl Solutions { .map(|allowance| { eth::Allowance { token: allowance.token.into(), - spender: allowance.spender.into(), - amount: allowance.amount.into_alloy(), + spender: allowance.spender, + amount: allowance.amount, } .into() }) @@ -203,14 +203,14 @@ impl Solutions { .post_interactions .into_iter() .map(|interaction| eth::Interaction { - target: interaction.target.into(), + target: interaction.target, value: interaction.value.into(), call_data: Bytes(interaction.calldata), }) .collect(), solver.clone(), weth, - solution.gas.map(|gas| eth::Gas(gas.into())), + solution.gas.map(eth::Gas::from), solver.config().fee_handler, auction.surplus_capturing_jit_order_owners(), solution.flashloans @@ -230,7 +230,7 @@ impl Solutions { )) }).collect()), solution.wrappers.iter().cloned().map(|w| WrapperCall { - address: eth::Address(w.address), + address: w.address, data: w.data, }).collect() ) @@ -256,11 +256,11 @@ pub struct JitOrder(solvers_dto::solution::JitOrder); impl JitOrder { fn raw_order_data(&self) -> OrderData { OrderData { - sell_token: self.0.sell_token.into_alloy(), - buy_token: self.0.buy_token.into_alloy(), - receiver: Some(self.0.receiver.into_alloy()), - sell_amount: self.0.sell_amount.into_alloy(), - buy_amount: self.0.buy_amount.into_alloy(), + sell_token: self.0.sell_token, + buy_token: self.0.buy_token, + receiver: Some(self.0.receiver), + sell_amount: self.0.sell_amount, + buy_amount: self.0.buy_amount, valid_to: self.0.valid_to, app_data: AppDataHash(self.0.app_data), fee_amount: alloy::primitives::U256::ZERO, @@ -324,7 +324,7 @@ impl JitOrder { signature.data = Bytes(self.0.signature[20..].to_vec()); } - signature.signer = signer.into_legacy().into(); + signature.signer = signer; Ok(signature) } @@ -333,7 +333,7 @@ impl JitOrder { let order_data = self.raw_order_data(); let signature = self.signature(domain)?; Ok(order_data - .uid(&DomainSeparator(domain.0), &signature.signer.into()) + .uid(&DomainSeparator(domain.0), &signature.signer.into_legacy()) .0 .into()) } diff --git a/crates/driver/src/infra/solver/mod.rs b/crates/driver/src/infra/solver/mod.rs index 3c526f2cfa..dbfbddcfd3 100644 --- a/crates/driver/src/infra/solver/mod.rs +++ b/crates/driver/src/infra/solver/mod.rs @@ -22,7 +22,7 @@ use { }, anyhow::Result, derive_more::{From, Into}, - ethrpc::alloy::conversions::IntoLegacy, + ethrpc::alloy::conversions::IntoAlloy, num::BigRational, observe::tracing::tracing_headers, reqwest::header::HeaderName, @@ -190,7 +190,7 @@ impl Solver { /// The blockchain address of this solver. pub fn address(&self) -> eth::Address { - self.config.account.address().into() + self.config.account.address().into_alloy() } /// The account which should be used to sign settlements for this solver. @@ -334,11 +334,11 @@ impl Solver { .flat_map(|order| { let hint = order.app_data.flashloan()?; let flashloan = eth::Flashloan { - liquidity_provider: hint.liquidity_provider.into_legacy().into(), - protocol_adapter: hint.protocol_adapter.into_legacy().into(), - receiver: hint.receiver.into_legacy().into(), - token: hint.token.into_legacy().into(), - amount: hint.amount.into_legacy().into(), + liquidity_provider: hint.liquidity_provider.into(), + protocol_adapter: hint.protocol_adapter.into(), + receiver: hint.receiver, + token: hint.token.into(), + amount: hint.amount.into(), }; Some((order.uid, flashloan)) }) @@ -357,7 +357,7 @@ impl Solver { let wrapper_calls = wrappers .iter() .map(|w| solvers_dto::auction::WrapperCall { - address: w.address.into_legacy(), + address: w.address, data: w.data.clone(), is_omittable: w.is_omittable, }) diff --git a/crates/driver/src/infra/tokens.rs b/crates/driver/src/infra/tokens.rs index 376b581c46..8eecd71d70 100644 --- a/crates/driver/src/infra/tokens.rs +++ b/crates/driver/src/infra/tokens.rs @@ -4,10 +4,7 @@ use { infra::{Ethereum, blockchain}, }, anyhow::Result, - ethrpc::{ - alloy::conversions::{IntoAlloy, IntoLegacy}, - block_stream::{self, CurrentBlockWatcher}, - }, + ethrpc::block_stream::{self, CurrentBlockWatcher}, futures::{FutureExt, StreamExt}, itertools::Itertools, model::order::BUY_ETH_ADDRESS, @@ -75,13 +72,7 @@ async fn update_task(blocks: CurrentBlockWatcher, inner: std::sync::Weak) /// Updates the settlement contract's balance for every cached token. async fn update_balances(inner: Arc) -> Result<(), blockchain::Error> { - let settlement = inner - .eth - .contracts() - .settlement() - .address() - .into_legacy() - .into(); + let settlement = *inner.eth.contracts().settlement().address(); let futures = { let cache = inner.cache.read().unwrap(); let tokens = cache.keys().cloned().collect::>(); @@ -141,13 +132,7 @@ impl Inner { &self, tokens: &[eth::TokenAddress], ) -> Vec> { - let settlement = self - .eth - .contracts() - .settlement() - .address() - .into_legacy() - .into(); + let settlement = *self.eth.contracts().settlement().address(); let futures = tokens.iter().map(|token| { let build_request = |token: ð::TokenAddress| { let token = self.eth.erc20(*token); @@ -213,7 +198,7 @@ impl Inner { .iter() // BUY_ETH_ADDRESS is just a marker and not a real address. We'll never be able to // fetch data for it so ignore it to avoid taking exclusive locks all the time. - .filter(|address| !cache.contains_key(*address) && address.0.0.into_alloy() != BUY_ETH_ADDRESS) + .filter(|address| !cache.contains_key(*address) && address.0.0 != BUY_ETH_ADDRESS) .cloned() .unique() .collect() diff --git a/crates/driver/src/tests/cases/example_config.rs b/crates/driver/src/tests/cases/example_config.rs index 8035fcdd20..23f5e98149 100644 --- a/crates/driver/src/tests/cases/example_config.rs +++ b/crates/driver/src/tests/cases/example_config.rs @@ -1,4 +1,4 @@ -use {crate::tests, shared::addr}; +use {crate::tests, alloy::primitives::address}; /// Test that the example configuration file is valid by checking that the /// driver does not crash when started with this file. @@ -8,9 +8,9 @@ async fn test() { let example_config_file = std::env::current_dir().unwrap().join("example.toml"); tests::setup() .config(example_config_file) - .settlement_address(&addr!("9008D19f58AAbD9eD0D60971565AA8510560ab41")) - .balances_address(&addr!("3e8C6De9510e7ECad902D005DE3Ab52f35cF4f1b")) - .signatures_address(&addr!("8262d639c38470F38d2eff15926F7071c28057Af")) + .settlement_address(address!("9008D19f58AAbD9eD0D60971565AA8510560ab41")) + .balances_address(address!("3e8C6De9510e7ECad902D005DE3Ab52f35cF4f1b")) + .signatures_address(address!("8262d639c38470F38d2eff15926F7071c28057Af")) .done() .await; } diff --git a/crates/driver/src/tests/cases/fees.rs b/crates/driver/src/tests/cases/fees.rs index 8b511cbf39..fe9b3d7cff 100644 --- a/crates/driver/src/tests/cases/fees.rs +++ b/crates/driver/src/tests/cases/fees.rs @@ -1,5 +1,5 @@ use crate::{ - domain::competition::order, + domain::{competition::order, eth}, infra::config::file::FeeHandler, tests::{ self, @@ -14,7 +14,7 @@ async fn solver_fee() { let order = ab_order() .kind(order::Kind::Limit) .side(side) - .solver_fee(Some(500.into())); + .solver_fee(Some(eth::U256::from(500))); let test = tests::setup() .name(format!("Solver Fee: {side:?}")) .solvers(vec![test_solver().fee_handler(FeeHandler::Driver)]) diff --git a/crates/driver/src/tests/cases/flashloan_hints.rs b/crates/driver/src/tests/cases/flashloan_hints.rs index cdb2fa6440..6b1a0a4923 100644 --- a/crates/driver/src/tests/cases/flashloan_hints.rs +++ b/crates/driver/src/tests/cases/flashloan_hints.rs @@ -8,8 +8,6 @@ use { }, alloy::primitives::Address, app_data::{Flashloan, ProtocolAppData, hash_full_app_data}, - ethrpc::alloy::conversions::IntoLegacy, - primitive_types::H160, std::sync::Arc, }; @@ -31,11 +29,11 @@ async fn solutions_with_flashloan() { protocol_app_data, ))); - let settlement = H160([5; 20]); + let settlement = Address::repeat_byte(5); let order = ab_order().app_data(app_data).receiver(Some(settlement)); let test = setup() - .settlement_address(&settlement) + .settlement_address(settlement) .pool(ab_pool()) .order(order.clone()) // This test is just about parsing the request JSON bodies so we don't care @@ -67,11 +65,11 @@ async fn solutions_without_flashloan() { let app_data = AppData::Full(Arc::new(protocol_app_data_into_validated( protocol_app_data, ))); - let settlement = H160([5; 20]); + let settlement = Address::repeat_byte(5); let order = ab_order().app_data(app_data).receiver(Some(settlement)); let test = setup() - .settlement_address(&settlement) + .settlement_address(settlement) .pool(ab_pool()) .order(order.clone()) .solution(ab_solution()) @@ -98,10 +96,10 @@ fn protocol_app_data_into_validated(protocol: ProtocolAppData) -> app_data::Vali fn flashloan_into_dto(flashloan: Flashloan) -> solvers_dto::solution::Flashloan { solvers_dto::solution::Flashloan { - liquidity_provider: flashloan.liquidity_provider.into_legacy(), - protocol_adapter: flashloan.protocol_adapter.into_legacy(), - receiver: flashloan.receiver.into_legacy(), - token: flashloan.token.into_legacy(), - amount: flashloan.amount.into_legacy(), + liquidity_provider: flashloan.liquidity_provider, + protocol_adapter: flashloan.protocol_adapter, + receiver: flashloan.receiver, + token: flashloan.token, + amount: flashloan.amount, } } diff --git a/crates/driver/src/tests/cases/jit_orders.rs b/crates/driver/src/tests/cases/jit_orders.rs index 10b8f403e6..66a7e44782 100644 --- a/crates/driver/src/tests/cases/jit_orders.rs +++ b/crates/driver/src/tests/cases/jit_orders.rs @@ -62,7 +62,7 @@ async fn protocol_fee_test_case(test_case: TestCase) { .sell_amount(test_case.execution.solver.sell) .buy_amount(test_case.execution.solver.buy); let pool = ab_adjusted_pool(quote); - let solver_fee = test_case.execution.driver.sell / 100; + let solver_fee = test_case.execution.driver.sell / eth::U256::from(100); // Amounts expected to be returned by the driver after fee processing let jit_order_expected_amounts = if test_case.is_surplus_capturing_jit_order { ExpectedOrderAmounts { @@ -93,7 +93,7 @@ async fn protocol_fee_test_case(test_case: TestCase) { .buy_amount(test_case.order.buy_amount) .solver_fee(Some(solver_fee)) .side(test_case.order.side) - .partial(0.into()) + .partial(eth::U256::ZERO) .no_surplus(); let solver = test_solver(); diff --git a/crates/driver/src/tests/cases/order_prioritization.rs b/crates/driver/src/tests/cases/order_prioritization.rs index 302f8e2114..792bc1661f 100644 --- a/crates/driver/src/tests/cases/order_prioritization.rs +++ b/crates/driver/src/tests/cases/order_prioritization.rs @@ -6,6 +6,7 @@ use { setup::{Order, OrderQuote, ab_order, ab_pool, ab_solution, setup, test_solver}, }, }, + alloy::primitives::U256, chrono::Utc, std::time::Duration, }; @@ -264,7 +265,7 @@ async fn filtering() { .order( Order { sell_amount: "4999999999900.002".ether().into_wei(), - surplus_factor: 1.into(), + surplus_factor: U256::ONE, ..ab_order() } .rename("fourth order") diff --git a/crates/driver/src/tests/cases/protocol_fees.rs b/crates/driver/src/tests/cases/protocol_fees.rs index 9c17eefcdf..dbcbbddfb3 100644 --- a/crates/driver/src/tests/cases/protocol_fees.rs +++ b/crates/driver/src/tests/cases/protocol_fees.rs @@ -55,7 +55,7 @@ async fn protocol_fee_test_case(test_case: TestCase) { .sell_amount(test_case.execution.solver.sell) .buy_amount(test_case.execution.solver.buy); let pool = ab_adjusted_pool(quote); - let solver_fee = test_case.execution.driver.sell / 100; + let solver_fee = test_case.execution.driver.sell / eth::U256::from(100); let executed = match test_case.order.side { order::Side::Buy => (test_case.order.buy_amount > test_case.execution.solver.buy) .then_some(test_case.execution.solver.buy), @@ -79,7 +79,7 @@ async fn protocol_fee_test_case(test_case: TestCase) { .side(test_case.order.side) .fee_policy(test_case.fee_policy) .executed(executed) - .partial(0.into()) + .partial(eth::U256::ZERO) // Surplus is configured explicitly via executed/quoted amounts .no_surplus() .expected_amounts(expected_amounts); diff --git a/crates/driver/src/tests/cases/solver_balance.rs b/crates/driver/src/tests/cases/solver_balance.rs index 2802327467..7bf57129a6 100644 --- a/crates/driver/src/tests/cases/solver_balance.rs +++ b/crates/driver/src/tests/cases/solver_balance.rs @@ -15,7 +15,7 @@ async fn test_unfunded() { .order(ab_order()) .solution(ab_solution()) .solvers(vec![ - test_solver().name("unfunded").balance(eth::U256::zero()), + test_solver().name("unfunded").balance(eth::U256::ZERO), ]) .done() .await; @@ -38,7 +38,7 @@ async fn test_just_enough_funded() { .name("barely_funded") // The solution uses ~500k gas units // With gas costs <20gwei, 0.01 ETH should suffice - .balance(eth::U256::exp10(16)), + .balance(eth::U256::from(10).pow(eth::U256::from(16))), ]) .done() .await; diff --git a/crates/driver/src/tests/mod.rs b/crates/driver/src/tests/mod.rs index 80718b9ed7..792e663a48 100644 --- a/crates/driver/src/tests/mod.rs +++ b/crates/driver/src/tests/mod.rs @@ -3,7 +3,3 @@ mod cases; mod setup; pub use setup::setup; - -fn hex_address(value: ethcontract::H160) -> String { - const_hex::encode_prefixed(value.as_bytes()) -} diff --git a/crates/driver/src/tests/setup/blockchain.rs b/crates/driver/src/tests/setup/blockchain.rs index 615d2413b8..9668034b64 100644 --- a/crates/driver/src/tests/setup/blockchain.rs +++ b/crates/driver/src/tests/setup/blockchain.rs @@ -70,7 +70,7 @@ pub struct Blockchain { #[derive(Debug, Clone, PartialEq)] pub struct Interaction { - pub address: ethcontract::H160, + pub address: eth::Address, pub calldata: Vec, pub inputs: Vec, pub outputs: Vec, @@ -108,7 +108,7 @@ impl Pool { ((input_reserve * output.amount * eth::U256::from(1000)) / ((output_reserve - output.amount) * eth::U256::from(997))) - + 1 + + eth::U256::ONE } } @@ -200,11 +200,11 @@ impl QuotedOrder { 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(), - sell_amount: self.sell_amount(), - buy_amount: self.buy_amount(), + sell_amount: self.sell_amount().into_legacy(), + buy_amount: self.buy_amount().into_legacy(), valid_to: self.order.valid_to, - receiver: self.order.receiver, - user_fee: self.order.fee_amount, + receiver: self.order.receiver.map(IntoLegacy::into_legacy), + user_fee: self.order.fee_amount.into_legacy(), side: self.order.side, secret_key, domain_separator: blockchain.domain_separator, @@ -219,9 +219,9 @@ pub struct Config { // Main trader secret key (the account deploying the contracts) pub main_trader_secret_key: SecretKey, pub solvers: Vec, - pub settlement_address: Option, - pub balances_address: Option, - pub signatures_address: Option, + pub settlement_address: Option, + pub balances_address: Option, + pub signatures_address: Option, pub rpc_args: Vec, } @@ -335,7 +335,7 @@ impl Blockchain { for i in 0..code.len() - 20 { let window = &mut code[i..][..20]; if window == settlement.address().as_slice() { - window.copy_from_slice(&settlement_address.0); + window.copy_from_slice(settlement_address.as_slice()); } } code @@ -347,17 +347,15 @@ impl Blockchain { .unwrap() .0; - set_code(&web3, vault_relayer.into_legacy(), &vault_relayer_code).await; + set_code(&web3, vault_relayer, &vault_relayer_code).await; set_code(&web3, settlement_address, &settlement_code).await; - settlement = GPv2Settlement::GPv2Settlement::new( - settlement_address.into_alloy(), - web3.alloy.clone(), - ); + settlement = + GPv2Settlement::GPv2Settlement::new(settlement_address, web3.alloy.clone()); } let balances_address = match config.balances_address { - Some(balances_address) => balances_address.into_alloy(), + Some(balances_address) => balances_address, None => Balances::Instance::deploy_builder(web3.alloy.clone()) .from(main_trader_account.address().into_alloy()) .deploy() @@ -374,7 +372,7 @@ impl Blockchain { .unwrap(); let signatures_address = if let Some(signatures_address) = config.signatures_address { - signatures_address.into_alloy() + signatures_address } else { Signatures::Instance::deploy_builder(web3.alloy.clone()) .from(main_trader_account.address().into_alloy()) @@ -396,7 +394,7 @@ impl Blockchain { let mut trader_accounts = Vec::new(); for config in config.solvers { authenticator - .addSolver(config.address().into_alloy()) + .addSolver(config.address()) .from(main_trader_account.address().into_alloy()) .send_and_watch() .await @@ -406,8 +404,8 @@ impl Blockchain { web3.eth() .send_transaction(web3::types::TransactionRequest { from: primary_address, - to: Some(config.address()), - value: Some(config.balance), + to: Some(config.address().into_legacy()), + value: Some(config.balance.into_legacy()), ..Default::default() }), ) @@ -495,25 +493,22 @@ impl Blockchain { pool: pool.to_owned(), }); if pool.reserve_a.token == "WETH" { - weth.transfer(*pair.address(), pool.reserve_a.amount.into_alloy()) + weth.transfer(*pair.address(), pool.reserve_a.amount) .from(primary_address.into_alloy()) .send_and_watch() .await .unwrap(); - weth.transfer(*settlement.address(), pool.reserve_a.amount.into_alloy()) + weth.transfer(*settlement.address(), pool.reserve_a.amount) .from(primary_address.into_alloy()) .send_and_watch() .await .unwrap(); for trader_account in trader_accounts.iter() { - weth.transfer( - trader_account.address().into_alloy(), - pool.reserve_a.amount.into_alloy(), - ) - .from(primary_address.into_alloy()) - .send_and_watch() - .await - .unwrap(); + weth.transfer(trader_account.address().into_alloy(), pool.reserve_a.amount) + .from(primary_address.into_alloy()) + .send_and_watch() + .await + .unwrap(); } } else { for trader_account in trader_accounts.iter() { @@ -532,7 +527,7 @@ impl Blockchain { tokens .get(pool.reserve_a.token) .unwrap() - .mint(*pair.address(), pool.reserve_a.amount.into_alloy()) + .mint(*pair.address(), pool.reserve_a.amount) .from(main_trader_account.address().into_alloy()) .send_and_watch() .await @@ -541,7 +536,7 @@ impl Blockchain { tokens .get(pool.reserve_a.token) .unwrap() - .mint(*settlement.address(), pool.reserve_a.amount.into_alloy()) + .mint(*settlement.address(), pool.reserve_a.amount) .from(main_trader_account.address().into_alloy()) .send_and_watch() .await @@ -551,10 +546,7 @@ impl Blockchain { tokens .get(pool.reserve_a.token) .unwrap() - .mint( - trader_account.address().into_alloy(), - pool.reserve_a.amount.into_alloy(), - ) + .mint(trader_account.address().into_alloy(), pool.reserve_a.amount) .from(main_trader_account.address().into_alloy()) .send_and_watch() .await @@ -562,25 +554,22 @@ impl Blockchain { } } if pool.reserve_b.token == "WETH" { - weth.transfer(*pair.address(), pool.reserve_b.amount.into_alloy()) + weth.transfer(*pair.address(), pool.reserve_b.amount) .from(primary_address.into_alloy()) .send_and_watch() .await .unwrap(); - weth.transfer(*settlement.address(), pool.reserve_b.amount.into_alloy()) + weth.transfer(*settlement.address(), pool.reserve_b.amount) .from(primary_address.into_alloy()) .send_and_watch() .await .unwrap(); for trader_account in trader_accounts.iter() { - weth.transfer( - trader_account.address().into_alloy(), - pool.reserve_b.amount.into_alloy(), - ) - .from(primary_address.into_alloy()) - .send_and_watch() - .await - .unwrap(); + weth.transfer(trader_account.address().into_alloy(), pool.reserve_b.amount) + .from(primary_address.into_alloy()) + .send_and_watch() + .await + .unwrap(); } } else { for trader_account in trader_accounts.iter() { @@ -599,7 +588,7 @@ impl Blockchain { tokens .get(pool.reserve_b.token) .unwrap() - .mint(*pair.address(), pool.reserve_b.amount.into_alloy()) + .mint(*pair.address(), pool.reserve_b.amount) .from(main_trader_account.address().into_alloy()) .send_and_watch() .await @@ -608,7 +597,7 @@ impl Blockchain { tokens .get(pool.reserve_b.token) .unwrap() - .mint(*settlement.address(), pool.reserve_b.amount.into_alloy()) + .mint(*settlement.address(), pool.reserve_b.amount) .from(main_trader_account.address().into_alloy()) .send_and_watch() .await @@ -617,10 +606,7 @@ impl Blockchain { tokens .get(pool.reserve_b.token) .unwrap() - .mint( - trader_account.address().into_alloy(), - pool.reserve_b.amount.into_alloy(), - ) + .mint(trader_account.address().into_alloy(), pool.reserve_b.amount) .from(main_trader_account.address().into_alloy()) .send_and_watch() .await @@ -778,7 +764,7 @@ impl Blockchain { .unwrap() .mint( trader_account.address().into_alloy(), - ("1e-7".ether().into_wei() * execution.sell).into_alloy(), + "1e-7".ether().into_wei() * execution.sell, ) .from(trader_account.address().into_alloy()) .send_and_watch() @@ -801,14 +787,14 @@ impl Blockchain { // Create the interactions fulfilling the order. let transfer_interaction = ERC20::ERC20::transferCall { recipient: *pair.contract.address(), - amount: execution.sell.into_alloy(), + amount: execution.sell, } .abi_encode(); let (amount_a_out, amount_b_out) = if pair.token_a == order.sell_token { - (0.into(), execution.buy) + (eth::U256::ZERO, execution.buy) } else { // Surplus fees stay in the contract. - (execution.sell - order.surplus_fee(), 0.into()) + (execution.sell - order.surplus_fee(), eth::U256::ZERO) }; let (amount_0_out, amount_1_out) = if self.get_token(pair.token_a) < self.get_token(pair.token_b) { @@ -819,8 +805,8 @@ impl Blockchain { let swap_interaction = pair .contract .swap( - amount_0_out.into_alloy(), - amount_1_out.into_alloy(), + amount_0_out, + amount_1_out, *self.settlement.address(), Default::default(), ) @@ -831,7 +817,7 @@ impl Blockchain { execution: execution.clone(), interactions: vec![ Interaction { - address: sell_token.address().into_legacy(), + address: *sell_token.address(), calldata: match solution.calldata { super::Calldata::Valid { additional_bytes } => transfer_interaction .into_iter() @@ -844,7 +830,7 @@ impl Blockchain { internalize: false, }, Interaction { - address: pair.contract.address().into_legacy(), + address: *pair.contract.address(), calldata: match solution.calldata { super::Calldata::Valid { .. } => swap_interaction, super::Calldata::Invalid => { @@ -852,12 +838,12 @@ impl Blockchain { } }, inputs: vec![eth::Asset { - token: sell_token.address().into_legacy().into(), + token: (*sell_token.address()).into(), // Surplus fees stay in the contract. amount: (execution.sell - order.surplus_fee()).into(), }], outputs: vec![eth::Asset { - token: buy_token.address().into_legacy().into(), + token: (*buy_token.address()).into(), amount: execution.buy.into(), }], internalize: order.internalize, @@ -872,7 +858,7 @@ impl Blockchain { pub fn get_token(&self, token: &str) -> Address { match token { "WETH" => *self.weth.address(), - "ETH" => eth::ETH_TOKEN.0.0.into_alloy(), + "ETH" => eth::ETH_TOKEN.0.0, _ => *self.tokens.get(token).unwrap().address(), } } @@ -1016,7 +1002,7 @@ pub async fn wait_for_block(web3: &Web3, block: u64) { } /// Sets code at a specific address for testing. -pub async fn set_code(web3: &Web3, address: eth::H160, code: &[u8]) { +pub async fn set_code(web3: &Web3, address: eth::Address, code: &[u8]) { use web3::Transport; web3.transport() diff --git a/crates/driver/src/tests/setup/driver.rs b/crates/driver/src/tests/setup/driver.rs index f32085f389..b0094ca057 100644 --- a/crates/driver/src/tests/setup/driver.rs +++ b/crates/driver/src/tests/setup/driver.rs @@ -3,13 +3,9 @@ use { crate::{ domain::competition::order, infra::config::file::OrderPriorityStrategy, - tests::{ - hex_address, - setup::{blockchain::Trade, orderbook::Orderbook}, - }, + tests::setup::{blockchain::Trade, orderbook::Orderbook}, }, const_hex::ToHexExt, - ethrpc::alloy::conversions::IntoLegacy, rand::seq::SliceRandom, serde_json::json, std::{io::Write, net::SocketAddr, path::PathBuf}, @@ -99,7 +95,7 @@ pub fn solve_req(test: &Test) -> serde_json::Value { order::Side::Sell => "sell", order::Side::Buy => "buy", }, - "owner": hex_address(test.trader_address), + "owner": (test.trader_address.encode_hex_with_prefix()), "partiallyFillable": matches!(quote.order.partial, Partial::Yes { .. }), "executed": match quote.order.partial { Partial::Yes { executed } => executed.to_string(), @@ -117,7 +113,7 @@ pub fn solve_req(test: &Test) -> serde_json::Value { "quote": quote.order.quote, }); if let Some(receiver) = quote.order.receiver { - order["receiver"] = json!(hex_address(receiver)); + order["receiver"] = json!((receiver.encode_hex_with_prefix())); } orders_json.push(order); } @@ -241,7 +237,7 @@ async fn create_config_file( blockchain.weth.address(), blockchain.balances.address(), blockchain.signatures.address(), - hex_address(blockchain.flashloan_router.address().into_legacy()), + blockchain.flashloan_router.address(), ) .unwrap(); diff --git a/crates/driver/src/tests/setup/fee.rs b/crates/driver/src/tests/setup/fee.rs index 384f2240f1..72f8c3aa86 100644 --- a/crates/driver/src/tests/setup/fee.rs +++ b/crates/driver/src/tests/setup/fee.rs @@ -19,7 +19,7 @@ pub struct Quote { /// additional sell amount. #[serde_as(as = "HexOrDecimalU256")] pub network_fee: eth::U256, - pub solver: eth::H160, + pub solver: eth::Address, } #[serde_as] diff --git a/crates/driver/src/tests/setup/mod.rs b/crates/driver/src/tests/setup/mod.rs index 2e751dfc4e..dbe969f163 100644 --- a/crates/driver/src/tests/setup/mod.rs +++ b/crates/driver/src/tests/setup/mod.rs @@ -37,7 +37,7 @@ use { }, }, }, - alloy::primitives::Address, + alloy::primitives::{Address, U256, address}, bigdecimal::{BigDecimal, FromPrimitive}, ethcontract::dyns::DynTransport, ethrpc::alloy::conversions::{IntoAlloy, IntoLegacy}, @@ -142,8 +142,8 @@ pub struct Order { /// order? True by default. pub funded: bool, pub fee_policy: Vec, - pub owner: H160, - pub receiver: Option, + pub owner: eth::Address, + pub receiver: Option, pub fee_amount: eth::U256, pub sell_token_source: SellTokenSource, pub buy_token_destination: BuyTokenDestination, @@ -178,7 +178,7 @@ impl Order { /// has a negative score. pub fn no_surplus(self) -> Self { Self { - surplus_factor: 1.into(), + surplus_factor: U256::ONE, ..self } } @@ -297,11 +297,11 @@ impl Order { fn surplus_fee(&self) -> eth::U256 { match self.kind { order::Kind::Limit => self.solver_fee.unwrap_or_default(), - _ => 0.into(), + _ => eth::U256::ZERO, } } - pub fn receiver(self, receiver: Option) -> Self { + pub fn receiver(self, receiver: Option) -> Self { Self { receiver, ..self } } } @@ -330,7 +330,7 @@ impl Default for Order { factor: 0.0, max_volume_factor: 0.06, }], - owner: eth::H160::from_str(TRADER_ADDRESS).unwrap(), + owner: TRADER_ADDRESS, receiver: Default::default(), fee_amount: Default::default(), sell_token_source: Default::default(), @@ -370,7 +370,7 @@ struct Slippage { pub fn test_solver() -> Solver { Solver { name: solver::NAME.to_owned(), - balance: eth::U256::exp10(18), + balance: eth::U256::from(10).pow(eth::U256::from(10)), private_key: ethcontract::PrivateKey::from_slice( const_hex::decode("a131a35fb8f614b31611f4fe68b6fc538b0febd2f75cd68e1282d8fd45b63326") .unwrap(), @@ -390,8 +390,8 @@ pub fn test_solver() -> Solver { } impl Solver { - pub fn address(&self) -> eth::H160 { - self.private_key.public_address() + pub fn address(&self) -> eth::Address { + self.private_key.public_address().into_alloy() } pub fn name(self, name: &str) -> Self { @@ -509,11 +509,11 @@ pub struct Setup { /// Should simulation be enabled? True by default. enable_simulation: bool, /// Ensure the settlement contract is deployed on a specific address? - settlement_address: Option, + settlement_address: Option, /// Ensure the Balances contract is deployed on a specific address? - balances_address: Option, + balances_address: Option, /// Ensure the Signatures contract is deployed on a specific address? - signatures_address: Option, + signatures_address: Option, /// Via which mempool the solutions should be submitted mempools: Vec, /// Extra configuration for the RPC node @@ -521,7 +521,7 @@ pub struct Setup { /// List of jit orders returned by the solver jit_orders: Vec, /// List of surplus capturing JIT-order owners - surplus_capturing_jit_order_owners: Vec, + surplus_capturing_jit_order_owners: Vec, /// In case your test requires multiple `/solve` requests allow_multiple_solve_requests: bool, /// Auction ID used during tests @@ -750,7 +750,7 @@ pub fn eth_solution() -> Solution { } // Hardcoded trader account. Don't use this account for anything else!!! -pub const TRADER_ADDRESS: &str = "d2525C68A663295BBE347B65C87c8e17De936a0a"; +pub const TRADER_ADDRESS: Address = address!("d2525C68A663295BBE347B65C87c8e17De936a0a"); impl Setup { /// Set an explicit name for this test. If a name is set, it will be logged @@ -815,20 +815,20 @@ impl Setup { } /// Ensure that the settlement contract is deployed to a specific address. - pub fn settlement_address(mut self, address: &H160) -> Self { - self.settlement_address = Some(*address); + pub fn settlement_address(mut self, address: Address) -> Self { + self.settlement_address = Some(address); self } /// Ensure that the Balances contract is deployed to a specific address - pub fn balances_address(mut self, address: &H160) -> Self { - self.balances_address = Some(*address); + pub fn balances_address(mut self, address: Address) -> Self { + self.balances_address = Some(address); self } /// Ensure that the Signatures contract is deployed to a specific address. - pub fn signatures_address(mut self, address: &H160) -> Self { - self.signatures_address = Some(*address); + pub fn signatures_address(mut self, address: Address) -> Self { + self.signatures_address = Some(address); self } @@ -844,7 +844,7 @@ impl Setup { pub fn surplus_capturing_jit_order_owners( mut self, - surplus_capturing_jit_order_owners: Vec, + surplus_capturing_jit_order_owners: Vec
, ) -> Self { self.surplus_capturing_jit_order_owners .extend(surplus_capturing_jit_order_owners); @@ -892,7 +892,7 @@ impl Setup { } = self; // Hardcoded trader account. Don't use this account for anything else!!! - let trader_address = eth::H160::from_str(TRADER_ADDRESS).unwrap(); + let trader_address = TRADER_ADDRESS; let trader_secret_key = SecretKey::from_slice( &const_hex::decode("f9f831cee763ef826b8d45557f0f8677b27045e0e011bcd78571a40acc8a6cc3") .unwrap(), @@ -1028,7 +1028,7 @@ pub struct Test { blockchain: Blockchain, driver: Driver, client: reqwest::Client, - trader_address: eth::H160, + trader_address: eth::Address, trades: Vec, trusted: HashSet<&'static str>, deadline: chrono::DateTime, @@ -1036,7 +1036,7 @@ pub struct Test { /// Is this testing the /quote endpoint? quote: bool, /// List of surplus capturing JIT-order owners - surplus_capturing_jit_order_owners: Vec, + surplus_capturing_jit_order_owners: Vec, auction_id: i64, } @@ -1158,30 +1158,29 @@ impl Test { let mut balances = HashMap::new(); for (token, contract) in self.blockchain.tokens.iter() { let balance = contract - .balanceOf(self.trader_address.into_alloy()) + .balanceOf(self.trader_address) .call() .await - .unwrap() - .into_legacy(); + .unwrap(); balances.insert(*token, balance); } balances.insert( "WETH", self.blockchain .weth - .balanceOf(self.trader_address.into_alloy()) + .balanceOf(self.trader_address) .call() .await - .unwrap() - .into_legacy(), + .unwrap(), ); balances.insert( "ETH", self.blockchain .web3 .eth() - .balance(self.trader_address, None) + .balance(self.trader_address.into_legacy(), None) .await + .map(IntoAlloy::into_alloy) .unwrap(), ); balances @@ -1275,7 +1274,7 @@ impl SolveOk<'_> { let solution = self.solution(); assert!(solution.get("score").is_some()); let score = solution.get("score").unwrap().as_str().unwrap(); - eth::U256::from_dec_str(score).unwrap() + eth::U256::from_str_radix(score, 10).unwrap() } /// Ensures that `/solve` returns no solutions. @@ -1306,8 +1305,9 @@ impl SolveOk<'_> { /// Find for a JIT order, given specific token pair and buy/sell amount, /// return true if the JIT order was found fn trade_matches(&self, trade: &serde_json::Value, expected: &JitOrder) -> bool { - let u256 = - |value: &serde_json::Value| eth::U256::from_dec_str(value.as_str().unwrap()).unwrap(); + let u256 = |value: &serde_json::Value| { + eth::U256::from_str_radix(value.as_str().unwrap(), 10).unwrap() + }; let sell_token = Address::deserialize(trade.get("sellToken").unwrap().into_deserializer()).unwrap(); let buy_token = @@ -1352,7 +1352,7 @@ impl SolveOk<'_> { .get(&uid.to_string()) .expect("Didn't find expected trade in solution"); let u256 = |value: &serde_json::Value| { - eth::U256::from_dec_str(value.as_str().unwrap()).unwrap() + eth::U256::from_str_radix(value.as_str().unwrap(), 10).unwrap() }; let (expected_sell, expected_buy) = match &expected.expected_amounts { @@ -1622,11 +1622,11 @@ pub struct OrderQuote { pub buy_amount: eth::U256, #[serde_as(as = "HexOrDecimalU256")] pub fee: eth::U256, - pub solver: eth::H160, + pub solver: eth::Address, } impl OrderQuote { - pub fn solver(self, solver: eth::H160) -> Self { + pub fn solver(self, solver: eth::Address) -> Self { Self { solver, ..self } } } diff --git a/crates/driver/src/tests/setup/solver.rs b/crates/driver/src/tests/setup/solver.rs index fb1eea74a5..2b560096a5 100644 --- a/crates/driver/src/tests/setup/solver.rs +++ b/crates/driver/src/tests/setup/solver.rs @@ -11,12 +11,12 @@ use { time::{self}, }, infra::{self, Ethereum, blockchain::contracts::Addresses, config::file::FeeHandler}, - tests::{hex_address, setup::blockchain::Trade}, + tests::setup::blockchain::Trade, }, + alloy::primitives::Address, const_hex::ToHexExt, contracts::alloy::ERC20, - ethereum_types::H160, - ethrpc::alloy::conversions::IntoLegacy, + ethrpc::alloy::conversions::IntoAlloy, itertools::Itertools, serde_json::json, solvers_dto::auction::FlashloanHint, @@ -45,7 +45,7 @@ pub struct Config<'a> { pub quote: bool, pub fee_handler: FeeHandler, pub private_key: ethcontract::PrivateKey, - pub expected_surplus_capturing_jit_order_owners: Vec, + pub expected_surplus_capturing_jit_order_owners: Vec
, pub allow_multiple_solve_requests: bool, } @@ -131,7 +131,7 @@ impl Solver { "buyAmount": buy_amount, "fullBuyAmount": if config.quote { buy_amount } else { quote.buy_amount().to_string() }, "validTo": quote.order.valid_to, - "owner": if config.quote { H160::zero() } else { quote.order.owner }, + "owner": if config.quote { eth::Address::ZERO } else { quote.order.owner }, "preInteractions": json!([]), "postInteractions": json!([]), "sellTokenSource": quote.order.sell_token_source, @@ -151,15 +151,15 @@ impl Solver { "signingScheme": if config.quote { "eip1271" } else { "eip712" }, }); if let Some(receiver) = quote.order.receiver { - order["receiver"] = json!(hex_address(receiver)); + order["receiver"] = json!(receiver.encode_hex_with_prefix()); } if let Some(flashloan) = quote.order.app_data.flashloan() { order["flashloanHint"] = json!(FlashloanHint { - liquidity_provider: flashloan.liquidity_provider.into_legacy(), - protocol_adapter: flashloan.protocol_adapter.into_legacy(), - receiver: flashloan.receiver.into_legacy(), - token: flashloan.token.into_legacy(), - amount: flashloan.amount.into_legacy(), + liquidity_provider: flashloan.liquidity_provider, + protocol_adapter: flashloan.protocol_adapter, + receiver: flashloan.receiver, + token: flashloan.token, + amount: flashloan.amount, }); } if config.fee_handler == FeeHandler::Solver { @@ -195,19 +195,19 @@ impl Solver { json!({ "kind": "custom", "internalize": interaction.internalize, - "target": hex_address(interaction.address), + "target": interaction.address.encode_hex_with_prefix(), "value": "0", "callData": const_hex::encode_prefixed(&interaction.calldata), "allowances": [], "inputs": interaction.inputs.iter().map(|input| { json!({ - "token": hex_address(input.token.into()), + "token": eth::Address::from(input.token).encode_hex_with_prefix(), "amount": input.amount.to_string(), }) }).collect_vec(), "outputs": interaction.outputs.iter().map(|output| { json!({ - "token": hex_address(output.token.into()), + "token": eth::Address::from(output.token).encode_hex_with_prefix(), "amount": output.amount.to_string(), }) }).collect_vec(), @@ -275,19 +275,19 @@ impl Solver { json!({ "kind": "custom", "internalize": interaction.internalize, - "target": hex_address(interaction.address), + "target": interaction.address.encode_hex_with_prefix(), "value": "0", "callData": const_hex::encode_prefixed(&interaction.calldata), "allowances": [], "inputs": interaction.inputs.iter().map(|input| { json!({ - "token": hex_address(input.token.into()), + "token": eth::Address::from(input.token).encode_hex_with_prefix(), "amount": input.amount.to_string(), }) }).collect_vec(), "outputs": interaction.outputs.iter().map(|output| { json!({ - "token": hex_address(output.token.into()), + "token": eth::Address::from(output.token).encode_hex_with_prefix(), "amount": output.amount.to_string(), }) }).collect_vec(), @@ -298,19 +298,19 @@ impl Solver { json!({ "kind": "custom", "internalize": interaction.internalize, - "target": hex_address(interaction.address), + "target": interaction.address.encode_hex_with_prefix(), "value": "0", "callData": const_hex::encode_prefixed(&interaction.calldata), "allowances": [], "inputs": interaction.inputs.iter().map(|input| { json!({ - "token": hex_address(input.token.into()), + "token": eth::Address::from(input.token).encode_hex_with_prefix(), "amount": input.amount.to_string(), }) }).collect_vec(), "outputs": interaction.outputs.iter().map(|output| { json!({ - "token": hex_address(output.token.into()), + "token": eth::Address::from(output.token).encode_hex_with_prefix(), "amount": output.amount.to_string(), }) }).collect_vec(), @@ -351,12 +351,12 @@ impl Solver { jit.quoted_order.order = jit .quoted_order .order - .receiver(Some(config.private_key.address())); + .receiver(Some(config.private_key.address().into_alloy())); 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), "buyToken": config.blockchain.get_token(jit.quoted_order.order.buy_token), - "receiver": hex_address(jit.quoted_order.order.receiver.unwrap_or_default()), + "receiver": jit.quoted_order.order.receiver.unwrap_or_default().encode_hex_with_prefix(), "sellAmount": jit.quoted_order.order.sell_amount.to_string(), "buyAmount": jit.quoted_order.order.buy_amount.unwrap_or_default().to_string(), "validTo": jit.quoted_order.order.valid_to, @@ -458,7 +458,7 @@ impl Solver { target_confirm_time: Default::default(), retry_interval: Default::default(), kind: infra::mempool::Kind::Public { - max_additional_tip: 0.into(), + max_additional_tip: eth::U256::ZERO, additional_tip_percentage: 0., revert_protection: infra::mempool::RevertProtection::Disabled, }, @@ -471,22 +471,15 @@ impl Solver { let eth = Ethereum::new( rpc, Addresses { - settlement: Some(config.blockchain.settlement.address().into_legacy().into()), - weth: Some(config.blockchain.weth.address().into_legacy().into()), - balances: Some(config.blockchain.balances.address().into_legacy().into()), - signatures: Some(config.blockchain.signatures.address().into_legacy().into()), + settlement: Some((*config.blockchain.settlement.address()).into()), + weth: Some((*config.blockchain.weth.address()).into()), + balances: Some((*config.blockchain.balances.address()).into()), + signatures: Some((*config.blockchain.signatures.address()).into()), cow_amm_helper_by_factory: Default::default(), - flashloan_router: Some( - config - .blockchain - .flashloan_router - .address() - .into_legacy() - .into(), - ), + flashloan_router: Some((*config.blockchain.flashloan_router.address()).into()), }, gas, - 45_000_000.into(), + eth::U256::from(45_000_000), &shared::current_block::Arguments { block_stream_poll_interval: None, node_ws_url: Some(config.blockchain.web3_ws_url.parse().unwrap()), diff --git a/crates/driver/src/util/conv/u256.rs b/crates/driver/src/util/conv/u256.rs index b6528ad04f..5836657979 100644 --- a/crates/driver/src/util/conv/u256.rs +++ b/crates/driver/src/util/conv/u256.rs @@ -1,5 +1,8 @@ use {crate::domain::eth, anyhow::Result, bigdecimal::Zero}; +// NOTE(jmg-duarte): ruint has support for num-traits, num-bigint, num-integer +// https://docs.rs/crate/ruint/latest/features + pub trait U256Ext: Sized { fn to_big_int(&self) -> num::BigInt; fn to_big_uint(&self) -> num::BigUint; @@ -20,9 +23,7 @@ impl U256Ext for eth::U256 { } fn to_big_uint(&self) -> num::BigUint { - let mut bytes = [0; 32]; - self.to_big_endian(&mut bytes); - num::BigUint::from_bytes_be(&bytes) + num::BigUint::from_bytes_be(self.to_be_bytes::<32>().as_slice()) } fn to_big_rational(&self) -> num::BigRational { @@ -30,7 +31,7 @@ impl U256Ext for eth::U256 { } fn checked_ceil_div(&self, other: &Self) -> Option { - self.checked_add(other.checked_sub(1.into())?)? + self.checked_add(other.checked_sub(eth::U256::ONE)?)? .checked_div(*other) } @@ -50,8 +51,8 @@ impl U256Ext for eth::U256 { // that requires to double check and adjust a few tests due to tiny // changes in rounding. const CONVERSION_FACTOR: f64 = 1_000_000_000_000_000_000.; - let multiplied = self.checked_mul(Self::from_f64_lossy(factor * CONVERSION_FACTOR))? - / Self::from_f64_lossy(CONVERSION_FACTOR); + let multiplied = self.checked_mul(Self::from(factor * CONVERSION_FACTOR))? + / Self::from(CONVERSION_FACTOR); Some(multiplied) } @@ -63,7 +64,7 @@ impl U256Ext for eth::U256 { fn from_big_uint(input: &num::BigUint) -> Result { let bytes = input.to_bytes_be(); anyhow::ensure!(bytes.len() <= 32, "too large"); - Ok(eth::U256::from_big_endian(&bytes)) + Ok(eth::U256::from_be_slice(&bytes)) } fn from_big_rational(value: &num::BigRational) -> Result { diff --git a/crates/driver/src/util/serialize/u256.rs b/crates/driver/src/util/serialize/u256.rs index 8cef0df143..3984c117dc 100644 --- a/crates/driver/src/util/serialize/u256.rs +++ b/crates/driver/src/util/serialize/u256.rs @@ -4,6 +4,8 @@ use { serde_with::{DeserializeAs, SerializeAs}, }; +// NOTE(jmg-duarte): not sure if we still need this module + /// Serialize and deserialize [`eth::U256`] as a decimal string. #[derive(Debug)] pub struct U256; @@ -23,7 +25,7 @@ impl<'de> DeserializeAs<'de, eth::U256> for U256 { where E: de::Error, { - eth::U256::from_dec_str(s).map_err(|err| { + eth::U256::from_str_radix(s, 10).map_err(|err| { de::Error::custom(format!("failed to decode {s:?} as a 256-bit number: {err}")) }) } @@ -35,12 +37,6 @@ impl<'de> DeserializeAs<'de, eth::U256> for U256 { impl SerializeAs for U256 { fn serialize_as(source: ð::U256, serializer: S) -> Result { - // `primitive_types::U256::to_string()` is so slow that - // it's still faster to first convert to alloy's U256 - // and convert that to string... - let mut buf = [0u8; 32]; - source.to_big_endian(&mut buf); - let source = alloy::primitives::U256::from_be_bytes(buf); serializer.serialize_str(&source.to_string()) } } diff --git a/crates/e2e/src/setup/solver/solution.rs b/crates/e2e/src/setup/solver/solution.rs index fb2e325649..a8847ec6da 100644 --- a/crates/e2e/src/setup/solver/solution.rs +++ b/crates/e2e/src/setup/solver/solution.rs @@ -26,11 +26,11 @@ pub struct JitOrder { impl JitOrder { fn data(&self) -> OrderData { OrderData { - sell_token: self.sell.token.into_alloy(), - buy_token: self.buy.token.into_alloy(), + sell_token: self.sell.token, + buy_token: self.buy.token, receiver: Some(self.receiver.into_alloy()), - sell_amount: self.sell.amount.into_alloy(), - buy_amount: self.buy.amount.into_alloy(), + sell_amount: self.sell.amount, + buy_amount: self.buy.amount, valid_to: self.valid_to, app_data: AppDataHash(self.app_data.0), fee_amount: alloy::primitives::U256::ZERO, @@ -69,14 +69,11 @@ impl JitOrder { model::signature::Signature::PreSign => panic!("Not supported PreSigned JIT orders"), }; let order = solvers_dto::solution::JitOrder { - sell_token: data.sell_token.into_legacy(), - buy_token: data.buy_token.into_legacy(), - receiver: data - .receiver - .map(IntoLegacy::into_legacy) - .unwrap_or_default(), - sell_amount: data.sell_amount.into_legacy(), - buy_amount: data.buy_amount.into_legacy(), + sell_token: data.sell_token, + buy_token: data.buy_token, + receiver: data.receiver.unwrap_or_default(), + sell_amount: data.sell_amount, + buy_amount: data.buy_amount, partially_fillable: data.partially_fillable, valid_to: data.valid_to, app_data: data.app_data.0, diff --git a/crates/e2e/tests/e2e/cow_amm.rs b/crates/e2e/tests/e2e/cow_amm.rs index 0cb6876214..22c81968e8 100644 --- a/crates/e2e/tests/e2e/cow_amm.rs +++ b/crates/e2e/tests/e2e/cow_amm.rs @@ -22,7 +22,7 @@ use { to_wei_with_exp, wait_for_condition, }, - ethcontract::{BlockId, BlockNumber, H160}, + ethcontract::{BlockId, BlockNumber}, ethrpc::alloy::{ CallBuilderExt, conversions::{IntoAlloy, IntoLegacy}, @@ -33,7 +33,7 @@ use { signature::EcdsaSigningScheme, }, secp256k1::SecretKey, - shared::{addr, ethrpc::Web3}, + shared::ethrpc::Web3, solvers_dto::solution::{ BuyTokenBalance, Call, @@ -259,8 +259,8 @@ async fn cow_amm_jit(web3: Web3) { &onchain.contracts().domain_separator, ); let cow_amm_commitment = Call { - target: cow_amm_commitment_data.target.into_legacy(), - value: cow_amm_commitment_data.value.into_legacy(), + target: cow_amm_commitment_data.target, + value: cow_amm_commitment_data.value, calldata: cow_amm_commitment_data.call_data, }; @@ -306,27 +306,23 @@ async fn cow_amm_jit(web3: Web3) { let amm_balance_before = dai.balanceOf(*cow_amm.address()).call().await.unwrap(); let bob_balance_before = dai.balanceOf(bob.address()).call().await.unwrap(); - let fee = ethcontract::U256::exp10(16); // 0.01 WETH - let fee_alloy = alloy::primitives::U256::from(fee.low_u128()); + let fee = alloy::primitives::U256::from(10).pow(alloy::primitives::U256::from(16)); // 0.01 WETH mock_solver.configure_solution(Some(Solution { id: 1, // assume price of the univ2 pool prices: HashMap::from([ - (dai.address().into_legacy(), to_wei(100)), - ( - onchain.contracts().weth.address().into_legacy(), - to_wei(300_000), - ), + (*dai.address(), eth(100)), + (*onchain.contracts().weth.address(), eth(300_000)), ]), trades: vec![ solvers_dto::solution::Trade::Jit(solvers_dto::solution::JitTrade { order: solvers_dto::solution::JitOrder { - sell_token: cow_amm_order.sellToken.into_legacy(), - buy_token: cow_amm_order.buyToken.into_legacy(), - receiver: cow_amm_order.receiver.into_legacy(), - sell_amount: cow_amm_order.sellAmount.into_legacy(), - buy_amount: cow_amm_order.buyAmount.into_legacy(), + sell_token: cow_amm_order.sellToken, + buy_token: cow_amm_order.buyToken, + receiver: cow_amm_order.receiver, + sell_amount: cow_amm_order.sellAmount, + buy_amount: cow_amm_order.buyAmount, partially_fillable: cow_amm_order.partiallyFillable, valid_to: cow_amm_order.validTo, app_data: cow_amm_order.appData.0, @@ -336,12 +332,12 @@ async fn cow_amm_jit(web3: Web3) { signing_scheme: SigningScheme::Eip1271, signature, }, - executed_amount: cow_amm_order.sellAmount.into_legacy() - fee, + executed_amount: cow_amm_order.sellAmount - fee, fee: Some(fee), }), solvers_dto::solution::Trade::Fulfillment(solvers_dto::solution::Fulfillment { order: solvers_dto::solution::OrderUid(user_order_id.0), - executed_amount: (user_order.sell_amount - fee_alloy).into_legacy(), + executed_amount: (user_order.sell_amount - fee), fee: Some(fee), }), ], @@ -422,14 +418,12 @@ async fn cow_amm_driver_support(web3: Web3) { // Unbalance the cow amm enough that baseline is able to rebalance // it with the current liquidity. - const USDC_WETH_COW_AMM: H160 = H160(hex_literal::hex!( - "f08d4dea369c456d26a3168ff0024b904f2d8b91" - )); + const USDC_WETH_COW_AMM: Address = address!("f08d4dea369c456d26a3168ff0024b904f2d8b91"); let weth_balance = onchain .contracts() .weth - .balanceOf(USDC_WETH_COW_AMM.into_alloy()) + .balanceOf(USDC_WETH_COW_AMM) .call() .await .unwrap(); @@ -451,17 +445,13 @@ async fn cow_amm_driver_support(web3: Web3) { onchain .contracts() .weth - .transfer(USDC_WETH_COW_AMM.into_alloy(), weth_to_send) + .transfer(USDC_WETH_COW_AMM, weth_to_send) .from(solver.address()) .send_and_watch() .await .unwrap(); - let amm_usdc_balance_before = usdc - .balanceOf(USDC_WETH_COW_AMM.into_alloy()) - .call() - .await - .unwrap(); + let amm_usdc_balance_before = usdc.balanceOf(USDC_WETH_COW_AMM).call().await.unwrap(); // Now we create an unfillable order just so the orderbook is not empty. // Otherwise all auctions would be skipped because there is no user order to @@ -630,11 +620,7 @@ factory = "0xf76c421bAb7df8548604E60deCCcE50477C10462" onchain.mint_block().await; tokio::time::sleep(tokio::time::Duration::from_millis(1_000)).await; - let amm_usdc_balance_after = usdc - .balanceOf(USDC_WETH_COW_AMM.into_alloy()) - .call() - .await - .unwrap(); + let amm_usdc_balance_after = usdc.balanceOf(USDC_WETH_COW_AMM).call().await.unwrap(); // CoW AMM traded automatically amm_usdc_balance_after != amm_usdc_balance_before }) @@ -658,8 +644,8 @@ factory = "0xf76c421bAb7df8548604E60deCCcE50477C10462" // all tokens traded by the cow amms tracing::info!("Waiting for all relevant native prices to be indexed."); let expected_prices = [ - addr!("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"), // WETH - addr!("A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"), // USDC + address!("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"), // WETH + address!("A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"), // USDC ]; wait_for_condition(TIMEOUT, || async { @@ -677,8 +663,8 @@ factory = "0xf76c421bAb7df8548604E60deCCcE50477C10462" let found_amm_jit_orders = auctions.iter().any(|auction| { auction.orders.iter().any(|order| { order.owner == USDC_WETH_COW_AMM - && order.sell_token == onchain.contracts().weth.address().into_legacy() - && order.buy_token == usdc.address().into_legacy() + && order.sell_token == *onchain.contracts().weth.address() + && order.buy_token == *usdc.address() }) }); @@ -904,8 +890,8 @@ async fn cow_amm_opposite_direction(web3: Web3) { &onchain.contracts().domain_separator, ); let cow_amm_commitment = Call { - target: cow_amm_commitment_data.target.into_legacy(), - value: cow_amm_commitment_data.value.into_legacy(), + target: cow_amm_commitment_data.target, + value: cow_amm_commitment_data.value, calldata: cow_amm_commitment_data.call_data, }; @@ -942,27 +928,24 @@ async fn cow_amm_opposite_direction(web3: Web3) { tokio::time::sleep(tokio::time::Duration::from_secs(1)).await; // Set the fees appropriately - let fee_cow_amm = ethcontract::U256::exp10(16); // 0.01 WETH - let fee_user = to_wei(1); // 1 DAI + let fee_cow_amm = alloy::primitives::U256::from(10).pow(alloy::primitives::U256::from(16)); // 0.01 WETH + let fee_user = eth(1); // 1 DAI let mocked_solutions = |order_uid: OrderUid| { Solution { id: 1, prices: HashMap::from([ - (dai.address().into_legacy(), to_wei(1)), // 1 DAI = $1 - ( - onchain.contracts().weth.address().into_legacy(), - to_wei(2300), - ), // 1 WETH = $2300 + (*dai.address(), eth(1)), // 1 DAI = $1 + (*onchain.contracts().weth.address(), eth(2300)), // 1 WETH = $2300 ]), trades: vec![ solvers_dto::solution::Trade::Jit(solvers_dto::solution::JitTrade { order: solvers_dto::solution::JitOrder { - sell_token: cow_amm_order.sellToken.into_legacy(), - buy_token: cow_amm_order.buyToken.into_legacy(), - receiver: cow_amm_order.receiver.into_legacy(), - sell_amount: cow_amm_order.sellAmount.into_legacy(), - buy_amount: cow_amm_order.buyAmount.into_legacy(), + sell_token: cow_amm_order.sellToken, + buy_token: cow_amm_order.buyToken, + receiver: cow_amm_order.receiver, + sell_amount: cow_amm_order.sellAmount, + buy_amount: cow_amm_order.buyAmount, partially_fillable: cow_amm_order.partiallyFillable, valid_to: cow_amm_order.validTo, app_data: cow_amm_order.appData.0, @@ -972,12 +955,12 @@ async fn cow_amm_opposite_direction(web3: Web3) { signing_scheme: SigningScheme::Eip1271, signature: signature.clone(), }, - executed_amount: cow_amm_order.sellAmount.into_legacy() - fee_cow_amm, + executed_amount: cow_amm_order.sellAmount - fee_cow_amm, fee: Some(fee_cow_amm), }), solvers_dto::solution::Trade::Fulfillment(solvers_dto::solution::Fulfillment { order: solvers_dto::solution::OrderUid(order_uid.0), - executed_amount: executed_amount.into_legacy() - fee_user, + executed_amount: executed_amount - fee_user, fee: Some(fee_user), }), ], diff --git a/crates/e2e/tests/e2e/jit_orders.rs b/crates/e2e/tests/e2e/jit_orders.rs index ce7132b31a..6984c53a44 100644 --- a/crates/e2e/tests/e2e/jit_orders.rs +++ b/crates/e2e/tests/e2e/jit_orders.rs @@ -135,12 +135,12 @@ async fn single_limit_order_test(web3: Web3) { let (jit_order, jit_order_uid) = JitOrder { owner: trader.address().into_legacy(), sell: Asset { - amount: to_wei(10), - token: token.address().into_legacy(), + amount: eth(10), + token: *token.address(), }, buy: Asset { - amount: to_wei(1), - token: onchain.contracts().weth.address().into_legacy(), + amount: eth(1), + token: *onchain.contracts().weth.address(), }, kind: OrderKind::Sell, partially_fillable: false, @@ -157,20 +157,20 @@ async fn single_limit_order_test(web3: Web3) { mock_solver.configure_solution(Some(Solution { id: 0, prices: HashMap::from([ - (token.address().into_legacy(), to_wei(1)), - (onchain.contracts().weth.address().into_legacy(), to_wei(1)), + (*token.address(), eth(1)), + (*onchain.contracts().weth.address(), eth(1)), ]), trades: vec![ solvers_dto::solution::Trade::Jit(solvers_dto::solution::JitTrade { order: jit_order, // Making it 9 + 1 so we cover the edge case of fill-or-kill solution mismatches // when observing settlements https://github.com/cowprotocol/services/pull/3440 - executed_amount: to_wei(9), - fee: Some(to_wei(1)), + executed_amount: eth(9), + fee: Some(eth(1)), }), solvers_dto::solution::Trade::Fulfillment(solvers_dto::solution::Fulfillment { - executed_amount: order.sell_amount.into_legacy(), - fee: Some(0.into()), + executed_amount: order.sell_amount, + fee: Some(::alloy::primitives::U256::ZERO), order: solvers_dto::solution::OrderUid(order_id.0), }), ], diff --git a/crates/e2e/tests/e2e/liquidity_source_notification.rs b/crates/e2e/tests/e2e/liquidity_source_notification.rs index 16fed65c09..5395f1924c 100644 --- a/crates/e2e/tests/e2e/liquidity_source_notification.rs +++ b/crates/e2e/tests/e2e/liquidity_source_notification.rs @@ -17,7 +17,6 @@ use { eth, mock::Mock, run_forked_test_with_block_number, - to_wei, to_wei_with_exp, wait_for_condition, }, @@ -61,7 +60,7 @@ async fn liquidity_source_notification(web3: Web3) { let mut onchain = OnchainComponents::deployed(web3.clone()).await; // Define trade params - let trade_amount = to_wei_with_exp(5, 8); + let trade_amount = to_wei_with_exp(5, 8).into_alloy(); // Create parties accounts // solver - represents both baseline solver engine for quoting and liquorice @@ -88,7 +87,7 @@ async fn liquidity_source_notification(web3: Web3) { web3.alloy .anvil_send_impersonated_transaction_with_config( token_usdc - .transfer(trader.address(), trade_amount.into_alloy()) + .transfer(trader.address(), trade_amount) .from(USDC_WHALE) .into_transaction_request(), ImpersonateConfig { @@ -106,7 +105,7 @@ async fn liquidity_source_notification(web3: Web3) { web3.alloy .anvil_send_impersonated_transaction_with_config( token_usdc - .transfer(solver.address(), trade_amount.into_alloy()) + .transfer(solver.address(), trade_amount) .from(USDC_WHALE) .into_transaction_request(), ImpersonateConfig { @@ -143,14 +142,13 @@ async fn liquidity_source_notification(web3: Web3) { .BALANCE_MANAGER() .call() .await - .expect("no balance manager found") - .into_legacy(); + .expect("no balance manager found"); // Fund `liquorice_maker` web3.alloy .anvil_send_impersonated_transaction_with_config( token_usdt - .transfer(liquorice_maker.address(), trade_amount.into_alloy()) + .transfer(liquorice_maker.address(), trade_amount) .from(USDT_WHALE) .into_transaction_request(), ImpersonateConfig { @@ -167,7 +165,7 @@ async fn liquidity_source_notification(web3: Web3) { // Maker gives approval to the Liquorice balance manager contract token_usdt .approve( - liquorice_balance_manager_address.into_alloy(), + liquorice_balance_manager_address, alloy::primitives::U256::MAX, ) .from(liquorice_maker.address()) @@ -238,9 +236,9 @@ http-timeout = "10s" let order_id = { let order = OrderCreation { sell_token: *token_usdc.address(), - sell_amount: trade_amount.into_alloy(), + sell_amount: trade_amount, buy_token: *token_usdt.address(), - buy_amount: trade_amount.into_alloy(), + buy_amount: trade_amount, valid_to: model::time::now_in_epoch_seconds() + 300, kind: OrderKind::Sell, ..Default::default() @@ -263,8 +261,8 @@ http-timeout = "10s" effectiveTrader: *onchain.contracts().gp_settlement.address(), baseToken: *token_usdc.address(), quoteToken: *token_usdt.address(), - baseTokenAmount: trade_amount.into_alloy(), - quoteTokenAmount: trade_amount.into_alloy(), + baseTokenAmount: trade_amount, + quoteTokenAmount: trade_amount, minFillAmount: U256::from(1), quoteExpiry: U256::from(Utc::now().timestamp() as u64 + 10), recipient: liquorice_maker.address(), @@ -308,24 +306,24 @@ http-timeout = "10s" liquorice_solver_api_mock.configure_solution(Some(Solution { id: 1, prices: HashMap::from([ - (token_usdc.address().into_legacy(), to_wei(11)), - (token_usdt.address().into_legacy(), to_wei(10)), + (*token_usdc.address(), eth(11)), + (*token_usdt.address(), eth(10)), ]), trades: vec![solvers_dto::solution::Trade::Fulfillment( solvers_dto::solution::Fulfillment { executed_amount: trade_amount, - fee: Some(0.into()), + fee: Some(alloy::primitives::U256::ZERO), order: solvers_dto::solution::OrderUid(order_id.0), }, )], pre_interactions: vec![], interactions: vec![solvers_dto::solution::Interaction::Custom( solvers_dto::solution::CustomInteraction { - target: liquorice_settlement.address().into_legacy(), + target: *liquorice_settlement.address(), calldata: liquorice_solution_calldata, - value: 0.into(), + value: alloy::primitives::U256::ZERO, allowances: vec![solvers_dto::solution::Allowance { - token: token_usdc.address().into_legacy(), + token: *token_usdc.address(), spender: liquorice_balance_manager_address, amount: trade_amount, }], diff --git a/crates/e2e/tests/e2e/solver_competition.rs b/crates/e2e/tests/e2e/solver_competition.rs index ceed182fc9..88b1910044 100644 --- a/crates/e2e/tests/e2e/solver_competition.rs +++ b/crates/e2e/tests/e2e/solver_competition.rs @@ -435,14 +435,11 @@ async fn store_filtered_solutions(web3: Web3) { // good solver settles order_ab at a price 3:1 good_solver.configure_solution(Some(Solution { id: 0, - prices: HashMap::from([ - (token_a.address().into_legacy(), to_wei(3)), - (token_b.address().into_legacy(), to_wei(1)), - ]), + prices: HashMap::from([(*token_a.address(), eth(3)), (*token_b.address(), eth(1))]), trades: vec![solvers_dto::solution::Trade::Fulfillment( solvers_dto::solution::Fulfillment { - executed_amount: order_ab.sell_amount.into_legacy(), - fee: Some(0.into()), + executed_amount: order_ab.sell_amount, + fee: Some(::alloy::primitives::U256::ZERO), order: solvers_dto::solution::OrderUid(order_ab_id.0), }, )], @@ -460,19 +457,19 @@ async fn store_filtered_solutions(web3: Web3) { bad_solver.configure_solution(Some(Solution { id: 0, prices: HashMap::from([ - (token_a.address().into_legacy(), to_wei(2)), - (token_b.address().into_legacy(), to_wei(1)), - (token_c.address().into_legacy(), to_wei(1)), + (*token_a.address(), eth(2)), + (*token_b.address(), eth(1)), + (*token_c.address(), eth(1)), ]), trades: vec![ solvers_dto::solution::Trade::Fulfillment(solvers_dto::solution::Fulfillment { - executed_amount: order_ab.sell_amount.into_legacy(), - fee: Some(0.into()), + executed_amount: order_ab.sell_amount, + fee: Some(::alloy::primitives::U256::ZERO), order: solvers_dto::solution::OrderUid(order_ab_id.0), }), solvers_dto::solution::Trade::Fulfillment(solvers_dto::solution::Fulfillment { - executed_amount: order_ac.sell_amount.into_legacy(), - fee: Some(0.into()), + executed_amount: order_ac.sell_amount, + fee: Some(::alloy::primitives::U256::ZERO), order: solvers_dto::solution::OrderUid(order_ac_id.0), }), ], diff --git a/crates/e2e/tests/e2e/solver_participation_guard.rs b/crates/e2e/tests/e2e/solver_participation_guard.rs index 24e23463a2..5b302ec30e 100644 --- a/crates/e2e/tests/e2e/solver_participation_guard.rs +++ b/crates/e2e/tests/e2e/solver_participation_guard.rs @@ -163,17 +163,13 @@ async fn low_settling_solver(web3: Web3) { // The competition still passes since the stats are updated only after a new // solution from anyone is received and stored. let now = Instant::now(); - assert!( - execute_order(&onchain, &trader_a, &token_a, &token_b, &services) - .await - .is_ok() - ); + execute_order(&onchain, &trader_a, &token_a, &token_b, &services) + .await + .unwrap(); // Now, the stat is updated, and the solver is banned. - assert!( - execute_order(&onchain, &trader_a, &token_a, &token_b, &services) - .await - .is_err() - ); + execute_order(&onchain, &trader_a, &token_a, &token_b, &services) + .await + .unwrap_err(); // 40 seconds is the cache TTL, and 5 seconds is added to compensate any // possible delays. diff --git a/crates/shared/src/baseline_solver.rs b/crates/shared/src/baseline_solver.rs index 38aac8b0ad..546203bac7 100644 --- a/crates/shared/src/baseline_solver.rs +++ b/crates/shared/src/baseline_solver.rs @@ -2,8 +2,7 @@ //! onchain liquidity. use { - alloy::primitives::Address, - ethcontract::U256, + alloy::primitives::{Address, U256}, model::TokenPair, std::collections::{HashMap, HashSet}, }; @@ -364,9 +363,13 @@ mod tests { pools[0].tokens => vec![pools[0]], }; - assert!(estimate_buy_amount(1.into(), &path, &pools).await.is_none()); assert!( - estimate_sell_amount(1.into(), &path, &pools) + estimate_buy_amount(U256::ONE, &path, &pools) + .await + .is_none() + ); + assert!( + estimate_sell_amount(U256::ONE, &path, &pools) .await .is_none() ); @@ -397,19 +400,19 @@ mod tests { }; assert_eq!( - estimate_buy_amount(10.into(), &path, &pools) + estimate_buy_amount(U256::from(10), &path, &pools) .await .unwrap() .value, - 2.into() + U256::from(2) ); assert_eq!( - estimate_sell_amount(10.into(), &path, &pools) + estimate_sell_amount(U256::from(10), &path, &pools) .await .unwrap() .value, - 105.into() + U256::from(105) ); } @@ -438,7 +441,7 @@ mod tests { }; assert!( - estimate_sell_amount(100.into(), &path, &pools) + estimate_sell_amount(U256::from(100), &path, &pools) .await .is_none() ); @@ -470,7 +473,7 @@ mod tests { second_pair => vec![second_hop_high_slippage, second_hop_low_slippage], }; - let buy_estimate = estimate_buy_amount(1000.into(), &path, &pools) + let buy_estimate = estimate_buy_amount(U256::from(1000), &path, &pools) .await .unwrap(); assert_eq!( @@ -478,7 +481,7 @@ mod tests { [&first_hop_low_price, &second_hop_low_slippage] ); - let sell_estimate = estimate_sell_amount(1000.into(), &path, &pools) + let sell_estimate = estimate_sell_amount(U256::from(1000), &path, &pools) .await .unwrap(); assert_eq!( @@ -489,7 +492,7 @@ mod tests { // For the reverse path we now expect to use the higher price for the first hop, // but still low slippage for the second path.reverse(); - let buy_estimate = estimate_buy_amount(1000.into(), &path, &pools) + let buy_estimate = estimate_buy_amount(U256::from(1000), &path, &pools) .await .unwrap(); assert_eq!( @@ -497,7 +500,7 @@ mod tests { [&second_hop_low_slippage, &first_hop_high_price] ); - let sell_estimate = estimate_sell_amount(1000.into(), &path, &pools) + let sell_estimate = estimate_sell_amount(U256::from(1000), &path, &pools) .await .unwrap(); assert_eq!( @@ -519,12 +522,12 @@ mod tests { pair => vec![valid_pool, invalid_pool], }; - let buy_estimate = estimate_buy_amount(1000.into(), &path, &pools) + let buy_estimate = estimate_buy_amount(U256::from(1000), &path, &pools) .await .unwrap(); assert_eq!(buy_estimate.path, [&valid_pool]); - let sell_estimate = estimate_sell_amount(1000.into(), &path, &pools) + let sell_estimate = estimate_sell_amount(U256::from(1000), &path, &pools) .await .unwrap(); assert_eq!(sell_estimate.path, [&valid_pool]); diff --git a/crates/shared/src/sources/balancer_v2/swap/mod.rs b/crates/shared/src/sources/balancer_v2/swap/mod.rs index d535b7e999..8e1490bd58 100644 --- a/crates/shared/src/sources/balancer_v2/swap/mod.rs +++ b/crates/shared/src/sources/balancer_v2/swap/mod.rs @@ -14,6 +14,7 @@ use { alloy::primitives::Address, error::Error, ethcontract::U256, + ethrpc::alloy::conversions::{IntoAlloy, IntoLegacy}, fixed_point::Bfp, std::collections::BTreeMap, }; @@ -114,16 +115,17 @@ impl BaselineSolvable for WeightedPoolRef<'_> { async fn get_amount_out( &self, out_token: Address, - (in_amount, in_token): (U256, Address), - ) -> Option { - self.get_amount_out_inner(out_token, in_amount, in_token) + (in_amount, in_token): (alloy::primitives::U256, Address), + ) -> Option { + self.get_amount_out_inner(out_token, in_amount.into_legacy(), in_token) + .map(IntoAlloy::into_alloy) } async fn get_amount_in( &self, in_token: Address, - (out_amount, out_token): (U256, Address), - ) -> Option { + (out_amount, out_token): (alloy::primitives::U256, Address), + ) -> Option { // Note that the output of this function does not depend on the pool // specialization. All contract branches compute this amount with: // https://github.com/balancer-labs/balancer-v2-monorepo/blob/6c9e24e22d0c46cca6dd15861d3d33da61a60b98/pkg/core/contracts/pools/BaseMinimalSwapInfoPool.sol#L75-L88 @@ -139,15 +141,16 @@ impl BaselineSolvable for WeightedPoolRef<'_> { in_reserves.weight, out_reserves.common.upscaled_balance().ok()?, out_reserves.weight, - out_reserves.common.upscale(out_amount).ok()?, + out_reserves.common.upscale(out_amount.into_legacy()).ok()?, ) .ok()?; let amount_in_before_fee = in_reserves.common.downscale_up(in_amount).ok()?; let in_amount = add_swap_fee_amount(amount_in_before_fee, self.swap_fee).ok()?; - converge_in_amount(in_amount, out_amount, |x| { + converge_in_amount(in_amount, out_amount.into_legacy(), |x| { self.get_amount_out_inner(out_token, x, in_token) }) + .map(IntoAlloy::into_alloy) } async fn gas_cost(&self) -> usize { @@ -278,7 +281,7 @@ impl<'a> StablePoolRef<'a> { /// Comes from `_swapWithBpt`: // https://etherscan.io/address/0xf9ac7B9dF2b3454E841110CcE5550bD5AC6f875F#code#F2#L301 - fn swap_with_bpt(&self) -> Option { + fn swap_with_bpt(&self) -> Option { // TODO: We currently do not implement swapping with BPT for composable // stable pools. None @@ -289,13 +292,14 @@ impl StablePoolRef<'_> { fn get_amount_out_inner( &self, out_token: Address, - in_amount: U256, + in_amount: alloy::primitives::U256, in_token: Address, - ) -> Option { + ) -> Option { if in_token == self.address || out_token == self.address { self.swap_with_bpt() } else { - self.regular_swap_given_in(out_token, (in_amount, in_token)) + self.regular_swap_given_in(out_token, (in_amount.into_legacy(), in_token)) + .map(IntoAlloy::into_alloy) } } } @@ -304,23 +308,26 @@ impl BaselineSolvable for StablePoolRef<'_> { async fn get_amount_out( &self, out_token: Address, - (in_amount, in_token): (U256, Address), - ) -> Option { + (in_amount, in_token): (alloy::primitives::U256, Address), + ) -> Option { self.get_amount_out_inner(out_token, in_amount, in_token) } async fn get_amount_in( &self, in_token: Address, - (out_amount, out_token): (U256, Address), - ) -> Option { + (out_amount, out_token): (alloy::primitives::U256, Address), + ) -> Option { if in_token == self.address || out_token == self.address { self.swap_with_bpt() } else { - let in_amount = self.regular_swap_given_out(in_token, (out_amount, out_token))?; - converge_in_amount(in_amount, out_amount, |x| { - self.get_amount_out_inner(out_token, x, in_token) + let in_amount = + self.regular_swap_given_out(in_token, (out_amount.into_legacy(), out_token))?; + converge_in_amount(in_amount, out_amount.into_legacy(), |x| { + self.get_amount_out_inner(out_token, x.into_alloy(), in_token) + .map(IntoLegacy::into_legacy) }) + .map(IntoAlloy::into_alloy) } } @@ -375,11 +382,19 @@ impl WeightedPool { } impl BaselineSolvable for WeightedPool { - async fn get_amount_out(&self, out_token: Address, input: (U256, Address)) -> Option { + async fn get_amount_out( + &self, + out_token: Address, + input: (alloy::primitives::U256, Address), + ) -> Option { self.as_pool_ref().get_amount_out(out_token, input).await } - async fn get_amount_in(&self, in_token: Address, output: (U256, Address)) -> Option { + async fn get_amount_in( + &self, + in_token: Address, + output: (alloy::primitives::U256, Address), + ) -> Option { self.as_pool_ref().get_amount_in(in_token, output).await } @@ -405,11 +420,19 @@ impl StablePool { } impl BaselineSolvable for StablePool { - async fn get_amount_out(&self, out_token: Address, input: (U256, Address)) -> Option { + async fn get_amount_out( + &self, + out_token: Address, + input: (alloy::primitives::U256, Address), + ) -> Option { self.as_pool_ref().get_amount_out(out_token, input).await } - async fn get_amount_in(&self, in_token: Address, output: (U256, Address)) -> Option { + async fn get_amount_in( + &self, + in_token: Address, + output: (alloy::primitives::U256, Address), + ) -> Option { self.as_pool_ref().get_amount_in(in_token, output).await } @@ -525,10 +548,16 @@ mod tests { ); assert_eq!( - b.get_amount_out(crv, (227_937_106_828_652_254_870_i128.into(), sdvecrv_dao)) - .await - .unwrap(), - 488_192_591_864_344_551_330_i128.into() + b.get_amount_out( + crv, + ( + alloy::primitives::U256::from(227_937_106_828_652_254_870_i128), + sdvecrv_dao + ) + ) + .await + .unwrap(), + alloy::primitives::U256::from(488_192_591_864_344_551_330_i128) ); } @@ -547,10 +576,10 @@ mod tests { ); assert_eq!( - b.get_amount_in(weth, (5_000_000_i128.into(), tusd)) + b.get_amount_in(weth, (alloy::primitives::U256::from(5_000_000_i128), tusd)) .await .unwrap(), - 1_225_715_511_430_411_i128.into() + alloy::primitives::U256::from(1_225_715_511_430_411_i128) ); } @@ -619,10 +648,10 @@ mod tests { ); // Etherscan for amount verification: // https://etherscan.io/tx/0x75be93fff064ad46b423b9e20cee09b0ae7f741087f43e4187d4f4cf59f54229 - let amount_in = 1_886_982_823_746_269_817_650_i128.into(); + let amount_in = alloy::primitives::U256::from(1_886_982_823_746_269_817_650_i128); let amount_out = 1_887_770_905_i128; let res_out = pool.get_amount_out(usdc, (amount_in, dai)).await; - assert_eq!(res_out.unwrap(), amount_out.into()); + assert_eq!(res_out.unwrap(), amount_out); } #[tokio::test] @@ -653,8 +682,8 @@ mod tests { // Etherscan for amount verification: // https://etherscan.io/tx/0x38487122158eef6b63570b5d3754ddc223c63af5c049d7b80acacb9e8ca89a63 let amount_in = 900_816_325_i128; - let amount_out = 900_000_000_000_000_000_000_u128.into(); + let amount_out = alloy::primitives::U256::from(900_000_000_000_000_000_000_u128); let res_out = pool.get_amount_in(usdc, (amount_out, dai)).await; - assert_eq!(res_out.unwrap(), amount_in.into()); + assert_eq!(res_out.unwrap(), amount_in); } } diff --git a/crates/shared/src/sources/uniswap_v2/pool_fetching.rs b/crates/shared/src/sources/uniswap_v2/pool_fetching.rs index 76832bc515..e5f2901f5b 100644 --- a/crates/shared/src/sources/uniswap_v2/pool_fetching.rs +++ b/crates/shared/src/sources/uniswap_v2/pool_fetching.rs @@ -12,7 +12,10 @@ use { errors::EthcontractErrorType, }, ethcontract::{BlockId, U256, errors::MethodError}, - ethrpc::alloy::{conversions::IntoAlloy, errors::ignore_non_node_error}, + ethrpc::alloy::{ + conversions::{IntoAlloy, IntoLegacy}, + errors::ignore_non_node_error, + }, futures::{ FutureExt as _, future::{self, BoxFuture}, @@ -172,24 +175,24 @@ impl BaselineSolvable for Pool { async fn get_amount_out( &self, out_token: Address, - (in_amount, in_token): (U256, Address), - ) -> Option { - self.get_amount_out(in_token, in_amount) + (in_amount, in_token): (alloy::primitives::U256, Address), + ) -> Option { + self.get_amount_out(in_token, in_amount.into_legacy()) .map(|(out_amount, token)| { assert_eq!(token, out_token); - out_amount + out_amount.into_alloy() }) } async fn get_amount_in( &self, in_token: Address, - (out_amount, out_token): (U256, Address), - ) -> Option { - self.get_amount_in(out_token, out_amount) + (out_amount, out_token): (alloy::primitives::U256, Address), + ) -> Option { + self.get_amount_in(out_token, out_amount.into_legacy()) .map(|(in_amount, token)| { assert_eq!(token, in_token); - in_amount + in_amount.into_alloy() }) } diff --git a/crates/solver/src/solver.rs b/crates/solver/src/solver.rs index a341c1bc75..aaa642c1f7 100644 --- a/crates/solver/src/solver.rs +++ b/crates/solver/src/solver.rs @@ -1,8 +1,7 @@ use { crate::liquidity::{ConstantProductOrder, WeightedProductOrder}, - alloy::primitives::Address, + alloy::primitives::{Address, U256}, anyhow::anyhow, - ethcontract::U256, shared::{ baseline_solver::BaselineSolvable, sources::{balancer_v2::swap::WeightedPoolRef, uniswap_v2::pool_fetching::Pool}, diff --git a/crates/solvers-dto/Cargo.toml b/crates/solvers-dto/Cargo.toml index 8860a4e0bb..7dbd01af6e 100644 --- a/crates/solvers-dto/Cargo.toml +++ b/crates/solvers-dto/Cargo.toml @@ -6,6 +6,7 @@ edition = "2024" license = "MIT OR Apache-2.0" [dependencies] +alloy = {workspace = true} 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/auction.rs b/crates/solvers-dto/src/auction.rs index 0f2ab355ec..ecb11ca914 100644 --- a/crates/solvers-dto/src/auction.rs +++ b/crates/solvers-dto/src/auction.rs @@ -1,12 +1,12 @@ use { super::serialize, + alloy::primitives::{Address, B256, U256}, app_data::AppDataHash, bigdecimal::BigDecimal, number::serialization::HexOrDecimalU256, serde::{Deserialize, Serialize}, serde_with::{DisplayFromStr, serde_as}, std::collections::HashMap, - web3::types::{H160, H256, U256}, }; #[serde_as] @@ -15,13 +15,13 @@ use { pub struct Auction { #[serde_as(as = "Option")] pub id: Option, - pub tokens: HashMap, + pub tokens: HashMap, pub orders: Vec, pub liquidity: Vec, #[serde_as(as = "HexOrDecimalU256")] pub effective_gas_price: U256, pub deadline: chrono::DateTime, - pub surplus_capturing_jit_order_owners: Vec, + pub surplus_capturing_jit_order_owners: Vec
, } #[serde_as] @@ -30,8 +30,8 @@ pub struct Auction { pub struct Order { #[serde_as(as = "serialize::Hex")] pub uid: [u8; 56], - pub sell_token: H160, - pub buy_token: H160, + pub sell_token: Address, + pub buy_token: Address, #[serde_as(as = "HexOrDecimalU256")] pub sell_amount: U256, #[serde_as(as = "HexOrDecimalU256")] @@ -45,8 +45,8 @@ pub struct Order { pub valid_to: u32, pub kind: Kind, #[serde(skip_serializing_if = "Option::is_none")] - pub receiver: Option, - pub owner: H160, + pub receiver: Option
, + pub owner: Address, pub partially_fillable: bool, pub pre_interactions: Vec, pub post_interactions: Vec, @@ -90,7 +90,7 @@ pub enum SellTokenSource { #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct InteractionData { - pub target: H160, + pub target: Address, #[serde_as(as = "HexOrDecimalU256")] pub value: U256, #[serde(with = "bytes_hex")] @@ -175,11 +175,11 @@ pub enum Liquidity { #[serde(rename_all = "camelCase")] pub struct ConstantProductPool { pub id: String, - pub address: H160, - pub router: H160, + pub address: Address, + pub router: Address, #[serde_as(as = "HexOrDecimalU256")] pub gas_estimate: U256, - pub tokens: HashMap, + pub tokens: HashMap, pub fee: BigDecimal, } @@ -196,11 +196,11 @@ pub struct ConstantProductReserve { #[serde(rename_all = "camelCase")] pub struct WeightedProductPool { pub id: String, - pub address: H160, - pub balancer_pool_id: H256, + pub address: Address, + pub balancer_pool_id: B256, #[serde_as(as = "HexOrDecimalU256")] pub gas_estimate: U256, - pub tokens: HashMap, + pub tokens: HashMap, pub fee: BigDecimal, pub version: WeightedProductVersion, } @@ -227,11 +227,11 @@ pub enum WeightedProductVersion { #[serde(rename_all = "camelCase")] pub struct StablePool { pub id: String, - pub address: H160, - pub balancer_pool_id: H256, + pub address: Address, + pub balancer_pool_id: B256, #[serde_as(as = "HexOrDecimalU256")] pub gas_estimate: U256, - pub tokens: HashMap, + pub tokens: HashMap, pub amplification_parameter: BigDecimal, pub fee: BigDecimal, } @@ -250,11 +250,11 @@ pub struct StableReserve { #[serde(rename_all = "camelCase")] pub struct ConcentratedLiquidityPool { pub id: String, - pub address: H160, - pub router: H160, + pub address: Address, + pub router: Address, #[serde_as(as = "HexOrDecimalU256")] pub gas_estimate: U256, - pub tokens: Vec, + pub tokens: Vec
, #[serde_as(as = "HexOrDecimalU256")] pub sqrt_price: U256, #[serde_as(as = "DisplayFromStr")] @@ -270,13 +270,13 @@ pub struct ConcentratedLiquidityPool { #[serde(rename_all = "camelCase")] pub struct ForeignLimitOrder { pub id: String, - pub address: H160, + pub address: Address, #[serde_as(as = "HexOrDecimalU256")] pub gas_estimate: U256, #[serde_as(as = "serialize::Hex")] pub hash: [u8; 32], - pub maker_token: H160, - pub taker_token: H160, + pub maker_token: Address, + pub taker_token: Address, #[serde_as(as = "HexOrDecimalU256")] pub maker_amount: U256, #[serde_as(as = "HexOrDecimalU256")] @@ -289,10 +289,10 @@ pub struct ForeignLimitOrder { #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct FlashloanHint { - pub liquidity_provider: H160, - pub protocol_adapter: H160, - pub receiver: H160, - pub token: H160, + pub liquidity_provider: Address, + pub protocol_adapter: Address, + pub receiver: Address, + pub token: Address, #[serde_as(as = "HexOrDecimalU256")] pub amount: U256, } @@ -300,7 +300,7 @@ pub struct FlashloanHint { #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct WrapperCall { - pub address: H160, + pub address: Address, #[serde(with = "bytes_hex")] pub data: Vec, /// Declares whether this wrapper (and its data) needs to be included diff --git a/crates/solvers-dto/src/solution.rs b/crates/solvers-dto/src/solution.rs index 2037117c3f..701d80f87c 100644 --- a/crates/solvers-dto/src/solution.rs +++ b/crates/solvers-dto/src/solution.rs @@ -1,10 +1,10 @@ use { super::serialize, + alloy::primitives::{Address, U256}, number::serialization::HexOrDecimalU256, serde::{Deserialize, Serialize}, serde_with::serde_as, std::collections::HashMap, - web3::types::{H160, U256}, }; #[derive(Debug, Serialize, Deserialize, Default)] @@ -19,7 +19,7 @@ pub struct Solutions { pub struct Solution { pub id: u64, #[serde_as(as = "HashMap<_, HexOrDecimalU256>")] - pub prices: HashMap, + pub prices: HashMap, pub trades: Vec, #[serde(default)] pub pre_interactions: Vec, @@ -73,9 +73,9 @@ pub struct JitTrade { #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct JitOrder { - pub sell_token: H160, - pub buy_token: H160, - pub receiver: H160, + pub sell_token: Address, + pub buy_token: Address, + pub receiver: Address, #[serde_as(as = "HexOrDecimalU256")] pub sell_amount: U256, #[serde_as(as = "HexOrDecimalU256")] @@ -111,7 +111,7 @@ pub enum Interaction { #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(tag = "kind", rename_all = "camelCase")] pub struct Call { - pub target: H160, + pub target: Address, pub value: U256, #[serde(rename = "callData")] #[serde_as(as = "serialize::Hex")] @@ -124,8 +124,8 @@ pub struct Call { pub struct LiquidityInteraction { pub internalize: bool, pub id: String, - pub input_token: H160, - pub output_token: H160, + pub input_token: Address, + pub output_token: Address, #[serde_as(as = "HexOrDecimalU256")] pub input_amount: U256, #[serde_as(as = "HexOrDecimalU256")] @@ -137,7 +137,7 @@ pub struct LiquidityInteraction { #[serde(rename_all = "camelCase")] pub struct CustomInteraction { pub internalize: bool, - pub target: H160, + pub target: Address, #[serde_as(as = "HexOrDecimalU256")] pub value: U256, #[serde(rename = "callData")] @@ -154,7 +154,7 @@ pub struct CustomInteraction { #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct OrderInteraction { - pub target: H160, + pub target: Address, #[serde_as(as = "HexOrDecimalU256")] pub value: U256, #[serde(rename = "callData")] @@ -166,7 +166,7 @@ pub struct OrderInteraction { #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Asset { - pub token: H160, + pub token: Address, #[serde_as(as = "HexOrDecimalU256")] pub amount: U256, } @@ -175,8 +175,8 @@ pub struct Asset { #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Allowance { - pub token: H160, - pub spender: H160, + pub token: Address, + pub spender: Address, #[serde_as(as = "HexOrDecimalU256")] pub amount: U256, } @@ -211,10 +211,10 @@ pub enum SigningScheme { #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Flashloan { - pub liquidity_provider: H160, - pub protocol_adapter: H160, - pub receiver: H160, - pub token: H160, + pub liquidity_provider: Address, + pub protocol_adapter: Address, + pub receiver: Address, + pub token: Address, #[serde_as(as = "HexOrDecimalU256")] pub amount: U256, } @@ -223,7 +223,7 @@ pub struct Flashloan { #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct WrapperCall { - pub address: H160, + pub address: Address, #[serde_as(as = "serialize::Hex")] #[serde(default)] pub data: Vec, diff --git a/crates/solvers/src/api/routes/solve/dto/auction.rs b/crates/solvers/src/api/routes/solve/dto/auction.rs index 3bbc635716..6b4116d5a8 100644 --- a/crates/solvers/src/api/routes/solve/dto/auction.rs +++ b/crates/solvers/src/api/routes/solve/dto/auction.rs @@ -63,9 +63,9 @@ pub fn into_domain(auction: Auction) -> Result { .flashloan_hint .clone() .map(|hint| order::FlashloanHint { - liquidity_provider: eth::Address(hint.liquidity_provider), - protocol_adapter: eth::Address(hint.protocol_adapter), - receiver: eth::Address(hint.receiver), + liquidity_provider: hint.liquidity_provider, + protocol_adapter: hint.protocol_adapter, + receiver: hint.receiver, token: eth::TokenAddress(hint.token), amount: hint.amount, }), diff --git a/crates/solvers/src/api/routes/solve/dto/solution.rs b/crates/solvers/src/api/routes/solve/dto/solution.rs index 206a9428c2..cd323dedae 100644 --- a/crates/solvers/src/api/routes/solve/dto/solution.rs +++ b/crates/solvers/src/api/routes/solve/dto/solution.rs @@ -115,14 +115,16 @@ pub fn from_domain(solutions: &[solution::Solution]) -> super::Solutions { } }) .collect(), - gas: solution.gas.map(|gas| gas.0.as_u64()), + gas: solution + .gas + .map(|gas| u64::try_from(gas.0).unwrap_or(u64::MAX)), // rely on driver to fill in the blanks flashloans: None, wrappers: solution .wrappers .iter() .map(|w| solvers_dto::solution::WrapperCall { - address: w.target.0, + address: w.target, data: w.data.clone(), }) .collect(), @@ -135,7 +137,7 @@ fn interaction_data_from_domain(interaction_data: &[eth::Interaction]) -> Vec Solver<'a> { max_hops: usize, ) -> Option> { let candidates = self.base_tokens.path_candidates_with_hops( - request.sell.token.0.into_alloy(), - request.buy.token.0.into_alloy(), + request.sell.token.0, + request.buy.token.0, max_hops, ); @@ -120,7 +119,7 @@ impl<'a> Solver<'a> { async fn traverse_path( &self, path: &[&OnchainLiquidity], - mut sell_token: H160, + mut sell_token: Address, mut sell_amount: U256, ) -> Option>> { let mut segments = Vec::new(); @@ -132,10 +131,10 @@ impl<'a> Solver<'a> { let buy_token = liquidity .token_pair - .other(&sell_token.into_alloy()) + .other(&sell_token) .expect("Inconsistent path"); let buy_amount = liquidity - .get_amount_out(buy_token, (sell_amount, sell_token.into_alloy())) + .get_amount_out(buy_token, (sell_amount, sell_token)) .await?; segments.push(solver::Segment { @@ -145,13 +144,13 @@ impl<'a> Solver<'a> { amount: sell_amount, }, output: eth::Asset { - token: eth::TokenAddress(buy_token.into_legacy()), + token: eth::TokenAddress(buy_token), amount: buy_amount, }, - gas: eth::Gas(liquidity.gas_cost().await.into()), + gas: eth::Gas(U256::from(liquidity.gas_cost().await)), }); - sell_token = buy_token.into_legacy(); + sell_token = buy_token; sell_amount = buy_amount; } Some(segments) @@ -203,9 +202,10 @@ fn to_boundary_liquidity( } } liquidity::State::Stable(pool) => { - if let Some(boundary_pool) = - boundary::liquidity::stable::to_boundary_pool(liquidity.address, pool) - { + if let Some(boundary_pool) = boundary::liquidity::stable::to_boundary_pool( + liquidity.address.into_legacy(), + pool, + ) { for pair in pool.reserves.token_pairs() { let token_pair = to_boundary_token_pair(&pair); onchain_liquidity.entry(token_pair).or_default().push( @@ -219,10 +219,9 @@ fn to_boundary_liquidity( } } liquidity::State::LimitOrder(limit_order) => { - if let Some(token_pair) = TokenPair::new( - limit_order.maker.token.0.into_alloy(), - limit_order.taker.token.0.into_alloy(), - ) { + if let Some(token_pair) = + TokenPair::new(limit_order.maker.token.0, limit_order.taker.token.0) + { onchain_liquidity .entry(token_pair) .or_default() @@ -250,7 +249,7 @@ fn to_boundary_liquidity( source: LiquiditySource::Concentrated( boundary::liquidity::concentrated::Pool { uni_v3_quoter_contract: uni_v3_quoter_v2_arc.clone(), - address: liquidity.address, + address: liquidity.address.into_legacy(), tokens: token_pair, fee, }, @@ -279,7 +278,11 @@ enum LiquiditySource { } impl BaselineSolvable for OnchainLiquidity { - async fn get_amount_out(&self, out_token: Address, input: (U256, Address)) -> Option { + async fn get_amount_out( + &self, + out_token: Address, + input: (alloy::primitives::U256, Address), + ) -> Option { match &self.source { LiquiditySource::ConstantProduct(pool) => pool.get_amount_out(out_token, input).await, LiquiditySource::WeightedProduct(pool) => pool.get_amount_out(out_token, input).await, @@ -291,7 +294,11 @@ impl BaselineSolvable for OnchainLiquidity { } } - async fn get_amount_in(&self, in_token: Address, out: (U256, Address)) -> Option { + async fn get_amount_in( + &self, + in_token: Address, + out: (alloy::primitives::U256, Address), + ) -> Option { match &self.source { LiquiditySource::ConstantProduct(pool) => pool.get_amount_in(in_token, out).await, LiquiditySource::WeightedProduct(pool) => pool.get_amount_in(in_token, out).await, @@ -318,14 +325,11 @@ fn to_boundary_base_tokens( weth: ð::WethAddress, base_tokens: &HashSet, ) -> BaseTokens { - let base_tokens = base_tokens - .iter() - .map(|token| token.0.into_alloy()) - .collect::>(); - BaseTokens::new(weth.0.into_alloy(), &base_tokens) + let base_tokens = base_tokens.iter().map(|token| token.0).collect::>(); + BaseTokens::new(weth.0, &base_tokens) } fn to_boundary_token_pair(pair: &liquidity::TokenPair) -> TokenPair { let (a, b) = pair.get(); - TokenPair::new(a.0.into_alloy(), b.0.into_alloy()).unwrap() + TokenPair::new(a.0, b.0).unwrap() } diff --git a/crates/solvers/src/boundary/liquidity/concentrated.rs b/crates/solvers/src/boundary/liquidity/concentrated.rs index c7e74889db..a01e3c40fb 100644 --- a/crates/solvers/src/boundary/liquidity/concentrated.rs +++ b/crates/solvers/src/boundary/liquidity/concentrated.rs @@ -1,11 +1,10 @@ use { - alloy::primitives::{Address, aliases::U24}, + alloy::primitives::{Address, U256, aliases::U24}, contracts::alloy::UniswapV3QuoterV2::IQuoterV2::{ QuoteExactInputSingleParams, QuoteExactOutputSingleParams, }, - ethcontract::{H160, U256}, - ethrpc::alloy::conversions::{IntoAlloy, IntoLegacy}, + ethcontract::H160, model::TokenPair, shared::baseline_solver::BaselineSolvable, std::sync::Arc, @@ -41,13 +40,13 @@ impl BaselineSolvable for Pool { .quoteExactInputSingle(QuoteExactInputSingleParams { tokenIn: in_token, tokenOut: out_token, - amountIn: in_amount.into_alloy(), + amountIn: in_amount, fee: self.fee, sqrtPriceLimitX96: alloy::primitives::U160::ZERO, }) .call() .await - .map(|result| result.amountOut.into_legacy()) + .map(|result| result.amountOut) .ok() } @@ -65,13 +64,13 @@ impl BaselineSolvable for Pool { .quoteExactOutputSingle(QuoteExactOutputSingleParams { tokenIn: in_token, tokenOut: out_token, - amount: out_amount.into_alloy(), + amount: out_amount, fee: self.fee, sqrtPriceLimitX96: alloy::primitives::U160::ZERO, }) .call() .await - .map(|result| result.amountIn.into_legacy()) + .map(|result| result.amountIn) .ok() } diff --git a/crates/solvers/src/boundary/liquidity/constant_product.rs b/crates/solvers/src/boundary/liquidity/constant_product.rs index 761fa03097..2105a47c59 100644 --- a/crates/solvers/src/boundary/liquidity/constant_product.rs +++ b/crates/solvers/src/boundary/liquidity/constant_product.rs @@ -1,31 +1,36 @@ pub use shared::sources::uniswap_v2::pool_fetching::Pool; use { crate::domain::liquidity, - ethereum_types::H160, - ethrpc::alloy::conversions::IntoAlloy, + alloy::primitives::{Address, U256}, model::TokenPair, }; /// Converts a domain pool into a [`shared`] Uniswap V2 pool. Returns `None` if /// the domain pool cannot be represented as a boundary pool. -pub fn to_boundary_pool(address: H160, pool: &liquidity::constant_product::Pool) -> Option { +pub fn to_boundary_pool( + address: Address, + pool: &liquidity::constant_product::Pool, +) -> Option { let reserves = pool.reserves.get(); - let tokens = TokenPair::new( - reserves.0.token.0.into_alloy(), - reserves.1.token.0.into_alloy(), - ) - .expect("tokens are distinct by construction"); + let tokens = TokenPair::new(reserves.0.token.0, reserves.1.token.0) + .expect("tokens are distinct by construction"); // reserves are ordered by construction. - let reserves = (reserves.0.amount.as_u128(), reserves.1.amount.as_u128()); + let reserves = ( + u128::try_from(reserves.0.amount).expect("value should be lower than u128::MAX"), + u128::try_from(reserves.1.amount).expect("value should be lower than u128::MAX"), + ); - if *pool.fee.numer() > u32::MAX.into() || *pool.fee.denom() > u32::MAX.into() { + if *pool.fee.numer() > U256::from(u32::MAX) || *pool.fee.denom() > U256::from(u32::MAX) { return None; } - let fee = num::rational::Ratio::new(pool.fee.numer().as_u32(), pool.fee.denom().as_u32()); + let fee = num::rational::Ratio::new( + u32::try_from(pool.fee.numer()).expect("previous check should ensure that n <= u32::MAX"), + u32::try_from(pool.fee.denom()).expect("previous check should ensure that n <= u32::MAX"), + ); Some(Pool { - address: address.into_alloy(), + address, tokens, reserves, fee, diff --git a/crates/solvers/src/boundary/liquidity/limit_order.rs b/crates/solvers/src/boundary/liquidity/limit_order.rs index cc1aab3065..671c9526dc 100644 --- a/crates/solvers/src/boundary/liquidity/limit_order.rs +++ b/crates/solvers/src/boundary/liquidity/limit_order.rs @@ -1,8 +1,6 @@ use { crate::domain::liquidity::limit_order::LimitOrder, - alloy::primitives::Address, - ethcontract::U256, - ethrpc::alloy::conversions::IntoAlloy, + alloy::primitives::{Address, U256}, shared::{baseline_solver::BaselineSolvable, price_estimation::gas::GAS_PER_ZEROEX_ORDER}, }; @@ -13,8 +11,8 @@ impl BaselineSolvable for LimitOrder { out_token: Address, (in_amount, in_token): (U256, Address), ) -> Option { - if in_token != self.taker.token.0.into_alloy() - || out_token != self.maker.token.0.into_alloy() + if in_token != self.taker.token.0 + || out_token != self.maker.token.0 || in_amount > self.taker.amount { return None; @@ -30,8 +28,8 @@ impl BaselineSolvable for LimitOrder { in_token: Address, (out_amount, out_token): (U256, Address), ) -> Option { - if out_token != self.maker.token.0.into_alloy() - || in_token != self.taker.token.0.into_alloy() + if out_token != self.maker.token.0 + || in_token != self.taker.token.0 || out_amount > self.maker.amount { return None; @@ -52,18 +50,17 @@ mod tests { use { super::*, crate::domain::{eth, liquidity::limit_order::TakerAmount}, - ethrpc::alloy::conversions::IntoAlloy, - shared::addr, + alloy::primitives::address, }; fn create_limit_order(maker_amount: U256, taker_amount: U256, fee_amount: U256) -> LimitOrder { let maker = eth::Asset { amount: maker_amount, - token: eth::TokenAddress(addr!("a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48")), + token: eth::TokenAddress(address!("a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48")), }; let taker = eth::Asset { amount: taker_amount, - token: eth::TokenAddress(addr!("c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2")), + token: eth::TokenAddress(address!("c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2")), }; let fee = TakerAmount(fee_amount); @@ -78,8 +75,8 @@ mod tests { let desired_in_amount = to_wei(50); let order = create_limit_order(maker_amount, taker_amount, fee_amount); - let out_token = order.maker.token.0.into_alloy(); - let in_token = order.taker.token.0.into_alloy(); + let out_token = order.maker.token.0; + let in_token = order.taker.token.0; let amount_out = order .get_amount_out(out_token, (desired_in_amount, in_token)) @@ -101,8 +98,8 @@ mod tests { let desired_out_amount = to_wei(50); let order = create_limit_order(maker_amount, taker_amount, fee_amount); - let out_token = order.maker.token.0.into_alloy(); - let in_token = order.taker.token.0.into_alloy(); + let out_token = order.maker.token.0; + let in_token = order.taker.token.0; let amount_in = order .get_amount_in(in_token, (desired_out_amount, out_token)) @@ -123,8 +120,8 @@ mod tests { let fee_amount = to_wei(10); let order = create_limit_order(maker_amount, taker_amount, fee_amount); - let out_token = order.maker.token.0.into_alloy(); - let in_token = order.taker.token.0.into_alloy(); + let out_token = order.maker.token.0; + let in_token = order.taker.token.0; let amount_in = taker_amount.checked_mul(U256::from(2)).unwrap(); let amount_out = order.get_amount_out(out_token, (amount_in, in_token)).await; @@ -138,8 +135,8 @@ mod tests { let fee_amount = to_wei(10); let order = create_limit_order(maker_amount, taker_amount, fee_amount); - let out_token = order.maker.token.0.into_alloy(); - let in_token = order.taker.token.0.into_alloy(); + let out_token = order.maker.token.0; + let in_token = order.taker.token.0; let amount_out = maker_amount.checked_mul(U256::from(2)).unwrap(); let amount_in = order.get_amount_in(in_token, (amount_out, out_token)).await; @@ -153,8 +150,8 @@ mod tests { let fee_amount = to_wei(10); let order = create_limit_order(maker_amount, taker_amount, fee_amount); - let out_token = order.maker.token.0.into_alloy(); - let in_token = order.taker.token.0.into_alloy(); + let out_token = order.maker.token.0; + let in_token = order.taker.token.0; let amount = to_wei(1); let amount_in = order.get_amount_in(out_token, (amount, in_token)).await; let amount_out = order.get_amount_out(in_token, (amount, out_token)).await; @@ -164,6 +161,6 @@ mod tests { } fn to_wei(base: u32) -> U256 { - U256::from(base) * U256::exp10(18) + U256::from(base) * U256::from(10).pow(U256::from(18)) } } diff --git a/crates/solvers/src/boundary/liquidity/stable.rs b/crates/solvers/src/boundary/liquidity/stable.rs index 75e6ddbef1..faa99eb7de 100644 --- a/crates/solvers/src/boundary/liquidity/stable.rs +++ b/crates/solvers/src/boundary/liquidity/stable.rs @@ -2,7 +2,7 @@ pub use shared::sources::balancer_v2::pool_fetching::StablePool as Pool; use { crate::domain::{eth, liquidity}, ethereum_types::{H160, H256, U256}, - ethrpc::alloy::conversions::IntoAlloy, + ethrpc::alloy::conversions::{IntoAlloy, IntoLegacy}, shared::sources::balancer_v2::{ pool_fetching::{AmplificationParameter, CommonPoolState, TokenState}, swap::fixed_point::Bfp, @@ -28,17 +28,17 @@ pub fn to_boundary_pool(address: H160, pool: &liquidity::stable::Pool) -> Option .iter() .map(|reserve| { Some(( - reserve.asset.token.0.into_alloy(), + reserve.asset.token.0, TokenState { - balance: reserve.asset.amount, + balance: reserve.asset.amount.into_legacy(), scaling_factor: to_fixed_point(&reserve.scale.get())?, }, )) }) .collect::>()?; let amplification_parameter = AmplificationParameter::try_new( - *pool.amplification_parameter.numer(), - *pool.amplification_parameter.denom(), + pool.amplification_parameter.numer().into_legacy(), + pool.amplification_parameter.denom().into_legacy(), ) .ok()?; @@ -60,6 +60,6 @@ fn to_fixed_point(ratio: ð::Rational) -> Option { // of a base 2 FP format you typically see). Just convert our ratio into // this format. let base = U256::exp10(18); - let wei = ratio.numer().checked_mul(base)? / ratio.denom(); + let wei = ratio.numer().into_legacy().checked_mul(base)? / ratio.denom().into_legacy(); Some(Bfp::from_wei(wei)) } diff --git a/crates/solvers/src/boundary/liquidity/weighted_product.rs b/crates/solvers/src/boundary/liquidity/weighted_product.rs index 8713ee90bf..2733260c61 100644 --- a/crates/solvers/src/boundary/liquidity/weighted_product.rs +++ b/crates/solvers/src/boundary/liquidity/weighted_product.rs @@ -1,8 +1,9 @@ pub use shared::sources::balancer_v2::pool_fetching::WeightedPool as Pool; use { crate::domain::{eth, liquidity}, - ethereum_types::{H160, H256, U256}, - ethrpc::alloy::conversions::IntoAlloy, + alloy::primitives::Address, + ethereum_types::{H256, U256}, + ethrpc::alloy::conversions::IntoLegacy, shared::sources::balancer_v2::{ pool_fetching::{CommonPoolState, TokenState, WeightedPoolVersion, WeightedTokenState}, swap::fixed_point::Bfp, @@ -11,14 +12,17 @@ use { /// Converts a domain pool into a [`shared`] Balancer V2 weighted pool. Returns /// `None` if the domain pool cannot be represented as a boundary pool. -pub fn to_boundary_pool(address: H160, pool: &liquidity::weighted_product::Pool) -> Option { +pub fn to_boundary_pool( + address: Address, + pool: &liquidity::weighted_product::Pool, +) -> Option { // NOTE: this is only used for encoding and not for solving, so it's OK to // use this an approximate value for now. In fact, Balancer V2 pool IDs // are `pool address || pool kind || pool index`, so this approximation is // pretty good. let id = { let mut buf = [0_u8; 32]; - buf[..20].copy_from_slice(address.as_bytes()); + buf[..20].copy_from_slice(address.as_slice()); H256(buf) }; @@ -28,10 +32,10 @@ pub fn to_boundary_pool(address: H160, pool: &liquidity::weighted_product::Pool) .iter() .map(|reserve| { Some(( - reserve.asset.token.0.into_alloy(), + reserve.asset.token.0, WeightedTokenState { common: TokenState { - balance: reserve.asset.amount, + balance: reserve.asset.amount.into_legacy(), scaling_factor: to_fixed_point(&reserve.scale.get())?, }, weight: to_fixed_point(&reserve.weight)?, @@ -43,7 +47,7 @@ pub fn to_boundary_pool(address: H160, pool: &liquidity::weighted_product::Pool) Some(Pool { common: CommonPoolState { id, - address: address.into_alloy(), + address, swap_fee, paused: false, }, @@ -61,6 +65,6 @@ fn to_fixed_point(ratio: ð::Rational) -> Option { // of a base 2 FP format you typically see). Just convert our ratio into // this format. let base = U256::exp10(18); - let wei = ratio.numer().checked_mul(base)? / ratio.denom(); + let wei = ratio.numer().into_legacy().checked_mul(base)? / ratio.denom().into_legacy(); Some(Bfp::from_wei(wei)) } diff --git a/crates/solvers/src/domain/auction.rs b/crates/solvers/src/domain/auction.rs index dcfc26e09f..b73340aaa8 100644 --- a/crates/solvers/src/domain/auction.rs +++ b/crates/solvers/src/domain/auction.rs @@ -1,6 +1,5 @@ use { crate::domain::{eth, liquidity, order}, - ethereum_types::U256, std::{ collections::HashMap, fmt::{self, Display, Formatter}, @@ -58,7 +57,7 @@ pub struct Token { pub decimals: Option, pub symbol: Option, pub reference_price: Option, - pub available_balance: U256, + pub available_balance: eth::U256, pub trusted: bool, } @@ -73,8 +72,10 @@ impl Price { /// Computes an amount equivalent in value to the specified [`eth::Ether`] /// at the given price. - pub fn ether_value(&self, eth: eth::Ether) -> Option { - eth.0.checked_mul(Self::BASE.into())?.checked_div(self.0.0) + pub fn ether_value(&self, eth: eth::Ether) -> Option { + eth.0 + .checked_mul(eth::U256::from(Self::BASE))? + .checked_div(self.0.0) } } diff --git a/crates/solvers/src/domain/eth/mod.rs b/crates/solvers/src/domain/eth/mod.rs index 41de18f275..08896eacc1 100644 --- a/crates/solvers/src/domain/eth/mod.rs +++ b/crates/solvers/src/domain/eth/mod.rs @@ -1,25 +1,25 @@ -pub use ethereum_types::{H160, H256, U256}; +pub use alloy::primitives::{Address, B256, U256}; use {crate::util::bytes::Bytes, derive_more::From, web3::types::AccessList}; /// A contract address. #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct ContractAddress(pub H160); +pub struct ContractAddress(pub Address); /// An ERC20 token address. /// /// https://eips.ethereum.org/EIPS/eip-20 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct TokenAddress(pub H160); +pub struct TokenAddress(pub Address); -impl From for TokenAddress { - fn from(inner: H160) -> Self { +impl From
for TokenAddress { + fn from(inner: Address) -> Self { Self(inner) } } /// The WETH token (or equivalent) for the EVM compatible network. #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct WethAddress(pub H160); +pub struct WethAddress(pub Address); /// An asset on the Ethereum blockchain. Represents a particular amount of a /// particular token. @@ -56,9 +56,9 @@ impl std::ops::Add for Gas { fn add(self, rhs: SignedGas) -> Self::Output { if rhs.0.is_positive() { - Self(self.0.saturating_add(rhs.0.into())) + Self(self.0.saturating_add(U256::from(rhs.0))) } else { - Self(self.0.saturating_sub(rhs.0.abs().into())) + Self(self.0.saturating_sub(U256::from(rhs.0.abs()))) } } } @@ -66,10 +66,6 @@ impl std::ops::Add for Gas { /// A 256-bit rational type. pub type Rational = num::rational::Ratio; -/// An address. Can be an EOA or a smart contract address. -#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct Address(pub H160); - /// An onchain transaction. #[derive(Debug, Clone)] pub struct Tx { diff --git a/crates/solvers/src/domain/liquidity/constant_product.rs b/crates/solvers/src/domain/liquidity/constant_product.rs index 14842109fd..c63015aaaf 100644 --- a/crates/solvers/src/domain/liquidity/constant_product.rs +++ b/crates/solvers/src/domain/liquidity/constant_product.rs @@ -2,7 +2,7 @@ use { crate::domain::{eth, liquidity}, - ethereum_types::U256, + alloy::primitives::U256, std::cmp::Ordering, }; diff --git a/crates/solvers/src/domain/liquidity/limit_order.rs b/crates/solvers/src/domain/liquidity/limit_order.rs index d2065f7a22..94a1463a45 100644 --- a/crates/solvers/src/domain/liquidity/limit_order.rs +++ b/crates/solvers/src/domain/liquidity/limit_order.rs @@ -1,4 +1,4 @@ -use {crate::domain::eth, ethereum_types::U256}; +use crate::domain::eth; /// A 0x-like foreign limit order. #[derive(Clone, Debug)] @@ -10,4 +10,4 @@ pub struct LimitOrder { /// An amount denominated in the taker token of a [`LimitOrder`]. #[derive(Debug, Clone, Copy)] -pub struct TakerAmount(pub U256); +pub struct TakerAmount(pub eth::U256); diff --git a/crates/solvers/src/domain/liquidity/mod.rs b/crates/solvers/src/domain/liquidity/mod.rs index eb7c265702..7a0075bee8 100644 --- a/crates/solvers/src/domain/liquidity/mod.rs +++ b/crates/solvers/src/domain/liquidity/mod.rs @@ -6,13 +6,13 @@ pub mod limit_order; pub mod stable; pub mod weighted_product; -use {crate::domain::eth, ethereum_types::H160, std::cmp::Ordering}; +use {crate::domain::eth, std::cmp::Ordering}; /// A source of liquidity which can be used by the solver. #[derive(Clone, Debug)] pub struct Liquidity { pub id: Id, - pub address: H160, + pub address: eth::Address, /// Estimation of gas needed to use this liquidity on-chain. pub gas: eth::Gas, pub state: State, @@ -74,6 +74,6 @@ impl ScalingFactor { impl Default for ScalingFactor { fn default() -> Self { - Self(eth::Rational::new_raw(1.into(), 1.into())) + Self(eth::Rational::new_raw(eth::U256::ONE, eth::U256::ONE)) } } diff --git a/crates/solvers/src/domain/notification.rs b/crates/solvers/src/domain/notification.rs index 83b255931d..2a33d5ef49 100644 --- a/crates/solvers/src/domain/notification.rs +++ b/crates/solvers/src/domain/notification.rs @@ -9,7 +9,7 @@ use { type RequiredEther = Ether; type TokensUsed = BTreeSet; -type TransactionHash = eth::H256; +type TransactionHash = eth::B256; type Transaction = eth::Tx; type BlockNo = u64; pub type SimulationSucceededAtLeastOnce = bool; diff --git a/crates/solvers/src/domain/order.rs b/crates/solvers/src/domain/order.rs index 026cd07679..c614950e6c 100644 --- a/crates/solvers/src/domain/order.rs +++ b/crates/solvers/src/domain/order.rs @@ -2,8 +2,8 @@ use { crate::{domain::eth, util}, - ethcontract::H160, - ethereum_types::{Address, H256}, + eth::Address, + ethereum_types::H256, std::fmt::{self, Debug, Display, Formatter}, }; @@ -149,6 +149,6 @@ pub struct FlashloanHint { #[derive(Debug, Clone)] pub struct WrapperCall { - pub address: H160, + pub address: eth::Address, pub data: Vec, } diff --git a/crates/solvers/src/domain/solution.rs b/crates/solvers/src/domain/solution.rs index ae81bb227b..7dcdb35d67 100644 --- a/crates/solvers/src/domain/solution.rs +++ b/crates/solvers/src/domain/solution.rs @@ -1,6 +1,6 @@ use { crate::domain::{auction, eth, liquidity, order}, - ethereum_types::{Address, U256}, + eth::{Address, U256}, std::{collections::HashMap, slice}, }; @@ -193,7 +193,7 @@ impl Single { wrappers: wrappers .iter() .map(|w| WrapperCall { - target: eth::Address(w.address), + target: w.address, data: w.data.clone(), }) .collect(), diff --git a/crates/solvers/src/domain/solver.rs b/crates/solvers/src/domain/solver.rs index 1946b9c6e4..4dda735318 100644 --- a/crates/solvers/src/domain/solver.rs +++ b/crates/solvers/src/domain/solver.rs @@ -18,7 +18,7 @@ use { }, infra::metrics, }, - ethereum_types::U256, + alloy::primitives::U256, reqwest::Url, std::{cmp, collections::HashSet, sync::Arc}, tracing::Instrument, @@ -161,7 +161,7 @@ impl Inner { Some(price) => price, None if sell_token == self.weth.0.into() => { // Early return if the sell token is native token - auction::Price(eth::Ether(eth::U256::exp10(18))) + auction::Price(eth::Ether(eth::U256::from(10).pow(eth::U256::from(18)))) } None => { // Estimate the price of the sell token in the native token @@ -173,8 +173,8 @@ impl Inner { Some(route) => { // how many units of buy_token are bought for one unit of sell_token // (buy_amount / sell_amount). - let price = self.native_token_price_estimation_amount.to_f64_lossy() - / route.input().amount.to_f64_lossy(); + let price = f64::from(self.native_token_price_estimation_amount) + / f64::from(route.input().amount); let Some(price) = to_normalized_price(price) else { continue; }; @@ -267,7 +267,7 @@ impl Inner { (0..n) .map(move |i| { - let divisor = U256::one() << i; + let divisor = U256::ONE << i; Request { sell: eth::Asset { token: sell.token, @@ -296,7 +296,7 @@ impl Inner { // `type(uint112).max` without overflowing a `uint256` on the smart // contract level. Requiring to trade more than `type(uint112).max` // is unlikely and would not work with Uniswap V2 anyway. - amount: eth::U256::one() << 144, + amount: eth::U256::ONE << 144, }; let buy = eth::Asset { @@ -318,7 +318,7 @@ fn to_normalized_price(price: f64) -> Option { let price_in_eth = 1e18 * price; if price_in_eth.is_normal() && price_in_eth >= 1. && price_in_eth < uint_max { - Some(U256::from_f64_lossy(price_in_eth)) + Some(U256::from(price_in_eth)) } else { None } @@ -374,8 +374,10 @@ impl<'a> Route<'a> { } fn gas(&self) -> eth::Gas { - eth::Gas(self.segments.iter().fold(U256::zero(), |acc, segment| { - acc.saturating_add(segment.gas.0) - })) + eth::Gas( + self.segments + .iter() + .fold(U256::ZERO, |acc, segment| acc.saturating_add(segment.gas.0)), + ) } } diff --git a/crates/solvers/src/infra/config.rs b/crates/solvers/src/infra/config.rs index 09efc92453..373debe69c 100644 --- a/crates/solvers/src/infra/config.rs +++ b/crates/solvers/src/infra/config.rs @@ -2,19 +2,15 @@ use { crate::{ domain::{eth, solver}, infra::contracts, - util::serialize, }, chain::Chain, - ethereum_types::H160, reqwest::Url, serde::Deserialize, - serde_with::serde_as, shared::price_estimation::gas::SETTLEMENT_OVERHEAD, std::{fmt::Debug, path::Path}, tokio::fs, }; -#[serde_as] #[derive(Deserialize)] #[serde(rename_all = "kebab-case", deny_unknown_fields)] struct Config { @@ -25,12 +21,12 @@ struct Config { /// Optional WETH contract address. This can be used to specify a manual /// value **instead** of using the canonical WETH contract for the /// configured chain. - weth: Option, + weth: Option, /// List of base tokens to use when path finding. This defines the tokens /// that can appear as intermediate "hops" within a trading route. Note that /// WETH is always considered as a base token. - base_tokens: Vec, + base_tokens: Vec, /// The maximum number of hops to consider when finding the optimal trading /// path. @@ -47,7 +43,6 @@ struct Config { /// The amount of the native token to use to estimate native price of a /// token - #[serde_as(as = "serialize::U256")] native_token_price_estimation_amount: eth::U256, /// If this is configured the solver will also use the Uniswap V3 liquidity diff --git a/crates/solvers/src/infra/contracts.rs b/crates/solvers/src/infra/contracts.rs index 0b159ca085..f57e5559e3 100644 --- a/crates/solvers/src/infra/contracts.rs +++ b/crates/solvers/src/infra/contracts.rs @@ -1,9 +1,4 @@ -use { - crate::domain::eth, - chain::Chain, - contracts::alloy::WETH9, - ethrpc::alloy::conversions::IntoLegacy, -}; +use {crate::domain::eth, chain::Chain, contracts::alloy::WETH9}; #[derive(Clone, Debug)] pub struct Contracts { @@ -15,8 +10,7 @@ impl Contracts { Self { weth: eth::WethAddress( WETH9::deployment_address(&chain.id()) - .expect("there should be a contract address for all supported chains") - .into_legacy(), + .expect("there should be a contract address for all supported chains"), ), } } diff --git a/crates/solvers/src/util/conv.rs b/crates/solvers/src/util/conv.rs index a7d1bdb6b4..616e0420f9 100644 --- a/crates/solvers/src/util/conv.rs +++ b/crates/solvers/src/util/conv.rs @@ -2,8 +2,8 @@ use { crate::domain::eth, + alloy::primitives::U256, bigdecimal::BigDecimal, - ethereum_types::U256, num::{BigInt, BigUint, One, rational::Ratio}, }; @@ -36,13 +36,11 @@ pub fn biguint_to_u256(i: &BigUint) -> Option { if bytes.len() > 32 { return None; } - Some(U256::from_big_endian(&bytes)) + Some(U256::from_be_slice(&bytes)) } pub fn u256_to_biguint(i: &U256) -> BigUint { - let mut bytes = [0_u8; 32]; - i.to_big_endian(&mut bytes); - BigUint::from_bytes_be(&bytes) + BigUint::from_bytes_be(i.to_be_bytes::<32>().as_slice()) } /// Converts a `BigDecimal` amount in Ether units to wei. @@ -59,7 +57,7 @@ pub fn ether_to_decimal(e: ð::Ether) -> BigDecimal { #[cfg(test)] mod tests { - use super::*; + use {super::*, alloy::primitives::U256}; #[test] fn decimal_to_rational_conversions() { @@ -74,8 +72,8 @@ mod tests { ("0.003", 3, 1000), ] { let result = decimal_to_rational(&value.parse().unwrap()).unwrap(); - assert_eq!(result.numer().as_u64(), numer); - assert_eq!(result.denom().as_u64(), denom); + assert_eq!(u64::try_from(result.numer()).unwrap(), numer); + assert_eq!(u64::try_from(result.denom()).unwrap(), denom); } } @@ -102,7 +100,7 @@ mod tests { ("10", 10_000_000_000_000_000_000), ] { let decimal = decimal.parse().unwrap(); - let ether = eth::Ether(ether.into()); + let ether = eth::Ether(U256::from(ether)); assert_eq!(decimal_to_ether(&decimal).unwrap(), ether); assert_eq!(ether_to_decimal(ðer), decimal); diff --git a/crates/solvers/src/util/mod.rs b/crates/solvers/src/util/mod.rs index 051f909a2d..6dc666de3d 100644 --- a/crates/solvers/src/util/mod.rs +++ b/crates/solvers/src/util/mod.rs @@ -1,4 +1,3 @@ pub mod bytes; pub mod conv; pub mod fmt; -pub mod serialize; diff --git a/crates/solvers/src/util/serialize/mod.rs b/crates/solvers/src/util/serialize/mod.rs deleted file mode 100644 index fdfefaeb6a..0000000000 --- a/crates/solvers/src/util/serialize/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod u256; - -pub use self::u256::U256; diff --git a/crates/solvers/src/util/serialize/u256.rs b/crates/solvers/src/util/serialize/u256.rs deleted file mode 100644 index ca196171a1..0000000000 --- a/crates/solvers/src/util/serialize/u256.rs +++ /dev/null @@ -1,19 +0,0 @@ -use { - serde::{Deserialize, Deserializer, de}, - serde_with::DeserializeAs, - std::borrow::Cow, -}; - -/// Serialize and deserialize [`ethereum_types::U256`] as a decimal string. -#[derive(Debug)] -pub struct U256; - -impl<'de> DeserializeAs<'de, ethereum_types::U256> for U256 { - fn deserialize_as>( - deserializer: D, - ) -> Result { - let s = Cow::::deserialize(deserializer)?; - ethereum_types::U256::from_dec_str(&s) - .map_err(|err| de::Error::custom(format!("failed to parse {s:?} as a U256: {err}"))) - } -} From 3b9222ed03b06d530081b15c34f9ed1e3c3762e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=CC=81=20Duarte?= Date: Tue, 9 Dec 2025 14:39:54 +0000 Subject: [PATCH 2/6] fix tests --- crates/autopilot/src/domain/auction/mod.rs | 12 +++++++--- .../driver/src/domain/competition/auction.rs | 24 ++++++++++++++----- crates/driver/src/tests/setup/mod.rs | 2 +- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/crates/autopilot/src/domain/auction/mod.rs b/crates/autopilot/src/domain/auction/mod.rs index e4c3bc6a50..3580bebe64 100644 --- a/crates/autopilot/src/domain/auction/mod.rs +++ b/crates/autopilot/src/domain/auction/mod.rs @@ -70,11 +70,17 @@ impl Price { /// ``` /// use autopilot::domain::{auction::Price, eth}; /// - /// let amount = eth::TokenAmount::from(eth::U256::exp10(18)); - /// let price = Price::try_new(eth::Ether::from(eth::U256::exp10(15))).unwrap(); // 0.001 ETH + /// let amount = eth::TokenAmount::from(eth::U256::from(10).pow(eth::U256::from(18))); + /// let price = Price::try_new(eth::Ether::from( + /// eth::U256::from(10).pow(eth::U256::from(15)), // 0.001 ETH + /// )) + /// .unwrap(); /// /// let eth = price.in_eth(amount); - /// assert_eq!(eth, eth::Ether::from(eth::U256::exp10(15))); + /// assert_eq!( + /// eth, + /// eth::Ether::from(eth::U256::from(10).pow(eth::U256::from(15))) + /// ); /// ``` pub fn in_eth(self, amount: eth::TokenAmount) -> eth::Ether { (amount.0 * self.0.0 / U256::from(Self::BASE)).into() diff --git a/crates/driver/src/domain/competition/auction.rs b/crates/driver/src/domain/competition/auction.rs index b111b2e664..b7de0e3715 100644 --- a/crates/driver/src/domain/competition/auction.rs +++ b/crates/driver/src/domain/competition/auction.rs @@ -173,11 +173,17 @@ impl Price { /// ``` /// use driver::domain::{competition::auction::Price, eth}; /// - /// let amount = eth::TokenAmount::from(eth::U256::exp10(18)); - /// let price = Price::try_new(eth::Ether::from(eth::U256::exp10(15))).unwrap(); // 0.001 ETH + /// let amount = eth::TokenAmount::from(eth::U256::from(10).pow(eth::U256::from(18))); + /// let price = Price::try_new(eth::Ether::from( + /// eth::U256::from(10).pow(eth::U256::from(15)), + /// )) + /// .unwrap(); // 0.001 ETH /// /// let eth = price.in_eth(amount); - /// assert_eq!(eth, eth::Ether::from(eth::U256::exp10(15))); + /// assert_eq!( + /// eth, + /// eth::Ether::from(eth::U256::from(10).pow(eth::U256::from(15))) + /// ); /// ``` pub fn in_eth(self, amount: eth::TokenAmount) -> eth::Ether { (amount.0 * self.0.0 / eth::U256::from(Self::BASE)).into() @@ -191,9 +197,15 @@ impl Price { /// ``` /// use driver::domain::{competition::auction::Price, eth}; /// - /// let amount = eth::Ether::from(eth::U256::exp10(18)); - /// let price = Price::try_new(eth::Ether::from(eth::U256::exp10(17))).unwrap(); // 0.1ETH - /// assert_eq!(price.from_eth(amount), eth::U256::exp10(19).into()); + /// let amount = eth::Ether::from(eth::U256::from(10).pow(eth::U256::from(18))); + /// let price = Price::try_new(eth::Ether::from( + /// eth::U256::from(10).pow(eth::U256::from(17)), + /// )) + /// .unwrap(); // 0.1ETH + /// assert_eq!( + /// price.from_eth(amount), + /// eth::U256::from(10).pow(eth::U256::from(19)).into() + /// ); /// ``` pub fn from_eth(self, amount: eth::Ether) -> eth::TokenAmount { (amount.0 * eth::U256::from(Self::BASE) / self.0.0).into() diff --git a/crates/driver/src/tests/setup/mod.rs b/crates/driver/src/tests/setup/mod.rs index dbe969f163..7fbd7433ec 100644 --- a/crates/driver/src/tests/setup/mod.rs +++ b/crates/driver/src/tests/setup/mod.rs @@ -370,7 +370,7 @@ struct Slippage { pub fn test_solver() -> Solver { Solver { name: solver::NAME.to_owned(), - balance: eth::U256::from(10).pow(eth::U256::from(10)), + balance: eth::U256::from(10).pow(eth::U256::from(18)), private_key: ethcontract::PrivateKey::from_slice( const_hex::decode("a131a35fb8f614b31611f4fe68b6fc538b0febd2f75cd68e1282d8fd45b63326") .unwrap(), From b202f00ac08dae56e8bd92a078732788503e7480 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=CC=81=20Duarte?= Date: Tue, 9 Dec 2025 17:31:34 +0000 Subject: [PATCH 3/6] Address comments --- crates/driver/src/domain/eth/mod.rs | 1 - crates/driver/src/infra/config/file/mod.rs | 12 +------ crates/driver/src/util/serialize/mod.rs | 3 +- crates/driver/src/util/serialize/u256.rs | 42 ---------------------- 4 files changed, 2 insertions(+), 56 deletions(-) delete mode 100644 crates/driver/src/util/serialize/u256.rs diff --git a/crates/driver/src/domain/eth/mod.rs b/crates/driver/src/domain/eth/mod.rs index 792a006e9c..4310732df9 100644 --- a/crates/driver/src/domain/eth/mod.rs +++ b/crates/driver/src/domain/eth/mod.rs @@ -259,7 +259,6 @@ impl From for num::BigInt { } } -// TODO: check if actually needed impl From for Ether { fn from(value: i32) -> Self { Self(U256::from(value)) diff --git a/crates/driver/src/infra/config/file/mod.rs b/crates/driver/src/infra/config/file/mod.rs index 2276787960..ef1dbaddab 100644 --- a/crates/driver/src/infra/config/file/mod.rs +++ b/crates/driver/src/infra/config/file/mod.rs @@ -1,8 +1,7 @@ pub use load::load; use { - crate::{domain::eth, infra, util::serialize}, + crate::{domain::eth, infra}, alloy::primitives::Address, - number::serialization::HexOrDecimalU256, reqwest::Url, serde::{Deserialize, Deserializer, Serialize}, serde_with::serde_as, @@ -30,7 +29,6 @@ struct Config { /// Disable gas simulation and always use this fixed gas value instead. This /// can be useful for testing, but shouldn't be used in production since it /// will cause the driver to return invalid scores. - #[serde_as(as = "Option")] disable_gas_simulation: Option, /// Defines the gas estimator to use. @@ -84,24 +82,20 @@ struct Config { #[serde(default)] flashloans_enabled: bool, - #[serde_as(as = "HexOrDecimalU256")] tx_gas_limit: eth::U256, } -#[serde_as] #[derive(Debug, Default, Deserialize)] #[serde(rename_all = "kebab-case", deny_unknown_fields)] struct SubmissionConfig { /// The minimum priority fee in Gwei the solver is ensuring to pay in a /// settlement. #[serde(default)] - #[serde_as(as = "serialize::U256")] min_priority_fee: eth::U256, /// The maximum gas price in Gwei the solver is willing to pay in a /// settlement. #[serde(default = "default_gas_price_cap")] - #[serde_as(as = "serialize::U256")] gas_price_cap: eth::U256, /// The target confirmation time for settlement transactions used @@ -144,7 +138,6 @@ impl From for web3::types::BlockNumber { } } -#[serde_as] #[derive(Debug, Deserialize)] #[serde(tag = "mempool")] #[serde(rename_all = "kebab-case", deny_unknown_fields)] @@ -154,7 +147,6 @@ enum Mempool { /// Maximum additional tip in Gwei that we are willing to pay /// above regular gas price estimation. #[serde(default = "default_max_additional_tip")] - #[serde_as(as = "serialize::U256")] max_additional_tip: eth::U256, /// Additional tip in percentage of max_fee_per_gas we are willing to /// pay above regular gas price estimation. Expects a @@ -169,7 +161,6 @@ enum Mempool { /// Maximum additional tip in Gwei that we are willing to give to /// MEVBlocker above regular gas price estimation. #[serde(default = "default_max_additional_tip")] - #[serde_as(as = "serialize::U256")] max_additional_tip: eth::U256, /// Additional tip in percentage of max_fee_per_gas we are giving to /// MEVBlocker above regular gas price estimation. Expects a @@ -382,7 +373,6 @@ struct Slippage { /// The absolute slippage allowed by the solver. #[serde(rename = "absolute-slippage")] - #[serde_as(as = "Option")] absolute: Option, } diff --git a/crates/driver/src/util/serialize/mod.rs b/crates/driver/src/util/serialize/mod.rs index 71ee479979..3a51113212 100644 --- a/crates/driver/src/util/serialize/mod.rs +++ b/crates/driver/src/util/serialize/mod.rs @@ -1,6 +1,5 @@ //! Serialization utilities for use with [`serde_with::serde_as`] macros. mod hex; -mod u256; -pub use {self::hex::Hex, u256::U256}; +pub use self::hex::Hex; diff --git a/crates/driver/src/util/serialize/u256.rs b/crates/driver/src/util/serialize/u256.rs deleted file mode 100644 index 3984c117dc..0000000000 --- a/crates/driver/src/util/serialize/u256.rs +++ /dev/null @@ -1,42 +0,0 @@ -use { - crate::domain::eth, - serde::{Deserializer, Serializer, de}, - serde_with::{DeserializeAs, SerializeAs}, -}; - -// NOTE(jmg-duarte): not sure if we still need this module - -/// Serialize and deserialize [`eth::U256`] as a decimal string. -#[derive(Debug)] -pub struct U256; - -impl<'de> DeserializeAs<'de, eth::U256> for U256 { - fn deserialize_as>(deserializer: D) -> Result { - struct Visitor; - - impl de::Visitor<'_> for Visitor { - type Value = eth::U256; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(formatter, "a 256-bit decimal string") - } - - fn visit_str(self, s: &str) -> Result - where - E: de::Error, - { - eth::U256::from_str_radix(s, 10).map_err(|err| { - de::Error::custom(format!("failed to decode {s:?} as a 256-bit number: {err}")) - }) - } - } - - deserializer.deserialize_str(Visitor) - } -} - -impl SerializeAs for U256 { - fn serialize_as(source: ð::U256, serializer: S) -> Result { - serializer.serialize_str(&source.to_string()) - } -} From e3af3046e0437a0341d833a35ab17e99b451510a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=CC=81=20Duarte?= Date: Wed, 10 Dec 2025 08:53:52 +0000 Subject: [PATCH 4/6] Revert "Address comments" This reverts commit b202f00ac08dae56e8bd92a078732788503e7480. --- crates/driver/src/domain/eth/mod.rs | 1 + crates/driver/src/infra/config/file/mod.rs | 12 ++++++- crates/driver/src/util/serialize/mod.rs | 3 +- crates/driver/src/util/serialize/u256.rs | 42 ++++++++++++++++++++++ 4 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 crates/driver/src/util/serialize/u256.rs diff --git a/crates/driver/src/domain/eth/mod.rs b/crates/driver/src/domain/eth/mod.rs index 4310732df9..792a006e9c 100644 --- a/crates/driver/src/domain/eth/mod.rs +++ b/crates/driver/src/domain/eth/mod.rs @@ -259,6 +259,7 @@ impl From for num::BigInt { } } +// TODO: check if actually needed impl From for Ether { fn from(value: i32) -> Self { Self(U256::from(value)) diff --git a/crates/driver/src/infra/config/file/mod.rs b/crates/driver/src/infra/config/file/mod.rs index ef1dbaddab..2276787960 100644 --- a/crates/driver/src/infra/config/file/mod.rs +++ b/crates/driver/src/infra/config/file/mod.rs @@ -1,7 +1,8 @@ pub use load::load; use { - crate::{domain::eth, infra}, + crate::{domain::eth, infra, util::serialize}, alloy::primitives::Address, + number::serialization::HexOrDecimalU256, reqwest::Url, serde::{Deserialize, Deserializer, Serialize}, serde_with::serde_as, @@ -29,6 +30,7 @@ struct Config { /// Disable gas simulation and always use this fixed gas value instead. This /// can be useful for testing, but shouldn't be used in production since it /// will cause the driver to return invalid scores. + #[serde_as(as = "Option")] disable_gas_simulation: Option, /// Defines the gas estimator to use. @@ -82,20 +84,24 @@ struct Config { #[serde(default)] flashloans_enabled: bool, + #[serde_as(as = "HexOrDecimalU256")] tx_gas_limit: eth::U256, } +#[serde_as] #[derive(Debug, Default, Deserialize)] #[serde(rename_all = "kebab-case", deny_unknown_fields)] struct SubmissionConfig { /// The minimum priority fee in Gwei the solver is ensuring to pay in a /// settlement. #[serde(default)] + #[serde_as(as = "serialize::U256")] min_priority_fee: eth::U256, /// The maximum gas price in Gwei the solver is willing to pay in a /// settlement. #[serde(default = "default_gas_price_cap")] + #[serde_as(as = "serialize::U256")] gas_price_cap: eth::U256, /// The target confirmation time for settlement transactions used @@ -138,6 +144,7 @@ impl From for web3::types::BlockNumber { } } +#[serde_as] #[derive(Debug, Deserialize)] #[serde(tag = "mempool")] #[serde(rename_all = "kebab-case", deny_unknown_fields)] @@ -147,6 +154,7 @@ enum Mempool { /// Maximum additional tip in Gwei that we are willing to pay /// above regular gas price estimation. #[serde(default = "default_max_additional_tip")] + #[serde_as(as = "serialize::U256")] max_additional_tip: eth::U256, /// Additional tip in percentage of max_fee_per_gas we are willing to /// pay above regular gas price estimation. Expects a @@ -161,6 +169,7 @@ enum Mempool { /// Maximum additional tip in Gwei that we are willing to give to /// MEVBlocker above regular gas price estimation. #[serde(default = "default_max_additional_tip")] + #[serde_as(as = "serialize::U256")] max_additional_tip: eth::U256, /// Additional tip in percentage of max_fee_per_gas we are giving to /// MEVBlocker above regular gas price estimation. Expects a @@ -373,6 +382,7 @@ struct Slippage { /// The absolute slippage allowed by the solver. #[serde(rename = "absolute-slippage")] + #[serde_as(as = "Option")] absolute: Option, } diff --git a/crates/driver/src/util/serialize/mod.rs b/crates/driver/src/util/serialize/mod.rs index 3a51113212..71ee479979 100644 --- a/crates/driver/src/util/serialize/mod.rs +++ b/crates/driver/src/util/serialize/mod.rs @@ -1,5 +1,6 @@ //! Serialization utilities for use with [`serde_with::serde_as`] macros. mod hex; +mod u256; -pub use self::hex::Hex; +pub use {self::hex::Hex, u256::U256}; diff --git a/crates/driver/src/util/serialize/u256.rs b/crates/driver/src/util/serialize/u256.rs new file mode 100644 index 0000000000..3984c117dc --- /dev/null +++ b/crates/driver/src/util/serialize/u256.rs @@ -0,0 +1,42 @@ +use { + crate::domain::eth, + serde::{Deserializer, Serializer, de}, + serde_with::{DeserializeAs, SerializeAs}, +}; + +// NOTE(jmg-duarte): not sure if we still need this module + +/// Serialize and deserialize [`eth::U256`] as a decimal string. +#[derive(Debug)] +pub struct U256; + +impl<'de> DeserializeAs<'de, eth::U256> for U256 { + fn deserialize_as>(deserializer: D) -> Result { + struct Visitor; + + impl de::Visitor<'_> for Visitor { + type Value = eth::U256; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "a 256-bit decimal string") + } + + fn visit_str(self, s: &str) -> Result + where + E: de::Error, + { + eth::U256::from_str_radix(s, 10).map_err(|err| { + de::Error::custom(format!("failed to decode {s:?} as a 256-bit number: {err}")) + }) + } + } + + deserializer.deserialize_str(Visitor) + } +} + +impl SerializeAs for U256 { + fn serialize_as(source: ð::U256, serializer: S) -> Result { + serializer.serialize_str(&source.to_string()) + } +} From 90a380f75f02e48c659f6866526802f6ef2bc0b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=CC=81=20Duarte?= Date: Wed, 10 Dec 2025 11:23:34 +0000 Subject: [PATCH 5/6] Address comments --- .../domain/competition/solution/scoring.rs | 5 +-- crates/driver/src/tests/setup/mod.rs | 3 +- .../boundary/liquidity/constant_product.rs | 39 +++++++++++++------ 3 files changed, 30 insertions(+), 17 deletions(-) diff --git a/crates/driver/src/domain/competition/solution/scoring.rs b/crates/driver/src/domain/competition/solution/scoring.rs index 89b25da344..3eda33bdf4 100644 --- a/crates/driver/src/domain/competition/solution/scoring.rs +++ b/crates/driver/src/domain/competition/solution/scoring.rs @@ -113,9 +113,8 @@ impl Trade { .widening_mul(self.signed_buy.amount.0) .checked_div(alloy::primitives::U512::from(self.signed_sell.amount.0)) .ok_or(Error::Math(Math::DivisionByZero))?; - let surplus_in_buy_tokens: eth::U256 = - eth::U256::uint_try_from(surplus_in_buy_tokens) - .map_err(|_| Error::Math(Math::Overflow))?; + let surplus_in_buy_tokens = eth::U256::uint_try_from(surplus_in_buy_tokens) + .map_err(|_| Error::Math(Math::Overflow))?; // Afterwards we convert the buy token surplus to the native token. native_price_buy.in_eth(surplus_in_buy_tokens.into()) diff --git a/crates/driver/src/tests/setup/mod.rs b/crates/driver/src/tests/setup/mod.rs index 7fbd7433ec..dfa812c73e 100644 --- a/crates/driver/src/tests/setup/mod.rs +++ b/crates/driver/src/tests/setup/mod.rs @@ -892,7 +892,6 @@ impl Setup { } = self; // Hardcoded trader account. Don't use this account for anything else!!! - let trader_address = TRADER_ADDRESS; let trader_secret_key = SecretKey::from_slice( &const_hex::decode("f9f831cee763ef826b8d45557f0f8677b27045e0e011bcd78571a40acc8a6cc3") .unwrap(), @@ -987,7 +986,7 @@ impl Setup { blockchain, driver, client: Default::default(), - trader_address, + trader_address: TRADER_ADDRESS, trades: solutions.into_iter().flat_map(|s| s.trades).collect(), trusted, deadline, diff --git a/crates/solvers/src/boundary/liquidity/constant_product.rs b/crates/solvers/src/boundary/liquidity/constant_product.rs index 2105a47c59..6fe32c2fc2 100644 --- a/crates/solvers/src/boundary/liquidity/constant_product.rs +++ b/crates/solvers/src/boundary/liquidity/constant_product.rs @@ -1,9 +1,5 @@ pub use shared::sources::uniswap_v2::pool_fetching::Pool; -use { - crate::domain::liquidity, - alloy::primitives::{Address, U256}, - model::TokenPair, -}; +use {crate::domain::liquidity, alloy::primitives::Address, model::TokenPair}; /// Converts a domain pool into a [`shared`] Uniswap V2 pool. Returns `None` if /// the domain pool cannot be represented as a boundary pool. @@ -17,16 +13,35 @@ pub fn to_boundary_pool( // reserves are ordered by construction. let reserves = ( - u128::try_from(reserves.0.amount).expect("value should be lower than u128::MAX"), - u128::try_from(reserves.1.amount).expect("value should be lower than u128::MAX"), + u128::try_from(reserves.0.amount) + .inspect_err(|_| { + tracing::trace!( + address = %reserves.0.token.0, + "failed to convert asset 0 amount to u128" + ); + }) + .ok()?, + u128::try_from(reserves.1.amount) + .inspect_err(|_| { + tracing::trace!( + address = %reserves.1.token.0, + "failed to convert asset 1 amount to u128" + ); + }) + .ok()?, ); - if *pool.fee.numer() > U256::from(u32::MAX) || *pool.fee.denom() > U256::from(u32::MAX) { - return None; - } let fee = num::rational::Ratio::new( - u32::try_from(pool.fee.numer()).expect("previous check should ensure that n <= u32::MAX"), - u32::try_from(pool.fee.denom()).expect("previous check should ensure that n <= u32::MAX"), + u32::try_from(pool.fee.numer()) + .inspect_err( + |_| tracing::trace!(pool = ?pool.reserves, "pool fee numerator > u32::MAX"), + ) + .ok()?, + u32::try_from(pool.fee.denom()) + .inspect_err( + |_| tracing::trace!(pool = ?pool.reserves, "pool fee numerator > u32::MAX"), + ) + .ok()?, ); Some(Pool { From 0e54ab5347562e445276e0ee875f733c0b4d7720 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=CC=81=20Duarte?= Date: Wed, 10 Dec 2025 11:30:37 +0000 Subject: [PATCH 6/6] log fix --- .../src/boundary/liquidity/constant_product.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/solvers/src/boundary/liquidity/constant_product.rs b/crates/solvers/src/boundary/liquidity/constant_product.rs index 6fe32c2fc2..dd68f4ef49 100644 --- a/crates/solvers/src/boundary/liquidity/constant_product.rs +++ b/crates/solvers/src/boundary/liquidity/constant_product.rs @@ -15,17 +15,17 @@ pub fn to_boundary_pool( let reserves = ( u128::try_from(reserves.0.amount) .inspect_err(|_| { - tracing::trace!( + tracing::debug!( address = %reserves.0.token.0, - "failed to convert asset 0 amount to u128" + "asset 0 amount > u128" ); }) .ok()?, u128::try_from(reserves.1.amount) .inspect_err(|_| { - tracing::trace!( + tracing::debug!( address = %reserves.1.token.0, - "failed to convert asset 1 amount to u128" + "asset 1 amount > u128" ); }) .ok()?, @@ -34,12 +34,12 @@ pub fn to_boundary_pool( let fee = num::rational::Ratio::new( u32::try_from(pool.fee.numer()) .inspect_err( - |_| tracing::trace!(pool = ?pool.reserves, "pool fee numerator > u32::MAX"), + |_| tracing::debug!(pool = ?pool.reserves, "pool fee numerator > u32::MAX"), ) .ok()?, u32::try_from(pool.fee.denom()) .inspect_err( - |_| tracing::trace!(pool = ?pool.reserves, "pool fee numerator > u32::MAX"), + |_| tracing::debug!(pool = ?pool.reserves, "pool fee denominator > u32::MAX"), ) .ok()?, );