From d4ffa3b547f853168d8dd27ba5c756bdd1246d61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=CC=81=20Duarte?= Date: Tue, 9 Dec 2025 16:14:09 +0000 Subject: [PATCH 1/2] Migrate the rest of the solver(s) crates to alloy --- Cargo.lock | 3 - .../src/boundary/liquidity/balancer/v2/mod.rs | 9 +- .../boundary/liquidity/balancer/v2/stable.rs | 3 +- .../liquidity/balancer/v2/weighted.rs | 3 +- .../driver/src/boundary/liquidity/zeroex.rs | 6 +- crates/solver/Cargo.toml | 2 - crates/solver/src/interactions/balancer_v2.rs | 14 +- crates/solver/src/interactions/uniswap_v2.rs | 30 +-- crates/solver/src/liquidity/balancer_v2.rs | 27 +- crates/solver/src/liquidity/mod.rs | 25 +- crates/solver/src/liquidity/slippage.rs | 47 ++-- crates/solver/src/liquidity/uniswap_v2.rs | 9 +- crates/solver/src/liquidity/zeroex.rs | 38 ++- crates/solver/src/settlement/mod.rs | 79 +++--- .../src/settlement/settlement_encoder.rs | 236 +++++++++--------- crates/solvers/Cargo.toml | 8 +- crates/solvers/src/boundary/baseline.rs | 10 +- .../src/boundary/liquidity/concentrated.rs | 3 +- .../solvers/src/boundary/liquidity/stable.rs | 22 +- .../boundary/liquidity/weighted_product.rs | 17 +- crates/solvers/src/domain/order.rs | 10 +- 21 files changed, 280 insertions(+), 321 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1b1128df48..71555b6003 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6465,7 +6465,6 @@ dependencies = [ "const-hex", "contracts", "derivative", - "ethcontract", "ethrpc", "futures", "hex-literal", @@ -6476,7 +6475,6 @@ dependencies = [ "num", "number", "observe", - "primitive-types", "prometheus", "prometheus-metric-storage", "serde_json", @@ -6503,7 +6501,6 @@ dependencies = [ "contracts", "derive_more 1.0.0", "ethcontract", - "ethereum-types", "ethrpc", "futures", "hex-literal", diff --git a/crates/driver/src/boundary/liquidity/balancer/v2/mod.rs b/crates/driver/src/boundary/liquidity/balancer/v2/mod.rs index d0a837776f..726b406c79 100644 --- a/crates/driver/src/boundary/liquidity/balancer/v2/mod.rs +++ b/crates/driver/src/boundary/liquidity/balancer/v2/mod.rs @@ -16,7 +16,10 @@ use { BalancerV2WeightedPoolFactory, BalancerV2WeightedPoolFactoryV3, }, - ethrpc::block_stream::{BlockRetrieving, CurrentBlockWatcher}, + ethrpc::{ + alloy::conversions::IntoAlloy, + block_stream::{BlockRetrieving, CurrentBlockWatcher}, + }, shared::{ http_solver::model::TokenAmount, sources::balancer_v2::{ @@ -27,7 +30,7 @@ use { }, solver::{ interactions::allowances::Allowances, - liquidity::{balancer_v2, balancer_v2::BalancerV2Liquidity}, + liquidity::balancer_v2::{self, BalancerV2Liquidity}, liquidity_collector::{BackgroundInitLiquiditySource, LiquidityCollecting}, }, std::sync::Arc, @@ -48,7 +51,7 @@ fn to_interaction( receiver: ð::Address, ) -> eth::Interaction { let handler = balancer_v2::SettlementHandler::new( - pool.id.into(), + pool.id.0.into_alloy(), // 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. diff --git a/crates/driver/src/boundary/liquidity/balancer/v2/stable.rs b/crates/driver/src/boundary/liquidity/balancer/v2/stable.rs index 03b21b48f4..69eea86112 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::IntoAlloy, + ethrpc::alloy::conversions::{IntoAlloy, IntoLegacy}, solver::liquidity::{StablePoolOrder, balancer_v2}, }; @@ -62,6 +62,7 @@ fn pool_id(pool: &StablePoolOrder) -> balancer::v2::Id { .downcast_ref::() .expect("downcast balancer settlement handler") .pool_id() + .into_legacy() .into() } diff --git a/crates/driver/src/boundary/liquidity/balancer/v2/weighted.rs b/crates/driver/src/boundary/liquidity/balancer/v2/weighted.rs index 4ddba4063c..6fdb2b019c 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::IntoAlloy, + ethrpc::alloy::conversions::{IntoAlloy, IntoLegacy}, shared::sources::balancer_v2::pool_fetching::WeightedPoolVersion, solver::liquidity::{WeightedProductOrder, balancer_v2}, }; @@ -66,6 +66,7 @@ fn pool_id(pool: &WeightedProductOrder) -> balancer::v2::Id { .downcast_ref::() .expect("downcast balancer settlement handler") .pool_id() + .into_legacy() .into() } diff --git a/crates/driver/src/boundary/liquidity/zeroex.rs b/crates/driver/src/boundary/liquidity/zeroex.rs index 0376d4a60f..13c15d4c3b 100644 --- a/crates/driver/src/boundary/liquidity/zeroex.rs +++ b/crates/driver/src/boundary/liquidity/zeroex.rs @@ -64,8 +64,10 @@ pub fn to_domain( let domain = zeroex::LimitOrder { order, fillable: Amounts { - maker: limit_order.sell_amount.as_u128(), - taker: limit_order.buy_amount.as_u128(), + maker: u128::try_from(limit_order.sell_amount) + .expect("value should be lower than u128::MAX"), + taker: u128::try_from(limit_order.buy_amount) + .expect("value should be lower than u128::MAX"), }, zeroex: handler.zeroex.clone(), }; diff --git a/crates/solver/Cargo.toml b/crates/solver/Cargo.toml index 0f6e8d6f23..e66b7180ac 100644 --- a/crates/solver/Cargo.toml +++ b/crates/solver/Cargo.toml @@ -16,7 +16,6 @@ anyhow = { workspace = true } arc-swap = { workspace = true } async-trait = { workspace = true } contracts = { workspace = true } -ethcontract = { workspace = true } ethrpc = { workspace = true } futures = { workspace = true } observe = { workspace = true } @@ -27,7 +26,6 @@ maplit = { workspace = true } model = { workspace = true } num = { workspace = true } number = { workspace = true } -primitive-types = { workspace = true } prometheus = { workspace = true } prometheus-metric-storage = { workspace = true } serde_json = { workspace = true } diff --git a/crates/solver/src/interactions/balancer_v2.rs b/crates/solver/src/interactions/balancer_v2.rs index 1004f781c4..b7bf413143 100644 --- a/crates/solver/src/interactions/balancer_v2.rs +++ b/crates/solver/src/interactions/balancer_v2.rs @@ -1,11 +1,9 @@ use { alloy::{ - primitives::{Address, U256}, + primitives::{Address, B256, Bytes, U256}, sol_types::SolCall, }, contracts::alloy::BalancerV2Vault::{BalancerV2Vault::swapCall, IVault}, - ethcontract::{Bytes, H256}, - ethrpc::alloy::conversions::IntoAlloy, shared::{ http_solver::model::TokenAmount, interaction::{EncodedInteraction, Interaction}, @@ -17,10 +15,10 @@ use { pub struct BalancerSwapGivenOutInteraction { pub settlement: Address, pub vault: Address, - pub pool_id: H256, + pub pool_id: B256, pub asset_in_max: TokenAmount, pub asset_out: TokenAmount, - pub user_data: Bytes>, + pub user_data: Bytes, } /// An impossibly distant future timestamp. Note that we use `0x80000...00` @@ -31,12 +29,12 @@ pub static NEVER: LazyLock = LazyLock::new(|| U256::from(1) << 255); impl BalancerSwapGivenOutInteraction { pub fn encode_swap(&self) -> EncodedInteraction { let single_swap = IVault::SingleSwap { - poolId: self.pool_id.into_alloy(), + poolId: self.pool_id, kind: 1, // GivenOut assetIn: self.asset_in_max.token, assetOut: self.asset_out.token, amount: self.asset_out.amount, - userData: self.user_data.clone().into_alloy(), + userData: self.user_data.clone(), }; let funds = IVault::FundManagement { sender: self.settlement, @@ -73,7 +71,7 @@ mod tests { let interaction = BalancerSwapGivenOutInteraction { settlement: Address::from_slice(&[0x02; 20]), vault: vault_address, - pool_id: H256([0x03; 32]), + pool_id: B256::repeat_byte(0x03), asset_in_max: TokenAmount::new( Address::repeat_byte(0x04), alloy::primitives::U256::from(1_337_000_000_000_000_000_000u128), diff --git a/crates/solver/src/interactions/uniswap_v2.rs b/crates/solver/src/interactions/uniswap_v2.rs index c5fe8acd97..4d9afca8c0 100644 --- a/crates/solver/src/interactions/uniswap_v2.rs +++ b/crates/solver/src/interactions/uniswap_v2.rs @@ -1,8 +1,9 @@ use { - alloy::{primitives::Address, sol_types::SolCall}, + alloy::{ + primitives::{Address, U256}, + sol_types::SolCall, + }, contracts::alloy::IUniswapLikeRouter, - ethrpc::alloy::conversions::IntoAlloy, - primitive_types::{H160, U256}, shared::interaction::{EncodedInteraction, Interaction}, }; @@ -12,8 +13,8 @@ pub struct UniswapInteraction { pub settlement: Address, pub amount_out: U256, pub amount_in_max: U256, - pub token_in: H160, - pub token_out: H160, + pub token_in: Address, + pub token_out: Address, } impl Interaction for UniswapInteraction { @@ -25,9 +26,9 @@ impl Interaction for UniswapInteraction { impl UniswapInteraction { pub fn encode_swap(&self) -> EncodedInteraction { let calldata = IUniswapLikeRouter::IUniswapLikeRouter::swapTokensForExactTokensCall { - amountOut: self.amount_out.into_alloy(), - amountInMax: self.amount_in_max.into_alloy(), - path: vec![self.token_in.into_alloy(), self.token_out.into_alloy()], + amountOut: self.amount_out, + amountInMax: self.amount_in_max, + path: vec![self.token_in, self.token_out], to: self.settlement, deadline: ::alloy::primitives::U256::MAX, } @@ -50,19 +51,19 @@ mod tests { fn encode_uniswap_call() { let amount_out = 5; let amount_in_max = 6; - let token_in = H160::from_low_u64_be(7); + let token_in = Address::with_last_byte(7); let token_out = 8; let payout_to = 9u8; let router_address = Address::from(&[1u8; 20]); - let settlement = H160::from_low_u64_be(payout_to as u64).into_alloy(); + let settlement = Address::with_last_byte(payout_to); let interaction = UniswapInteraction { router: router_address, settlement, - amount_out: amount_out.into(), - amount_in_max: amount_in_max.into(), + amount_out: U256::from(amount_out), + amount_in_max: U256::from(amount_in_max), token_in, - token_out: H160::from_low_u64_be(token_out as u64), + token_out: Address::with_last_byte(token_out), }; let swap_call = interaction.encode(); @@ -73,6 +74,7 @@ mod tests { let path_offset = 160; let path_size = 2; let deadline = [0xffu8; 32]; + assert_eq!(call[0..4], swap_signature); assert_eq!(call[4..36], u8_as_32_bytes_be(amount_out)); assert_eq!(call[36..68], u8_as_32_bytes_be(amount_in_max)); @@ -80,7 +82,7 @@ mod tests { assert_eq!(call[100..132], u8_as_32_bytes_be(payout_to)); assert_eq!(call[132..164], deadline); assert_eq!(call[164..196], u8_as_32_bytes_be(path_size)); - assert_eq!(&call[208..228], token_in.as_fixed_bytes()); + assert_eq!(&call[208..228], &token_in); assert_eq!(call[228..260], u8_as_32_bytes_be(token_out)); } } diff --git a/crates/solver/src/liquidity/balancer_v2.rs b/crates/solver/src/liquidity/balancer_v2.rs index aa916e3143..d0f3a66c48 100644 --- a/crates/solver/src/liquidity/balancer_v2.rs +++ b/crates/solver/src/liquidity/balancer_v2.rs @@ -16,9 +16,9 @@ use { liquidity_collector::LiquidityCollecting, settlement::SettlementEncoder, }, - alloy::primitives::Address, + alloy::primitives::{Address, B256}, anyhow::Result, - ethcontract::H256, + ethrpc::alloy::conversions::IntoAlloy, model::TokenPair, shared::{ ethrpc::Web3, @@ -83,7 +83,7 @@ impl BalancerV2Liquidity { fee: pool.common.swap_fee, version: pool.version, settlement_handling: Arc::new(SettlementHandler { - pool_id: pool.common.id, + pool_id: pool.common.id.into_alloy(), inner: inner.clone(), }), }) @@ -97,7 +97,7 @@ impl BalancerV2Liquidity { fee: pool.common.swap_fee, amplification_parameter: pool.amplification_parameter, settlement_handling: Arc::new(SettlementHandler { - pool_id: pool.common.id, + pool_id: pool.common.id.into_alloy(), inner: inner.clone(), }), }) @@ -128,7 +128,7 @@ impl LiquidityCollecting for BalancerV2Liquidity { } pub struct SettlementHandler { - pool_id: H256, + pool_id: B256, inner: Arc, } @@ -139,7 +139,7 @@ struct Inner { } impl SettlementHandler { - pub fn new(pool_id: H256, settlement: Address, vault: Address, allowances: Allowances) -> Self { + pub fn new(pool_id: B256, settlement: Address, vault: Address, allowances: Allowances) -> Self { SettlementHandler { pool_id, inner: Arc::new(Inner { @@ -154,7 +154,7 @@ impl SettlementHandler { &self.inner.vault } - pub fn pool_id(&self) -> H256 { + pub fn pool_id(&self) -> B256 { self.pool_id } @@ -229,6 +229,7 @@ mod tests { crate::interactions::allowances::{Approval, MockAllowanceManaging}, alloy::primitives::U256, contracts::alloy::BalancerV2Vault, + ethrpc::alloy::conversions::IntoLegacy, maplit::{btreemap, hashmap, hashset}, mockall::predicate::*, model::TokenPair, @@ -276,7 +277,7 @@ mod tests { let weighted_pools = vec![ WeightedPool { common: CommonPoolState { - id: H256([0x90; 32]), + id: B256::repeat_byte(0x90).into_legacy(), address: Address::repeat_byte(0x90), swap_fee: "0.002".parse().unwrap(), paused: true, @@ -308,7 +309,7 @@ mod tests { }, WeightedPool { common: CommonPoolState { - id: H256([0x91; 32]), + id: B256::repeat_byte(0x91).into_legacy(), address: Address::repeat_byte(0x91), swap_fee: "0.001".parse().unwrap(), paused: true, @@ -335,7 +336,7 @@ mod tests { let stable_pools = vec![StablePool { common: CommonPoolState { - id: H256([0x92; 32]), + id: B256::repeat_byte(0x92).into_legacy(), address: Address::repeat_byte(0x92), swap_fee: "0.002".parse().unwrap(), paused: true, @@ -473,7 +474,7 @@ mod tests { ), }); let handler = SettlementHandler { - pool_id: H256([0x90; 32]), + pool_id: B256::repeat_byte(0x90), inner, }; @@ -513,7 +514,7 @@ mod tests { BalancerSwapGivenOutInteraction { settlement, vault: *vault.address(), - pool_id: H256([0x90; 32]), + pool_id: B256::repeat_byte(0x90), asset_in_max: TokenAmount::new(Address::repeat_byte(0x70), U256::from(10)), asset_out: TokenAmount::new(Address::repeat_byte(0x71), U256::from(11)), user_data: Default::default(), @@ -522,7 +523,7 @@ mod tests { BalancerSwapGivenOutInteraction { settlement, vault: *vault.address(), - pool_id: H256([0x90; 32]), + pool_id: B256::repeat_byte(0x90), asset_in_max: TokenAmount::new(Address::repeat_byte(0x71), U256::from(12)), asset_out: TokenAmount::new(Address::repeat_byte(0x72), U256::from(13)), user_data: Default::default(), diff --git a/crates/solver/src/liquidity/mod.rs b/crates/solver/src/liquidity/mod.rs index 114932ff4c..cd4c789f49 100644 --- a/crates/solver/src/liquidity/mod.rs +++ b/crates/solver/src/liquidity/mod.rs @@ -8,14 +8,13 @@ pub mod zeroex; use derivative::Derivative; use { crate::settlement::SettlementEncoder, - alloy::primitives::Address, + alloy::primitives::{Address, U256}, anyhow::Result, model::{ TokenPair, order::{Order, OrderKind, OrderUid}, }, num::rational::Ratio, - primitive_types::{H160, U256}, shared::{ http_solver::model::TokenAmount, sources::{ @@ -136,8 +135,8 @@ impl From for LimitOrderId { pub struct LimitOrder { // Opaque Identifier for debugging purposes pub id: LimitOrderId, - pub sell_token: H160, - pub buy_token: H160, + pub sell_token: Address, + pub buy_token: Address, /// The amount that can be sold to acquire the required `buy_token`. pub sell_amount: U256, pub buy_amount: U256, @@ -427,26 +426,22 @@ pub mod tests { #[test] fn limit_order_full_execution_amounts() { - fn simple_limit_order( - kind: OrderKind, - sell_amount: impl Into, - buy_amount: impl Into, - ) -> LimitOrder { + fn simple_limit_order(kind: OrderKind, sell_amount: U256, buy_amount: U256) -> LimitOrder { LimitOrder { - sell_amount: sell_amount.into(), - buy_amount: buy_amount.into(), + sell_amount, + buy_amount, kind, ..Default::default() } } assert_eq!( - simple_limit_order(OrderKind::Sell, 1, 2).full_execution_amount(), - 1.into(), + simple_limit_order(OrderKind::Sell, U256::ONE, U256::from(2)).full_execution_amount(), + U256::from(1), ); assert_eq!( - simple_limit_order(OrderKind::Buy, 1, 2).full_execution_amount(), - 2.into(), + simple_limit_order(OrderKind::Buy, U256::ONE, U256::from(2)).full_execution_amount(), + U256::from(2), ); } } diff --git a/crates/solver/src/liquidity/slippage.rs b/crates/solver/src/liquidity/slippage.rs index ec4f009c9b..7acfbfec52 100644 --- a/crates/solver/src/liquidity/slippage.rs +++ b/crates/solver/src/liquidity/slippage.rs @@ -2,9 +2,8 @@ use { super::AmmOrderExecution, + alloy::primitives::U256, anyhow::{Context as _, Result}, - ethcontract::U256, - ethrpc::alloy::conversions::IntoAlloy, num::{BigInt, BigRational, CheckedDiv, Integer as _, ToPrimitive as _}, shared::{external_prices::ExternalPrices, http_solver::model::TokenAmount}, std::{borrow::Cow, cmp, sync::LazyLock}, @@ -114,7 +113,7 @@ impl SlippageCalculator { pub fn from_bps(relative_bps: u32, absolute: Option) -> Self { Self { relative: BigRational::new(relative_bps.into(), BPS_BASE.into()), - absolute: absolute.map(|value| number::conversions::u256_to_big_int(&value)), + absolute: absolute.map(|value| number::conversions::alloy::u256_to_big_int(&value)), } } @@ -179,14 +178,14 @@ impl SlippageAmount { let relative = relative .to_f64() .context("relative slippage ratio is not a number")?; - let absolute = number::conversions::big_int_to_u256(absolute)?; + let absolute = number::conversions::alloy::big_int_to_u256(absolute)?; Ok(Self { relative, absolute }) } /// Increase the specified amount by the constant slippage. - pub fn add_to_amount(&self, amount: alloy::primitives::U256) -> alloy::primitives::U256 { - amount.saturating_add(self.absolute.into_alloy()) + pub fn add_to_amount(&self, amount: U256) -> U256 { + amount.saturating_add(self.absolute) } } @@ -206,52 +205,38 @@ mod tests { #[test] fn amm_execution_slippage() { - let calculator = SlippageCalculator::from_bps(100, Some(U256::exp10(18))); + let calculator = + SlippageCalculator::from_bps(100, Some(U256::from(10).pow(U256::from(18)))); let prices = externalprices! { native_token: WETH }; let slippage = calculator.context(&prices); let cases = [ ( AmmOrderExecution { - input_max: TokenAmount::new( - WETH, - alloy::primitives::U256::from(1_000_000_000_000_000_000_u128), - ), - output: TokenAmount::new( - GNO, - alloy::primitives::U256::from(10_000_000_000_000_000_000_u128), - ), + input_max: TokenAmount::new(WETH, U256::from(1_000_000_000_000_000_000_u128)), + output: TokenAmount::new(GNO, U256::from(10_000_000_000_000_000_000_u128)), internalizable: false, }, - alloy::primitives::U256::from(1_010_000_000_000_000_000_u128), + U256::from(1_010_000_000_000_000_000_u128), ), ( AmmOrderExecution { input_max: TokenAmount::new( GNO, - alloy::primitives::U256::from(10_000_000_000_000_000_000_000_u128), - ), - output: TokenAmount::new( - WETH, - alloy::primitives::U256::from(1_000_000_000_000_000_000_000_u128), + U256::from(10_000_000_000_000_000_000_000_u128), ), + output: TokenAmount::new(WETH, U256::from(1_000_000_000_000_000_000_000_u128)), internalizable: false, }, - alloy::primitives::U256::from(10_010_000_000_000_000_000_000_u128), + U256::from(10_010_000_000_000_000_000_000_u128), ), ( AmmOrderExecution { - input_max: TokenAmount::new( - USDC, - alloy::primitives::U256::from(200_000_000_u128), - ), - output: TokenAmount::new( - GNO, - alloy::primitives::U256::from(2_000_000_000_000_000_000_u128), - ), + input_max: TokenAmount::new(USDC, U256::from(200_000_000_u128)), + output: TokenAmount::new(GNO, U256::from(2_000_000_000_000_000_000_u128)), internalizable: false, }, - alloy::primitives::U256::from(202_000_000_u128), + U256::from(202_000_000_u128), ), ]; diff --git a/crates/solver/src/liquidity/uniswap_v2.rs b/crates/solver/src/liquidity/uniswap_v2.rs index bcd3999247..4b917d5dc3 100644 --- a/crates/solver/src/liquidity/uniswap_v2.rs +++ b/crates/solver/src/liquidity/uniswap_v2.rs @@ -11,7 +11,6 @@ use { }, alloy::primitives::Address, anyhow::Result, - ethrpc::alloy::conversions::IntoLegacy, model::TokenPair, shared::{ ethrpc::Web3, @@ -138,10 +137,10 @@ impl Inner { UniswapInteraction { router: self.router, settlement: self.gpv2_settlement, - amount_out: token_amount_out.amount.into_legacy(), - amount_in_max: token_amount_in_max.amount.into_legacy(), - token_in: token_amount_in_max.token.into_legacy(), - token_out: token_amount_out.token.into_legacy(), + amount_out: token_amount_out.amount, + amount_in_max: token_amount_in_max.amount, + token_in: token_amount_in_max.token, + token_out: token_amount_out.token, }, ) } diff --git a/crates/solver/src/liquidity/zeroex.rs b/crates/solver/src/liquidity/zeroex.rs index 5224c22e3a..d31d4adb83 100644 --- a/crates/solver/src/liquidity/zeroex.rs +++ b/crates/solver/src/liquidity/zeroex.rs @@ -9,18 +9,14 @@ use { liquidity_collector::LiquidityCollecting, settlement::SettlementEncoder, }, - alloy::primitives::Address, + alloy::primitives::{Address, U256}, anyhow::Result, arc_swap::ArcSwap, contracts::alloy::IZeroex, - ethrpc::{ - alloy::conversions::{IntoAlloy, IntoLegacy}, - block_stream::{CurrentBlockWatcher, into_stream}, - }, + ethrpc::block_stream::{CurrentBlockWatcher, into_stream}, futures::StreamExt, itertools::Itertools, model::{TokenPair, order::OrderKind}, - primitive_types::U256, shared::{ ethrpc::Web3, http_solver::model::TokenAmount, @@ -72,7 +68,7 @@ impl ZeroExLiquidity { record: OrderRecord, allowances: Arc, ) -> Option { - let sell_amount: U256 = record.remaining_maker_amount().ok()?.into(); + let sell_amount = U256::from(record.remaining_maker_amount().ok()?); if sell_amount.is_zero() || record.metadata().remaining_fillable_taker_amount == 0 { // filter out orders with 0 amounts to prevent errors in the solver return None; @@ -82,13 +78,13 @@ impl ZeroExLiquidity { id: LimitOrderId::Liquidity(LiquidityOrderId::ZeroEx(const_hex::encode( &record.metadata().order_hash, ))), - sell_token: record.order().maker_token.into_legacy(), - buy_token: record.order().taker_token.into_legacy(), + sell_token: record.order().maker_token, + buy_token: record.order().taker_token, sell_amount, - buy_amount: record.metadata().remaining_fillable_taker_amount.into(), + buy_amount: U256::from(record.metadata().remaining_fillable_taker_amount), kind: OrderKind::Buy, partially_fillable: true, - user_fee: U256::zero(), + user_fee: U256::ZERO, settlement_handling: Arc::new(OrderSettlementHandler { order_record: record, zeroex: self.zeroex.clone(), @@ -230,18 +226,18 @@ impl SettlementHandling for OrderSettlementHandler { execution: LimitOrderExecution, encoder: &mut SettlementEncoder, ) -> Result<()> { - if execution.filled > u128::MAX.into() { + let Ok(execution_filled) = u128::try_from(execution.filled) else { anyhow::bail!("0x only supports executed amounts of size u128"); - } + }; let approval = self.allowances.approve_token(TokenAmount::new( self.order_record.order().taker_token, - execution.filled.into_alloy(), + execution.filled, ))?; if let Some(approval) = approval { encoder.append_to_execution_plan(Arc::new(approval)); } encoder.append_to_execution_plan(Arc::new(ZeroExInteraction { - taker_token_fill_amount: execution.filled.as_u128(), + taker_token_fill_amount: execution_filled, order: self.order_record.order().clone(), zeroex: self.zeroex.clone(), })); @@ -389,10 +385,8 @@ pub mod tests { Default::default(), ethrpc::mock::web3().alloy, )); - let allowances = Allowances::new( - *zeroex.address(), - hashmap! { sell_token => alloy::primitives::U256::from(99) }, - ); + let allowances = + Allowances::new(*zeroex.address(), hashmap! { sell_token => U256::from(99) }); let order_record = OrderRecord::new( zeroex_api::Order { taker_amount: 100, @@ -407,7 +401,7 @@ pub mod tests { allowances: Arc::new(allowances), }; let mut encoder = SettlementEncoder::default(); - let execution = LimitOrderExecution::new(100.into(), 0.into()); + let execution = LimitOrderExecution::new(U256::from(100), U256::ZERO); handler.encode(execution, &mut encoder).unwrap(); let [_, interactions, _] = encoder .finish(InternalizationStrategy::SkipInternalizableInteraction) @@ -439,7 +433,7 @@ pub mod tests { )); let allowances = Allowances::new( *zeroex.address(), - hashmap! { sell_token => alloy::primitives::U256::from(100) }, + hashmap! { sell_token => U256::from(100) }, ); let order_record = OrderRecord::new( zeroex_api::Order { @@ -455,7 +449,7 @@ pub mod tests { allowances: Arc::new(allowances), }; let mut encoder = SettlementEncoder::default(); - let execution = LimitOrderExecution::new(100.into(), 0.into()); + let execution = LimitOrderExecution::new(U256::from(100), U256::ZERO); handler.encode(execution, &mut encoder).unwrap(); let [_, interactions, _] = encoder .finish(InternalizationStrategy::SkipInternalizableInteraction) diff --git a/crates/solver/src/settlement/mod.rs b/crates/solver/src/settlement/mod.rs index ca27ac43be..2ead4d0da1 100644 --- a/crates/solver/src/settlement/mod.rs +++ b/crates/solver/src/settlement/mod.rs @@ -2,11 +2,10 @@ mod settlement_encoder; use { crate::liquidity::Settleable, - alloy::primitives::Address, + alloy::primitives::{Address, U256}, anyhow::Result, ethrpc::alloy::conversions::IntoLegacy, model::order::{Order, OrderKind}, - primitive_types::U256, shared::{ conversions::U256Ext as _, encoded_settlement::{EncodedSettlement, EncodedTrade, encode_trade}, @@ -37,7 +36,7 @@ impl Trade { // Returns the executed fee amount (prorated of executed amount) // cf. https://github.com/cowprotocol/contracts/blob/v1.1.2/src/contracts/GPv2Settlement.sol#L383-L385 fn executed_fee(&self) -> Option { - self.scale_amount(self.order.data.fee_amount.into_legacy()) + self.scale_amount(self.order.data.fee_amount) } /// Scales the passed `amount` based on the `executed_amount`. @@ -45,10 +44,10 @@ impl Trade { match self.order.data.kind { model::order::OrderKind::Buy => amount .checked_mul(self.executed_amount)? - .checked_div(self.order.data.buy_amount.into_legacy()), + .checked_div(self.order.data.buy_amount), model::order::OrderKind::Sell => amount .checked_mul(self.executed_amount)? - .checked_div(self.order.data.sell_amount.into_legacy()), + .checked_div(self.order.data.sell_amount), } } @@ -95,7 +94,7 @@ impl Trade { self.order.metadata.owner.into_legacy(), sell_token_index, buy_token_index, - &self.executed_amount, + &self.executed_amount.into_legacy(), ) } } @@ -208,15 +207,15 @@ pub mod tests { }, ..Default::default() }, - executed_amount: 5.into(), + executed_amount: U256::from(5), ..Default::default() }; - let sell_price = 3.into(); - let buy_price = 4.into(); + let sell_price = U256::from(3); + let buy_price = U256::from(4); let execution = trade.executed_amounts(sell_price, buy_price).unwrap(); - assert_eq!(execution.sell_amount, 5.into()); - assert_eq!(execution.buy_amount, 4.into()); // round up! + assert_eq!(execution.sell_amount, U256::from(5)); + assert_eq!(execution.buy_amount, U256::from(4)); // round up! } #[test] @@ -231,15 +230,15 @@ pub mod tests { }, ..Default::default() }, - executed_amount: 5.into(), + executed_amount: U256::from(5), ..Default::default() }; - let sell_price = 3.into(); - let buy_price = 4.into(); + let sell_price = U256::from(3); + let buy_price = U256::from(4); let execution = trade.executed_amounts(sell_price, buy_price).unwrap(); - assert_eq!(execution.sell_amount, 6.into()); // round down! - assert_eq!(execution.buy_amount, 5.into()); + assert_eq!(execution.sell_amount, U256::from(6)); // round down! + assert_eq!(execution.buy_amount, U256::from(5)); } #[test] @@ -260,17 +259,17 @@ pub mod tests { ..Default::default() }; let sell_price = U256::from(2); - let buy_price = U256::one(); + let buy_price = U256::from(1); assert!(trade.executed_amounts(sell_price, buy_price).is_none()); // div let trade = Trade { order, - executed_amount: U256::one(), + executed_amount: U256::from(1), ..Default::default() }; - let sell_price = U256::one(); - let buy_price = U256::zero(); + let sell_price = U256::from(1); + let buy_price = U256::ZERO; assert!(trade.executed_amounts(sell_price, buy_price).is_none()); } } @@ -296,24 +295,24 @@ pub mod tests { }; let mut settlement = Settlement::new(hashmap! { - token0 => 1.into(), - token1 => 1.into(), + token0 => U256::from(1), + token1 => U256::from(1), }); assert!( settlement .encoder - .add_trade(order.clone(), 10.into(), 0.into()) + .add_trade(order.clone(), U256::from(10), U256::from(0)) .is_ok() ); let mut settlement = Settlement::new(hashmap! { - token0 => 1.into(), - token1 => 0.into(), + token0 => U256::from(1), + token1 => U256::from(0), }); assert!( settlement .encoder - .add_trade(order, 10.into(), 0.into()) + .add_trade(order, U256::from(10), U256::from(0)) .is_err() ); } @@ -330,10 +329,10 @@ pub mod tests { }, ..Default::default() }, - executed_amount: 100.into(), + executed_amount: U256::from(100), ..Default::default() }; - assert_eq!(fully_filled_sell.executed_fee().unwrap(), 5.into()); + assert_eq!(fully_filled_sell.executed_fee().unwrap(), U256::from(5)); let partially_filled_sell = Trade { order: Order { @@ -345,10 +344,10 @@ pub mod tests { }, ..Default::default() }, - executed_amount: 50.into(), + executed_amount: U256::from(50), ..Default::default() }; - assert_eq!(partially_filled_sell.executed_fee().unwrap(), 2.into()); + assert_eq!(partially_filled_sell.executed_fee().unwrap(), U256::from(2)); let fully_filled_buy = Trade { order: Order { @@ -360,10 +359,10 @@ pub mod tests { }, ..Default::default() }, - executed_amount: 100.into(), + executed_amount: U256::from(100), ..Default::default() }; - assert_eq!(fully_filled_buy.executed_fee().unwrap(), 5.into()); + assert_eq!(fully_filled_buy.executed_fee().unwrap(), U256::from(5)); let partially_filled_buy = Trade { order: Order { @@ -375,10 +374,10 @@ pub mod tests { }, ..Default::default() }, - executed_amount: 50.into(), + executed_amount: U256::from(50), ..Default::default() }; - assert_eq!(partially_filled_buy.executed_fee().unwrap(), 2.into()); + assert_eq!(partially_filled_buy.executed_fee().unwrap(), U256::from(2)); } #[test] @@ -393,7 +392,7 @@ pub mod tests { }, ..Default::default() }, - executed_amount: U256::max_value(), + executed_amount: U256::MAX, ..Default::default() }; assert_eq!(large_amounts.executed_fee(), None); @@ -408,7 +407,7 @@ pub mod tests { }, ..Default::default() }, - executed_amount: U256::zero(), + executed_amount: U256::ZERO, ..Default::default() }; assert_eq!(zero_amounts.executed_fee(), None); @@ -421,8 +420,8 @@ pub mod tests { let settlement = test_settlement( hashmap! { - sell_token => 100_000_u128.into(), - buy_token => 100_000_u128.into(), + sell_token => U256::from(100_000_u128), + buy_token => U256::from(100_000_u128), }, vec![Trade { order: Order { @@ -440,8 +439,8 @@ pub mod tests { }, ..Default::default() }, - executed_amount: 99_000_u128.into(), - fee: 1_000_u128.into(), + executed_amount: U256::from(99_000_u128), + fee: U256::from(1_000_u128), }], ) .encode(InternalizationStrategy::SkipInternalizableInteraction); diff --git a/crates/solver/src/settlement/settlement_encoder.rs b/crates/solver/src/settlement/settlement_encoder.rs index 445e494b87..3b8416e183 100644 --- a/crates/solver/src/settlement/settlement_encoder.rs +++ b/crates/solver/src/settlement/settlement_encoder.rs @@ -1,15 +1,14 @@ use { super::{Trade, TradeExecution}, crate::interactions::UnwrapWethInteraction, - alloy::primitives::Address, + alloy::primitives::{Address, U256}, anyhow::{Context as _, Result, ensure}, - ethrpc::alloy::conversions::{IntoAlloy, IntoLegacy}, + ethrpc::alloy::conversions::IntoLegacy, itertools::Either, model::{ interaction::InteractionData, order::{Order, OrderClass, OrderKind}, }, - primitive_types::U256, shared::{ conversions::U256Ext, encoded_settlement::EncodedSettlement, @@ -218,13 +217,7 @@ impl SettlementEncoder { OrderClass::Market => self.add_market_trade(order, executed_amount, fee)?, OrderClass::Liquidity => { let (sell_price, buy_price) = (order.data.buy_amount, order.data.sell_amount); - self.add_custom_price_trade( - order, - executed_amount, - fee, - sell_price.into_legacy(), - buy_price.into_legacy(), - )? + self.add_custom_price_trade(order, executed_amount, fee, sell_price, buy_price)? } OrderClass::Limit => { let surplus_fee = fee; @@ -272,9 +265,8 @@ impl SettlementEncoder { OrderKind::Sell => order.data.sell_amount, }; anyhow::ensure!( - (order.data.partially_fillable && executed_amount <= target_amount.into_legacy()) - || (!order.data.partially_fillable - && executed_amount == target_amount.into_legacy()), + (order.data.partially_fillable && executed_amount <= target_amount) + || (!order.data.partially_fillable && executed_amount == target_amount), "this function should only be called with valid executed amounts" ); @@ -481,10 +473,10 @@ impl SettlementEncoder { .tokens .iter() .map(|token| { - self.clearing_prices + *self + .clearing_prices .get(token) .expect("missing clearing price for token") - .into_alloy() }) .collect(); @@ -499,14 +491,8 @@ impl SettlementEncoder { sell_token_price, buy_token_price, } => Some(vec![ - ( - trade.data.order.data.sell_token, - sell_token_price.into_alloy(), - ), - ( - trade.data.order.data.buy_token, - buy_token_price.into_alloy(), - ), + (trade.data.order.data.sell_token, sell_token_price), + (trade.data.order.data.buy_token, buy_token_price), ]), _ => None, }) @@ -587,16 +573,16 @@ pub(crate) fn verify_executed_amount(order: &Order, executed: U256) -> Result<() let remaining = shared::remaining_amounts::Remaining::from_order(&order.into())?; let valid_executed_amount = match (order.data.partially_fillable, order.data.kind) { (true, OrderKind::Sell) => { - executed <= remaining.remaining(order.data.sell_amount.into_legacy())? + executed.into_legacy() <= remaining.remaining(order.data.sell_amount.into_legacy())? } (true, OrderKind::Buy) => { - executed <= remaining.remaining(order.data.buy_amount.into_legacy())? + executed.into_legacy() <= remaining.remaining(order.data.buy_amount.into_legacy())? } (false, OrderKind::Sell) => { - executed == remaining.remaining(order.data.sell_amount.into_legacy())? + executed.into_legacy() == remaining.remaining(order.data.sell_amount.into_legacy())? } (false, OrderKind::Buy) => { - executed == remaining.remaining(order.data.buy_amount.into_legacy())? + executed.into_legacy() == remaining.remaining(order.data.buy_amount.into_legacy())? } }; ensure!(valid_executed_amount, "invalid executed amount"); @@ -621,9 +607,9 @@ pub mod tests { let order0 = Order { data: OrderData { sell_token: token0, - sell_amount: alloy::primitives::U256::ONE, + sell_amount: U256::ONE, buy_token: token1, - buy_amount: alloy::primitives::U256::ONE, + buy_amount: U256::ONE, ..Default::default() }, ..Default::default() @@ -631,21 +617,21 @@ pub mod tests { let order1 = Order { data: OrderData { sell_token: token1, - sell_amount: alloy::primitives::U256::ONE, + sell_amount: U256::ONE, buy_token: token0, - buy_amount: alloy::primitives::U256::ONE, + buy_amount: U256::ONE, ..Default::default() }, ..Default::default() }; let mut settlement = SettlementEncoder::new(maplit::hashmap! { - token0 => 1.into(), - token1 => 1.into(), + token0 => U256::ONE, + token1 => U256::ONE, }); - assert!(settlement.add_trade(order0, 1.into(), 1.into()).is_ok()); - assert!(settlement.add_trade(order1, 1.into(), 0.into()).is_ok()); + settlement.add_trade(order0, U256::ONE, U256::ONE).unwrap(); + settlement.add_trade(order1, U256::ONE, U256::ZERO).unwrap(); } #[test] @@ -655,11 +641,11 @@ pub mod tests { let mut encoder = SettlementEncoder::new(HashMap::new()); encoder.add_unwrap(UnwrapWethInteraction { weth: weth.clone(), - amount: alloy::primitives::U256::ONE, + amount: U256::ONE, }); encoder.add_unwrap(UnwrapWethInteraction { weth: weth.clone(), - amount: alloy::primitives::U256::from(2), + amount: U256::from(2), }); assert_eq!( @@ -668,7 +654,7 @@ pub mod tests { .interactions[1], [UnwrapWethInteraction { weth, - amount: alloy::primitives::U256::from(3), + amount: U256::from(3), } .encode()], ); @@ -677,27 +663,31 @@ pub mod tests { #[test] fn settlement_reflects_different_price_for_normal_and_liquidity_order() { let mut settlement = SettlementEncoder::new(maplit::hashmap! { - Address::with_last_byte(0) => 3.into(), - Address::with_last_byte(1) => 10.into(), + Address::with_last_byte(0) => U256::from(3), + Address::with_last_byte(1) => U256::from(10), }); let order01 = OrderBuilder::default() .with_sell_token(Address::with_last_byte(0)) - .with_sell_amount(alloy::primitives::U256::from(30)) + .with_sell_amount(U256::from(30)) .with_buy_token(Address::with_last_byte(1)) - .with_buy_amount(alloy::primitives::U256::from(10)) + .with_buy_amount(U256::from(10)) .build(); let order10 = OrderBuilder::default() .with_sell_token(Address::with_last_byte(1)) - .with_sell_amount(alloy::primitives::U256::from(10)) + .with_sell_amount(U256::from(10)) .with_buy_token(Address::with_last_byte(0)) - .with_buy_amount(alloy::primitives::U256::from(20)) + .with_buy_amount(U256::from(20)) .with_class(OrderClass::Liquidity) .build(); - assert!(settlement.add_trade(order01, 10.into(), 0.into()).is_ok()); - assert!(settlement.add_trade(order10, 20.into(), 0.into()).is_ok()); + settlement + .add_trade(order01, U256::from(10), U256::from(0)) + .unwrap(); + settlement + .add_trade(order10, U256::from(20), U256::from(0)) + .unwrap(); let finished_settlement = settlement.finish(InternalizationStrategy::SkipInternalizableInteraction); assert_eq!( @@ -712,10 +702,10 @@ pub mod tests { assert_eq!( finished_settlement.clearing_prices, vec![ - alloy::primitives::U256::from(3), - alloy::primitives::U256::from(10), - alloy::primitives::U256::from(20), - alloy::primitives::U256::from(10) + U256::from(3), + U256::from(10), + U256::from(20), + U256::from(10) ] ); assert_eq!( @@ -731,18 +721,18 @@ pub mod tests { #[test] fn settlement_inserts_sell_price_for_new_liquidity_order_if_price_did_not_exist() { let mut settlement = SettlementEncoder::new(maplit::hashmap! { - Address::with_last_byte(1) => 9.into(), + Address::with_last_byte(1) => U256::from(9), }); let order01 = OrderBuilder::default() .with_sell_token(Address::with_last_byte(0)) - .with_sell_amount(alloy::primitives::U256::from(30)) + .with_sell_amount(U256::from(30)) .with_buy_token(Address::with_last_byte(1)) - .with_buy_amount(alloy::primitives::U256::from(10)) + .with_buy_amount(U256::from(10)) .with_class(OrderClass::Liquidity) .build(); assert!( settlement - .add_trade(order01.clone(), 10.into(), 0.into()) + .add_trade(order01.clone(), U256::from(10), U256::ZERO) .is_ok() ); // ensures that the output of add_liquidity_order is not changed after adding @@ -777,11 +767,11 @@ pub mod tests { let mut encoder = SettlementEncoder::new(HashMap::new()); encoder.add_unwrap(UnwrapWethInteraction { weth: WETH9::Instance::new([0x01; 20].into(), ethrpc::mock::web3().alloy), - amount: alloy::primitives::U256::ONE, + amount: U256::ONE, }); encoder.add_unwrap(UnwrapWethInteraction { weth: WETH9::Instance::new([0x02; 20].into(), ethrpc::mock::web3().alloy), - amount: alloy::primitives::U256::from(2), + amount: U256::from(2), }); assert_eq!( @@ -791,8 +781,8 @@ pub mod tests { .map(|unwrap| (*unwrap.weth.address(), unwrap.amount)) .collect::>(), vec![ - ([0x01; 20].into(), alloy::primitives::U256::ONE), - ([0x02; 20].into(), alloy::primitives::U256::from(2)) + ([0x01; 20].into(), U256::ONE), + ([0x02; 20].into(), U256::from(2)) ], ); } @@ -801,12 +791,12 @@ pub mod tests { fn settlement_unwraps_after_execution_plan() { let interaction: EncodedInteraction = ( Address::new([0x01; 20]), - alloy::primitives::U256::ZERO, + U256::ZERO, alloy::primitives::Bytes::default(), ); let unwrap = UnwrapWethInteraction { weth: WETH9::Instance::new([0x01; 20].into(), ethrpc::mock::web3().alloy), - amount: alloy::primitives::U256::ONE, + amount: U256::ONE, }; let mut encoder = SettlementEncoder::new(HashMap::new()); @@ -826,23 +816,23 @@ pub mod tests { let token_a = Address::repeat_byte(0x00); let token_b = Address::repeat_byte(0xff); let mut encoder = SettlementEncoder::new(hashmap! { - token_a => 1.into(), - token_b => 2.into(), + token_a => U256::ONE, + token_b => U256::from(2), }); encoder .add_trade( Order { data: OrderData { sell_token: token_a, - sell_amount: alloy::primitives::U256::from(6), + sell_amount: U256::from(6), buy_token: token_b, - buy_amount: alloy::primitives::U256::from(3), + buy_amount: U256::from(3), ..Default::default() }, ..Default::default() }, - 3.into(), - 0.into(), + U256::from(3), + U256::ZERO, ) .unwrap(); @@ -887,24 +877,24 @@ pub mod tests { let token_a = Address::repeat_byte(1); let token_b = Address::repeat_byte(2); let mut encoder = SettlementEncoder::new(hashmap! { - token_a => 1.into(), - token_b => 2.into(), + token_a => U256::ONE, + token_b => U256::from(2), }); assert!(encoder.add_token_equivalency(token_a, token_b).is_err()); } #[test] fn trades_add_interactions_to_the_encoded_and_later_get_encoded() { - let prices = hashmap! { Address::with_last_byte(1) => 1.into(), Address::with_last_byte(3) => 3.into() }; + let prices = hashmap! { Address::with_last_byte(1) => U256::ONE, Address::with_last_byte(3) => U256::from(3) }; let mut encoder = SettlementEncoder::new(prices); let i1 = InteractionData { target: Address::from_slice(&[12; 20]), - value: alloy::primitives::U256::from(321), + value: U256::from(321), call_data: vec![1, 2, 3, 4], }; let i2 = InteractionData { target: Address::from_slice(&[42; 20]), - value: alloy::primitives::U256::from(1212), + value: U256::from(1212), call_data: vec![4, 3, 2, 1], }; encoder @@ -912,9 +902,9 @@ pub mod tests { Order { data: OrderData { sell_token: Address::with_last_byte(1), - sell_amount: alloy::primitives::U256::from(33), + sell_amount: U256::from(33), buy_token: Address::with_last_byte(3), - buy_amount: alloy::primitives::U256::from(11), + buy_amount: U256::from(11), kind: OrderKind::Sell, ..Default::default() }, @@ -924,8 +914,8 @@ pub mod tests { }, ..Default::default() }, - 33.into(), - 5.into(), + U256::from(33), + U256::from(5), ) .unwrap(); @@ -935,9 +925,9 @@ pub mod tests { Order { data: OrderData { sell_token: Address::with_last_byte(1), - sell_amount: alloy::primitives::U256::from(66), + sell_amount: U256::from(66), buy_token: Address::with_last_byte(3), - buy_amount: alloy::primitives::U256::from(22), + buy_amount: U256::from(22), kind: OrderKind::Sell, ..Default::default() }, @@ -947,8 +937,8 @@ pub mod tests { }, ..Default::default() }, - 66.into(), - 5.into(), + U256::from(66), + U256::from(5), ) .unwrap(); @@ -967,26 +957,28 @@ pub mod tests { #[test] fn encoding_strips_unnecessary_tokens_and_prices() { let prices = hashmap! { - Address::with_last_byte(1) => 7.into(), - Address::with_last_byte(2) => 2.into(), - Address::with_last_byte(3) => 9.into(), - Address::with_last_byte(4) => 44.into() + Address::with_last_byte(1) => U256::from(7), + Address::with_last_byte(2) => U256::from(2), + Address::with_last_byte(3) => U256::from(9), + Address::with_last_byte(4) => U256::from(44), }; let mut encoder = SettlementEncoder::new(prices); let order_1_3 = OrderBuilder::default() .with_sell_token(Address::with_last_byte(1)) - .with_sell_amount(alloy::primitives::U256::from(33)) + .with_sell_amount(U256::from(33)) .with_buy_token(Address::with_last_byte(3)) - .with_buy_amount(alloy::primitives::U256::from(11)) + .with_buy_amount(U256::from(11)) .build(); - encoder.add_trade(order_1_3, 11.into(), 0.into()).unwrap(); + encoder + .add_trade(order_1_3, U256::from(11), U256::ZERO) + .unwrap(); let weth = WETH9::Instance::new(Address::with_last_byte(2), ethrpc::mock::web3().alloy); encoder.add_unwrap(UnwrapWethInteraction { weth, - amount: alloy::primitives::U256::from(12), + amount: U256::from(12), }); let encoded = encoder.finish(InternalizationStrategy::SkipInternalizableInteraction); @@ -996,10 +988,7 @@ pub mod tests { assert_eq!(expected_tokens, encoded.tokens); // only the prices for token 1 and 2 remain and they are in the correct order - let expected_prices: Vec<_> = [7, 9] - .into_iter() - .map(alloy::primitives::U256::from) - .collect(); + let expected_prices: Vec<_> = [7, 9].into_iter().map(U256::from).collect(); assert_eq!(expected_prices, encoded.clearing_prices); let encoded_trade = &encoded.trades[0]; @@ -1019,7 +1008,7 @@ pub mod tests { fn encode(&self) -> EncodedInteraction { ( Address::ZERO, - alloy::primitives::U256::ZERO, + U256::ZERO, alloy::primitives::Bytes::default(), ) } @@ -1027,7 +1016,7 @@ pub mod tests { #[test] fn optionally_encodes_internalizable_transactions() { - let prices = hashmap! {Address::with_last_byte(1) => 7.into() }; + let prices = hashmap! {Address::with_last_byte(1) => U256::from(7) }; let mut encoder = SettlementEncoder::new(prices); encoder.append_to_execution_plan_internalizable(Arc::new(TestInteraction), true); @@ -1048,8 +1037,8 @@ pub mod tests { let usdc = Address::with_last_byte(2); let prices = hashmap! { // assumption 1 WETH == 1_000 USDC (all prices multiplied by 10^18) - weth => U256::exp10(18), - usdc => U256::exp10(27) // 1 ETH buys 1_000 * 10^6 units of USDC + weth => U256::from(10).pow(U256::from(18)), + usdc => U256::from(10).pow(U256::from(27)) // 1 ETH buys 1_000 * 10^6 units of USDC }; let mut encoder = SettlementEncoder::new(prices); @@ -1057,23 +1046,27 @@ pub mod tests { let order = OrderBuilder::default() .with_class(OrderClass::Limit) .with_sell_token(weth) - .with_sell_amount(alloy::primitives::U256::from(1_010_000_000_000_000_000u128)) // 1.01 WETH + .with_sell_amount(U256::from(1_010_000_000_000_000_000u128)) // 1.01 WETH .with_buy_token(usdc) - .with_buy_amount(alloy::primitives::U256::from(10).pow(alloy::primitives::U256::from(9))) // 1_000 USDC - .with_fee_amount(alloy::primitives::U256::ZERO) + .with_buy_amount(U256::from(10).pow(U256::from(9))) // 1_000 USDC + .with_fee_amount(U256::ZERO) .with_kind(OrderKind::Sell) .build(); let execution = encoder - .add_trade(order.clone(), U256::exp10(18), U256::exp10(16)) + .add_trade( + order.clone(), + U256::from(10).pow(U256::from(18)), + U256::from(10).pow(U256::from(16)), + ) .unwrap(); assert_eq!( TradeExecution { sell_token: weth, buy_token: usdc, - sell_amount: 1_010_000_000_000_000_000u128.into(), // 1.01 WETH - buy_amount: U256::exp10(9), // 1_000 USDC - fee_amount: 0.into(), + sell_amount: U256::from(1_010_000_000_000_000_000u128), // 1.01 WETH + buy_amount: U256::from(10).pow(U256::from(9)), // 1_000 USDC + fee_amount: U256::ZERO, }, execution ); @@ -1081,15 +1074,16 @@ pub mod tests { EncoderTrade { data: Trade { order, - executed_amount: 1_010_000_000_000_000_000u128.into(), // 1.01 WETH - fee: U256::exp10(16) // 0.01 WETH (10 USDC) + executed_amount: U256::from(1_010_000_000_000_000_000u128), // 1.01 WETH + fee: U256::from(10).pow(U256::from(16)), /* 0.01 WETH (10 + * USDC) */ }, tokens: TokenReference::CustomPrice { - sell_token_price: U256::exp10(9), + sell_token_price: U256::from(10).pow(U256::from(9)), // Instead of the (solver) anticipated 1 WETH required to buy 1_000 USDC we had // to sell 1.01 WETH (to pocket the fee). This caused the // USDC price to increase by 1%. - buy_token_price: 1_010_000_000_000_000_000u128.into() + buy_token_price: U256::from(1_010_000_000_000_000_000u128) }, }, encoder.trades[0] @@ -1102,8 +1096,8 @@ pub mod tests { let usdc = Address::with_last_byte(2); // assuming 1 WETH == 1_000 USDC let prices = hashmap! { - weth => U256::exp10(18), - usdc => U256::exp10(27) // 1 ETH buys 1_000 * 10^6 units of USDC + weth => U256::from(10).pow(U256::from(18)), + usdc => U256::from(10).pow(U256::from(27)) // 1 ETH buys 1_000 * 10^6 units of USDC }; let mut encoder = SettlementEncoder::new(prices); @@ -1111,15 +1105,19 @@ pub mod tests { let order = OrderBuilder::default() .with_class(OrderClass::Limit) .with_buy_token(weth) - .with_buy_amount(alloy::primitives::U256::from(10).pow(alloy::primitives::U256::from(18))) // 1 WETH + .with_buy_amount(U256::from(10).pow(U256::from(18))) // 1 WETH .with_sell_token(usdc) - .with_sell_amount(alloy::primitives::U256::from(1_010_000_000u128)) // 1_010 USDC - .with_fee_amount(alloy::primitives::U256::ZERO) + .with_sell_amount(U256::from(1_010_000_000u128)) // 1_010 USDC + .with_fee_amount(U256::ZERO) .with_kind(OrderKind::Buy) .build(); let execution = encoder - .add_trade(order.clone(), U256::exp10(18), U256::exp10(7)) + .add_trade( + order.clone(), + U256::from(10).pow(U256::from(18)), + U256::from(10).pow(U256::from(7)), + ) .unwrap(); assert_eq!( TradeExecution { @@ -1127,9 +1125,9 @@ pub mod tests { buy_token: weth, // With the original price selling 1_000 USDC would have been enough. // With the adjusted price we actually have to sell all 1_010 USDC. - sell_amount: 1_010_000_000u128.into(), // 1_010 USDC - buy_amount: U256::exp10(18), // 1 WETH - fee_amount: 0.into(), + sell_amount: U256::from(1_010_000_000u128), // 1_010 USDC + buy_amount: U256::from(10).pow(U256::from(18)), // 1 WETH + fee_amount: U256::ZERO, }, execution ); @@ -1137,15 +1135,15 @@ pub mod tests { EncoderTrade { data: Trade { order, - executed_amount: U256::exp10(18), // 1 WETH - fee: U256::exp10(7) // 10 USDC + executed_amount: U256::from(10).pow(U256::from(18)), // 1 WETH + fee: U256::from(10).pow(U256::from(7)) // 10 USDC }, tokens: TokenReference::CustomPrice { - sell_token_price: U256::exp10(18), + sell_token_price: U256::from(10).pow(U256::from(18)), // Instead of the (solver) anticipated 1_000 USDC required to buy 1 WETH we had // to sell 1_010 USDC (to pocket the fee). This caused the // WETH price to increase by 1%. - buy_token_price: 1_010_000_000u128.into() + buy_token_price: U256::from(1_010_000_000u128) } }, encoder.trades[0] diff --git a/crates/solvers/Cargo.toml b/crates/solvers/Cargo.toml index e351085096..e66e86405c 100644 --- a/crates/solvers/Cargo.toml +++ b/crates/solvers/Cargo.toml @@ -19,30 +19,28 @@ bigdecimal = { workspace = true, features = ["serde"] } chain = { workspace = true } chrono = { workspace = true, features = ["serde"], default-features = false } clap = { workspace = true, features = ["derive", "env"] } +const-hex = { workspace = true } derive_more = { workspace = true } -ethereum-types = { workspace = true } ethrpc = { workspace = true } futures = { workspace = true } -const-hex = { workspace = true } hex-literal = { workspace = true } hyper = { workspace = true } -ethcontract = { workspace = true } itertools = { workspace = true } mimalloc = { workspace = true, optional = true } -tikv-jemallocator = { workspace = true } num = { workspace = true } prometheus = { workspace = true } prometheus-metric-storage = { workspace = true } reqwest = { workspace = true } -url = { workspace = true, features = ["serde"] } serde = { workspace = true } serde_json = { workspace = true } serde_with = { workspace = true } solvers-dto = { workspace = true } +tikv-jemallocator = { workspace = true } tokio = { workspace = true, features = ["macros", "rt-multi-thread", "signal", "time"] } toml = { workspace = true } tower = { workspace = true } tower-http = { workspace = true, features = ["limit", "trace"] } +url = { workspace = true, features = ["serde"] } web3 = { workspace = true } # TODO Once solvers are ported and E2E tests set up, slowly migrate code and diff --git a/crates/solvers/src/boundary/baseline.rs b/crates/solvers/src/boundary/baseline.rs index 02073911c8..412a10f752 100644 --- a/crates/solvers/src/boundary/baseline.rs +++ b/crates/solvers/src/boundary/baseline.rs @@ -7,7 +7,6 @@ use { }, alloy::primitives::{Address, U256}, contracts::alloy::UniswapV3QuoterV2, - ethrpc::alloy::conversions::IntoLegacy, model::TokenPair, shared::baseline_solver::{self, BaseTokens, BaselineSolvable}, std::{ @@ -202,10 +201,9 @@ fn to_boundary_liquidity( } } liquidity::State::Stable(pool) => { - if let Some(boundary_pool) = boundary::liquidity::stable::to_boundary_pool( - liquidity.address.into_legacy(), - pool, - ) { + if let Some(boundary_pool) = + boundary::liquidity::stable::to_boundary_pool(liquidity.address, pool) + { for pair in pool.reserves.token_pairs() { let token_pair = to_boundary_token_pair(&pair); onchain_liquidity.entry(token_pair).or_default().push( @@ -249,7 +247,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.into_legacy(), + address: liquidity.address, tokens: token_pair, fee, }, diff --git a/crates/solvers/src/boundary/liquidity/concentrated.rs b/crates/solvers/src/boundary/liquidity/concentrated.rs index a01e3c40fb..c20777c044 100644 --- a/crates/solvers/src/boundary/liquidity/concentrated.rs +++ b/crates/solvers/src/boundary/liquidity/concentrated.rs @@ -4,7 +4,6 @@ use { QuoteExactInputSingleParams, QuoteExactOutputSingleParams, }, - ethcontract::H160, model::TokenPair, shared::baseline_solver::BaselineSolvable, std::sync::Arc, @@ -13,7 +12,7 @@ use { #[derive(Debug)] pub struct Pool { pub uni_v3_quoter_contract: Arc, - pub address: H160, + pub address: Address, pub tokens: TokenPair, pub fee: U24, } diff --git a/crates/solvers/src/boundary/liquidity/stable.rs b/crates/solvers/src/boundary/liquidity/stable.rs index faa99eb7de..5cc9ecddd0 100644 --- a/crates/solvers/src/boundary/liquidity/stable.rs +++ b/crates/solvers/src/boundary/liquidity/stable.rs @@ -1,8 +1,8 @@ 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, IntoLegacy}, + alloy::primitives::{Address, B256, U256}, + ethrpc::alloy::conversions::IntoLegacy, shared::sources::balancer_v2::{ pool_fetching::{AmplificationParameter, CommonPoolState, TokenState}, swap::fixed_point::Bfp, @@ -11,16 +11,12 @@ use { /// Converts a domain pool into a [`shared`] Balancer V2 stable pool. Returns /// `None` if the domain pool cannot be represented as a boundary pool. -pub fn to_boundary_pool(address: H160, pool: &liquidity::stable::Pool) -> Option { +pub fn to_boundary_pool(address: Address, pool: &liquidity::stable::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()); - H256(buf) - }; + let id = B256::right_padding_from(address.as_slice()); let swap_fee = to_fixed_point(&pool.fee)?; let reserves = pool @@ -44,8 +40,8 @@ pub fn to_boundary_pool(address: H160, pool: &liquidity::stable::Pool) -> Option Some(Pool { common: CommonPoolState { - id, - address: address.into_alloy(), + id: id.into_legacy(), + address, swap_fee, paused: false, }, @@ -59,7 +55,7 @@ fn to_fixed_point(ratio: ð::Rational) -> Option { // Balancer "fixed point numbers" are in a weird decimal FP format (instead // 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().into_legacy().checked_mul(base)? / ratio.denom().into_legacy(); - Some(Bfp::from_wei(wei)) + let base = U256::from(10).pow(U256::from(18)); + let wei = ratio.numer().checked_mul(base)? / ratio.denom(); + Some(Bfp::from_wei(wei.into_legacy())) } diff --git a/crates/solvers/src/boundary/liquidity/weighted_product.rs b/crates/solvers/src/boundary/liquidity/weighted_product.rs index 2733260c61..20839258ac 100644 --- a/crates/solvers/src/boundary/liquidity/weighted_product.rs +++ b/crates/solvers/src/boundary/liquidity/weighted_product.rs @@ -1,8 +1,7 @@ pub use shared::sources::balancer_v2::pool_fetching::WeightedPool as Pool; use { crate::domain::{eth, liquidity}, - alloy::primitives::Address, - ethereum_types::{H256, U256}, + alloy::primitives::{Address, B256, U256}, ethrpc::alloy::conversions::IntoLegacy, shared::sources::balancer_v2::{ pool_fetching::{CommonPoolState, TokenState, WeightedPoolVersion, WeightedTokenState}, @@ -20,11 +19,7 @@ pub fn to_boundary_pool( // 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_slice()); - H256(buf) - }; + let id = B256::right_padding_from(address.as_slice()); let swap_fee = to_fixed_point(&pool.fee)?; let reserves = pool @@ -46,7 +41,7 @@ pub fn to_boundary_pool( Some(Pool { common: CommonPoolState { - id, + id: id.into_legacy(), address, swap_fee, paused: false, @@ -64,7 +59,7 @@ fn to_fixed_point(ratio: ð::Rational) -> Option { // Balancer "fixed point numbers" are in a weird decimal FP format (instead // 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().into_legacy().checked_mul(base)? / ratio.denom().into_legacy(); - Some(Bfp::from_wei(wei)) + let base = U256::from(10).pow(U256::from(18)); + let wei = ratio.numer().checked_mul(base)? / ratio.denom(); + Some(Bfp::from_wei(wei.into_legacy())) } diff --git a/crates/solvers/src/domain/order.rs b/crates/solvers/src/domain/order.rs index c614950e6c..738d8b6483 100644 --- a/crates/solvers/src/domain/order.rs +++ b/crates/solvers/src/domain/order.rs @@ -2,8 +2,8 @@ use { crate::{domain::eth, util}, + alloy::primitives::B256, eth::Address, - ethereum_types::H256, std::fmt::{self, Debug, Display, Formatter}, }; @@ -108,16 +108,16 @@ pub enum Signature { #[derive(Clone, Copy, Debug, Default)] pub struct EcdsaSignature { - pub r: H256, - pub s: H256, + pub r: B256, + pub s: B256, pub v: u8, } impl EcdsaSignature { pub fn to_bytes(self) -> [u8; 65] { let mut bytes = [0u8; 65]; - bytes[..32].copy_from_slice(self.r.as_bytes()); - bytes[32..64].copy_from_slice(self.s.as_bytes()); + bytes[..32].copy_from_slice(self.r.as_slice()); + bytes[32..64].copy_from_slice(self.s.as_slice()); bytes[64] = self.v; bytes } From 6defb2a92bb9c1a929017efb29354810e029869b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=CC=81=20Duarte?= Date: Wed, 10 Dec 2025 13:08:16 +0000 Subject: [PATCH 2/2] address comment --- crates/solver/src/settlement/mod.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/crates/solver/src/settlement/mod.rs b/crates/solver/src/settlement/mod.rs index 2ead4d0da1..b46798ee55 100644 --- a/crates/solver/src/settlement/mod.rs +++ b/crates/solver/src/settlement/mod.rs @@ -259,16 +259,16 @@ pub mod tests { ..Default::default() }; let sell_price = U256::from(2); - let buy_price = U256::from(1); + let buy_price = U256::ONE; assert!(trade.executed_amounts(sell_price, buy_price).is_none()); // div let trade = Trade { order, - executed_amount: U256::from(1), + executed_amount: U256::ONE, ..Default::default() }; - let sell_price = U256::from(1); + let sell_price = U256::ONE; let buy_price = U256::ZERO; assert!(trade.executed_amounts(sell_price, buy_price).is_none()); } @@ -295,24 +295,24 @@ pub mod tests { }; let mut settlement = Settlement::new(hashmap! { - token0 => U256::from(1), - token1 => U256::from(1), + token0 => U256::ONE, + token1 => U256::ONE, }); assert!( settlement .encoder - .add_trade(order.clone(), U256::from(10), U256::from(0)) + .add_trade(order.clone(), U256::from(10), U256::ZERO) .is_ok() ); let mut settlement = Settlement::new(hashmap! { - token0 => U256::from(1), - token1 => U256::from(0), + token0 => U256::ONE, + token1 => U256::ZERO, }); assert!( settlement .encoder - .add_trade(order, U256::from(10), U256::from(0)) + .add_trade(order, U256::from(10), U256::ZERO) .is_err() ); }