From 379285ece995b0f9e38e2a64261fb2c3d8e156e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Fri, 7 Nov 2025 09:43:42 +0000 Subject: [PATCH 01/17] Migrate quote DTO to alloy --- crates/autopilot/src/domain/fee/mod.rs | 7 ++-- crates/autopilot/src/domain/quote/mod.rs | 3 +- .../src/infra/persistence/dto/order.rs | 37 ++++++++++--------- .../src/infra/persistence/dto/quote.rs | 5 ++- 4 files changed, 28 insertions(+), 24 deletions(-) diff --git a/crates/autopilot/src/domain/fee/mod.rs b/crates/autopilot/src/domain/fee/mod.rs index 456380f5fd..8b265c181b 100644 --- a/crates/autopilot/src/domain/fee/mod.rs +++ b/crates/autopilot/src/domain/fee/mod.rs @@ -12,6 +12,7 @@ use { boundary::{self}, domain::{self, eth}, }, + alloy::primitives::Address, app_data::Validator, derive_more::Into, primitive_types::{H160, U256}, @@ -209,7 +210,7 @@ impl ProtocolFees { sell_amount: order.data.sell_amount.into(), buy_amount: U256::zero().into(), fee: order.data.fee_amount.into(), - solver: H160::zero().into(), + solver: Address::ZERO, }); let partner_fee = @@ -333,7 +334,7 @@ pub struct Quote { pub buy_amount: U256, /// The amount that needs to be paid, denominated in the sell token. pub fee: U256, - pub solver: H160, + pub solver: Address, } impl Quote { @@ -342,7 +343,7 @@ impl Quote { sell_amount: value.sell_amount.into(), buy_amount: value.buy_amount.into(), fee: value.fee.into(), - solver: value.solver.into(), + solver: value.solver, } } } diff --git a/crates/autopilot/src/domain/quote/mod.rs b/crates/autopilot/src/domain/quote/mod.rs index e9174ee6fd..41131c37ef 100644 --- a/crates/autopilot/src/domain/quote/mod.rs +++ b/crates/autopilot/src/domain/quote/mod.rs @@ -1,6 +1,7 @@ use { super::OrderUid, crate::{boundary::Amounts, domain::eth}, + alloy::primitives::Address, }; #[derive(Clone, Debug, PartialEq)] @@ -9,7 +10,7 @@ pub struct Quote { pub sell_amount: eth::SellTokenAmount, pub buy_amount: eth::TokenAmount, pub fee: eth::SellTokenAmount, - pub solver: eth::Address, + pub solver: Address, } impl From<&Quote> for Amounts { diff --git a/crates/autopilot/src/infra/persistence/dto/order.rs b/crates/autopilot/src/infra/persistence/dto/order.rs index f3da508f65..be8a1b63e7 100644 --- a/crates/autopilot/src/infra/persistence/dto/order.rs +++ b/crates/autopilot/src/infra/persistence/dto/order.rs @@ -3,6 +3,7 @@ use { boundary::{self}, domain::{self, OrderUid, eth, fee::FeeFactor}, }, + alloy::primitives::Address, app_data::AppDataHash, ethrpc::alloy::conversions::{IntoAlloy, IntoLegacy}, number::serialization::HexOrDecimalU256, @@ -289,9 +290,9 @@ impl FeePolicy { factor: factor.into(), max_volume_factor: max_volume_factor.into(), quote: Quote { - sell_amount: quote.sell_amount, - buy_amount: quote.buy_amount, - fee: quote.fee, + sell_amount: quote.sell_amount.into_alloy(), + buy_amount: quote.buy_amount.into_alloy(), + fee: quote.fee.into_alloy(), solver: quote.solver, }, }, @@ -318,9 +319,9 @@ impl FeePolicy { factor: FeeFactor::try_from(factor).unwrap(), max_volume_factor: FeeFactor::try_from(max_volume_factor).unwrap(), quote: domain::fee::Quote { - sell_amount: quote.sell_amount, - buy_amount: quote.buy_amount, - fee: quote.fee, + sell_amount: quote.sell_amount.into_legacy(), + buy_amount: quote.buy_amount.into_legacy(), + fee: quote.fee.into_legacy(), solver: quote.solver, }, }, @@ -336,31 +337,31 @@ impl FeePolicy { #[serde(rename_all = "camelCase")] pub struct Quote { #[serde_as(as = "HexOrDecimalU256")] - pub sell_amount: U256, + pub sell_amount: alloy::primitives::U256, #[serde_as(as = "HexOrDecimalU256")] - pub buy_amount: U256, + pub buy_amount: alloy::primitives::U256, #[serde_as(as = "HexOrDecimalU256")] - pub fee: U256, - pub solver: H160, + pub fee: alloy::primitives::U256, + pub solver: Address, } impl Quote { fn from_domain(quote: domain::Quote) -> Self { Quote { - sell_amount: quote.sell_amount.0, - buy_amount: quote.buy_amount.0, - fee: quote.fee.0, - solver: quote.solver.0, + sell_amount: quote.sell_amount.0.into_alloy(), + buy_amount: quote.buy_amount.0.into_alloy(), + fee: quote.fee.0.into_alloy(), + solver: quote.solver, } } pub fn to_domain(&self, order_uid: OrderUid) -> domain::Quote { domain::Quote { order_uid, - sell_amount: self.sell_amount.into(), - buy_amount: self.buy_amount.into(), - fee: self.fee.into(), - solver: self.solver.into(), + sell_amount: self.sell_amount.into_legacy().into(), + buy_amount: self.buy_amount.into_legacy().into(), + fee: self.fee.into_legacy().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 7ce1cdfa0b..d3216d024e 100644 --- a/crates/autopilot/src/infra/persistence/dto/quote.rs +++ b/crates/autopilot/src/infra/persistence/dto/quote.rs @@ -1,8 +1,9 @@ use { crate::{ boundary, - domain::{self, eth}, + domain::{self}, }, + alloy::primitives::Address, bigdecimal::{ FromPrimitive, num_traits::{CheckedDiv, CheckedMul}, @@ -33,7 +34,7 @@ pub fn into_domain(quote: boundary::database::orders::Quote) -> Result Date: Fri, 7 Nov 2025 12:12:23 +0000 Subject: [PATCH 02/17] Migrate the native price estimation endpoint and trait to alloy --- crates/autopilot/src/domain/fee/mod.rs | 19 ++++++----- .../src/domain/settlement/trade/math.rs | 7 ++-- .../src/infra/persistence/dto/fee_policy.rs | 7 ++-- .../src/infra/persistence/dto/order.rs | 12 +++---- crates/autopilot/src/solvable_orders.rs | 24 ++++++------- crates/orderbook/src/api/get_native_price.rs | 15 ++++---- crates/shared/src/order_quoting.rs | 25 +++++++------- .../shared/src/price_estimation/buffered.rs | 28 ++++++++------- .../price_estimation/competition/native.rs | 4 +-- .../src/price_estimation/competition/quote.rs | 7 ++-- .../src/price_estimation/instrumented.rs | 4 +-- .../src/price_estimation/native/coingecko.rs | 33 ++++++++++++------ .../shared/src/price_estimation/native/mod.rs | 12 ++++--- .../src/price_estimation/native/oneinch.rs | 19 +++++++---- .../price_estimation/native_price_cache.rs | 34 +++++++++++++------ 15 files changed, 144 insertions(+), 106 deletions(-) diff --git a/crates/autopilot/src/domain/fee/mod.rs b/crates/autopilot/src/domain/fee/mod.rs index 8b265c181b..97f2db76cb 100644 --- a/crates/autopilot/src/domain/fee/mod.rs +++ b/crates/autopilot/src/domain/fee/mod.rs @@ -12,10 +12,11 @@ use { boundary::{self}, domain::{self, eth}, }, - alloy::primitives::Address, + alloy::primitives::{Address, U256}, app_data::Validator, derive_more::Into, - primitive_types::{H160, U256}, + ethrpc::alloy::conversions::{IntoAlloy, IntoLegacy}, + primitive_types::H160, rust_decimal::Decimal, std::{collections::HashSet, str::FromStr}, }; @@ -183,9 +184,9 @@ impl ProtocolFees { factor, max_volume_factor, quote: Quote { - sell_amount: quote.sell_amount.into(), - buy_amount: quote.buy_amount.into(), - fee: quote.fee.into(), + sell_amount: quote.sell_amount.0.into_alloy(), + buy_amount: quote.buy_amount.0.into_alloy(), + fee: quote.fee.0.into_alloy(), solver: quote.solver.into(), }, } @@ -208,7 +209,7 @@ impl ProtocolFees { let reference_quote = quote.clone().unwrap_or(domain::Quote { order_uid: order.metadata.uid.into(), sell_amount: order.data.sell_amount.into(), - buy_amount: U256::zero().into(), + buy_amount: U256::ZERO.into_legacy().into(), fee: order.data.fee_amount.into(), solver: Address::ZERO, }); @@ -340,9 +341,9 @@ pub struct Quote { impl Quote { fn from_domain(value: &domain::Quote) -> Self { Self { - sell_amount: value.sell_amount.into(), - buy_amount: value.buy_amount.into(), - fee: value.fee.into(), + sell_amount: value.sell_amount.0.into_alloy(), + buy_amount: value.buy_amount.0.into_alloy(), + fee: value.fee.0.into_alloy(), solver: value.solver, } } diff --git a/crates/autopilot/src/domain/settlement/trade/math.rs b/crates/autopilot/src/domain/settlement/trade/math.rs index b94507d985..c8635850da 100644 --- a/crates/autopilot/src/domain/settlement/trade/math.rs +++ b/crates/autopilot/src/domain/settlement/trade/math.rs @@ -16,6 +16,7 @@ use { util::conv::U256Ext, }, error::Math, + ethrpc::alloy::conversions::IntoLegacy, num::{CheckedAdd, CheckedDiv, CheckedMul, CheckedSub}, std::collections::HashMap, }; @@ -383,9 +384,9 @@ impl Trade { side: self.side, }, Quote { - sell: quote.sell_amount.into(), - buy: quote.buy_amount.into(), - fee: quote.fee.into(), + sell: quote.sell_amount.into_legacy().into(), + buy: quote.buy_amount.into_legacy().into(), + fee: quote.fee.into_legacy().into(), }, )?; self.surplus_over(&self.prices.custom, quote) diff --git a/crates/autopilot/src/infra/persistence/dto/fee_policy.rs b/crates/autopilot/src/infra/persistence/dto/fee_policy.rs index 6686020caf..976bcadd3b 100644 --- a/crates/autopilot/src/infra/persistence/dto/fee_policy.rs +++ b/crates/autopilot/src/infra/persistence/dto/fee_policy.rs @@ -2,6 +2,7 @@ use { crate::{boundary, domain}, anyhow::Context, database::fee_policies::{FeePolicy, FeePolicyKind}, + ethrpc::alloy::conversions::IntoAlloy, }; pub fn from_domain( @@ -83,9 +84,9 @@ pub fn try_into_domain( quote: { let quote = quote.ok_or(Error::MissingQuote)?; domain::fee::Quote { - sell_amount: quote.sell_amount.into(), - buy_amount: quote.buy_amount.into(), - fee: quote.fee.into(), + sell_amount: quote.sell_amount.0.into_alloy(), + buy_amount: quote.buy_amount.0.into_alloy(), + fee: quote.fee.0.into_alloy(), solver: quote.solver.into(), } }, diff --git a/crates/autopilot/src/infra/persistence/dto/order.rs b/crates/autopilot/src/infra/persistence/dto/order.rs index be8a1b63e7..0f3c1745a6 100644 --- a/crates/autopilot/src/infra/persistence/dto/order.rs +++ b/crates/autopilot/src/infra/persistence/dto/order.rs @@ -290,9 +290,9 @@ impl FeePolicy { factor: factor.into(), max_volume_factor: max_volume_factor.into(), quote: Quote { - sell_amount: quote.sell_amount.into_alloy(), - buy_amount: quote.buy_amount.into_alloy(), - fee: quote.fee.into_alloy(), + sell_amount: quote.sell_amount, + buy_amount: quote.buy_amount, + fee: quote.fee, solver: quote.solver, }, }, @@ -319,9 +319,9 @@ impl FeePolicy { factor: FeeFactor::try_from(factor).unwrap(), max_volume_factor: FeeFactor::try_from(max_volume_factor).unwrap(), quote: domain::fee::Quote { - sell_amount: quote.sell_amount.into_legacy(), - buy_amount: quote.buy_amount.into_legacy(), - fee: quote.fee.into_legacy(), + sell_amount: quote.sell_amount, + buy_amount: quote.buy_amount, + fee: quote.fee, solver: quote.solver, }, }, diff --git a/crates/autopilot/src/solvable_orders.rs b/crates/autopilot/src/solvable_orders.rs index 1ecc12c019..491ee96634 100644 --- a/crates/autopilot/src/solvable_orders.rs +++ b/crates/autopilot/src/solvable_orders.rs @@ -230,7 +230,7 @@ impl SolvableOrdersCache { .timed_future( "weth_price_fetch", self.native_price_estimator - .estimate_native_price(self.weth, Default::default()), + .estimate_native_price(self.weth.into_alloy(), Default::default()), ) .await .expect("weth price fetching can never fail"); @@ -924,17 +924,17 @@ mod tests { let mut native_price_estimator = MockNativePriceEstimating::new(); native_price_estimator .expect_estimate_native_price() - .withf(move |token, _| *token == token1) + .withf(move |token, _| *token == token1.into_alloy()) .returning(|_, _| async { Ok(2.) }.boxed()); native_price_estimator .expect_estimate_native_price() .times(1) - .withf(move |token, _| *token == token2) + .withf(move |token, _| *token == token2.into_alloy()) .returning(|_, _| async { Err(PriceEstimationError::NoLiquidity) }.boxed()); native_price_estimator .expect_estimate_native_price() .times(1) - .withf(move |token, _| *token == token3) + .withf(move |token, _| *token == token3.into_alloy()) .returning(|_, _| async { Ok(0.25) }.boxed()); let native_price_estimator = CachingNativePriceEstimator::new( @@ -1005,27 +1005,27 @@ mod tests { let mut native_price_estimator = MockNativePriceEstimating::new(); native_price_estimator .expect_estimate_native_price() - .withf(move |token, _| *token == token1) + .withf(move |token, _| *token == token1.into_alloy()) .returning(|_, _| async { Ok(2.) }.boxed()); native_price_estimator .expect_estimate_native_price() .times(1) - .withf(move |token, _| *token == token2) + .withf(move |token, _| *token == token2.into_alloy()) .returning(|_, _| async { Err(PriceEstimationError::NoLiquidity) }.boxed()); native_price_estimator .expect_estimate_native_price() .times(1) - .withf(move |token, _| *token == token3) + .withf(move |token, _| *token == token3.into_alloy()) .returning(|_, _| async { Ok(0.25) }.boxed()); native_price_estimator .expect_estimate_native_price() .times(1) - .withf(move |token, _| *token == token4) + .withf(move |token, _| *token == token4.into_alloy()) .returning(|_, _| async { Ok(0.) }.boxed()); native_price_estimator .expect_estimate_native_price() .times(1) - .withf(move |token, _| *token == token5) + .withf(move |token, _| *token == token5.into_alloy()) .returning(|_, _| async { Ok(5.) }.boxed()); let native_price_estimator = CachingNativePriceEstimator::new( @@ -1112,17 +1112,17 @@ mod tests { native_price_estimator .expect_estimate_native_price() .times(1) - .withf(move |token, _| *token == token3) + .withf(move |token, _| *token == token3.into_alloy()) .returning(|_, _| async { Ok(3.) }.boxed()); native_price_estimator .expect_estimate_native_price() .times(1) - .withf(move |token, _| *token == token_approx1) + .withf(move |token, _| *token == token_approx1.into_alloy()) .returning(|_, _| async { Ok(40.) }.boxed()); native_price_estimator .expect_estimate_native_price() .times(1) - .withf(move |token, _| *token == token_approx2) + .withf(move |token, _| *token == token_approx2.into_alloy()) .returning(|_, _| async { Ok(50.) }.boxed()); let native_price_estimator = CachingNativePriceEstimator::new( diff --git a/crates/orderbook/src/api/get_native_price.rs b/crates/orderbook/src/api/get_native_price.rs index 9b4c46034e..b2c027ebce 100644 --- a/crates/orderbook/src/api/get_native_price.rs +++ b/crates/orderbook/src/api/get_native_price.rs @@ -1,22 +1,22 @@ use { crate::api::{ApiReply, IntoWarpReply}, + alloy::primitives::Address, anyhow::Result, - ethcontract::H160, model::quote::NativeTokenPrice, shared::price_estimation::native::NativePriceEstimating, std::{convert::Infallible, sync::Arc, time::Duration}, warp::{Filter, Rejection, hyper::StatusCode, reply::with_status}, }; -fn get_native_prices_request() -> impl Filter + Clone { - warp::path!("v1" / "token" / H160 / "native_price").and(warp::get()) +fn get_native_prices_request() -> impl Filter + Clone { + warp::path!("v1" / "token" / Address / "native_price").and(warp::get()) } pub fn get_native_price( estimator: Arc, quote_timeout: Duration, ) -> impl Filter + Clone { - get_native_prices_request().and_then(move |token: H160| { + get_native_prices_request().and_then(move |token: Address| { let estimator = estimator.clone(); async move { let result = estimator.estimate_native_price(token, quote_timeout).await; @@ -34,7 +34,7 @@ pub fn get_native_price( #[cfg(test)] mod tests { - use {super::*, futures::FutureExt, hex_literal::hex, warp::test::request}; + use {super::*, alloy::primitives::address, futures::FutureExt, warp::test::request}; #[test] fn native_prices_query() { @@ -45,9 +45,6 @@ mod tests { .now_or_never() .unwrap() .unwrap(); - assert_eq!( - result, - H160(hex!("dac17f958d2ee523a2206206994597c13d831ec7")) - ); + assert_eq!(result, address!("dac17f958d2ee523a2206206994597c13d831ec7")); } } diff --git a/crates/shared/src/order_quoting.rs b/crates/shared/src/order_quoting.rs index cfcd32c7d5..914c198d6f 100644 --- a/crates/shared/src/order_quoting.rs +++ b/crates/shared/src/order_quoting.rs @@ -469,13 +469,13 @@ impl OrderQuoter { .estimate(trade_query.clone()) .map_err(|err| (EstimatorKind::Regular, err).into()), self.native_price_estimator - .estimate_native_price(parameters.sell_token, trade_query.timeout) + .estimate_native_price(parameters.sell_token.into_alloy(), trade_query.timeout) .map_err(|err| (EstimatorKind::NativeSell, err).into()), // We don't care about the native price of the buy_token for the quote but we need it // when we build the auction. To prevent creating orders which we can't settle later on // we make the native buy_token price a requirement here as well. self.native_price_estimator - .estimate_native_price(parameters.buy_token, trade_query.timeout) + .estimate_native_price(parameters.buy_token.into_alloy(), trade_query.timeout) .map_err(|err| (EstimatorKind::NativeBuy, err).into()), )?; @@ -787,6 +787,7 @@ mod tests { alloy::primitives::Address, chrono::Utc, ethcontract::H160, + ethrpc::alloy::conversions::IntoLegacy, futures::FutureExt, gas_estimation::GasPrice1559, mockall::{Sequence, predicate::eq}, @@ -886,14 +887,14 @@ mod tests { .expect_estimate_native_price() .withf({ let sell_token = parameters.sell_token; - move |q, _| q == &sell_token + move |q, _| q.into_legacy() == sell_token }) .returning(|_, _| async { Ok(0.2) }.boxed()); native_price_estimator .expect_estimate_native_price() .withf({ let buy_token = parameters.buy_token; - move |q, _| q == &buy_token + move |q, _| q.into_legacy() == buy_token }) .returning(|_, _| async { Ok(0.2) }.boxed()); @@ -1027,14 +1028,14 @@ mod tests { .expect_estimate_native_price() .withf({ let sell_token = parameters.sell_token; - move |q, _| q == &sell_token + move |q, _| q.into_legacy() == sell_token }) .returning(|_, _| async { Ok(0.2) }.boxed()); native_price_estimator .expect_estimate_native_price() .withf({ let buy_token = parameters.buy_token; - move |q, _| q == &buy_token + move |q, _| q.into_legacy() == buy_token }) .returning(|_, _| async { Ok(0.2) }.boxed()); @@ -1163,14 +1164,14 @@ mod tests { .expect_estimate_native_price() .withf({ let sell_token = parameters.sell_token; - move |q, _| q == &sell_token + move |q, _| q.into_legacy() == sell_token }) .returning(|_, _| async { Ok(0.2) }.boxed()); native_price_estimator .expect_estimate_native_price() .withf({ let buy_token = parameters.buy_token; - move |q, _| q == &buy_token + move |q, _| q.into_legacy() == buy_token }) .returning(|_, _| async { Ok(0.2) }.boxed()); @@ -1284,14 +1285,14 @@ mod tests { .expect_estimate_native_price() .withf({ let sell_token = parameters.sell_token; - move |q, _| q == &sell_token + move |q, _| q.into_legacy() == sell_token }) .returning(|_, _| async { Ok(1.) }.boxed()); native_price_estimator .expect_estimate_native_price() .withf({ let buy_token = parameters.buy_token; - move |q, _| q == &buy_token + move |q, _| q.into_legacy() == buy_token }) .returning(|_, _| async { Ok(1.) }.boxed()); @@ -1358,14 +1359,14 @@ mod tests { .expect_estimate_native_price() .withf({ let sell_token = parameters.sell_token; - move |q, _| q == &sell_token + move |q, _| q.into_legacy() == sell_token }) .returning(|_, _| async { Ok(1.) }.boxed()); native_price_estimator .expect_estimate_native_price() .withf({ let buy_token = parameters.buy_token; - move |q, _| q == &buy_token + move |q, _| q.into_legacy() == buy_token }) .returning(|_, _| async { Err(PriceEstimationError::NoLiquidity) }.boxed()); diff --git a/crates/shared/src/price_estimation/buffered.rs b/crates/shared/src/price_estimation/buffered.rs index e84db5b5d1..0f23d3bc25 100644 --- a/crates/shared/src/price_estimation/buffered.rs +++ b/crates/shared/src/price_estimation/buffered.rs @@ -6,7 +6,9 @@ use { PriceEstimationError, native::{NativePriceEstimateResult, NativePriceEstimating}, }, + alloy::primitives::Address, anyhow::anyhow, + ethrpc::alloy::conversions::IntoLegacy, futures::{ channel::mpsc, future::FutureExt as _, @@ -86,7 +88,7 @@ where #[instrument(skip_all)] fn estimate_native_price( &self, - token: H160, + token: Address, timeout: Duration, ) -> futures::future::BoxFuture<'_, NativePriceEstimateResult> { async move { @@ -97,17 +99,19 @@ where let mut rx = self.results.subscribe(); // Sends the token for requesting price - self.requests.unbounded_send(token).map_err(|e| { - PriceEstimationError::ProtocolInternal(anyhow!( - "failed to append a new token to the queue: {e:?}" - )) - })?; + self.requests + .unbounded_send(token.into_legacy()) + .map_err(|e| { + PriceEstimationError::ProtocolInternal(anyhow!( + "failed to append a new token to the queue: {e:?}" + )) + })?; tokio::time::timeout(timeout, async { loop { match rx.recv().await { Ok(value) => { - if value.token == token { + if value.token == token.into_legacy() { return value.result; } } @@ -262,15 +266,15 @@ mod tests { impl NativePriceEstimating for MockNativePriceBatchFetching { fn estimate_native_price( &self, - token: H160, + token: Address, timeout: Duration, ) -> futures::future::BoxFuture<'_, NativePriceEstimateResult> { async move { let prices = self - .fetch_native_prices(HashSet::from([token]), timeout) + .fetch_native_prices(HashSet::from([token.into_legacy()]), timeout) .await?; prices - .get(&token) + .get(&token.into_legacy()) .cloned() .ok_or(PriceEstimationError::NoLiquidity)? } @@ -278,8 +282,8 @@ mod tests { } } - fn token(u: u64) -> H160 { - H160::from_low_u64_be(u) + fn token(u: u64) -> Address { + Address::left_padding_from(&u.to_be_bytes()) } #[tokio::test] diff --git a/crates/shared/src/price_estimation/competition/native.rs b/crates/shared/src/price_estimation/competition/native.rs index e3f9883712..2c987362c0 100644 --- a/crates/shared/src/price_estimation/competition/native.rs +++ b/crates/shared/src/price_estimation/competition/native.rs @@ -4,10 +4,10 @@ use { PriceEstimationError, native::{NativePriceEstimateResult, NativePriceEstimating, is_price_malformed}, }, + alloy::primitives::Address, anyhow::Context, futures::{FutureExt, future::BoxFuture}, model::order::OrderKind, - primitive_types::H160, std::{cmp::Ordering, sync::Arc, time::Duration}, tracing::instrument, }; @@ -16,7 +16,7 @@ impl NativePriceEstimating for CompetitionEstimator BoxFuture<'_, NativePriceEstimateResult> { let started_at = std::time::Instant::now(); diff --git a/crates/shared/src/price_estimation/competition/quote.rs b/crates/shared/src/price_estimation/competition/quote.rs index 814061d264..6a20b1231a 100644 --- a/crates/shared/src/price_estimation/competition/quote.rs +++ b/crates/shared/src/price_estimation/competition/quote.rs @@ -9,6 +9,7 @@ use { QuoteVerificationMode, }, anyhow::Context, + ethrpc::alloy::conversions::IntoAlloy, futures::future::{BoxFuture, FutureExt, TryFutureExt}, model::order::OrderKind, primitive_types::{H160, U256}, @@ -109,8 +110,10 @@ impl PriceRanking { .estimate() .map_ok(|gas| gas.effective_gas_price()) .map_err(PriceEstimationError::ProtocolInternal); - let (native_price, gas_price) = - futures::try_join!(native.estimate_native_price(token, timeout), gas)?; + let (native_price, gas_price) = futures::try_join!( + native.estimate_native_price(token.into_alloy(), timeout), + gas + )?; Ok(RankingContext { native_price, diff --git a/crates/shared/src/price_estimation/instrumented.rs b/crates/shared/src/price_estimation/instrumented.rs index 23a911fe99..ce89101d11 100644 --- a/crates/shared/src/price_estimation/instrumented.rs +++ b/crates/shared/src/price_estimation/instrumented.rs @@ -5,9 +5,9 @@ use { Query, native::{NativePriceEstimateResult, NativePriceEstimating}, }, + alloy::primitives::Address, ethcontract::jsonrpc::futures_util::future::BoxFuture, futures::future::FutureExt, - primitive_types::H160, prometheus::{HistogramVec, IntCounterVec}, std::{ sync::Arc, @@ -85,7 +85,7 @@ impl PriceEstimating for InstrumentedPriceEstimator { impl NativePriceEstimating for InstrumentedPriceEstimator { fn estimate_native_price( &self, - token: H160, + token: Address, timeout: Duration, ) -> BoxFuture<'_, NativePriceEstimateResult> { async move { diff --git a/crates/shared/src/price_estimation/native/coingecko.rs b/crates/shared/src/price_estimation/native/coingecko.rs index 20fc412120..ccf6d371ea 100644 --- a/crates/shared/src/price_estimation/native/coingecko.rs +++ b/crates/shared/src/price_estimation/native/coingecko.rs @@ -4,8 +4,10 @@ use { price_estimation::{PriceEstimationError, buffered::NativePriceBatchFetching}, token_info::{TokenInfo, TokenInfoFetching}, }, + alloy::primitives::Address, anyhow::{Context, Result, anyhow}, chain::Chain, + ethrpc::alloy::conversions::IntoLegacy, futures::{FutureExt, future::BoxFuture}, primitive_types::H160, reqwest::{Client, StatusCode}, @@ -252,15 +254,15 @@ impl NativePriceEstimating for CoinGecko { #[instrument(skip_all)] fn estimate_native_price( &self, - token: Token, + token: Address, timeout: Duration, ) -> BoxFuture<'_, NativePriceEstimateResult> { async move { let prices = self - .fetch_native_prices(HashSet::from([token]), timeout) + .fetch_native_prices(HashSet::from([token.into_legacy()]), timeout) .await?; prices - .get(&token) + .get(&token.into_legacy()) .ok_or(PriceEstimationError::NoLiquidity)? .clone() } @@ -324,6 +326,7 @@ mod tests { price_estimation::HEALTHY_PRICE_ESTIMATION_TIME, token_info::{MockTokenInfoFetching, TokenInfo}, }, + alloy::primitives::address, std::env, }; @@ -402,7 +405,7 @@ mod tests { #[tokio::test] #[ignore] async fn works() { - let native_token = addr!("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"); + let native_token = address!("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"); let instance = CoinGecko::new_for_test( Client::default(), Url::parse(BASE_API_URL).unwrap(), @@ -425,7 +428,7 @@ mod tests { #[ignore] async fn works_xdai() { // USDT - let native_token = addr!("4ECaBa5870353805a9F068101A40E0f32ed605C6"); + let native_token = address!("4ECaBa5870353805a9F068101A40E0f32ed605C6"); let instance = CoinGecko::new_for_test( Client::default(), Url::parse(BASE_API_PRO_URL).unwrap(), @@ -505,14 +508,18 @@ mod tests { #[tokio::test] #[ignore] async fn prices_adjusted_for_token_with_fewer_decimals() { - let usdc = addr!("2a22f9c3b484c3629090FeED35F17Ff8F88f76F0"); - let wxdai = addr!("e91D153E0b41518A2Ce8Dd3D7944Fa863463a97d"); + let usdc = address!("2a22f9c3b484c3629090FeED35F17Ff8F88f76F0"); + let wxdai = address!("e91D153E0b41518A2Ce8Dd3D7944Fa863463a97d"); let mut mock = MockTokenInfoFetching::new(); mock.expect_get_token_infos().returning(move |tokens| { tokens .iter() .map(|t| { - let decimals = if *t == usdc { Some(6) } else { Some(18) }; + let decimals = if *t == usdc.into_legacy() { + Some(6) + } else { + Some(18) + }; let info = TokenInfo { decimals, symbol: None, @@ -557,8 +564,8 @@ mod tests { #[tokio::test] #[ignore] async fn prices_adjusted_for_token_with_more_decimals() { - let usdc = addr!("2a22f9c3b484c3629090FeED35F17Ff8F88f76F0"); - let wxdai = addr!("e91D153E0b41518A2Ce8Dd3D7944Fa863463a97d"); + let usdc = address!("2a22f9c3b484c3629090FeED35F17Ff8F88f76F0"); + let wxdai = address!("e91D153E0b41518A2Ce8Dd3D7944Fa863463a97d"); let mut mock = MockTokenInfoFetching::new(); mock.expect_get_token_infos().returning(move |tokens| { tokens @@ -566,7 +573,11 @@ mod tests { .map(|t| { // Let's pretend USDC has 21 decimals to check if the price adjustment // also works when the requested token has more decimals. - let decimals = if *t == usdc { Some(21) } else { Some(18) }; + let decimals = if *t == usdc.into_legacy() { + Some(21) + } else { + Some(18) + }; let info = TokenInfo { decimals, symbol: None, diff --git a/crates/shared/src/price_estimation/native/mod.rs b/crates/shared/src/price_estimation/native/mod.rs index af52cefaa4..85fab12c23 100644 --- a/crates/shared/src/price_estimation/native/mod.rs +++ b/crates/shared/src/price_estimation/native/mod.rs @@ -1,6 +1,8 @@ use { crate::price_estimation::{PriceEstimating, PriceEstimationError, Query}, + alloy::primitives::Address, bigdecimal::{BigDecimal, ToPrimitive}, + ethrpc::alloy::conversions::IntoLegacy, futures::FutureExt, model::order::OrderKind, number::nonzero::U256 as NonZeroU256, @@ -51,7 +53,7 @@ pub trait NativePriceEstimating: Send + Sync { /// that is needed to buy 1 unit of the specified token). fn estimate_native_price( &self, - token: H160, + token: Address, timeout: Duration, ) -> futures::future::BoxFuture<'_, NativePriceEstimateResult>; } @@ -95,11 +97,11 @@ impl NativePriceEstimating for NativePriceEstimator { #[instrument(skip_all)] fn estimate_native_price( &self, - token: H160, + token: Address, timeout: Duration, ) -> futures::future::BoxFuture<'_, NativePriceEstimateResult> { async move { - let query = Arc::new(self.query(&token, timeout)); + let query = Arc::new(self.query(&token.into_legacy(), timeout)); let estimate = self.inner.estimate(query.clone()).await?; let price = estimate.price_in_buy_token_f64(&query); if is_price_malformed(price) { @@ -151,7 +153,7 @@ mod tests { }; let result = native_price_estimator - .estimate_native_price(H160::from_low_u64_be(3), HEALTHY_PRICE_ESTIMATION_TIME) + .estimate_native_price(Address::with_last_byte(3), HEALTHY_PRICE_ESTIMATION_TIME) .await; assert_eq!(result.unwrap(), 1. / 0.123456789); } @@ -172,7 +174,7 @@ mod tests { }; let result = native_price_estimator - .estimate_native_price(H160::from_low_u64_be(2), HEALTHY_PRICE_ESTIMATION_TIME) + .estimate_native_price(Address::with_last_byte(2), HEALTHY_PRICE_ESTIMATION_TIME) .await; assert!(matches!(result, Err(PriceEstimationError::NoLiquidity))); } diff --git a/crates/shared/src/price_estimation/native/oneinch.rs b/crates/shared/src/price_estimation/native/oneinch.rs index 559ebe411e..71328f2954 100644 --- a/crates/shared/src/price_estimation/native/oneinch.rs +++ b/crates/shared/src/price_estimation/native/oneinch.rs @@ -1,8 +1,12 @@ use { super::{NativePrice, NativePriceEstimateResult, NativePriceEstimating}, crate::{price_estimation::PriceEstimationError, token_info::TokenInfoFetching}, + alloy::primitives::Address, anyhow::{Context, Result, anyhow}, - ethrpc::block_stream::{CurrentBlockWatcher, into_stream}, + ethrpc::{ + alloy::conversions::IntoAlloy, + block_stream::{CurrentBlockWatcher, into_stream}, + }, futures::{FutureExt, StreamExt, future::BoxFuture}, num::ToPrimitive, number::{conversions::u256_to_big_rational, serialization::HexOrDecimalU256}, @@ -23,7 +27,7 @@ use { #[derive(Debug, Deserialize)] struct Response(#[serde_as(as = "HashMap<_, HexOrDecimalU256>")] HashMap); -type Token = H160; +type Token = Address; pub struct OneInch { prices: Arc>>, @@ -93,7 +97,7 @@ impl NativePriceEstimating for OneInch { #[instrument(skip_all)] fn estimate_native_price( &self, - token: Token, + token: Address, _timeout: Duration, // ignored since cache lookup take ms anyway ) -> BoxFuture<'_, NativePriceEstimateResult> { async move { @@ -151,7 +155,7 @@ async fn get_current_prices( let unit = num::BigRational::from_integer(num::BigInt::from(10u64).pow(decimals.into())); let normalized_price = u256_to_big_rational(&price) / unit; - Some((token, normalized_price.to_f64()?)) + Some((token.into_alloy(), normalized_price.to_f64()?)) }) .collect(); Ok(normalized_prices) @@ -165,7 +169,8 @@ mod tests { price_estimation::HEALTHY_PRICE_ESTIMATION_TIME, token_info::{MockTokenInfoFetching, TokenInfo}, }, - std::{env, str::FromStr}, + alloy::primitives::address, + std::env, }; const BASE_URL: &str = "https://api.1inch.dev/"; @@ -203,7 +208,7 @@ mod tests { .unwrap(); assert!(!prices.is_empty()); - let native_token = H160::from_str("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2").unwrap(); + let native_token = address!("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"); let instance = OneInch { prices: Arc::new(Mutex::new(prices)), }; @@ -220,7 +225,7 @@ mod tests { assert!( 1. / instance .estimate_native_price( - H160::from_str("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48").unwrap(), + address!("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"), HEALTHY_PRICE_ESTIMATION_TIME, ) .await diff --git a/crates/shared/src/price_estimation/native_price_cache.rs b/crates/shared/src/price_estimation/native_price_cache.rs index 61c68a3462..adb6802366 100644 --- a/crates/shared/src/price_estimation/native_price_cache.rs +++ b/crates/shared/src/price_estimation/native_price_cache.rs @@ -5,7 +5,9 @@ use { NativePriceEstimating, from_normalized_price, }, + alloy::primitives::Address, bigdecimal::BigDecimal, + ethrpc::alloy::conversions::{IntoAlloy, IntoLegacy}, futures::{FutureExt, StreamExt}, indexmap::IndexSet, primitive_types::H160, @@ -195,7 +197,7 @@ impl Inner { let result = self .estimator - .estimate_native_price(token_to_fetch, request_timeout) + .estimate_native_price(token_to_fetch.into_alloy(), request_timeout) .await; // update price in cache @@ -439,14 +441,20 @@ impl NativePriceEstimating for CachingNativePriceEstimator { #[instrument(skip_all)] fn estimate_native_price( &self, - token: H160, + token: Address, timeout: Duration, ) -> futures::future::BoxFuture<'_, NativePriceEstimateResult> { async move { let cached = { let now = Instant::now(); let mut cache = self.0.cache.lock().unwrap(); - Inner::get_ready_to_use_cached_price(token, now, &mut cache, &self.0.max_age, false) + Inner::get_ready_to_use_cached_price( + token.into_legacy(), + now, + &mut cache, + &self.0.max_age, + false, + ) }; let label = if cached.is_some() { "hits" } else { "misses" }; @@ -460,7 +468,7 @@ impl NativePriceEstimating for CachingNativePriceEstimator { } self.0 - .estimate_prices_and_update_cache(&[token], self.0.max_age, timeout) + .estimate_prices_and_update_cache(&[token.into_legacy()], self.0.max_age, timeout) .next() .await .unwrap() @@ -484,8 +492,8 @@ mod tests { num::ToPrimitive, }; - fn token(u: u64) -> H160 { - H160::from_low_u64_be(u) + fn token(u: u64) -> Address { + Address::left_padding_from(&u.to_be_bytes()) } #[tokio::test] @@ -497,8 +505,9 @@ mod tests { let min_age = Duration::from_secs(MAX_AGE_SECS * 49 / 100); let max_age = Duration::from_secs(MAX_AGE_SECS * 91 / 100); - let prices = - HashMap::from_iter((0..10).map(|t| (token(t), BigDecimal::try_from(1e18).unwrap()))); + let prices = HashMap::from_iter( + (0..10).map(|t| (token(t).into_legacy(), BigDecimal::try_from(1e18).unwrap())), + ); let estimator = CachingNativePriceEstimator::new( Box::new(inner), Duration::from_secs(MAX_AGE_SECS), @@ -583,7 +592,10 @@ mod tests { Default::default(), 1, // set token approximations for tokens 1 and 2 - HashMap::from([(token(1), token(100)), (token(2), token(200))]), + HashMap::from([ + (token(1).into_legacy(), token(100).into_legacy()), + (token(2).into_legacy(), token(200).into_legacy()), + ]), HEALTHY_PRICE_ESTIMATION_TIME, ); @@ -887,7 +899,7 @@ mod tests { HEALTHY_PRICE_ESTIMATION_TIME, ); - let tokens: Vec<_> = (0..10).map(H160::from_low_u64_be).collect(); + let tokens: Vec<_> = (0..10).map(Address::with_last_byte).collect(); for token in &tokens { let price = estimator .estimate_native_price(*token, HEALTHY_PRICE_ESTIMATION_TIME) @@ -940,7 +952,7 @@ mod tests { HEALTHY_PRICE_ESTIMATION_TIME, ); - let tokens: Vec<_> = (0..BATCH_SIZE as u64).map(H160::from_low_u64_be).collect(); + let tokens: Vec<_> = (0..BATCH_SIZE as u64).map(token).collect(); for token in &tokens { let price = estimator .estimate_native_price(*token, HEALTHY_PRICE_ESTIMATION_TIME) From 1cf04a3097468e9cdd938d4370852a1b8c0e6731 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Fri, 7 Nov 2025 12:18:44 +0000 Subject: [PATCH 03/17] Clippy --- crates/autopilot/src/domain/fee/mod.rs | 2 +- crates/autopilot/src/infra/persistence/dto/fee_policy.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/autopilot/src/domain/fee/mod.rs b/crates/autopilot/src/domain/fee/mod.rs index 8b265c181b..68f871e024 100644 --- a/crates/autopilot/src/domain/fee/mod.rs +++ b/crates/autopilot/src/domain/fee/mod.rs @@ -186,7 +186,7 @@ impl ProtocolFees { sell_amount: quote.sell_amount.into(), buy_amount: quote.buy_amount.into(), fee: quote.fee.into(), - solver: quote.solver.into(), + solver: quote.solver, }, } } diff --git a/crates/autopilot/src/infra/persistence/dto/fee_policy.rs b/crates/autopilot/src/infra/persistence/dto/fee_policy.rs index 6686020caf..97d0749dc8 100644 --- a/crates/autopilot/src/infra/persistence/dto/fee_policy.rs +++ b/crates/autopilot/src/infra/persistence/dto/fee_policy.rs @@ -86,7 +86,7 @@ pub fn try_into_domain( sell_amount: quote.sell_amount.into(), buy_amount: quote.buy_amount.into(), fee: quote.fee.into(), - solver: quote.solver.into(), + solver: quote.solver, } }, }, From 09209ba98d00b6278a9dfef92dc74e484d589b49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Fri, 7 Nov 2025 12:54:14 +0000 Subject: [PATCH 04/17] Migrate get_orders_by_tx endpoint to alloy --- crates/autopilot/src/domain/fee/mod.rs | 6 +++--- .../autopilot/src/infra/persistence/dto/fee_policy.rs | 6 +++--- crates/orderbook/src/api/get_orders_by_tx.rs | 10 +++++----- crates/orderbook/src/database/orders.rs | 9 +++++---- crates/orderbook/src/orderbook.rs | 4 ++-- 5 files changed, 18 insertions(+), 17 deletions(-) diff --git a/crates/autopilot/src/domain/fee/mod.rs b/crates/autopilot/src/domain/fee/mod.rs index 7d93fb69c3..262091226f 100644 --- a/crates/autopilot/src/domain/fee/mod.rs +++ b/crates/autopilot/src/domain/fee/mod.rs @@ -184,9 +184,9 @@ impl ProtocolFees { factor, max_volume_factor, quote: Quote { - sell_amount: quote.sell_amount.into(), - buy_amount: quote.buy_amount.into(), - fee: quote.fee.into(), + sell_amount: quote.sell_amount.0.into_alloy(), + buy_amount: quote.buy_amount.0.into_alloy(), + fee: quote.fee.0.into_alloy(), solver: quote.solver, }, } diff --git a/crates/autopilot/src/infra/persistence/dto/fee_policy.rs b/crates/autopilot/src/infra/persistence/dto/fee_policy.rs index 43738a920c..b6700777bc 100644 --- a/crates/autopilot/src/infra/persistence/dto/fee_policy.rs +++ b/crates/autopilot/src/infra/persistence/dto/fee_policy.rs @@ -84,9 +84,9 @@ pub fn try_into_domain( quote: { let quote = quote.ok_or(Error::MissingQuote)?; domain::fee::Quote { - sell_amount: quote.sell_amount.into(), - buy_amount: quote.buy_amount.into(), - fee: quote.fee.into(), + sell_amount: quote.sell_amount.0.into_alloy(), + buy_amount: quote.buy_amount.0.into_alloy(), + fee: quote.fee.0.into_alloy(), solver: quote.solver, } }, diff --git a/crates/orderbook/src/api/get_orders_by_tx.rs b/crates/orderbook/src/api/get_orders_by_tx.rs index db568c892b..dc357227de 100644 --- a/crates/orderbook/src/api/get_orders_by_tx.rs +++ b/crates/orderbook/src/api/get_orders_by_tx.rs @@ -1,20 +1,20 @@ use { crate::{api::ApiReply, orderbook::Orderbook}, + alloy::primitives::B256, anyhow::Result, - ethcontract::H256, reqwest::StatusCode, std::{convert::Infallible, sync::Arc}, warp::{Filter, Rejection, reply::with_status}, }; -pub fn get_orders_by_tx_request() -> impl Filter + Clone { - warp::path!("v1" / "transactions" / H256 / "orders").and(warp::get()) +pub fn get_orders_by_tx_request() -> impl Filter + Clone { + warp::path!("v1" / "transactions" / B256 / "orders").and(warp::get()) } pub fn get_orders_by_tx( orderbook: Arc, ) -> impl Filter + Clone { - get_orders_by_tx_request().and_then(move |hash: H256| { + get_orders_by_tx_request().and_then(move |hash: B256| { let orderbook = orderbook.clone(); async move { let result = orderbook.get_orders_for_tx(&hash).await; @@ -42,6 +42,6 @@ mod tests { .filter(&get_orders_by_tx_request()) .await .unwrap(); - assert_eq!(result.0, H256::from_str(hash_str).unwrap().0); + assert_eq!(result.0, B256::from_str(hash_str).unwrap().0); } } diff --git a/crates/orderbook/src/database/orders.rs b/crates/orderbook/src/database/orders.rs index 10366a8d98..ccbee0b64d 100644 --- a/crates/orderbook/src/database/orders.rs +++ b/crates/orderbook/src/database/orders.rs @@ -1,6 +1,7 @@ use { super::Postgres, crate::dto::TokenMetadata, + alloy::primitives::B256, anyhow::{Context as _, Result}, app_data::AppDataHash, async_trait::async_trait, @@ -66,7 +67,7 @@ pub trait OrderStoring: Send + Sync { old_order: &OrderUid, new_order: &Order, ) -> Result<(), InsertionError>; - async fn orders_for_tx(&self, tx_hash: &H256) -> Result>; + async fn orders_for_tx(&self, tx_hash: &B256) -> Result>; /// All orders of a single user ordered by creation date descending (newest /// orders first). async fn user_orders( @@ -315,7 +316,7 @@ impl OrderStoring for Postgres { .transpose() } - async fn orders_for_tx(&self, tx_hash: &H256) -> Result> { + async fn orders_for_tx(&self, tx_hash: &B256) -> Result> { tokio::try_join!( self.user_order_for_tx(tx_hash), self.jit_orders_for_tx(tx_hash) @@ -367,7 +368,7 @@ impl OrderStoring for Postgres { impl Postgres { /// Retrieve all user posted orders for a given transaction. - pub async fn user_order_for_tx(&self, tx_hash: &H256) -> Result> { + pub async fn user_order_for_tx(&self, tx_hash: &B256) -> Result> { let _timer = super::Metrics::get() .database_queries .with_label_values(&["user_order_for_tx"]) @@ -384,7 +385,7 @@ impl Postgres { } /// Retrieve all JIT orders for a given transaction. - pub async fn jit_orders_for_tx(&self, tx_hash: &H256) -> Result> { + pub async fn jit_orders_for_tx(&self, tx_hash: &B256) -> Result> { let _timer = super::Metrics::get() .database_queries .with_label_values(&["jit_orders_for_tx"]) diff --git a/crates/orderbook/src/orderbook.rs b/crates/orderbook/src/orderbook.rs index 64caec0b49..186a182b87 100644 --- a/crates/orderbook/src/orderbook.rs +++ b/crates/orderbook/src/orderbook.rs @@ -7,12 +7,12 @@ use { dto, solver_competition::{Identifier, LoadSolverCompetitionError, SolverCompetitionStoring}, }, + alloy::primitives::B256, anyhow::{Context, Result}, app_data::{AppDataHash, Validator}, bigdecimal::ToPrimitive, chrono::Utc, database::order_events::OrderEventLabel, - ethcontract::H256, ethrpc::alloy::conversions::IntoLegacy, model::{ DomainSeparator, @@ -496,7 +496,7 @@ impl Orderbook { self.database_replica.single_order(uid).await } - pub async fn get_orders_for_tx(&self, hash: &H256) -> Result> { + pub async fn get_orders_for_tx(&self, hash: &B256) -> Result> { self.database_replica.orders_for_tx(hash).await } From 0c8d46986d58922ac1dff7df76f4c88c7e28dd98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Fri, 7 Nov 2025 15:07:06 +0000 Subject: [PATCH 05/17] fix compilation error --- crates/autopilot/src/domain/fee/mod.rs | 6 +++--- crates/autopilot/src/infra/persistence/dto/fee_policy.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/autopilot/src/domain/fee/mod.rs b/crates/autopilot/src/domain/fee/mod.rs index 7d93fb69c3..262091226f 100644 --- a/crates/autopilot/src/domain/fee/mod.rs +++ b/crates/autopilot/src/domain/fee/mod.rs @@ -184,9 +184,9 @@ impl ProtocolFees { factor, max_volume_factor, quote: Quote { - sell_amount: quote.sell_amount.into(), - buy_amount: quote.buy_amount.into(), - fee: quote.fee.into(), + sell_amount: quote.sell_amount.0.into_alloy(), + buy_amount: quote.buy_amount.0.into_alloy(), + fee: quote.fee.0.into_alloy(), solver: quote.solver, }, } diff --git a/crates/autopilot/src/infra/persistence/dto/fee_policy.rs b/crates/autopilot/src/infra/persistence/dto/fee_policy.rs index 43738a920c..b6700777bc 100644 --- a/crates/autopilot/src/infra/persistence/dto/fee_policy.rs +++ b/crates/autopilot/src/infra/persistence/dto/fee_policy.rs @@ -84,9 +84,9 @@ pub fn try_into_domain( quote: { let quote = quote.ok_or(Error::MissingQuote)?; domain::fee::Quote { - sell_amount: quote.sell_amount.into(), - buy_amount: quote.buy_amount.into(), - fee: quote.fee.into(), + sell_amount: quote.sell_amount.0.into_alloy(), + buy_amount: quote.buy_amount.0.into_alloy(), + fee: quote.fee.0.into_alloy(), solver: quote.solver, } }, From cd115d9069fdf6c85328543ad42922ae9e42409c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Fri, 7 Nov 2025 15:31:19 +0000 Subject: [PATCH 06/17] Migrate solver competition endpoint to alloy --- crates/orderbook/src/api/get_solver_competition.rs | 4 ++-- crates/orderbook/src/api/get_solver_competition_v2.rs | 4 ++-- crates/orderbook/src/database/solver_competition_v2.rs | 3 ++- crates/orderbook/src/orderbook.rs | 3 +-- crates/orderbook/src/solver_competition.rs | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/crates/orderbook/src/api/get_solver_competition.rs b/crates/orderbook/src/api/get_solver_competition.rs index 8966b50c70..26e7a38390 100644 --- a/crates/orderbook/src/api/get_solver_competition.rs +++ b/crates/orderbook/src/api/get_solver_competition.rs @@ -1,8 +1,8 @@ use { crate::solver_competition::{Identifier, LoadSolverCompetitionError, SolverCompetitionStoring}, + alloy::primitives::B256, anyhow::Result, model::{AuctionId, solver_competition::SolverCompetitionAPI}, - primitive_types::H256, reqwest::StatusCode, std::{convert::Infallible, sync::Arc}, warp::{ @@ -19,7 +19,7 @@ fn request_id() -> impl Filter + Clo } fn request_hash() -> impl Filter + Clone { - warp::path!("v1" / "solver_competition" / "by_tx_hash" / H256) + warp::path!("v1" / "solver_competition" / "by_tx_hash" / B256) .and(warp::get()) .map(Identifier::Transaction) } diff --git a/crates/orderbook/src/api/get_solver_competition_v2.rs b/crates/orderbook/src/api/get_solver_competition_v2.rs index e1acb16304..85850a8ec9 100644 --- a/crates/orderbook/src/api/get_solver_competition_v2.rs +++ b/crates/orderbook/src/api/get_solver_competition_v2.rs @@ -3,9 +3,9 @@ use { database::Postgres, solver_competition::{Identifier, LoadSolverCompetitionError}, }, + alloy::primitives::B256, anyhow::Result, model::{AuctionId, solver_competition_v2::Response}, - primitive_types::H256, reqwest::StatusCode, std::convert::Infallible, warp::{ @@ -22,7 +22,7 @@ fn request_id() -> impl Filter + Clo } fn request_hash() -> impl Filter + Clone { - warp::path!("v2" / "solver_competition" / "by_tx_hash" / H256) + warp::path!("v2" / "solver_competition" / "by_tx_hash" / B256) .and(warp::get()) .map(Identifier::Transaction) } diff --git a/crates/orderbook/src/database/solver_competition_v2.rs b/crates/orderbook/src/database/solver_competition_v2.rs index 838e1fb3a2..70f3c54996 100644 --- a/crates/orderbook/src/database/solver_competition_v2.rs +++ b/crates/orderbook/src/database/solver_competition_v2.rs @@ -1,6 +1,7 @@ use { super::Postgres, crate::solver_competition::LoadSolverCompetitionError, + alloy::primitives::B256, anyhow::{Context, Result}, database::{byte_array::ByteArray, solver_competition_v2::SolverCompetition as DbResponse}, model::{ @@ -32,7 +33,7 @@ impl Postgres { pub async fn load_competition_by_tx_hash( &self, - tx_hash: H256, + tx_hash: B256, ) -> Result { let _timer = super::Metrics::get() .database_queries diff --git a/crates/orderbook/src/orderbook.rs b/crates/orderbook/src/orderbook.rs index 186a182b87..26343278a7 100644 --- a/crates/orderbook/src/orderbook.rs +++ b/crates/orderbook/src/orderbook.rs @@ -13,7 +13,6 @@ use { bigdecimal::ToPrimitive, chrono::Utc, database::order_events::OrderEventLabel, - ethrpc::alloy::conversions::IntoLegacy, model::{ DomainSeparator, order::{ @@ -576,7 +575,7 @@ impl Orderbook { Some(Some(tx_hash)) => { let competition = self .database - .load_competition(Identifier::Transaction(tx_hash.into_legacy())) + .load_competition(Identifier::Transaction(tx_hash)) .await?; return Ok(dto::order::Status::Traded(solutions(competition))); } diff --git a/crates/orderbook/src/solver_competition.rs b/crates/orderbook/src/solver_competition.rs index c6ee804f2a..9cd1c2c2e0 100644 --- a/crates/orderbook/src/solver_competition.rs +++ b/crates/orderbook/src/solver_competition.rs @@ -1,16 +1,16 @@ //! Manage solver competition data received by the driver through a private spi. use { + alloy::primitives::B256, anyhow::Result, database::auction::AuctionId, model::solver_competition::SolverCompetitionAPI, - primitive_types::H256, thiserror::Error, }; pub enum Identifier { Id(AuctionId), - Transaction(H256), + Transaction(B256), } /// Component used for saving and loading past solver competitions. From 93293d70a45975849fa257ad7ae961295cda9d7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Fri, 7 Nov 2025 15:36:25 +0000 Subject: [PATCH 07/17] Migrate get_token_metadata endpoint to alloy --- crates/orderbook/Cargo.toml | 1 + crates/orderbook/src/api/get_token_metadata.rs | 8 ++++---- crates/orderbook/src/database/orders.rs | 17 +++++++++-------- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/crates/orderbook/Cargo.toml b/crates/orderbook/Cargo.toml index 81724c7419..10411832f4 100644 --- a/crates/orderbook/Cargo.toml +++ b/crates/orderbook/Cargo.toml @@ -60,6 +60,7 @@ warp = { workspace = true } [dev-dependencies] mockall = { workspace = true } tokio = { workspace = true, features = ["test-util"] } +shared = { workspace = true, features = ["test-util"] } [build-dependencies] anyhow = { workspace = true } diff --git a/crates/orderbook/src/api/get_token_metadata.rs b/crates/orderbook/src/api/get_token_metadata.rs index d87e8898d8..d8f0631564 100644 --- a/crates/orderbook/src/api/get_token_metadata.rs +++ b/crates/orderbook/src/api/get_token_metadata.rs @@ -1,19 +1,19 @@ use { crate::database::Postgres, + alloy::primitives::Address, hyper::StatusCode, - primitive_types::H160, std::convert::Infallible, warp::{Filter, Rejection, reply}, }; -fn get_native_prices_request() -> impl Filter + Clone { - warp::path!("v1" / "token" / H160 / "metadata").and(warp::get()) +fn get_native_prices_request() -> impl Filter + Clone { + warp::path!("v1" / "token" / Address / "metadata").and(warp::get()) } pub fn get_token_metadata( db: Postgres, ) -> impl Filter + Clone { - get_native_prices_request().and_then(move |token: H160| { + get_native_prices_request().and_then(move |token: Address| { let db = db.clone(); async move { let result = db.token_metadata(&token).await; diff --git a/crates/orderbook/src/database/orders.rs b/crates/orderbook/src/database/orders.rs index ccbee0b64d..21630021e7 100644 --- a/crates/orderbook/src/database/orders.rs +++ b/crates/orderbook/src/database/orders.rs @@ -1,7 +1,7 @@ use { super::Postgres, crate::dto::TokenMetadata, - alloy::primitives::B256, + alloy::primitives::{Address, B256}, anyhow::{Context as _, Result}, app_data::AppDataHash, async_trait::async_trait, @@ -399,11 +399,11 @@ impl Postgres { .collect::>>() } - pub async fn token_metadata(&self, token: &H160) -> Result { + pub async fn token_metadata(&self, token: &Address) -> Result { let (first_trade_block, native_price): (Option, Option) = tokio::try_join!( self.execute_instrumented("token_first_trade_block", async { let mut ex = self.pool.acquire().await?; - database::trades::token_first_trade_block(&mut ex, ByteArray(token.0)) + database::trades::token_first_trade_block(&mut ex, ByteArray(token.0.0)) .await .map_err(anyhow::Error::from)? .map(u32::try_from) @@ -412,12 +412,13 @@ impl Postgres { }), self.execute_instrumented("fetch_latest_token_price", async { let mut ex = self.pool.acquire().await?; - Ok( - database::auction_prices::fetch_latest_token_price(&mut ex, ByteArray(token.0)) - .await - .map_err(anyhow::Error::from)? - .and_then(|price| big_decimal_to_u256(&price)), + Ok(database::auction_prices::fetch_latest_token_price( + &mut ex, + ByteArray(token.0.0), ) + .await + .map_err(anyhow::Error::from)? + .and_then(|price| big_decimal_to_u256(&price))) }) )?; From 38f47fb2a2860ad3668a385bf8c63393d0a30703 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Fri, 7 Nov 2025 16:19:26 +0000 Subject: [PATCH 08/17] Migrate get_total_surplus_endpoint to alloy --- crates/orderbook/src/api/get_total_surplus.rs | 4 ++-- crates/orderbook/src/database/total_surplus.rs | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/orderbook/src/api/get_total_surplus.rs b/crates/orderbook/src/api/get_total_surplus.rs index 2f8358ee29..afdbc07b93 100644 --- a/crates/orderbook/src/api/get_total_surplus.rs +++ b/crates/orderbook/src/api/get_total_surplus.rs @@ -1,13 +1,13 @@ use { crate::database::Postgres, - primitive_types::H160, + alloy::primitives::Address, serde_json::json, std::convert::Infallible, warp::{Filter, Rejection, http::StatusCode, reply::with_status}, }; pub fn get(db: Postgres) -> impl Filter + Clone { - warp::path!("v1" / "users" / H160 / "total_surplus") + warp::path!("v1" / "users" / Address / "total_surplus") .and(warp::get()) .and_then(move |user| { let db = db.clone(); diff --git a/crates/orderbook/src/database/total_surplus.rs b/crates/orderbook/src/database/total_surplus.rs index 76c7ed0c72..3fc446fa1c 100644 --- a/crates/orderbook/src/database/total_surplus.rs +++ b/crates/orderbook/src/database/total_surplus.rs @@ -1,7 +1,7 @@ use { + alloy::primitives::U256, anyhow::Result, database::{Address, byte_array::ByteArray}, - primitive_types::{H160, U256}, sqlx::PgConnection, }; @@ -61,8 +61,8 @@ trade_components AS ( JOIN trades t ON j.uid = t.order_uid JOIN order_execution oe ON j.uid = oe.order_uid WHERE j.owner = $1 AND NOT EXISTS ( - SELECT 1 - FROM orders o + SELECT 1 + FROM orders o WHERE o.uid = j.uid ) ), @@ -88,14 +88,14 @@ FROM trade_surplus } impl super::Postgres { - pub async fn total_surplus(&self, user: &H160) -> Result { + pub async fn total_surplus(&self, user: &alloy::primitives::Address) -> Result { let _timer = super::Metrics::get() .database_queries .with_label_values(&["get_total_surplus"]) .start_timer(); let mut ex = self.pool.acquire().await?; - let surplus = fetch_total_surplus(&mut ex, &ByteArray(user.0)).await?; - Ok(U256::from_f64_lossy(surplus)) + let surplus = fetch_total_surplus(&mut ex, &ByteArray(user.0.0)).await?; + Ok(U256::from(surplus)) } } From e5b167151573b2ea605ad3bb22993679ead940cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Fri, 7 Nov 2025 16:54:24 +0000 Subject: [PATCH 09/17] Migrate get_trades endpoint to alloy --- crates/orderbook/src/api/get_trades.rs | 10 ++++------ crates/orderbook/src/database/trades.rs | 5 ++--- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/crates/orderbook/src/api/get_trades.rs b/crates/orderbook/src/api/get_trades.rs index 57c2261fb7..a104c7cb55 100644 --- a/crates/orderbook/src/api/get_trades.rs +++ b/crates/orderbook/src/api/get_trades.rs @@ -6,9 +6,9 @@ use { trades::{TradeFilter, TradeRetrieving}, }, }, + alloy::primitives::Address, anyhow::{Context, Result}, model::order::OrderUid, - primitive_types::H160, serde::Deserialize, std::convert::Infallible, warp::{Filter, Rejection, hyper::StatusCode, reply::with_status}, @@ -18,7 +18,7 @@ use { #[serde(rename_all = "camelCase")] struct Query { pub order_uid: Option, - pub owner: Option, + pub owner: Option
, } #[derive(Debug, Eq, PartialEq)] @@ -80,8 +80,6 @@ pub fn get_trades(db: Postgres) -> impl Filter, + pub owner: Option
, pub order_uid: Option, } @@ -33,7 +32,7 @@ impl TradeRetrieving for Postgres { let mut ex = self.pool.acquire().await?; let trades = database::trades::trades( &mut ex, - filter.owner.map(|owner| ByteArray(owner.0)).as_ref(), + filter.owner.map(|owner| ByteArray(owner.0.0)).as_ref(), filter.order_uid.map(|uid| ByteArray(uid.0)).as_ref(), ) .into_inner() From f5018ab0c1eaf9f7e7a670912de4443892c4bc35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Fri, 7 Nov 2025 17:01:26 +0000 Subject: [PATCH 10/17] Migrate get_user_orders endpoint to alloy --- crates/orderbook/src/api/get_user_orders.rs | 12 ++++++------ crates/orderbook/src/database/orders.rs | 9 +++++---- crates/orderbook/src/orderbook.rs | 4 ++-- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/crates/orderbook/src/api/get_user_orders.rs b/crates/orderbook/src/api/get_user_orders.rs index f4fc4f7f62..77783b29bf 100644 --- a/crates/orderbook/src/api/get_user_orders.rs +++ b/crates/orderbook/src/api/get_user_orders.rs @@ -1,7 +1,7 @@ use { crate::{api::ApiReply, orderbook::Orderbook}, + alloy::primitives::Address, anyhow::Result, - primitive_types::H160, serde::Deserialize, std::{convert::Infallible, sync::Arc}, warp::{Filter, Rejection, hyper::StatusCode, reply::with_status}, @@ -13,8 +13,8 @@ struct Query { limit: Option, } -fn request() -> impl Filter + Clone { - warp::path!("v1" / "account" / H160 / "orders") +fn request() -> impl Filter + Clone { + warp::path!("v1" / "account" / Address / "orders") .and(warp::get()) .and(warp::query::()) } @@ -22,7 +22,7 @@ fn request() -> impl Filter + Clone pub fn get_user_orders( orderbook: Arc, ) -> impl Filter + Clone { - request().and_then(move |owner: H160, query: Query| { + request().and_then(move |owner: Address, query: Query| { let orderbook = orderbook.clone(); async move { const DEFAULT_OFFSET: u64 = 0; @@ -54,7 +54,7 @@ pub fn get_user_orders( #[cfg(test)] mod tests { - use {super::*, shared::addr}; + use super::*; #[tokio::test] async fn request_() { @@ -65,7 +65,7 @@ mod tests { .filter(&request()) .await .unwrap(); - assert_eq!(result.0, addr!("0000000000000000000000000000000000000001")); + assert_eq!(result.0, Address::with_last_byte(1)); assert_eq!(result.1.offset, None); assert_eq!(result.1.limit, None); diff --git a/crates/orderbook/src/database/orders.rs b/crates/orderbook/src/database/orders.rs index 21630021e7..50348b6378 100644 --- a/crates/orderbook/src/database/orders.rs +++ b/crates/orderbook/src/database/orders.rs @@ -72,7 +72,7 @@ pub trait OrderStoring: Send + Sync { /// orders first). async fn user_orders( &self, - owner: &H160, + owner: &Address, offset: u64, limit: Option, ) -> Result>; @@ -329,7 +329,7 @@ impl OrderStoring for Postgres { async fn user_orders( &self, - owner: &H160, + owner: &Address, offset: u64, limit: Option, ) -> Result> { @@ -341,7 +341,7 @@ impl OrderStoring for Postgres { let mut ex = self.pool.acquire().await?; database::order_history::user_orders( &mut ex, - &ByteArray(owner.0), + &ByteArray(owner.0.0), i64::try_from(offset).unwrap_or(i64::MAX), limit.map(|l| i64::try_from(l).unwrap_or(i64::MAX)), ) @@ -641,6 +641,7 @@ mod tests { SigningScheme as DbSigningScheme, }, }, + ethrpc::alloy::conversions::IntoAlloy, model::{ interaction::InteractionData, order::{Order, OrderData, OrderMetadata, OrderStatus, OrderUid}, @@ -904,7 +905,7 @@ mod tests { .unwrap(); let order_statuses = db - .user_orders(&owner, 0, None) + .user_orders(&owner.into_alloy(), 0, None) .await .unwrap() .iter() diff --git a/crates/orderbook/src/orderbook.rs b/crates/orderbook/src/orderbook.rs index 26343278a7..ba040e8ff9 100644 --- a/crates/orderbook/src/orderbook.rs +++ b/crates/orderbook/src/orderbook.rs @@ -7,7 +7,7 @@ use { dto, solver_competition::{Identifier, LoadSolverCompetitionError, SolverCompetitionStoring}, }, - alloy::primitives::B256, + alloy::primitives::{Address, B256}, anyhow::{Context, Result}, app_data::{AppDataHash, Validator}, bigdecimal::ToPrimitive, @@ -512,7 +512,7 @@ impl Orderbook { pub async fn get_user_orders( &self, - owner: &H160, + owner: &Address, offset: u64, limit: u64, ) -> Result> { From 7e4b069c4c020b27ed0a7b63517406552cf142aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Fri, 7 Nov 2025 17:19:37 +0000 Subject: [PATCH 11/17] Migrate orderbook::database::auction_prices to alloy --- crates/orderbook/src/database/auction_prices.rs | 6 +++--- crates/orderbook/src/run.rs | 8 +++++++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/crates/orderbook/src/database/auction_prices.rs b/crates/orderbook/src/database/auction_prices.rs index 7411a8e0f5..19a0ae0145 100644 --- a/crates/orderbook/src/database/auction_prices.rs +++ b/crates/orderbook/src/database/auction_prices.rs @@ -1,13 +1,13 @@ use { super::Postgres, + alloy::primitives::Address, anyhow::Result, bigdecimal::BigDecimal, - primitive_types::H160, std::collections::HashMap, }; impl Postgres { - pub async fn fetch_latest_prices(&self) -> Result> { + pub async fn fetch_latest_prices(&self) -> Result> { let _timer = super::Metrics::get() .database_queries .with_label_values(&["fetch_latest_prices"]) @@ -17,7 +17,7 @@ impl Postgres { Ok(database::auction_prices::fetch_latest_prices(&mut ex) .await? .into_iter() - .map(|auction_price| (H160::from(auction_price.token.0), auction_price.price)) + .map(|auction_price| (Address::new(auction_price.token.0), auction_price.price)) .collect::>()) } } diff --git a/crates/orderbook/src/run.rs b/crates/orderbook/src/run.rs index 7e392ce6a1..4ea05dba5c 100644 --- a/crates/orderbook/src/run.rs +++ b/crates/orderbook/src/run.rs @@ -331,7 +331,13 @@ pub async fn run(args: Arguments) { ) .await .unwrap(); - let prices = postgres_write.fetch_latest_prices().await.unwrap(); + let prices = postgres_write + .fetch_latest_prices() + .await + .unwrap() + .into_iter() + .map(|(k, v)| (k.into_legacy(), v)) + .collect(); native_price_estimator.initialize_cache(prices); let price_estimator = price_estimator_factory From 8b15cd9b0a61c54cd206d52eb0ae388432b3544b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Mon, 10 Nov 2025 11:12:14 +0000 Subject: [PATCH 12/17] Migrate orderbook::database::solver_competition to alloy --- crates/model/src/solver_competition.rs | 7 ++++--- crates/orderbook/src/database/solver_competition.rs | 12 ++++++------ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/crates/model/src/solver_competition.rs b/crates/model/src/solver_competition.rs index 1024346c43..6c5d80c6e8 100644 --- a/crates/model/src/solver_competition.rs +++ b/crates/model/src/solver_competition.rs @@ -1,7 +1,8 @@ use { crate::{AuctionId, order::OrderUid}, + alloy::primitives::B256, number::serialization::HexOrDecimalU256, - primitive_types::{H160, H256, U256}, + primitive_types::{H160, U256}, serde::{Deserialize, Serialize}, serde_with::serde_as, std::collections::BTreeMap, @@ -24,7 +25,7 @@ pub struct SolverCompetitionDB { pub struct SolverCompetitionAPI { #[serde(default)] pub auction_id: AuctionId, - pub transaction_hashes: Vec, + pub transaction_hashes: Vec, #[serde(flatten)] pub common: SolverCompetitionDB, } @@ -177,7 +178,7 @@ mod tests { let orig = SolverCompetitionAPI { auction_id: 0, - transaction_hashes: vec![H256([0x11; 32])], + transaction_hashes: vec![B256::new([0x11; 32])], common: SolverCompetitionDB { auction_start_block: 13, competition_simulation_block: 15, diff --git a/crates/orderbook/src/database/solver_competition.rs b/crates/orderbook/src/database/solver_competition.rs index d58a8fc8d6..8aba3a057d 100644 --- a/crates/orderbook/src/database/solver_competition.rs +++ b/crates/orderbook/src/database/solver_competition.rs @@ -1,20 +1,20 @@ use { super::Postgres, crate::solver_competition::{Identifier, LoadSolverCompetitionError, SolverCompetitionStoring}, + alloy::primitives::B256, anyhow::{Context, Result}, database::byte_array::ByteArray, model::{ AuctionId, solver_competition::{SolverCompetitionAPI, SolverCompetitionDB}, }, - primitive_types::H256, sqlx::types::JsonValue, }; fn deserialize_solver_competition( json: JsonValue, auction_id: AuctionId, - transaction_hashes: Vec, + transaction_hashes: Vec, ) -> Result { let common: SolverCompetitionDB = serde_json::from_value(json).context("deserialize SolverCompetitionDB")?; @@ -45,7 +45,7 @@ impl SolverCompetitionStoring for Postgres { deserialize_solver_competition( row.json, row.id, - row.tx_hashes.iter().map(|hash| H256(hash.0)).collect(), + row.tx_hashes.iter().map(|hash| B256::new(hash.0)).collect(), ) }), Identifier::Transaction(hash) => { @@ -56,7 +56,7 @@ impl SolverCompetitionStoring for Postgres { deserialize_solver_competition( row.json, row.id, - row.tx_hashes.iter().map(|hash| H256(hash.0)).collect(), + row.tx_hashes.iter().map(|hash| B256::new(hash.0)).collect(), ) }) } @@ -80,7 +80,7 @@ impl SolverCompetitionStoring for Postgres { deserialize_solver_competition( row.json, row.id, - row.tx_hashes.iter().map(|hash| H256(hash.0)).collect(), + row.tx_hashes.iter().map(|hash| B256::new(hash.0)).collect(), ) }) .ok_or(LoadSolverCompetitionError::NotFound)? @@ -108,7 +108,7 @@ impl SolverCompetitionStoring for Postgres { deserialize_solver_competition( row.json, row.id, - row.tx_hashes.iter().map(|hash| H256(hash.0)).collect(), + row.tx_hashes.iter().map(|hash| B256::new(hash.0)).collect(), ) }) .collect::, _>>()?; From d10497150dde090c3c52ce9f44488c02a53c6f20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Mon, 10 Nov 2025 11:52:10 +0000 Subject: [PATCH 13/17] Migrate orderbook::database::solver_competition_v2 into alloy --- crates/model/src/solver_competition_v2.rs | 31 ++++++++++--------- .../src/database/solver_competition_v2.rs | 21 +++++++------ 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/crates/model/src/solver_competition_v2.rs b/crates/model/src/solver_competition_v2.rs index e8df29620e..bb5d154db8 100644 --- a/crates/model/src/solver_competition_v2.rs +++ b/crates/model/src/solver_competition_v2.rs @@ -1,7 +1,8 @@ use { crate::{AuctionId, order::OrderUid}, + alloy::primitives::{Address, B256}, number::serialization::HexOrDecimalU256, - primitive_types::{H160, H256, U256}, + primitive_types::U256, serde::{Deserialize, Serialize}, serde_with::serde_as, std::collections::BTreeMap, @@ -13,9 +14,9 @@ use { pub struct Response { pub auction_id: AuctionId, pub auction_start_block: i64, - pub transaction_hashes: Vec, + pub transaction_hashes: Vec, #[serde_as(as = "BTreeMap<_, HexOrDecimalU256>")] - pub reference_scores: BTreeMap, + pub reference_scores: BTreeMap, pub auction: Auction, pub solutions: Vec, } @@ -26,23 +27,23 @@ pub struct Response { pub struct Auction { pub orders: Vec, #[serde_as(as = "BTreeMap<_, HexOrDecimalU256>")] - pub prices: BTreeMap, + pub prices: BTreeMap, } #[serde_as] #[derive(Clone, Default, Deserialize, Serialize, PartialEq, Debug)] #[serde(rename_all = "camelCase")] pub struct Solution { - pub solver_address: H160, + pub solver_address: Address, #[serde_as(as = "HexOrDecimalU256")] pub score: U256, pub ranking: i64, #[serde_as(as = "BTreeMap<_, HexOrDecimalU256>")] - pub clearing_prices: BTreeMap, + pub clearing_prices: BTreeMap, pub orders: Vec, pub is_winner: bool, pub filtered_out: bool, - pub tx_hash: Option, + pub tx_hash: Option, #[serde_as(as = "Option")] pub reference_score: Option, } @@ -59,9 +60,9 @@ pub struct Order { #[serde_as(as = "HexOrDecimalU256")] pub buy_amount: U256, /// The buy token address. - pub buy_token: H160, + pub buy_token: Address, /// The sell token address. - pub sell_token: H160, + pub sell_token: Address, } #[cfg(test)] @@ -112,8 +113,8 @@ mod tests { ], }); - let solver = H160([0x22; 20]); - let tx = H256([0x33; 32]); + let solver = Address::new([0x22; 20]); + let tx = B256::new([0x33; 32]); let orig = Response { auction_id: 0, @@ -125,7 +126,7 @@ mod tests { auction: Auction { orders: vec![OrderUid([0x11; 56])], prices: btreemap! { - H160([0x22; 20]) => 2000.into(), + Address::new([0x22; 20]) => 2000.into(), }, }, solutions: vec![Solution { @@ -133,14 +134,14 @@ mod tests { score: 123.into(), ranking: 1, clearing_prices: btreemap! { - H160([0x22; 20]) => 8.into(), + Address::new([0x22; 20]) => 8.into(), }, orders: vec![Order { id: OrderUid([0x11; 56]), sell_amount: 12.into(), buy_amount: 13.into(), - buy_token: H160([0x22; 20]), - sell_token: H160([0x22; 20]), + buy_token: Address::new([0x22; 20]), + sell_token: Address::new([0x22; 20]), }], is_winner: true, filtered_out: false, diff --git a/crates/orderbook/src/database/solver_competition_v2.rs b/crates/orderbook/src/database/solver_competition_v2.rs index 70f3c54996..71d735e089 100644 --- a/crates/orderbook/src/database/solver_competition_v2.rs +++ b/crates/orderbook/src/database/solver_competition_v2.rs @@ -1,7 +1,7 @@ use { super::Postgres, crate::solver_competition::LoadSolverCompetitionError, - alloy::primitives::B256, + alloy::primitives::{Address, B256}, anyhow::{Context, Result}, database::{byte_array::ByteArray, solver_competition_v2::SolverCompetition as DbResponse}, model::{ @@ -9,7 +9,6 @@ use { solver_competition_v2::{Auction, Order, Response as ApiResponse, Solution}, }, number::conversions::big_decimal_to_u256, - primitive_types::{H160, H256}, std::collections::{BTreeMap, HashMap}, }; @@ -71,7 +70,7 @@ fn try_into_dto(value: DbResponse) -> Result Result = value .settlements .into_iter() - .map(|row| (row.solution_uid, H256(row.tx_hash.0))) + .map(|row| (row.solution_uid, B256::new(row.tx_hash.0))) .collect(); let reference_scores: BTreeMap<_, _> = value @@ -88,7 +87,7 @@ fn try_into_dto(value: DbResponse) -> Result Result Result Result>()?; Ok(Solution { - solver_address: H160(solution.solver.0), + solver_address: Address::new(solution.solver.0), score: big_decimal_to_u256(&solution.score) .context("could not convert score to U256")?, ranking: solution.ranking, @@ -141,7 +140,9 @@ fn try_into_dto(value: DbResponse) -> Result>()?; From cb99ac4899640696f2e66c86f49e600e580a5f34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Mon, 10 Nov 2025 14:13:28 +0000 Subject: [PATCH 14/17] compilation fix --- crates/e2e/tests/e2e/autopilot_leader.rs | 6 ++++-- crates/e2e/tests/e2e/solver_competition.rs | 20 ++++++++++---------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/crates/e2e/tests/e2e/autopilot_leader.rs b/crates/e2e/tests/e2e/autopilot_leader.rs index 4fedd84cc0..5eece8c177 100644 --- a/crates/e2e/tests/e2e/autopilot_leader.rs +++ b/crates/e2e/tests/e2e/autopilot_leader.rs @@ -145,7 +145,8 @@ async fn dual_autopilot_only_leader_produces_auctions(web3: Web3) { .as_ref() .and_then(|competition| competition.solutions.first()) .map(|solution| { - solution.is_winner && solution.solver_address == solver1.address() + solution.is_winner + && solution.solver_address == solver1.address().into_alloy() }) } else { None @@ -181,7 +182,8 @@ async fn dual_autopilot_only_leader_produces_auctions(web3: Web3) { .as_ref() .and_then(|competition| competition.solutions.first()) .map(|solution| { - solution.is_winner && solution.solver_address == solver2.address() + solution.is_winner + && solution.solver_address == solver2.address().into_alloy() }) } else { None diff --git a/crates/e2e/tests/e2e/solver_competition.rs b/crates/e2e/tests/e2e/solver_competition.rs index 53eb5f02d0..85dcbcd069 100644 --- a/crates/e2e/tests/e2e/solver_competition.rs +++ b/crates/e2e/tests/e2e/solver_competition.rs @@ -295,7 +295,7 @@ async fn wrong_solution_submission_address(web3: Web3) { tracing::info!(?competition, "competition"); assert_eq!( competition.solutions.last().unwrap().solver_address, - solver.address() + solver.address().into_alloy() ); assert_eq!(competition.solutions.len(), 1); } @@ -522,17 +522,14 @@ async fn store_filtered_solutions(web3: Web3) { .unwrap(); assert_eq!(competition.transaction_hashes.len(), 1); - assert_eq!( - competition.transaction_hashes[0], - trade.tx_hash.unwrap().into_legacy() - ); + assert_eq!(competition.transaction_hashes[0], trade.tx_hash.unwrap()); assert_eq!(competition.reference_scores.len(), 1); // since the only other solutions were unfair the reference score is zero assert_eq!( competition .reference_scores - .get(&good_solver_account.address()), + .get(&good_solver_account.address().into_alloy()), Some(&0.into()) ); @@ -543,7 +540,10 @@ async fn store_filtered_solutions(web3: Web3) { assert_eq!(bad_solution.ranking, 2); assert!(bad_solution.filtered_out); assert!(!bad_solution.is_winner); - assert_eq!(bad_solution.solver_address, bad_solver_account.address()); + assert_eq!( + bad_solution.solver_address, + bad_solver_account.address().into_alloy() + ); assert!(bad_solution.tx_hash.is_none()); assert!(bad_solution.reference_score.is_none()); @@ -551,11 +551,11 @@ async fn store_filtered_solutions(web3: Web3) { assert_eq!(good_solution.ranking, 1); assert!(!good_solution.filtered_out); assert!(good_solution.is_winner); - assert_eq!(good_solution.solver_address, good_solver_account.address()); assert_eq!( - good_solution.tx_hash.unwrap(), - trade.tx_hash.unwrap().into_legacy() + good_solution.solver_address, + good_solver_account.address().into_alloy() ); + assert_eq!(good_solution.tx_hash.unwrap(), trade.tx_hash.unwrap()); // since the only other solutions were unfair the reference score is zero assert_eq!(good_solution.reference_score, Some(0.into())); From f10166b459d7ba6371ec02ec82a555614a3ae299 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Mon, 10 Nov 2025 16:50:09 +0000 Subject: [PATCH 15/17] Migrate OrderMetadata and OnchainOrderData models to alloy --- crates/autopilot/src/boundary/order.rs | 5 +++-- crates/autopilot/src/domain/fee/mod.rs | 2 +- crates/autopilot/src/solvable_orders.rs | 8 +++----- crates/e2e/tests/e2e/ethflow.rs | 7 ++----- crates/model/src/order.rs | 22 +++++++++++----------- crates/orderbook/src/database/orders.rs | 23 ++++++++++++----------- crates/orderbook/src/orderbook.rs | 17 +++++++++++------ crates/shared/src/account_balances/mod.rs | 8 ++++++-- crates/shared/src/db_order_conversions.rs | 10 ++++++---- crates/shared/src/order_validation.rs | 4 ++-- crates/solver/src/settlement/mod.rs | 3 ++- 11 files changed, 59 insertions(+), 50 deletions(-) diff --git a/crates/autopilot/src/boundary/order.rs b/crates/autopilot/src/boundary/order.rs index e68747273f..3b3891a122 100644 --- a/crates/autopilot/src/boundary/order.rs +++ b/crates/autopilot/src/boundary/order.rs @@ -1,5 +1,6 @@ use { - crate::{domain, domain::eth}, + crate::domain::{self, eth}, + ethrpc::alloy::conversions::IntoLegacy, shared::remaining_amounts, }; @@ -26,7 +27,7 @@ pub fn to_domain( valid_to: order.data.valid_to, side: order.data.kind.into(), receiver: order.data.receiver.map(Into::into), - owner: order.metadata.owner.into(), + owner: order.metadata.owner.into_legacy().into(), partially_fillable: order.data.partially_fillable, executed: remaining_order.executed_amount.into(), pre_interactions: if order_is_untouched { diff --git a/crates/autopilot/src/domain/fee/mod.rs b/crates/autopilot/src/domain/fee/mod.rs index 262091226f..760ee87786 100644 --- a/crates/autopilot/src/domain/fee/mod.rs +++ b/crates/autopilot/src/domain/fee/mod.rs @@ -217,7 +217,7 @@ impl ProtocolFees { let partner_fee = Self::get_partner_fee(&order, &reference_quote, self.max_partner_fee.into()); - if surplus_capturing_jit_order_owners.contains(&order.metadata.owner.into()) { + if surplus_capturing_jit_order_owners.contains(&order.metadata.owner.into_legacy().into()) { return boundary::order::to_domain(order, partner_fee, quote); } diff --git a/crates/autopilot/src/solvable_orders.rs b/crates/autopilot/src/solvable_orders.rs index d6233eea8e..5b2dd8cffd 100644 --- a/crates/autopilot/src/solvable_orders.rs +++ b/crates/autopilot/src/solvable_orders.rs @@ -444,16 +444,14 @@ async fn find_banned_user_orders(orders: &[Order], banned_users: &banned::Users) let banned = banned_users .banned(orders.iter().flat_map(|order| { std::iter::once(order.metadata.owner) - .chain(order.data.receiver) - .map(IntoAlloy::into_alloy) + .chain(order.data.receiver.map(IntoAlloy::into_alloy)) })) .await; orders .iter() .filter_map(|order| { std::iter::once(order.metadata.owner) - .chain(order.data.receiver) - .map(IntoAlloy::into_alloy) + .chain(order.data.receiver.map(IntoAlloy::into_alloy)) .any(|addr| banned.contains(&addr)) .then_some(order.metadata.uid) }) @@ -1173,7 +1171,7 @@ mod tests { .enumerate() .map(|(i, owner)| Order { metadata: OrderMetadata { - owner, + owner: owner.into_alloy(), uid: OrderUid([i as u8; 56]), ..Default::default() }, diff --git a/crates/e2e/tests/e2e/ethflow.rs b/crates/e2e/tests/e2e/ethflow.rs index b31e80bd53..b6edc19b3e 100644 --- a/crates/e2e/tests/e2e/ethflow.rs +++ b/crates/e2e/tests/e2e/ethflow.rs @@ -596,10 +596,7 @@ async fn test_order_parameters( ) { // Expected values from actual EIP1271 order instead of eth-flow order assert_eq!(response.data.valid_to, u32::MAX); - assert_eq!( - response.metadata.owner, - ethflow_contract.address().into_legacy() - ); + assert_eq!(response.metadata.owner, *ethflow_contract.address()); assert_eq!( response.data.sell_token, contracts.weth.address().into_legacy() @@ -616,7 +613,7 @@ async fn test_order_parameters( assert_eq!( response.metadata.onchain_order_data, Some(OnchainOrderData { - sender: *owner, + sender: owner.into_alloy(), placement_error: None, }) ); diff --git a/crates/model/src/order.rs b/crates/model/src/order.rs index f546a50779..5ea725d3cd 100644 --- a/crates/model/src/order.rs +++ b/crates/model/src/order.rs @@ -161,7 +161,7 @@ impl OrderBuilder { domain: &DomainSeparator, key: SecretKeyRef, ) -> Self { - self.0.metadata.owner = key.address(); + self.0.metadata.owner = Address::new(key.address().0); self.0.metadata.uid = self.0.data.uid(domain, &key.address()); self.0.signature = EcdsaSignature::sign(signing_scheme, domain, &self.0.data.hash_struct(), key) @@ -170,13 +170,13 @@ impl OrderBuilder { } pub fn with_eip1271(mut self, owner: H160, signature: Vec) -> Self { - self.0.metadata.owner = owner; + self.0.metadata.owner = Address::new(owner.0); self.0.signature = Signature::Eip1271(signature); self } pub fn with_presign(mut self, owner: H160) -> Self { - self.0.metadata.owner = owner; + self.0.metadata.owner = Address::new(owner.0); self.0.signature = Signature::PreSign; self } @@ -687,7 +687,7 @@ pub enum OnchainOrderPlacementError { #[derive(Eq, PartialEq, Clone, Default, Deserialize, Serialize, Debug)] #[serde(rename_all = "camelCase")] pub struct OnchainOrderData { - pub sender: H160, + pub sender: Address, pub placement_error: Option, } @@ -697,7 +697,7 @@ pub struct OnchainOrderData { #[serde(rename_all = "camelCase")] pub struct OrderMetadata { pub creation_date: DateTime, - pub owner: H160, + pub owner: Address, pub uid: OrderUid, /// deprecated, always set to null #[serde_as(as = "Option")] @@ -714,18 +714,18 @@ pub struct OrderMetadata { pub executed_fee_amount: U256, #[serde_as(as = "HexOrDecimalU256")] pub executed_fee: U256, - pub executed_fee_token: H160, + pub executed_fee_token: Address, pub invalidated: bool, pub status: OrderStatus, #[serde(flatten)] pub class: OrderClass, - pub settlement_contract: H160, + pub settlement_contract: Address, #[serde(default, skip_serializing_if = "Option::is_none")] pub ethflow_data: Option, #[serde(default, skip_serializing_if = "Option::is_none")] pub onchain_order_data: Option, #[serde(default, skip_serializing_if = "Option::is_none")] - pub onchain_user: Option, + pub onchain_user: Option
, pub is_liquidity_order: bool, /// Full app data that `OrderData::app_data` is a hash of. Can be None if /// the backend doesn't know about the full app data. @@ -1119,7 +1119,7 @@ mod tests { metadata: OrderMetadata { creation_date: Utc.timestamp_millis_opt(3_000).unwrap(), class: OrderClass::Limit, - owner: H160::from_low_u64_be(1), + owner: Address::with_last_byte(1), uid: OrderUid([17u8; 56]), available_balance: None, executed_buy_amount: BigUint::from_bytes_be(&[3]), @@ -1127,10 +1127,10 @@ mod tests { executed_sell_amount_before_fees: 4.into(), executed_fee_amount: 1.into(), executed_fee: 1.into(), - executed_fee_token: H160::from_low_u64_be(10), + executed_fee_token: Address::with_last_byte(10), invalidated: true, status: OrderStatus::Open, - settlement_contract: H160::from_low_u64_be(2), + settlement_contract: Address::with_last_byte(2), full_app_data: Some("123".to_string()), ..Default::default() }, diff --git a/crates/orderbook/src/database/orders.rs b/crates/orderbook/src/database/orders.rs index 50348b6378..4298f7aa5e 100644 --- a/crates/orderbook/src/database/orders.rs +++ b/crates/orderbook/src/database/orders.rs @@ -157,7 +157,7 @@ async fn insert_order(order: &Order, ex: &mut PgConnection) -> Result<(), Insert let db_order = database::orders::Order { uid: order_uid, - owner: ByteArray(order.metadata.owner.0), + owner: ByteArray(order.metadata.owner.0.0), creation_timestamp: order.metadata.creation_date, sell_token: ByteArray(order.data.sell_token.0), buy_token: ByteArray(order.data.buy_token.0), @@ -172,7 +172,7 @@ async fn insert_order(order: &Order, ex: &mut PgConnection) -> Result<(), Insert partially_fillable: order.data.partially_fillable, signature: order.signature.to_bytes(), signing_scheme: signing_scheme_into(order.signature.scheme()), - settlement_contract: ByteArray(order.metadata.settlement_contract.0), + settlement_contract: ByteArray(order.metadata.settlement_contract.0.0), sell_token_balance: sell_token_source_into(order.data.sell_token_balance), buy_token_balance: buy_token_destination_into(order.data.buy_token_balance), cancellation_timestamp: None, @@ -535,7 +535,9 @@ fn full_order_with_quote_into_model_order( } else { None }; - let onchain_user = order.onchain_user.map(|onchain_user| H160(onchain_user.0)); + let onchain_user = order + .onchain_user + .map(|onchain_user| Address::new(onchain_user.0)); let class = order_class_from(&order); let onchain_placement_error = onchain_order_placement_error_from(&order); let onchain_order_data = onchain_user.map(|onchain_user| OnchainOrderData { @@ -545,7 +547,7 @@ fn full_order_with_quote_into_model_order( let metadata = OrderMetadata { creation_date: order.creation_timestamp, - owner: H160(order.owner.0), + owner: Address::new(order.owner.0), uid: OrderUid(order.uid.0), available_balance: Default::default(), executed_buy_amount: big_decimal_to_big_uint(&order.sum_buy) @@ -563,12 +565,12 @@ fn full_order_with_quote_into_model_order( .context("executed fee amount is not a valid u256")?, executed_fee: big_decimal_to_u256(&order.executed_fee) .context("executed fee is not a valid u256")?, - executed_fee_token: H160(order.executed_fee_token.0), + executed_fee_token: Address::new(order.executed_fee_token.0), invalidated: order.invalidated, status, is_liquidity_order: class == OrderClass::Liquidity, class, - settlement_contract: H160(order.settlement_contract.0), + settlement_contract: Address::new(order.settlement_contract.0), ethflow_data, onchain_user, onchain_order_data, @@ -641,7 +643,6 @@ mod tests { SigningScheme as DbSigningScheme, }, }, - ethrpc::alloy::conversions::IntoAlloy, model::{ interaction::InteractionData, order::{Order, OrderData, OrderMetadata, OrderStatus, OrderUid}, @@ -868,7 +869,7 @@ mod tests { #[tokio::test] #[ignore] async fn postgres_replace_order() { - let owner = H160([0x77; 20]); + let owner = Address::repeat_byte(0x77); let db = Postgres::try_new("postgresql://").unwrap(); database::clear_DANGER(&db.pool).await.unwrap(); @@ -905,7 +906,7 @@ mod tests { .unwrap(); let order_statuses = db - .user_orders(&owner.into_alloy(), 0, None) + .user_orders(&owner, 0, None) .await .unwrap() .iter() @@ -934,7 +935,7 @@ mod tests { #[tokio::test] #[ignore] async fn postgres_replace_order_no_cancellation_on_error() { - let owner = H160([0x77; 20]); + let owner = Address::repeat_byte(0x77); let db = Postgres::try_new("postgresql://").unwrap(); database::clear_DANGER(&db.pool).await.unwrap(); @@ -1009,7 +1010,7 @@ mod tests { let insert_presignature = |signed: bool| { let db = db.clone(); let block_number = &block_number; - let owner = order.metadata.owner.as_bytes(); + let owner = order.metadata.owner.as_slice(); async move { sqlx::query( "INSERT INTO presignature_events (block_number, log_index, owner, order_uid, \ diff --git a/crates/orderbook/src/orderbook.rs b/crates/orderbook/src/orderbook.rs index ba040e8ff9..4563e2d358 100644 --- a/crates/orderbook/src/orderbook.rs +++ b/crates/orderbook/src/orderbook.rs @@ -13,6 +13,7 @@ use { bigdecimal::ToPrimitive, chrono::Utc, database::order_events::OrderEventLabel, + ethrpc::alloy::conversions::IntoLegacy, model::{ DomainSeparator, order::{ @@ -348,7 +349,10 @@ impl Orderbook { let signer = cancellation .validate(&self.domain_separator) .map_err(|_| OrderCancellationError::InvalidSignature)?; - if orders.iter().any(|order| signer != order.metadata.owner) { + if orders + .iter() + .any(|order| signer != order.metadata.owner.into_legacy()) + { return Err(OrderCancellationError::WrongOwner); }; @@ -378,7 +382,7 @@ impl Orderbook { let signer = cancellation .validate(&self.domain_separator) .map_err(|_| OrderCancellationError::InvalidSignature)?; - if signer != order.metadata.owner { + if signer != order.metadata.owner.into_legacy() { return Err(OrderCancellationError::WrongOwner); }; @@ -632,6 +636,7 @@ mod tests { super::*, crate::database::orders::MockOrderStoring, ethcontract::H160, + ethrpc::alloy::conversions::{IntoAlloy, IntoLegacy}, mockall::predicate::eq, model::{ order::{OrderData, OrderMetadata}, @@ -646,7 +651,7 @@ mod tests { let old_order = Order { metadata: OrderMetadata { uid: OrderUid([1; 56]), - owner: H160([1; 20]), + owner: Address::new([1; 20]), ..Default::default() }, data: OrderData { @@ -674,7 +679,7 @@ mod tests { Ok(( Order { metadata: OrderMetadata { - owner: creation.from.unwrap(), + owner: creation.from.unwrap().into_alloy(), uid: new_order_uid, ..Default::default() }, @@ -750,7 +755,7 @@ mod tests { assert!(matches!( orderbook .add_order(OrderCreation { - from: Some(old_order.metadata.owner), + from: Some(old_order.metadata.owner.into_legacy()), signature: Signature::PreSign, app_data: OrderCreationAppData::Full { full: format!( @@ -769,7 +774,7 @@ mod tests { // Stars align... let (order_id, _) = orderbook .add_order(OrderCreation { - from: Some(old_order.metadata.owner), + from: Some(old_order.metadata.owner.into_legacy()), signature: Signature::Eip712(Default::default()), app_data: OrderCreationAppData::Full { full: format!( diff --git a/crates/shared/src/account_balances/mod.rs b/crates/shared/src/account_balances/mod.rs index e28f05fb71..576882f6bc 100644 --- a/crates/shared/src/account_balances/mod.rs +++ b/crates/shared/src/account_balances/mod.rs @@ -6,7 +6,11 @@ use { alloy::sol_types::{SolCall, SolType, sol_data}, contracts::alloy::{GPv2Settlement, support::Balances}, ethcontract::state_overrides::StateOverrides, - ethrpc::{Web3, alloy::conversions::IntoAlloy, block_stream::CurrentBlockWatcher}, + ethrpc::{ + Web3, + alloy::conversions::{IntoAlloy, IntoLegacy}, + block_stream::CurrentBlockWatcher, + }, model::{ interaction::InteractionData, order::{Order, SellTokenSource}, @@ -31,7 +35,7 @@ pub struct Query { impl Query { pub fn from_order(o: &Order) -> Self { Self { - owner: o.metadata.owner, + owner: o.metadata.owner.into_legacy(), token: o.data.sell_token, source: o.data.sell_token_balance, interactions: o.interactions.pre.clone(), diff --git a/crates/shared/src/db_order_conversions.rs b/crates/shared/src/db_order_conversions.rs index 76fdb8cf8d..102bb19997 100644 --- a/crates/shared/src/db_order_conversions.rs +++ b/crates/shared/src/db_order_conversions.rs @@ -57,7 +57,9 @@ pub fn full_order_into_model_order(order: database::orders::FullOrder) -> Result } else { None }; - let onchain_user = order.onchain_user.map(|onchain_user| H160(onchain_user.0)); + let onchain_user = order + .onchain_user + .map(|onchain_user| Address::new(onchain_user.0)); let class = order_class_from(&order); let onchain_placement_error = onchain_order_placement_error_from(&order); let onchain_order_data = onchain_user.map(|onchain_user| OnchainOrderData { @@ -68,7 +70,7 @@ pub fn full_order_into_model_order(order: database::orders::FullOrder) -> Result let metadata = OrderMetadata { creation_date: order.creation_timestamp, - owner: H160(order.owner.0), + owner: Address::new(order.owner.0), uid: OrderUid(order.uid.0), available_balance: Default::default(), executed_buy_amount: big_decimal_to_big_uint(&order.sum_buy) @@ -86,12 +88,12 @@ pub fn full_order_into_model_order(order: database::orders::FullOrder) -> Result .context("executed fee amount is not a valid u256")?, executed_fee: big_decimal_to_u256(&order.executed_fee) .context("executed fee is not a valid u256")?, - executed_fee_token: H160(order.executed_fee_token.0), + executed_fee_token: Address::new(order.executed_fee_token.0), invalidated: order.invalidated, status, is_liquidity_order: class == OrderClass::Liquidity, class, - settlement_contract: H160(order.settlement_contract.0), + settlement_contract: Address::new(order.settlement_contract.0), ethflow_data, onchain_user, onchain_order_data, diff --git a/crates/shared/src/order_validation.rs b/crates/shared/src/order_validation.rs index dd5cba688e..611cc9fad0 100644 --- a/crates/shared/src/order_validation.rs +++ b/crates/shared/src/order_validation.rs @@ -773,10 +773,10 @@ impl OrderValidating for OrderValidator { let order = Order { metadata: OrderMetadata { - owner, + owner: owner.into_alloy(), creation_date: chrono::offset::Utc::now(), uid, - settlement_contract, + settlement_contract: settlement_contract.into_alloy(), class, full_app_data: match order.app_data { OrderCreationAppData::Both { full, .. } diff --git a/crates/solver/src/settlement/mod.rs b/crates/solver/src/settlement/mod.rs index 33cd9edd8c..769e1da6d8 100644 --- a/crates/solver/src/settlement/mod.rs +++ b/crates/solver/src/settlement/mod.rs @@ -3,6 +3,7 @@ mod settlement_encoder; use { crate::liquidity::Settleable, anyhow::Result, + ethrpc::alloy::conversions::IntoLegacy, model::order::{Order, OrderKind}, primitive_types::{H160, U256}, shared::{ @@ -90,7 +91,7 @@ impl Trade { encode_trade( &self.order.data, &self.order.signature, - self.order.metadata.owner, + self.order.metadata.owner.into_legacy(), sell_token_index, buy_token_index, &self.executed_amount, From 9e23e125a790ad35ef5cc6e1475f7a977b532792 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Wed, 19 Nov 2025 21:33:57 -0300 Subject: [PATCH 16/17] compilation fixes --- crates/autopilot/src/boundary/order.rs | 2 +- crates/e2e/tests/e2e/ethflow.rs | 5 +---- crates/orderbook/src/database/orders.rs | 3 +-- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/crates/autopilot/src/boundary/order.rs b/crates/autopilot/src/boundary/order.rs index 5ca88fbdb3..31cb5b5a15 100644 --- a/crates/autopilot/src/boundary/order.rs +++ b/crates/autopilot/src/boundary/order.rs @@ -31,7 +31,7 @@ pub fn to_domain( .receiver .map(IntoLegacy::into_legacy) .map(Into::into), - owner: order.metadata.owner.into(), + owner: order.metadata.owner.into_legacy().into(), partially_fillable: order.data.partially_fillable, executed: remaining_order.executed_amount.into(), pre_interactions: if order_is_untouched { diff --git a/crates/e2e/tests/e2e/ethflow.rs b/crates/e2e/tests/e2e/ethflow.rs index c1ad195b67..2d3be7829c 100644 --- a/crates/e2e/tests/e2e/ethflow.rs +++ b/crates/e2e/tests/e2e/ethflow.rs @@ -596,10 +596,7 @@ async fn test_order_parameters( ) { // Expected values from actual EIP1271 order instead of eth-flow order assert_eq!(response.data.valid_to, u32::MAX); - assert_eq!( - response.metadata.owner, - ethflow_contract.address().into_legacy() - ); + assert_eq!(response.metadata.owner, *ethflow_contract.address()); assert_eq!(response.data.sell_token, *contracts.weth.address()); // Specific parameters return the missing values diff --git a/crates/orderbook/src/database/orders.rs b/crates/orderbook/src/database/orders.rs index 99e409c09c..bbc424b2b6 100644 --- a/crates/orderbook/src/database/orders.rs +++ b/crates/orderbook/src/database/orders.rs @@ -654,7 +654,6 @@ mod tests { SigningScheme as DbSigningScheme, }, }, - ethrpc::alloy::conversions::IntoAlloy, model::{ interaction::InteractionData, order::{Order, OrderData, OrderMetadata, OrderStatus, OrderUid}, @@ -918,7 +917,7 @@ mod tests { .unwrap(); let order_statuses = db - .user_orders(&owner.into_alloy(), 0, None) + .user_orders(&owner, 0, None) .await .unwrap() .iter() From 9543cc463937392080d156b1963752c61a282332 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Wed, 19 Nov 2025 21:41:18 -0300 Subject: [PATCH 17/17] Migrate orderbook::orderbook to alloy --- crates/orderbook/src/orderbook.rs | 15 +++++++-------- crates/orderbook/src/run.rs | 2 +- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/crates/orderbook/src/orderbook.rs b/crates/orderbook/src/orderbook.rs index 6d33bf29e0..3677b18c4a 100644 --- a/crates/orderbook/src/orderbook.rs +++ b/crates/orderbook/src/orderbook.rs @@ -13,7 +13,7 @@ use { bigdecimal::ToPrimitive, chrono::Utc, database::order_events::OrderEventLabel, - ethrpc::alloy::conversions::IntoLegacy, + ethrpc::alloy::conversions::{IntoAlloy, IntoLegacy}, model::{ DomainSeparator, order::{ @@ -29,7 +29,6 @@ use { solver_competition::{self, SolverCompetitionAPI}, }, observe::metrics::LivenessChecking, - primitive_types::H160, shared::{ fee::FeeParameters, order_quoting::Quote, @@ -217,21 +216,21 @@ pub enum OrderReplacementError { #[derive(Debug)] pub struct QuoteMetadata { pub id: Option, - pub solver: H160, + pub solver: Address, } impl From<&Quote> for QuoteMetadata { fn from(value: &Quote) -> Self { Self { id: value.id, - solver: value.data.solver, + solver: value.data.solver.into_alloy(), } } } pub struct Orderbook { domain_separator: DomainSeparator, - settlement_contract: H160, + settlement_contract: Address, database: crate::database::Postgres, database_replica: crate::database::Postgres, order_validator: Arc, @@ -242,7 +241,7 @@ pub struct Orderbook { impl Orderbook { pub fn new( domain_separator: DomainSeparator, - settlement_contract: H160, + settlement_contract: Address, database: crate::database::Postgres, database_replica: crate::database::Postgres, order_validator: Arc, @@ -287,7 +286,7 @@ impl Orderbook { .validate_and_construct_order( payload, &self.domain_separator, - self.settlement_contract, + self.settlement_contract.into_legacy(), full_app_data_override, ) .await?; @@ -706,7 +705,7 @@ mod tests { database_replica, order_validator: Arc::new(order_validator), domain_separator: Default::default(), - settlement_contract: H160([0xba; 20]), + settlement_contract: Address::repeat_byte(0xba), app_data, active_order_competition_threshold: Default::default(), }; diff --git a/crates/orderbook/src/run.rs b/crates/orderbook/src/run.rs index cff280fe87..43bea7eec5 100644 --- a/crates/orderbook/src/run.rs +++ b/crates/orderbook/src/run.rs @@ -447,7 +447,7 @@ pub async fn run(args: Arguments) { )); let orderbook = Arc::new(Orderbook::new( domain_separator, - settlement_contract.address().into_legacy(), + *settlement_contract.address(), postgres_write.clone(), postgres_read.clone(), order_validator.clone(),