diff --git a/Cargo.lock b/Cargo.lock index c632674da8..6473177a8d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3038,10 +3038,12 @@ version = "0.1.0" dependencies = [ "anyhow", "bigdecimal", + "derive_more", "num", "primitive-types", "serde", "serde_with", + "uint", ] [[package]] @@ -4221,6 +4223,7 @@ dependencies = [ "itertools 0.11.0", "model", "num", + "number", "observe", "prometheus", "prometheus-metric-storage", diff --git a/crates/alerter/src/lib.rs b/crates/alerter/src/lib.rs index e6360f53cf..47fef93c30 100644 --- a/crates/alerter/src/lib.rs +++ b/crates/alerter/src/lib.rs @@ -7,11 +7,9 @@ use { anyhow::{Context, Result}, clap::Parser, model::order::{OrderClass, OrderKind, OrderStatus, OrderUid, BUY_ETH_ADDRESS}, - number::serialization::HexOrDecimalU256, - primitive_types::{H160, U256}, + primitive_types::H160, prometheus::IntGauge, reqwest::Client, - serde_with::serde_as, std::{ collections::HashMap, time::{Duration, Instant}, @@ -19,17 +17,14 @@ use { url::Url, }; -#[serde_as] #[derive(Debug, serde::Deserialize, Eq, PartialEq)] #[serde(rename_all = "camelCase")] struct Order { kind: OrderKind, buy_token: H160, - #[serde_as(as = "HexOrDecimalU256")] - buy_amount: U256, + buy_amount: number::U256, sell_token: H160, - #[serde_as(as = "HexOrDecimalU256")] - sell_amount: U256, + sell_amount: number::U256, uid: OrderUid, partially_fillable: bool, #[serde(flatten)] @@ -130,14 +125,11 @@ impl ZeroExApi { .append_pair("buyToken", &format!("{buy_token:#x}")) .append_pair(amount_name, &amount.to_string()); - #[serde_as] #[derive(Debug, serde::Deserialize)] #[serde(rename_all = "camelCase")] pub struct Response { - #[serde_as(as = "HexOrDecimalU256")] - pub sell_amount: U256, - #[serde_as(as = "HexOrDecimalU256")] - pub buy_amount: U256, + pub sell_amount: number::U256, + pub buy_amount: number::U256, } let response: Response = self diff --git a/crates/autopilot/src/boundary/order.rs b/crates/autopilot/src/boundary/order.rs index 46c710875d..b8082606ea 100644 --- a/crates/autopilot/src/boundary/order.rs +++ b/crates/autopilot/src/boundary/order.rs @@ -11,9 +11,9 @@ pub fn to_domain( uid: order.metadata.uid.into(), sell_token: order.data.sell_token, buy_token: order.data.buy_token, - sell_amount: order.data.sell_amount, - buy_amount: order.data.buy_amount, - user_fee: order.data.fee_amount, + sell_amount: *order.data.sell_amount, + buy_amount: *order.data.buy_amount, + user_fee: *order.data.fee_amount, protocol_fees, valid_to: order.data.valid_to, kind: order.data.kind.into(), diff --git a/crates/autopilot/src/database/onchain_order_events.rs b/crates/autopilot/src/database/onchain_order_events.rs index 81409b14b5..bd35446c0a 100644 --- a/crates/autopilot/src/database/onchain_order_events.rs +++ b/crates/autopilot/src/database/onchain_order_events.rs @@ -546,9 +546,9 @@ async fn get_quote( let parameters = QuoteSearchParameters { sell_token: H160::from(order_data.sell_token.0), buy_token: H160::from(order_data.buy_token.0), - sell_amount: order_data.sell_amount, - buy_amount: order_data.buy_amount, - fee_amount: order_data.fee_amount, + sell_amount: *order_data.sell_amount, + buy_amount: *order_data.buy_amount, + fee_amount: *order_data.fee_amount, kind: order_data.kind, signing_scheme: quote_signing_scheme, additional_gas: 0, @@ -569,9 +569,14 @@ async fn get_quote( true => None, false => Some(order_data.fee_amount), }; - get_quote_and_check_fee(quoter, ¶meters.clone(), Some(*quote_id), fee_amount) - .await - .map_err(onchain_order_placement_error_from) + get_quote_and_check_fee( + quoter, + ¶meters.clone(), + Some(*quote_id), + fee_amount.map(Into::into), + ) + .await + .map_err(onchain_order_placement_error_from) } #[allow(clippy::too_many_arguments)] @@ -658,11 +663,11 @@ fn extract_order_data_from_onchain_order_placement_event( sell_token: order_placement.order.0, buy_token: order_placement.order.1, receiver, - sell_amount: order_placement.order.3, - buy_amount: order_placement.order.4, + sell_amount: order_placement.order.3.into(), + buy_amount: order_placement.order.4.into(), valid_to: order_placement.order.5, app_data: AppDataHash(order_placement.order.6 .0), - fee_amount: order_placement.order.7, + fee_amount: order_placement.order.7.into(), kind: OrderKind::from_contract_bytes(order_placement.order.8 .0)?, partially_fillable: order_placement.order.9, sell_token_balance: SellTokenSource::from_contract_bytes(order_placement.order.10 .0)?, @@ -767,11 +772,11 @@ mod test { sell_token, buy_token, receiver: Some(receiver), - sell_amount, - buy_amount, + sell_amount: sell_amount.into(), + buy_amount: buy_amount.into(), valid_to, app_data: AppDataHash(app_data.0), - fee_amount, + fee_amount: fee_amount.into(), kind: OrderKind::Sell, partially_fillable: order_placement.order.9, sell_token_balance: SellTokenSource::Erc20, @@ -813,11 +818,11 @@ mod test { sell_token, buy_token, receiver: None, - sell_amount, - buy_amount, + sell_amount: sell_amount.into(), + buy_amount: buy_amount.into(), valid_to, app_data: AppDataHash(app_data.0), - fee_amount, + fee_amount: fee_amount.into(), kind: OrderKind::Sell, partially_fillable: order_placement.order.9, sell_token_balance: SellTokenSource::Erc20, @@ -844,11 +849,11 @@ mod test { sell_token, buy_token, receiver: Some(receiver), - sell_amount, - buy_amount, + sell_amount: sell_amount.into(), + buy_amount: buy_amount.into(), valid_to, app_data: AppDataHash(app_data.0), - fee_amount, + fee_amount: fee_amount.into(), kind: OrderKind::Sell, partially_fillable: false, sell_token_balance: SellTokenSource::Erc20, @@ -893,11 +898,11 @@ mod test { sell_token, buy_token, receiver: Some(receiver), - sell_amount, - buy_amount, + sell_amount: sell_amount.into(), + buy_amount: buy_amount.into(), valid_to, app_data: AppDataHash(app_data.0), - fee_amount, + fee_amount: fee_amount.into(), kind: OrderKind::Sell, partially_fillable: order_placement.order.9, sell_token_balance: SellTokenSource::Erc20, @@ -952,11 +957,11 @@ mod test { sell_token, buy_token, receiver: Some(receiver), - sell_amount, - buy_amount, + sell_amount: sell_amount.into(), + buy_amount: buy_amount.into(), valid_to, app_data: AppDataHash(app_data.0), - fee_amount, + fee_amount: fee_amount.into(), kind: OrderKind::Sell, partially_fillable: false, sell_token_balance: SellTokenSource::Erc20, @@ -1004,8 +1009,8 @@ mod test { sell_token, buy_token, receiver: Some(receiver), - sell_amount, - buy_amount, + sell_amount: sell_amount.into(), + buy_amount: buy_amount.into(), valid_to, app_data: AppDataHash(app_data.0), fee_amount: 0.into(), @@ -1252,11 +1257,11 @@ mod test { sell_token, buy_token, receiver: Some(receiver), - sell_amount, - buy_amount, + sell_amount: sell_amount.into(), + buy_amount: buy_amount.into(), valid_to, app_data: AppDataHash(app_data.0), - fee_amount, + fee_amount: fee_amount.into(), kind: OrderKind::Sell, partially_fillable: order_placement.order.9, sell_token_balance: SellTokenSource::Erc20, diff --git a/crates/autopilot/src/decoded_settlement.rs b/crates/autopilot/src/decoded_settlement.rs index 6d2e128218..153026d94a 100644 --- a/crates/autopilot/src/decoded_settlement.rs +++ b/crates/autopilot/src/decoded_settlement.rs @@ -77,11 +77,11 @@ impl DecodedTrade { let order = OrderData { sell_token: tokens[self.sell_token_index.as_u64() as usize], buy_token: tokens[self.buy_token_index.as_u64() as usize], - sell_amount: self.sell_amount, - buy_amount: self.buy_amount, + sell_amount: self.sell_amount.into(), + buy_amount: self.buy_amount.into(), valid_to: self.valid_to, app_data: AppDataHash(self.app_data.0), - fee_amount: self.fee_amount, + fee_amount: self.fee_amount.into(), kind: self.flags.order_kind(), partially_fillable: self.flags.partially_fillable(), receiver: Some(self.receiver), diff --git a/crates/autopilot/src/domain/fee/policy.rs b/crates/autopilot/src/domain/fee/policy.rs index 4b1296aa7c..73c4ab42db 100644 --- a/crates/autopilot/src/domain/fee/policy.rs +++ b/crates/autopilot/src/domain/fee/policy.rs @@ -62,9 +62,9 @@ impl Surplus { Some(policy) } else { let order_ = boundary::Amounts { - sell: order.data.sell_amount, - buy: order.data.buy_amount, - fee: order.data.fee_amount, + sell: *order.data.sell_amount, + buy: *order.data.buy_amount, + fee: *order.data.fee_amount, }; let quote_ = boundary::Amounts { sell: quote.sell_amount, diff --git a/crates/autopilot/src/driver_model.rs b/crates/autopilot/src/driver_model.rs new file mode 100644 index 0000000000..fef274e507 --- /dev/null +++ b/crates/autopilot/src/driver_model.rs @@ -0,0 +1,171 @@ +//! Types for communicating with drivers as defined in +//! `crates/driver/openapi.yml`. + +// TODO: parse proper error type with kind and description, that driver returns. + +pub mod quote { + use { + primitive_types::{H160}, + serde::{Deserialize, Serialize}, + }; + + #[derive(Clone, Debug, Default, Serialize)] + #[serde(rename_all = "camelCase")] + pub struct Request { + pub sell_token: H160, + pub buy_token: H160, + pub kind: Kind, + pub amount: number::U256, + } + + #[derive(Clone, Debug, Default, Serialize)] + #[serde(rename_all = "camelCase")] + pub enum Kind { + #[default] + Buy, + Sell, + } + + #[derive(Clone, Debug, Deserialize)] + #[serde(untagged, rename_all = "camelCase", deny_unknown_fields)] + pub enum Response { + Successful { + sell_amount: number::U256, + buy_amount: number::U256, + gas: u64, + }, + Unfillable { + unfillable_reason: String, + }, + } +} + +pub mod solve { + use { + crate::{boundary, infra::persistence::dto::order::Order}, + chrono::{DateTime, Utc}, + primitive_types::{H160}, + serde::{Deserialize, Serialize}, + serde_with::{serde_as, DisplayFromStr}, + std::collections::HashMap, + }; + + #[serde_as] + #[derive(Clone, Debug, Default, Serialize)] + #[serde(rename_all = "camelCase")] + pub struct Request { + #[serde_as(as = "DisplayFromStr")] + pub id: i64, + pub tokens: Vec, + pub orders: Vec, + pub deadline: DateTime, + pub score_cap: number::U256, + } + + #[derive(Clone, Debug, Serialize)] + #[serde(rename_all = "camelCase")] + pub struct Token { + pub address: H160, + pub price: Option, + pub trusted: bool, + } + + #[derive(Clone, Debug, Default, Deserialize)] + #[serde(rename_all = "camelCase", deny_unknown_fields)] + pub struct TradedAmounts { + /// The effective amount that left the user's wallet including all fees. + pub sell_amount: number::U256, + /// The effective amount the user received after all fees. + pub buy_amount: number::U256, + } + + #[serde_as] + #[derive(Clone, Debug, Default, Deserialize)] + #[serde(rename_all = "camelCase", deny_unknown_fields)] + pub struct Solution { + /// Unique ID of the solution (per driver competition), used to identify + /// it in subsequent requests (reveal, settle). + #[serde_as(as = "serde_with::DisplayFromStr")] + pub solution_id: u64, + pub score: number::U256, + /// Address used by the driver to submit the settlement onchain. + pub submission_address: H160, + pub orders: HashMap, + pub clearing_prices: HashMap, + } + + #[derive(Clone, Debug, Default, Deserialize)] + #[serde(rename_all = "camelCase", deny_unknown_fields)] + pub struct Response { + pub solutions: Vec, + } +} + +pub mod reveal { + use { + model::bytes_hex, + serde::{Deserialize, Serialize}, + serde_with::serde_as, + }; + + #[serde_as] + #[derive(Clone, Debug, Default, Serialize)] + #[serde(rename_all = "camelCase")] + pub struct Request { + /// Unique ID of the solution (per driver competition), to reveal. + #[serde_as(as = "serde_with::DisplayFromStr")] + pub solution_id: u64, + } + + #[serde_as] + #[derive(Clone, Debug, Default, Deserialize)] + #[serde(rename_all = "camelCase", deny_unknown_fields)] + pub struct Calldata { + #[serde(with = "bytes_hex")] + pub internalized: Vec, + #[serde(with = "bytes_hex")] + pub uninternalized: Vec, + } + + #[derive(Clone, Debug, Default, Deserialize)] + #[serde(rename_all = "camelCase", deny_unknown_fields)] + pub struct Response { + pub calldata: Calldata, + } +} + +pub mod settle { + use { + model::bytes_hex, + primitive_types::H256, + serde::{Deserialize, Serialize}, + serde_with::serde_as, + }; + + #[serde_as] + #[derive(Clone, Debug, Default, Serialize)] + #[serde(rename_all = "camelCase")] + pub struct Request { + /// Unique ID of the solution (per driver competition), to settle. + #[serde_as(as = "serde_with::DisplayFromStr")] + pub solution_id: u64, + } + + #[serde_as] + #[derive(Clone, Debug, Default, Deserialize)] + #[serde(rename_all = "camelCase", deny_unknown_fields)] + pub struct Response { + pub calldata: Calldata, + pub tx_hash: H256, + } + + #[serde_as] + #[derive(Clone, Debug, Default, Deserialize)] + #[serde(rename_all = "camelCase", deny_unknown_fields)] + pub struct Calldata { + #[serde(with = "bytes_hex")] + pub internalized: Vec, + #[serde(with = "bytes_hex")] + pub uninternalized: Vec, + } +} diff --git a/crates/autopilot/src/infra/persistence/dto/auction.rs b/crates/autopilot/src/infra/persistence/dto/auction.rs index ca58c7aedb..2773fe3adc 100644 --- a/crates/autopilot/src/infra/persistence/dto/auction.rs +++ b/crates/autopilot/src/infra/persistence/dto/auction.rs @@ -1,8 +1,7 @@ use { super::order::Order, crate::domain, - number::serialization::HexOrDecimalU256, - primitive_types::{H160, U256}, + primitive_types::H160, serde::{Deserialize, Serialize}, serde_with::serde_as, std::collections::BTreeMap, @@ -17,7 +16,11 @@ pub fn from_domain(auction: domain::Auction) -> Auction { .into_iter() .map(super::order::from_domain) .collect(), - prices: auction.prices, + prices: auction + .prices + .iter() + .map(|(key, val)| (*key, (*val).into())) + .collect(), } } @@ -30,19 +33,21 @@ pub fn to_domain(auction: Auction) -> domain::Auction { .into_iter() .map(super::order::to_domain) .collect(), - prices: auction.prices, + prices: auction + .prices + .iter() + .map(|(key, val)| (*key, (*val).into())) + .collect(), } } -#[serde_as] #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Auction { pub block: u64, pub latest_settlement_block: u64, pub orders: Vec, - #[serde_as(as = "BTreeMap<_, HexOrDecimalU256>")] - pub prices: BTreeMap, + pub prices: BTreeMap, } pub type AuctionId = i64; diff --git a/crates/autopilot/src/infra/persistence/dto/order.rs b/crates/autopilot/src/infra/persistence/dto/order.rs index bc4fdb4a3c..3174ba3105 100644 --- a/crates/autopilot/src/infra/persistence/dto/order.rs +++ b/crates/autopilot/src/infra/persistence/dto/order.rs @@ -3,33 +3,27 @@ use { boundary::{self}, domain, }, - number::serialization::HexOrDecimalU256, primitive_types::{H160, U256}, serde::{Deserialize, Serialize}, serde_with::serde_as, }; -#[serde_as] #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Order { pub uid: boundary::OrderUid, pub sell_token: H160, pub buy_token: H160, - #[serde_as(as = "HexOrDecimalU256")] - pub sell_amount: U256, - #[serde_as(as = "HexOrDecimalU256")] - pub buy_amount: U256, - #[serde_as(as = "HexOrDecimalU256")] - pub user_fee: U256, + pub sell_amount: number::U256, + pub buy_amount: number::U256, + pub user_fee: number::U256, pub protocol_fees: Vec, pub valid_to: u32, pub kind: boundary::OrderKind, pub receiver: Option, pub owner: H160, pub partially_fillable: bool, - #[serde_as(as = "HexOrDecimalU256")] - pub executed: U256, + pub executed: number::U256, pub pre_interactions: Vec, pub post_interactions: Vec, pub sell_token_balance: boundary::SellTokenSource, @@ -46,16 +40,16 @@ pub fn from_domain(order: domain::Order) -> Order { uid: order.uid.into(), sell_token: order.sell_token, buy_token: order.buy_token, - sell_amount: order.sell_amount, - buy_amount: order.buy_amount, - user_fee: order.user_fee, + sell_amount: order.sell_amount.into(), + buy_amount: order.buy_amount.into(), + user_fee: order.user_fee.into(), protocol_fees: order.protocol_fees.into_iter().map(Into::into).collect(), valid_to: order.valid_to, kind: order.kind.into(), receiver: order.receiver, owner: order.owner, partially_fillable: order.partially_fillable, - executed: order.executed, + executed: order.executed.into(), pre_interactions: order.pre_interactions.into_iter().map(Into::into).collect(), post_interactions: order .post_interactions @@ -75,16 +69,16 @@ pub fn to_domain(order: Order) -> domain::Order { uid: order.uid.into(), sell_token: order.sell_token, buy_token: order.buy_token, - sell_amount: order.sell_amount, - buy_amount: order.buy_amount, - user_fee: order.user_fee, + sell_amount: *order.sell_amount, + buy_amount: *order.buy_amount, + user_fee: *order.user_fee, protocol_fees: order.protocol_fees.into_iter().map(Into::into).collect(), valid_to: order.valid_to, kind: order.kind.into(), receiver: order.receiver, owner: order.owner, partially_fillable: order.partially_fillable, - executed: order.executed, + executed: *order.executed, pre_interactions: order.pre_interactions.into_iter().map(Into::into).collect(), post_interactions: order .post_interactions @@ -153,7 +147,7 @@ impl From for boundary::InteractionData { fn from(interaction: domain::auction::order::Interaction) -> Self { Self { target: interaction.target, - value: interaction.value, + value: interaction.value.into(), call_data: interaction.call_data, } } @@ -163,7 +157,7 @@ impl From for domain::auction::order::Interaction { fn from(interaction: boundary::InteractionData) -> Self { Self { target: interaction.target, - value: interaction.value, + value: *interaction.value, call_data: interaction.call_data, } } diff --git a/crates/autopilot/src/infra/solvers/dto/solve.rs b/crates/autopilot/src/infra/solvers/dto/solve.rs index bdb194df23..70b26d03a3 100644 --- a/crates/autopilot/src/infra/solvers/dto/solve.rs +++ b/crates/autopilot/src/infra/solvers/dto/solve.rs @@ -6,7 +6,6 @@ use { }, chrono::{DateTime, Utc}, itertools::Itertools, - number::serialization::HexOrDecimalU256, primitive_types::{H160, U256}, serde::{Deserialize, Serialize}, serde_with::{serde_as, DisplayFromStr}, @@ -37,7 +36,7 @@ impl Request { .iter() .map(|(address, price)| Token { address: address.to_owned(), - price: Some(price.to_owned()), + price: Some(price.to_owned().into()), trusted: trusted_tokens.contains(address), }) .chain(trusted_tokens.iter().map(|&address| Token { @@ -48,7 +47,7 @@ impl Request { .unique_by(|token| token.address) .collect(), deadline: Utc::now() + chrono::Duration::from_std(time_limit).unwrap(), - score_cap, + score_cap: score_cap.into(), } } } @@ -62,30 +61,24 @@ pub struct Request { pub tokens: Vec, pub orders: Vec, pub deadline: DateTime, - #[serde_as(as = "HexOrDecimalU256")] - pub score_cap: U256, + pub score_cap: number::U256, } -#[serde_as] #[derive(Clone, Debug, Serialize)] #[serde(rename_all = "camelCase")] pub struct Token { pub address: H160, - #[serde_as(as = "Option")] - pub price: Option, + pub price: Option, pub trusted: bool, } -#[serde_as] #[derive(Clone, Debug, Default, Deserialize)] #[serde(rename_all = "camelCase", deny_unknown_fields)] pub struct TradedAmounts { /// The effective amount that left the user's wallet including all fees. - #[serde_as(as = "HexOrDecimalU256")] - pub sell_amount: U256, + pub sell_amount: number::U256, /// The effective amount the user received after all fees. - #[serde_as(as = "HexOrDecimalU256")] - pub buy_amount: U256, + pub buy_amount: number::U256, } #[serde_as] @@ -96,13 +89,11 @@ pub struct Solution { /// it in subsequent requests (reveal, settle). #[serde_as(as = "serde_with::DisplayFromStr")] pub solution_id: u64, - #[serde_as(as = "HexOrDecimalU256")] - pub score: U256, + pub score: number::U256, /// Address used by the driver to submit the settlement onchain. pub submission_address: H160, pub orders: HashMap, - #[serde_as(as = "HashMap<_, HexOrDecimalU256>")] - pub clearing_prices: HashMap, + pub clearing_prices: HashMap, } #[derive(Clone, Debug, Default, Deserialize)] diff --git a/crates/autopilot/src/run_loop.rs b/crates/autopilot/src/run_loop.rs index c55700f959..67ef740e43 100644 --- a/crates/autopilot/src/run_loop.rs +++ b/crates/autopilot/src/run_loop.rs @@ -210,7 +210,11 @@ impl RunLoop { .iter() .map(|order| order.uid.into()) .collect(), - prices: auction.prices.clone(), + prices: auction + .prices + .iter() + .map(|(key, val)| (*key, (*val).into())) + .collect::>(), }, solutions: solutions .iter() @@ -220,7 +224,7 @@ impl RunLoop { let mut settlement = SolverSettlement { solver: participant.driver.name.clone(), solver_address: participant.solution.account, - score: Some(Score::Solver(participant.solution.score.get())), + score: Some(Score::Solver(participant.solution.score.get().into())), ranking: solutions.len() - index, orders: participant .solution @@ -236,7 +240,7 @@ impl RunLoop { .solution .clearing_prices .iter() - .map(|(token, price)| (*token, *price)) + .map(|(token, price)| (*token, (*price).into())) .collect(), call_data: None, uninternalized_call_data: None, @@ -375,13 +379,17 @@ impl RunLoop { Ok(Solution { id: solution.solution_id, account: solution.submission_address, - score: NonZeroU256::new(solution.score).ok_or(ZeroScoreError)?, + score: NonZeroU256::new(*solution.score).ok_or(ZeroScoreError)?, orders: solution .orders .into_iter() .map(|(o, amounts)| (o.into(), amounts)) .collect(), - clearing_prices: solution.clearing_prices, + clearing_prices: solution + .clearing_prices + .iter() + .map(|(key, val)| (*key, (*val).into())) + .collect(), }) }) .collect()) diff --git a/crates/autopilot/src/shadow.rs b/crates/autopilot/src/shadow.rs index fe7931b905..9e0403a787 100644 --- a/crates/autopilot/src/shadow.rs +++ b/crates/autopilot/src/shadow.rs @@ -228,7 +228,7 @@ impl RunLoop { }) .ok_or(Error::NoSolutions)?; - let score = NonZeroU256::new(score).ok_or(Error::ZeroScore)?; + let score = NonZeroU256::new(*score).ok_or(Error::ZeroScore)?; let revealed = driver .reveal(&reveal::Request { solution_id }) diff --git a/crates/autopilot/src/solvable_orders.rs b/crates/autopilot/src/solvable_orders.rs index af2b409d22..29b5885d57 100644 --- a/crates/autopilot/src/solvable_orders.rs +++ b/crates/autopilot/src/solvable_orders.rs @@ -354,7 +354,7 @@ fn orders_with_balance(mut orders: Vec, balances: &Balances) -> Vec return false, Some(balance) => balance, }; @@ -384,8 +384,8 @@ fn filter_dust_orders(mut orders: Vec, balances: &Balances) -> Vec }; let (Ok(sell_amount), Ok(buy_amount)) = ( - remaining.remaining(order.data.sell_amount), - remaining.remaining(order.data.buy_amount), + remaining.remaining(*order.data.sell_amount), + remaining.remaining(*order.data.buy_amount), ) else { return false; }; @@ -874,12 +874,12 @@ mod tests { interactions: Interactions { pre: vec![InteractionData { target: H160([0xe1; 20]), - value: U256::zero(), + value: U256::zero().into(), call_data: vec![1, 2], }], post: vec![InteractionData { target: H160([0xe2; 20]), - value: U256::zero(), + value: U256::zero().into(), call_data: vec![3, 4], }], }, @@ -894,12 +894,12 @@ mod tests { interactions: Interactions { pre: vec![InteractionData { target: H160([0xe3; 20]), - value: U256::zero(), + value: U256::zero().into(), call_data: vec![5, 6], }], post: vec![InteractionData { target: H160([0xe4; 20]), - value: U256::zero(), + value: U256::zero().into(), call_data: vec![7, 9], }], }, @@ -940,7 +940,7 @@ mod tests { signature: vec![2, 2], interactions: vec![InteractionData { target: H160([0xe3; 20]), - value: U256::zero(), + value: U256::zero().into(), call_data: vec![5, 6], }], }, diff --git a/crates/driver/src/boundary/liquidity/uniswap/v3.rs b/crates/driver/src/boundary/liquidity/uniswap/v3.rs index 60a2b2fc5f..51af05c4e1 100644 --- a/crates/driver/src/boundary/liquidity/uniswap/v3.rs +++ b/crates/driver/src/boundary/liquidity/uniswap/v3.rs @@ -47,7 +47,7 @@ pub fn to_domain(id: liquidity::Id, pool: ConcentratedLiquidity) -> Result Result http_solver::model::Score::Solver { score }, + competition::SolverScore::Solver(score) => http_solver::model::Score::Solver { + score: score.into(), + }, competition::SolverScore::RiskAdjusted(success_probability) => { http_solver::model::Score::RiskAdjusted { success_probability, @@ -206,7 +208,7 @@ impl Settlement { pub fn score(&self) -> competition::SolverScore { match self.inner.score { - http_solver::model::Score::Solver { score } => competition::SolverScore::Solver(score), + http_solver::model::Score::Solver { score } => competition::SolverScore::Solver(*score), http_solver::model::Score::RiskAdjusted { success_probability, .. @@ -265,9 +267,9 @@ fn to_boundary_order(order: &competition::Order) -> Order { data: OrderData { sell_token: order.sell.token.into(), buy_token: order.buy.token.into(), - sell_amount: order.sell.amount.into(), - buy_amount: order.buy.amount.into(), - fee_amount: order.user_fee.into(), + sell_amount: eth::U256::from(order.sell.amount).into(), + buy_amount: eth::U256::from(order.buy.amount).into(), + fee_amount: eth::U256::from(order.user_fee).into(), receiver: order.receiver.map(Into::into), valid_to: order.valid_to.into(), app_data: AppDataHash(order.app_data.into()), @@ -288,7 +290,7 @@ fn to_boundary_order(order: &competition::Order) -> Order { }, metadata: OrderMetadata { full_fee_amount: Default::default(), - solver_fee: order.user_fee.into(), + solver_fee: eth::U256::from(order.user_fee).into(), class: match order.kind { competition::order::Kind::Market => OrderClass::Market, competition::order::Kind::Liquidity => OrderClass::Liquidity, @@ -319,7 +321,7 @@ fn to_boundary_order(order: &competition::Order) -> Order { .iter() .map(|interaction| model::interaction::InteractionData { target: interaction.target.into(), - value: interaction.value.into(), + value: eth::U256::from(interaction.value).into(), call_data: interaction.call_data.clone().into(), }) .collect(), @@ -328,7 +330,7 @@ fn to_boundary_order(order: &competition::Order) -> Order { .iter() .map(|interaction| model::interaction::InteractionData { target: interaction.target.into(), - value: interaction.value.into(), + value: eth::U256::from(interaction.value).into(), call_data: interaction.call_data.clone().into(), }) .collect(), @@ -341,11 +343,11 @@ fn to_boundary_jit_order(domain: &DomainSeparator, order: &order::Jit) -> Order sell_token: order.sell.token.into(), buy_token: order.buy.token.into(), receiver: Some(order.receiver.into()), - sell_amount: order.sell.amount.into(), - buy_amount: order.buy.amount.into(), + sell_amount: eth::U256::from(order.sell.amount).into(), + buy_amount: eth::U256::from(order.buy.amount).into(), valid_to: order.valid_to.into(), app_data: AppDataHash(order.app_data.into()), - fee_amount: order.fee.into(), + fee_amount: eth::U256::from(order.fee).into(), kind: match order.side { competition::order::Side::Buy => OrderKind::Buy, competition::order::Side::Sell => OrderKind::Sell, @@ -363,7 +365,7 @@ fn to_boundary_jit_order(domain: &DomainSeparator, order: &order::Jit) -> Order }; let metadata = OrderMetadata { owner: order.signature.signer.into(), - full_fee_amount: order.fee.into(), + full_fee_amount: eth::U256::from(order.fee).into(), // All foreign orders **MUST** be liquidity, this is // important so they cannot be used to affect the objective. class: OrderClass::Liquidity, @@ -410,7 +412,7 @@ pub fn to_boundary_interaction( match interaction { competition::solution::Interaction::Custom(custom) => Ok(InteractionData { target: custom.target.into(), - value: custom.value.into(), + value: eth::U256::from(custom.value).into(), call_data: custom.call_data.clone().into(), }), competition::solution::Interaction::Liquidity(liquidity) => { @@ -429,11 +431,11 @@ pub fn to_boundary_interaction( let input = liquidity::MaxInput(eth::Asset { token: boundary_execution.input_max.token.into(), - amount: boundary_execution.input_max.amount.into(), + amount: (*boundary_execution.input_max.amount).into(), }); let output = liquidity::ExactOutput(eth::Asset { token: boundary_execution.output.token.into(), - amount: boundary_execution.output.amount.into(), + amount: (*boundary_execution.output.amount).into(), }); let interaction = match &liquidity.liquidity.kind { @@ -457,7 +459,7 @@ pub fn to_boundary_interaction( Ok(InteractionData { target: interaction.target.into(), - value: interaction.value.into(), + value: eth::U256::from(interaction.value).into(), call_data: interaction.call_data.into(), }) } diff --git a/crates/driver/src/infra/api/routes/quote/dto/order.rs b/crates/driver/src/infra/api/routes/quote/dto/order.rs index 6bf7115560..333bdd2226 100644 --- a/crates/driver/src/infra/api/routes/quote/dto/order.rs +++ b/crates/driver/src/infra/api/routes/quote/dto/order.rs @@ -2,10 +2,9 @@ use { crate::{ domain::{competition, eth, quote, time}, infra::solver::Timeouts, - util::serialize, }, + number::U256, serde::Deserialize, - serde_with::serde_as, }; impl Order { @@ -13,7 +12,7 @@ impl Order { Ok(quote::Order { tokens: quote::Tokens::new(self.sell_token.into(), self.buy_token.into()) .map_err(|quote::SameTokens| Error::SameTokens)?, - amount: self.amount.into(), + amount: eth::U256::from(self.amount).into(), side: match self.kind { Kind::Sell => competition::order::Side::Sell, Kind::Buy => competition::order::Side::Buy, @@ -23,14 +22,12 @@ impl Order { } } -#[serde_as] #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase", deny_unknown_fields)] pub struct Order { sell_token: eth::H160, buy_token: eth::H160, - #[serde_as(as = "serialize::U256")] - amount: eth::U256, + amount: U256, kind: Kind, deadline: chrono::DateTime, } diff --git a/crates/driver/src/infra/api/routes/quote/dto/quote.rs b/crates/driver/src/infra/api/routes/quote/dto/quote.rs index dc72e3729d..ea8f9e03d0 100644 --- a/crates/driver/src/infra/api/routes/quote/dto/quote.rs +++ b/crates/driver/src/infra/api/routes/quote/dto/quote.rs @@ -3,6 +3,7 @@ use { domain::{eth, quote}, util::serialize, }, + number::U256, serde::Serialize, serde_with::serde_as, }; @@ -10,13 +11,13 @@ use { impl Quote { pub fn new(quote: "e::Quote) -> Self { Self { - amount: quote.amount, + amount: quote.amount.into(), interactions: quote .interactions .iter() .map(|interaction| Interaction { target: interaction.target.into(), - value: interaction.value.into(), + value: eth::U256::from(interaction.value).into(), call_data: interaction.call_data.clone().into(), }) .collect(), @@ -25,12 +26,10 @@ impl Quote { } } -#[serde_as] #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] pub struct Quote { - #[serde_as(as = "serialize::U256")] - amount: eth::U256, + amount: U256, interactions: Vec, solver: eth::H160, } @@ -40,8 +39,7 @@ pub struct Quote { #[serde(rename_all = "camelCase")] struct Interaction { target: eth::H160, - #[serde_as(as = "serialize::U256")] - value: eth::U256, + value: U256, #[serde_as(as = "serialize::Hex")] call_data: Vec, } diff --git a/crates/driver/src/infra/api/routes/solve/dto/auction.rs b/crates/driver/src/infra/api/routes/solve/dto/auction.rs index f602e79919..1ab63e6b19 100644 --- a/crates/driver/src/infra/api/routes/solve/dto/auction.rs +++ b/crates/driver/src/infra/api/routes/solve/dto/auction.rs @@ -1,13 +1,18 @@ use { crate::{ domain::{ - competition::{self, auction, order}, + competition::{ + self, + auction::{self}, + order, + }, eth, time, }, infra::{solver::Timeouts, tokens, Ethereum}, util::serialize, }, + number::U256, serde::Deserialize, serde_with::serde_as, }; @@ -35,18 +40,18 @@ impl Auction { receiver: order.receiver.map(Into::into), valid_to: order.valid_to.into(), buy: eth::Asset { - amount: order.buy_amount.into(), + amount: (*order.buy_amount).into(), token: order.buy_token.into(), }, sell: eth::Asset { - amount: order.sell_amount.into(), + amount: (*order.sell_amount).into(), token: order.sell_token.into(), }, side: match order.kind { Kind::Sell => competition::order::Side::Sell, Kind::Buy => competition::order::Side::Buy, }, - user_fee: order.user_fee.into(), + user_fee: (*order.user_fee).into(), kind: match order.class { Class::Market => competition::order::Kind::Market, Class::Limit => competition::order::Kind::Limit, @@ -57,9 +62,11 @@ impl Auction { competition::order::Partial::Yes { available: match order.kind { Kind::Sell => { - order.sell_amount.saturating_sub(order.executed).into() + (*order.sell_amount).saturating_sub(*order.executed).into() + } + Kind::Buy => { + (*order.buy_amount).saturating_sub(*order.executed).into() } - Kind::Buy => order.buy_amount.saturating_sub(order.executed).into(), }, } } else { @@ -70,7 +77,7 @@ impl Auction { .into_iter() .map(|interaction| eth::Interaction { target: interaction.target.into(), - value: interaction.value.into(), + value: (*interaction.value).into(), call_data: interaction.call_data.into(), }) .collect(), @@ -79,7 +86,7 @@ impl Auction { .into_iter() .map(|interaction| eth::Interaction { target: interaction.target.into(), - value: interaction.value.into(), + value: (*interaction.value).into(), call_data: interaction.call_data.into(), }) .collect(), @@ -145,14 +152,16 @@ impl Auction { decimals: info.and_then(|i| i.decimals), symbol: info.and_then(|i| i.symbol.clone()), address: token.address.into(), - price: token.price.map(Into::into), + price: token.price.map(|price| (*price).into()), available_balance: info.map(|i| i.balance).unwrap_or(0.into()).into(), trusted: token.trusted, } }), time::Deadline::new(self.deadline, timeouts), eth, - self.score_cap.try_into().map_err(|_| Error::ZeroScoreCap)?, + (*self.score_cap) + .try_into() + .map_err(|_| Error::ZeroScoreCap)?, ) .await .map_err(Into::into) @@ -200,8 +209,7 @@ pub struct Auction { tokens: Vec, orders: Vec, deadline: chrono::DateTime, - #[serde_as(as = "serialize::U256")] - score_cap: eth::U256, + score_cap: U256, } impl Auction { @@ -210,13 +218,11 @@ impl Auction { } } -#[serde_as] #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase", deny_unknown_fields)] struct Token { pub address: eth::H160, - #[serde_as(as = "Option")] - pub price: Option, + pub price: Option, pub trusted: bool, } @@ -228,12 +234,9 @@ struct Order { uid: [u8; order::UID_LEN], sell_token: eth::H160, buy_token: eth::H160, - #[serde_as(as = "serialize::U256")] - sell_amount: eth::U256, - #[serde_as(as = "serialize::U256")] - buy_amount: eth::U256, - #[serde_as(as = "serialize::U256")] - user_fee: eth::U256, + sell_amount: U256, + buy_amount: U256, + user_fee: U256, protocol_fees: Vec, valid_to: u32, kind: Kind, @@ -241,8 +244,7 @@ struct Order { owner: eth::H160, partially_fillable: bool, /// Always zero if the order is not partially fillable. - #[serde_as(as = "serialize::U256")] - executed: eth::U256, + executed: U256, pre_interactions: Vec, post_interactions: Vec, #[serde(default)] @@ -269,8 +271,7 @@ enum Kind { #[serde(rename_all = "camelCase", deny_unknown_fields)] struct Interaction { target: eth::H160, - #[serde_as(as = "serialize::U256")] - value: eth::U256, + value: U256, #[serde_as(as = "serialize::Hex")] call_data: Vec, } diff --git a/crates/driver/src/infra/api/routes/solve/dto/solved.rs b/crates/driver/src/infra/api/routes/solve/dto/solved.rs index e6af9b01a0..b34224b084 100644 --- a/crates/driver/src/infra/api/routes/solve/dto/solved.rs +++ b/crates/driver/src/infra/api/routes/solve/dto/solved.rs @@ -4,6 +4,7 @@ use { infra::Solver, util::serialize, }, + number::U256, serde::Serialize, serde_with::serde_as, std::collections::HashMap, @@ -30,7 +31,7 @@ impl Solution { pub fn new(solution_id: u64, solved: competition::Solved, solver: &Solver) -> Self { Self { solution_id, - score: solved.score.0.get(), + score: solved.score.0.get().into(), submission_address: solver.address().into(), orders: solved .trades @@ -39,8 +40,8 @@ impl Solution { ( order_id.into(), TradedAmounts { - sell_amount: amounts.sell.into(), - buy_amount: amounts.buy.into(), + sell_amount: eth::U256::from(amounts.sell).into(), + buy_amount: eth::U256::from(amounts.buy).into(), }, ) }) @@ -48,22 +49,19 @@ impl Solution { clearing_prices: solved .prices .into_iter() - .map(|(k, v)| (k.into(), v.into())) + .map(|(k, v)| (k.into(), eth::U256::from(v).into())) .collect(), } } } -#[serde_as] #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] pub struct TradedAmounts { /// The effective amount that left the user's wallet including all fees. - #[serde_as(as = "serialize::U256")] - pub sell_amount: eth::U256, + pub sell_amount: U256, /// The effective amount the user received after all fees. - #[serde_as(as = "serialize::U256")] - pub buy_amount: eth::U256, + pub buy_amount: U256, } type OrderId = [u8; order::UID_LEN]; @@ -76,11 +74,9 @@ pub struct Solution { /// in subsequent requests (reveal, settle). #[serde_as(as = "serde_with::DisplayFromStr")] solution_id: u64, - #[serde_as(as = "serialize::U256")] - score: eth::U256, + score: U256, submission_address: eth::H160, #[serde_as(as = "HashMap")] orders: HashMap, - #[serde_as(as = "HashMap<_, serialize::U256>")] - clearing_prices: HashMap, + clearing_prices: HashMap, } diff --git a/crates/driver/src/infra/config/file/load.rs b/crates/driver/src/infra/config/file/load.rs index f8168a94bf..093ed1b80f 100644 --- a/crates/driver/src/infra/config/file/load.rs +++ b/crates/driver/src/infra/config/file/load.rs @@ -39,7 +39,10 @@ pub async fn load(network: &blockchain::Network, path: &Path) -> infra::Config { }); assert_eq!( - config.chain_id.map(eth::ChainId).unwrap_or(network.chain), + config + .chain_id + .map(|chain_id| eth::ChainId::from(*chain_id)) + .unwrap_or(network.chain), network.chain, "The configured chain ID does not match connected Ethereum node" ); @@ -69,7 +72,10 @@ pub async fn load(network: &blockchain::Network, path: &Path) -> infra::Config { name: config.name.into(), slippage: solver::Slippage { relative: config.slippage.relative, - absolute: config.slippage.absolute.map(eth::Ether), + absolute: config + .slippage + .absolute + .map(|absolute| eth::Ether::from(*absolute)), }, liquidity: if config.skip_liquidity { solver::Liquidity::Skip @@ -254,8 +260,8 @@ pub async fn load(network: &blockchain::Network, path: &Path) -> infra::Config { .mempools .iter() .map(|mempool| mempool::Config { - min_priority_fee: config.submission.min_priority_fee, - gas_price_cap: config.submission.gas_price_cap, + min_priority_fee: *config.submission.min_priority_fee, + gas_price_cap: *config.submission.gas_price_cap, target_confirm_time: config.submission.target_confirm_time, max_confirm_time: config.submission.max_confirm_time, retry_interval: config.submission.retry_interval, @@ -284,7 +290,7 @@ pub async fn load(network: &blockchain::Network, path: &Path) -> infra::Config { use_soft_cancellations, } => mempool::Kind::MEVBlocker { url: url.to_owned(), - max_additional_tip: *max_additional_tip, + max_additional_tip: (*max_additional_tip).into(), additional_tip_percentage: *additional_tip_percentage, use_soft_cancellations: *use_soft_cancellations, }, @@ -322,6 +328,8 @@ pub async fn load(network: &blockchain::Network, path: &Path) -> infra::Config { .map(|contracts| contracts.into_iter().map(eth::Address).collect()), }, disable_access_list_simulation: config.disable_access_list_simulation, - disable_gas_simulation: config.disable_gas_simulation.map(Into::into), + disable_gas_simulation: config + .disable_gas_simulation + .map(|disable_gas_simulation| (*disable_gas_simulation).into()), } } diff --git a/crates/driver/src/infra/config/file/mod.rs b/crates/driver/src/infra/config/file/mod.rs index 60b2f7ae97..1cd82e5cb5 100644 --- a/crates/driver/src/infra/config/file/mod.rs +++ b/crates/driver/src/infra/config/file/mod.rs @@ -1,6 +1,7 @@ pub use load::load; use { - crate::{domain::eth, util::serialize}, + crate::domain::eth, + number::U256, reqwest::Url, serde::Deserialize, serde_with::serde_as, @@ -10,7 +11,6 @@ use { mod load; -#[serde_as] #[derive(Debug, Deserialize)] #[serde(rename_all = "kebab-case", deny_unknown_fields)] struct Config { @@ -18,7 +18,7 @@ struct Config { /// Note that the actual chain ID is fetched from the configured Ethereum /// RPC endpoint, and the driver will exit if it does not match this /// value. - chain_id: Option, + chain_id: Option, /// Disable access list simulation, useful for environments that don't /// support this, such as less popular blockchains. @@ -28,8 +28,7 @@ struct Config { /// Disable gas simulation and always use this fixed gas value instead. This /// can be useful for testing, but shouldn't be used in production since it /// will cause the driver to return invalid scores. - #[serde_as(as = "Option")] - disable_gas_simulation: Option, + disable_gas_simulation: Option, /// Parameters related to settlement submission. #[serde(default)] @@ -52,21 +51,18 @@ struct Config { liquidity: LiquidityConfig, } -#[serde_as] #[derive(Debug, Default, Deserialize)] #[serde(rename_all = "kebab-case", deny_unknown_fields)] struct SubmissionConfig { /// The minimum priority fee in Gwei the solver is ensuring to pay in a /// settlement. #[serde(default)] - #[serde_as(as = "serialize::U256")] - min_priority_fee: eth::U256, + min_priority_fee: U256, /// The maximum gas price in Gwei the solver is willing to pay in a /// settlement. #[serde(default = "default_gas_price_cap")] - #[serde_as(as = "serialize::U256")] - gas_price_cap: eth::U256, + gas_price_cap: U256, /// The target confirmation time for settlement transactions used /// to estimate gas price. @@ -92,7 +88,6 @@ struct SubmissionConfig { logic: Logic, } -#[serde_as] #[derive(Debug, Deserialize)] #[serde(tag = "mempool")] #[serde(rename_all = "kebab-case", deny_unknown_fields)] @@ -105,8 +100,7 @@ enum Mempool { /// Maximum additional tip in Gwei that we are willing to give to /// MEVBlocker above regular gas price estimation. #[serde(default = "default_max_additional_tip")] - #[serde_as(as = "serialize::U256")] - max_additional_tip: eth::U256, + max_additional_tip: U256, /// Additional tip in percentage of max_fee_per_gas we are giving to /// MEVBlocker above regular gas price estimation. Expects a /// floating point value between 0 and 1. @@ -127,8 +121,8 @@ fn default_additional_tip_percentage() -> f64 { } /// 1000 gwei -fn default_gas_price_cap() -> eth::U256 { - eth::U256::from(1000) * eth::U256::exp10(9) +fn default_gas_price_cap() -> U256 { + U256::from(eth::U256::from(1000) * eth::U256::exp10(9)) } fn default_target_confirm_time() -> Duration { @@ -144,8 +138,8 @@ fn default_max_confirm_time() -> Duration { } /// 3 gwei -fn default_max_additional_tip() -> eth::U256 { - eth::U256::from(3) * eth::U256::exp10(9) +fn default_max_additional_tip() -> U256 { + U256::from(eth::U256::from(3) * eth::U256::exp10(9)) } fn default_soft_cancellations_flag() -> bool { @@ -230,8 +224,7 @@ struct Slippage { /// The absolute slippage allowed by the solver. #[serde(rename = "absolute-slippage")] - #[serde_as(as = "Option")] - absolute: Option, + absolute: Option, } #[derive(Debug, Default, Deserialize)] diff --git a/crates/driver/src/infra/solver/dto/auction.rs b/crates/driver/src/infra/solver/dto/auction.rs index a89491d75a..fd8c59d034 100644 --- a/crates/driver/src/infra/solver/dto/auction.rs +++ b/crates/driver/src/infra/solver/dto/auction.rs @@ -7,6 +7,7 @@ use { }, }, indexmap::IndexMap, + number::U256, serde::Serialize, serde_with::serde_as, std::collections::{BTreeMap, HashMap}, @@ -27,8 +28,8 @@ impl Auction { Token { decimals: token.decimals, symbol: token.symbol.clone(), - reference_price: token.price.map(Into::into), - available_balance: token.available_balance, + reference_price: token.price.map(eth::U256::from).map(Into::into), + available_balance: token.available_balance.into(), trusted: token.trusted, }, ) @@ -64,9 +65,9 @@ impl Auction { uid: order.uid.into(), sell_token: available.sell.token.into(), buy_token: available.buy.token.into(), - sell_amount: available.sell.amount.into(), - buy_amount: available.buy.amount.into(), - fee_amount: available.user_fee.into(), + sell_amount: eth::U256::from(available.sell.amount).into(), + buy_amount: eth::U256::from(available.buy.amount).into(), + fee_amount: eth::U256::from(available.user_fee).into(), kind: match order.side { competition::order::Side::Buy => Kind::Buy, competition::order::Side::Sell => Kind::Sell, @@ -87,7 +88,7 @@ impl Auction { Liquidity::ConstantProduct(ConstantProductPool { id: liquidity.id.into(), address: pool.address.into(), - gas_estimate: liquidity.gas.into(), + gas_estimate: eth::U256::from(liquidity.gas).into(), tokens: pool .reserves .iter() @@ -95,7 +96,7 @@ impl Auction { ( asset.token.into(), ConstantProductReserve { - balance: asset.amount.into(), + balance: eth::U256::from(asset.amount).into(), }, ) }) @@ -107,9 +108,9 @@ impl Auction { Liquidity::ConcentratedLiquidity(ConcentratedLiquidityPool { id: liquidity.id.into(), address: pool.address.0, - gas_estimate: liquidity.gas.0, + gas_estimate: liquidity.gas.0.into(), tokens: vec![pool.tokens.get().0.into(), pool.tokens.get().1.into()], - sqrt_price: pool.sqrt_price.0, + sqrt_price: pool.sqrt_price.0.into(), liquidity: pool.liquidity.0, tick: pool.tick.0, liquidity_net: pool @@ -123,7 +124,7 @@ impl Auction { liquidity::Kind::BalancerV2Stable(pool) => Liquidity::Stable(StablePool { id: liquidity.id.into(), address: pool.id.address().into(), - gas_estimate: liquidity.gas.into(), + gas_estimate: eth::U256::from(liquidity.gas).into(), tokens: pool .reserves .iter() @@ -131,7 +132,7 @@ impl Auction { ( r.asset.token.into(), StableReserve { - balance: r.asset.amount.into(), + balance: eth::U256::from(r.asset.amount).into(), scaling_factor: scaling_factor_to_decimal(r.scale), }, ) @@ -147,7 +148,7 @@ impl Auction { Liquidity::WeightedProduct(WeightedProductPool { id: liquidity.id.into(), address: pool.id.address().into(), - gas_estimate: liquidity.gas.into(), + gas_estimate: eth::U256::from(liquidity.gas).into(), tokens: pool .reserves .iter() @@ -155,7 +156,7 @@ impl Auction { ( r.asset.token.into(), WeightedProductReserve { - balance: r.asset.amount.into(), + balance: eth::U256::from(r.asset.amount).into(), scaling_factor: scaling_factor_to_decimal(r.scale), weight: weight_to_decimal(r.weight), }, @@ -177,7 +178,7 @@ impl Auction { Liquidity::ConstantProduct(ConstantProductPool { id: liquidity.id.into(), address: pool.base.address.into(), - gas_estimate: liquidity.gas.into(), + gas_estimate: eth::U256::from(liquidity.gas).into(), tokens: pool .base .reserves @@ -186,7 +187,7 @@ impl Auction { ( asset.token.into(), ConstantProductReserve { - balance: asset.amount.into(), + balance: eth::U256::from(asset.amount).into(), }, ) }) @@ -198,13 +199,12 @@ impl Auction { }) .collect(), tokens, - effective_gas_price: auction.gas_price().effective().into(), + effective_gas_price: eth::U256::from(auction.gas_price().effective()).into(), deadline: auction.deadline().solvers(), } } } -#[serde_as] #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] pub struct Auction { @@ -212,8 +212,7 @@ pub struct Auction { tokens: HashMap, orders: Vec, liquidity: Vec, - #[serde_as(as = "serialize::U256")] - effective_gas_price: eth::U256, + effective_gas_price: U256, deadline: chrono::DateTime, } @@ -225,12 +224,9 @@ struct Order { uid: [u8; order::UID_LEN], sell_token: eth::H160, buy_token: eth::H160, - #[serde_as(as = "serialize::U256")] - sell_amount: eth::U256, - #[serde_as(as = "serialize::U256")] - buy_amount: eth::U256, - #[serde_as(as = "serialize::U256")] - fee_amount: eth::U256, + sell_amount: U256, + buy_amount: U256, + fee_amount: U256, kind: Kind, partially_fillable: bool, class: Class, @@ -251,16 +247,13 @@ enum Class { Liquidity, } -#[serde_as] #[derive(Default, Debug, Serialize)] #[serde(rename_all = "camelCase")] struct Token { decimals: Option, symbol: Option, - #[serde_as(as = "Option")] - reference_price: Option, - #[serde_as(as = "serialize::U256")] - available_balance: eth::U256, + reference_price: Option, + available_balance: U256, trusted: bool, } @@ -283,18 +276,15 @@ struct ConstantProductPool { #[serde_as(as = "serde_with::DisplayFromStr")] id: usize, address: eth::H160, - #[serde_as(as = "serialize::U256")] - gas_estimate: eth::U256, + gas_estimate: U256, tokens: BTreeMap, #[serde_as(as = "serde_with::DisplayFromStr")] fee: bigdecimal::BigDecimal, } -#[serde_as] #[derive(Debug, Serialize)] struct ConstantProductReserve { - #[serde_as(as = "serialize::U256")] - balance: eth::U256, + balance: U256, } #[serde_as] @@ -304,8 +294,7 @@ struct WeightedProductPool { #[serde_as(as = "serde_with::DisplayFromStr")] id: usize, address: eth::H160, - #[serde_as(as = "serialize::U256")] - gas_estimate: eth::U256, + gas_estimate: U256, tokens: IndexMap, #[serde_as(as = "serde_with::DisplayFromStr")] fee: bigdecimal::BigDecimal, @@ -316,8 +305,7 @@ struct WeightedProductPool { #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] struct WeightedProductReserve { - #[serde_as(as = "serialize::U256")] - balance: eth::U256, + balance: U256, #[serde_as(as = "serde_with::DisplayFromStr")] scaling_factor: bigdecimal::BigDecimal, #[serde_as(as = "serde_with::DisplayFromStr")] @@ -338,8 +326,7 @@ struct StablePool { #[serde_as(as = "serde_with::DisplayFromStr")] id: usize, address: eth::H160, - #[serde_as(as = "serialize::U256")] - gas_estimate: eth::U256, + gas_estimate: U256, tokens: IndexMap, #[serde_as(as = "serde_with::DisplayFromStr")] amplification_parameter: bigdecimal::BigDecimal, @@ -351,8 +338,7 @@ struct StablePool { #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] struct StableReserve { - #[serde_as(as = "serialize::U256")] - balance: eth::U256, + balance: U256, #[serde_as(as = "serde_with::DisplayFromStr")] scaling_factor: bigdecimal::BigDecimal, } @@ -364,11 +350,9 @@ struct ConcentratedLiquidityPool { #[serde_as(as = "serde_with::DisplayFromStr")] id: usize, address: eth::H160, - #[serde_as(as = "serialize::U256")] - gas_estimate: eth::U256, + gas_estimate: U256, tokens: Vec, - #[serde_as(as = "serialize::U256")] - sqrt_price: eth::U256, + sqrt_price: U256, #[serde_as(as = "serde_with::DisplayFromStr")] liquidity: u128, tick: i32, @@ -385,18 +369,14 @@ struct ForeignLimitOrder { #[serde_as(as = "serde_with::DisplayFromStr")] id: usize, address: eth::H160, - #[serde_as(as = "serialize::U256")] - gas_estimate: eth::U256, + gas_estimate: U256, #[serde_as(as = "serialize::Hex")] hash: [u8; 32], maker_token: eth::H160, taker_token: eth::H160, - #[serde_as(as = "serialize::U256")] - maker_amount: eth::U256, - #[serde_as(as = "serialize::U256")] - taker_amount: eth::U256, - #[serde_as(as = "serialize::U256")] - taker_token_fee_amount: eth::U256, + maker_amount: U256, + taker_amount: U256, + taker_token_fee_amount: U256, } fn fee_to_decimal(fee: liquidity::balancer::v2::Fee) -> bigdecimal::BigDecimal { diff --git a/crates/driver/src/infra/solver/dto/notification.rs b/crates/driver/src/infra/solver/dto/notification.rs index b8cb5d1f5c..90795ce08e 100644 --- a/crates/driver/src/infra/solver/dto/notification.rs +++ b/crates/driver/src/infra/solver/dto/notification.rs @@ -7,6 +7,7 @@ use { infra::notify, util::serialize, }, + number::U256, serde::Serialize, serde_with::serde_as, std::collections::BTreeSet, @@ -32,7 +33,7 @@ impl Notification { from: tx.from.into(), to: tx.to.into(), input: tx.input.into(), - value: tx.value.into(), + value: eth::U256::from(tx.value).into(), access_list: tx.access_list.into(), }, succeeded_once, @@ -43,8 +44,8 @@ impl Notification { score, quality, )) => Kind::ScoreHigherThanQuality { - score: score.0.get(), - quality: quality.0, + score: score.0.get().into(), + quality: quality.0.into(), }, notify::Kind::ScoringFailed(notify::ScoreKind::SuccessProbabilityOutOfRange( success_probability, @@ -55,15 +56,15 @@ impl Notification { quality, gas_cost, )) => Kind::ObjectiveValueNonPositive { - quality: quality.0, - gas_cost: gas_cost.get().0, + quality: quality.0.into(), + gas_cost: gas_cost.get().0.into(), }, notify::Kind::NonBufferableTokensUsed(tokens) => Kind::NonBufferableTokensUsed { tokens: tokens.into_iter().map(|token| token.0 .0).collect(), }, notify::Kind::SolverAccountInsufficientBalance(required) => { Kind::SolverAccountInsufficientBalance { - required: required.0, + required: required.0.into(), } } notify::Kind::DuplicatedSolutionId => Kind::DuplicatedSolutionId, @@ -94,7 +95,6 @@ pub struct Notification { kind: Kind, } -#[serde_as] #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase", tag = "kind")] pub enum Kind { @@ -109,27 +109,22 @@ pub enum Kind { }, ZeroScore, ScoreHigherThanQuality { - #[serde_as(as = "serialize::U256")] - score: eth::U256, - #[serde_as(as = "serialize::U256")] - quality: eth::U256, + score: U256, + quality: U256, }, SuccessProbabilityOutOfRange { probability: f64, }, #[serde(rename_all = "camelCase")] ObjectiveValueNonPositive { - #[serde_as(as = "serialize::U256")] - quality: eth::U256, - #[serde_as(as = "serialize::U256")] - gas_cost: eth::U256, + quality: U256, + gas_cost: U256, }, NonBufferableTokensUsed { tokens: BTreeSet, }, SolverAccountInsufficientBalance { - #[serde_as(as = "serialize::U256")] - required: eth::U256, + required: U256, }, Success { transaction: eth::H256, @@ -155,7 +150,6 @@ pub struct Tx { pub to: eth::H160, #[serde_as(as = "serialize::Hex")] pub input: Vec, - #[serde_as(as = "serialize::U256")] - pub value: eth::U256, + pub value: U256, pub access_list: AccessList, } diff --git a/crates/driver/src/infra/solver/dto/solution.rs b/crates/driver/src/infra/solver/dto/solution.rs index 2ed5bc3772..0741220927 100644 --- a/crates/driver/src/infra/solver/dto/solution.rs +++ b/crates/driver/src/infra/solver/dto/solution.rs @@ -5,6 +5,7 @@ use { util::serialize, }, itertools::Itertools, + number::U256, serde::Deserialize, serde_with::serde_as, std::collections::HashMap, @@ -40,10 +41,10 @@ impl Solutions { competition::solution::trade::Fulfillment::new( order, - fulfillment.executed_amount.into(), + eth::U256::from(fulfillment.executed_amount).into(), match fulfillment.fee { Some(fee) => competition::solution::trade::Fee::Dynamic( - competition::order::SellAmount(fee), + competition::order::SellAmount(fee.into()), ), None => competition::solution::trade::Fee::Static, }, @@ -55,14 +56,14 @@ impl Solutions { competition::solution::trade::Jit::new( competition::order::Jit { sell: eth::Asset { - amount: jit.order.sell_amount.into(), + amount: (*jit.order.sell_amount).into(), token: jit.order.sell_token.into(), }, buy: eth::Asset { - amount: jit.order.buy_amount.into(), + amount: (*jit.order.buy_amount).into(), token: jit.order.buy_token.into(), }, - fee: jit.order.fee_amount.into(), + fee: (*jit.order.fee_amount).into(), receiver: jit.order.receiver.into(), valid_to: jit.order.valid_to.into(), app_data: jit.order.app_data.into(), @@ -109,7 +110,7 @@ impl Solutions { signer: solver.address(), }, }, - jit.executed_amount.into(), + eth::U256::from(jit.executed_amount).into(), ) .map_err(|err| super::Error(format!("invalid JIT trade: {err}")))?, )), @@ -118,7 +119,7 @@ impl Solutions { solution .prices .into_iter() - .map(|(address, price)| (address.into(), price)) + .map(|(address, price)| (address.into(), price.into())) .collect(), solution .interactions @@ -128,7 +129,7 @@ impl Solutions { Ok(competition::solution::Interaction::Custom( competition::solution::interaction::Custom { target: interaction.target.into(), - value: interaction.value.into(), + value: (*interaction.value).into(), call_data: interaction.call_data.into(), allowances: interaction .allowances @@ -137,7 +138,7 @@ impl Solutions { eth::Allowance { token: allowance.token.into(), spender: allowance.spender.into(), - amount: allowance.amount, + amount: allowance.amount.into(), } .into() }) @@ -146,7 +147,7 @@ impl Solutions { .inputs .into_iter() .map(|input| eth::Asset { - amount: input.amount.into(), + amount: (*input.amount).into(), token: input.token.into(), }) .collect(), @@ -154,7 +155,7 @@ impl Solutions { .outputs .into_iter() .map(|input| eth::Asset { - amount: input.amount.into(), + amount: (*input.amount).into(), token: input.token.into(), }) .collect(), @@ -174,11 +175,11 @@ impl Solutions { competition::solution::interaction::Liquidity { liquidity, input: eth::Asset { - amount: interaction.input_amount.into(), + amount: (*interaction.input_amount).into(), token: interaction.input_token.into(), }, output: eth::Asset { - amount: interaction.output_amount.into(), + amount: (*interaction.output_amount).into(), token: interaction.output_token.into(), }, internalize: interaction.internalize, @@ -190,7 +191,7 @@ impl Solutions { solver.clone(), match solution.score { Score::Solver { score } => { - competition::solution::SolverScore::Solver(score) + competition::solution::SolverScore::Solver(score.into()) } Score::RiskAdjusted { success_probability, @@ -218,13 +219,11 @@ pub struct Solutions { solutions: Vec, } -#[serde_as] #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase", deny_unknown_fields)] pub struct Solution { id: u64, - #[serde_as(as = "HashMap<_, serialize::U256>")] - prices: HashMap, + prices: HashMap, trades: Vec, interactions: Vec, score: Score, @@ -243,19 +242,15 @@ enum Trade { struct Fulfillment { #[serde_as(as = "serialize::Hex")] order: [u8; order::UID_LEN], - #[serde_as(as = "serialize::U256")] - executed_amount: eth::U256, - #[serde_as(as = "Option")] - fee: Option, + executed_amount: U256, + fee: Option, } -#[serde_as] #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase", deny_unknown_fields)] struct JitTrade { order: JitOrder, - #[serde_as(as = "serialize::U256")] - executed_amount: eth::U256, + executed_amount: U256, } #[serde_as] @@ -265,15 +260,12 @@ struct JitOrder { sell_token: eth::H160, buy_token: eth::H160, receiver: eth::H160, - #[serde_as(as = "serialize::U256")] - sell_amount: eth::U256, - #[serde_as(as = "serialize::U256")] - buy_amount: eth::U256, + sell_amount: U256, + buy_amount: U256, valid_to: u32, #[serde_as(as = "serialize::Hex")] app_data: [u8; order::APP_DATA_LEN], - #[serde_as(as = "serialize::U256")] - fee_amount: eth::U256, + fee_amount: U256, kind: Kind, partially_fillable: bool, sell_token_balance: SellTokenBalance, @@ -306,10 +298,8 @@ struct LiquidityInteraction { id: usize, input_token: eth::H160, output_token: eth::H160, - #[serde_as(as = "serialize::U256")] - input_amount: eth::U256, - #[serde_as(as = "serialize::U256")] - output_amount: eth::U256, + input_amount: U256, + output_amount: U256, } #[serde_as] @@ -318,8 +308,7 @@ struct LiquidityInteraction { struct CustomInteraction { internalize: bool, target: eth::H160, - #[serde_as(as = "serialize::U256")] - value: eth::U256, + value: U256, #[serde_as(as = "serialize::Hex")] call_data: Vec, allowances: Vec, @@ -327,23 +316,19 @@ struct CustomInteraction { outputs: Vec, } -#[serde_as] #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase", deny_unknown_fields)] struct Asset { token: eth::H160, - #[serde_as(as = "serialize::U256")] - amount: eth::U256, + amount: U256, } -#[serde_as] #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase", deny_unknown_fields)] struct Allowance { token: eth::H160, spender: eth::H160, - #[serde_as(as = "serialize::U256")] - amount: eth::U256, + amount: U256, } #[derive(Debug, Default, Deserialize)] @@ -372,14 +357,14 @@ enum SigningScheme { Eip1271, } -#[serde_as] #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase", deny_unknown_fields, tag = "kind")] pub enum Score { Solver { - #[serde_as(as = "serialize::U256")] - score: eth::U256, + score: U256, }, #[serde(rename_all = "camelCase")] - RiskAdjusted { success_probability: f64 }, + RiskAdjusted { + success_probability: f64, + }, } diff --git a/crates/driver/src/tests/setup/mod.rs b/crates/driver/src/tests/setup/mod.rs index ac97b81a7d..681abd001b 100644 --- a/crates/driver/src/tests/setup/mod.rs +++ b/crates/driver/src/tests/setup/mod.rs @@ -23,14 +23,14 @@ use { }, setup::blockchain::Blockchain, }, - util::{self, serialize}, + util::{self}, }, bigdecimal::FromPrimitive, ethcontract::BlockId, futures::future::join_all, hyper::StatusCode, + number::U256, secp256k1::SecretKey, - serde_with::serde_as, std::{ collections::{HashMap, HashSet}, path::PathBuf, @@ -59,16 +59,16 @@ pub enum Partial { }, } -#[serde_as] #[derive(Debug, Clone, serde::Serialize)] #[serde(rename_all = "camelCase", tag = "kind")] pub enum Score { Solver { - #[serde_as(as = "serialize::U256")] - score: eth::U256, + score: U256, }, #[serde(rename_all = "camelCase")] - RiskAdjusted { success_probability: f64 }, + RiskAdjusted { + success_probability: f64, + }, } impl Default for Score { diff --git a/crates/driver/src/util/serialize/mod.rs b/crates/driver/src/util/serialize/mod.rs index 71ee479979..3a51113212 100644 --- a/crates/driver/src/util/serialize/mod.rs +++ b/crates/driver/src/util/serialize/mod.rs @@ -1,6 +1,5 @@ //! Serialization utilities for use with [`serde_with::serde_as`] macros. mod hex; -mod u256; -pub use {self::hex::Hex, u256::U256}; +pub use self::hex::Hex; diff --git a/crates/e2e/tests/e2e/app_data.rs b/crates/e2e/tests/e2e/app_data.rs index e631a4935b..0d6bbf6e51 100644 --- a/crates/e2e/tests/e2e/app_data.rs +++ b/crates/e2e/tests/e2e/app_data.rs @@ -40,10 +40,10 @@ async fn app_data(web3: Web3) { let order = OrderCreation { app_data, sell_token: token_a.address(), - sell_amount: to_wei(2), - fee_amount: to_wei(1), + sell_amount: to_wei(2).into(), + fee_amount: to_wei(1).into(), buy_token: token_b.address(), - buy_amount: to_wei(1), + buy_amount: to_wei(1).into(), valid_to, kind: OrderKind::Sell, ..Default::default() diff --git a/crates/e2e/tests/e2e/app_data_signer.rs b/crates/e2e/tests/e2e/app_data_signer.rs index 7983eac22e..e1b61b78ff 100644 --- a/crates/e2e/tests/e2e/app_data_signer.rs +++ b/crates/e2e/tests/e2e/app_data_signer.rs @@ -43,10 +43,10 @@ async fn order_creation_checks_metadata_signer(web3: Web3) { let order = OrderCreation { app_data, sell_token: token_a.address(), - sell_amount: to_wei(2), - fee_amount: to_wei(1), + sell_amount: to_wei(2).into(), + fee_amount: to_wei(1).into(), buy_token: token_b.address(), - buy_amount: to_wei(1), + buy_amount: to_wei(1).into(), valid_to, kind: OrderKind::Sell, ..Default::default() diff --git a/crates/e2e/tests/e2e/buffers.rs b/crates/e2e/tests/e2e/buffers.rs index f9b044c4cf..0f71b7db1c 100644 --- a/crates/e2e/tests/e2e/buffers.rs +++ b/crates/e2e/tests/e2e/buffers.rs @@ -76,10 +76,10 @@ async fn onchain_settlement_without_liquidity(web3: Web3) { // Place Order let order = OrderCreation { sell_token: token_a.address(), - sell_amount: to_wei(9), - fee_amount: to_wei(1), + sell_amount: to_wei(9).into(), + fee_amount: to_wei(1).into(), buy_token: token_b.address(), - buy_amount: to_wei(5), + buy_amount: to_wei(5).into(), valid_to: model::time::now_in_epoch_seconds() + 300, kind: OrderKind::Buy, ..Default::default() @@ -92,8 +92,9 @@ async fn onchain_settlement_without_liquidity(web3: Web3) { services.create_order(&order).await.unwrap(); tracing::info!("waiting for first trade"); - let trade_happened = - || async { token_b.balance_of(trader.address()).call().await.unwrap() == order.buy_amount }; + let trade_happened = || async { + token_b.balance_of(trader.address()).call().await.unwrap() == *order.buy_amount + }; wait_for_condition(TIMEOUT, trade_happened).await.unwrap(); // Check that settlement buffers were traded. @@ -119,7 +120,7 @@ async fn onchain_settlement_without_liquidity(web3: Web3) { tracing::info!("waiting for second trade"); let trade_happened = || async { - token_b.balance_of(trader.address()).call().await.unwrap() == order.buy_amount * 2 + token_b.balance_of(trader.address()).call().await.unwrap() == *order.buy_amount * 2 }; wait_for_condition(TIMEOUT, trade_happened).await.unwrap(); } diff --git a/crates/e2e/tests/e2e/eth_integration.rs b/crates/e2e/tests/e2e/eth_integration.rs index 2d74fb6b6a..58e9c10a79 100644 --- a/crates/e2e/tests/e2e/eth_integration.rs +++ b/crates/e2e/tests/e2e/eth_integration.rs @@ -74,10 +74,10 @@ async fn eth_integration(web3: Web3) { let order_buy_eth_a = OrderCreation { kind: OrderKind::Buy, sell_token: token.address(), - sell_amount: to_wei(50), - fee_amount: to_wei(1), + sell_amount: to_wei(50).into(), + fee_amount: to_wei(1).into(), buy_token: BUY_ETH_ADDRESS, - buy_amount: to_wei(49), + buy_amount: to_wei(49).into(), valid_to: model::time::now_in_epoch_seconds() + 300, ..Default::default() } @@ -90,10 +90,10 @@ async fn eth_integration(web3: Web3) { let order_buy_eth_b = OrderCreation { kind: OrderKind::Sell, sell_token: token.address(), - sell_amount: to_wei(50), - fee_amount: to_wei(1), + sell_amount: to_wei(50).into(), + fee_amount: to_wei(1).into(), buy_token: BUY_ETH_ADDRESS, - buy_amount: to_wei(49), + buy_amount: to_wei(49).into(), valid_to: model::time::now_in_epoch_seconds() + 300, ..Default::default() } diff --git a/crates/e2e/tests/e2e/eth_safe.rs b/crates/e2e/tests/e2e/eth_safe.rs index 516cb2e9f7..eae1695bb0 100644 --- a/crates/e2e/tests/e2e/eth_safe.rs +++ b/crates/e2e/tests/e2e/eth_safe.rs @@ -51,9 +51,9 @@ async fn test(web3: Web3) { assert_eq!(balance, 0.into()); let order = OrderCreation { sell_token: token.address(), - sell_amount: to_wei(4), + sell_amount: to_wei(4).into(), buy_token: BUY_ETH_ADDRESS, - buy_amount: to_wei(3), + buy_amount: to_wei(3).into(), valid_to: model::time::now_in_epoch_seconds() + 300, partially_fillable: true, kind: OrderKind::Sell, diff --git a/crates/e2e/tests/e2e/ethflow.rs b/crates/e2e/tests/e2e/ethflow.rs index d1558c972b..95a1919b7a 100644 --- a/crates/e2e/tests/e2e/ethflow.rs +++ b/crates/e2e/tests/e2e/ethflow.rs @@ -135,7 +135,7 @@ async fn eth_flow_tx_zero_fee(web3: Web3) { .get_order(ðflow_order.uid(onchain.contracts()).await) .await .unwrap(); - order.metadata.executed_surplus_fee > U256::zero() + order.metadata.executed_surplus_fee > U256::zero().into() }; wait_for_condition(TIMEOUT, fee_charged).await.unwrap(); @@ -351,9 +351,15 @@ async fn test_submit_quote( // Ideally the fee would be nonzero, but this is not the case in the test // environment assert_ne!(response.quote.fee_amount, 0.into()); // Amount is reasonable (±10% from real price) - let approx_output: U256 = response.quote.sell_amount * DAI_PER_ETH; - assert!(response.quote.buy_amount.gt(&(approx_output * 9u64 / 10))); - assert!(response.quote.buy_amount.lt(&(approx_output * 11u64 / 10))); + let approx_output: U256 = *response.quote.sell_amount * DAI_PER_ETH; + assert!(response + .quote + .buy_amount + .gt(&(approx_output * 9u64 / 10).into())); + assert!(response + .quote + .buy_amount + .lt(&(approx_output * 11u64 / 10).into())); let OrderQuoteSide::Sell { sell_amount: @@ -365,7 +371,10 @@ async fn test_submit_quote( panic!("untested!"); }; - assert_eq!(response.quote.sell_amount, sell_amount_after_fees.get()); + assert_eq!( + response.quote.sell_amount, + sell_amount_after_fees.get().into() + ); response } @@ -606,10 +615,10 @@ impl ExtendedEthFlowOrder { ExtendedEthFlowOrder(EthflowOrder { buy_token: quote.buy_token, receiver: quote.receiver.expect("eth-flow order without receiver"), - sell_amount: quote.sell_amount, - buy_amount: quote.buy_amount, + sell_amount: *quote.sell_amount, + buy_amount: *quote.buy_amount, app_data: ethcontract::Bytes(quote.app_data.hash().0), - fee_amount: quote.fee_amount, + fee_amount: *quote.fee_amount, valid_to, // note: valid to in the quote is always unlimited partially_fillable: quote.partially_fillable, quote_id: quote_response.id.expect("No quote id"), diff --git a/crates/e2e/tests/e2e/hooks.rs b/crates/e2e/tests/e2e/hooks.rs index 3d9bd939dc..1a2226b721 100644 --- a/crates/e2e/tests/e2e/hooks.rs +++ b/crates/e2e/tests/e2e/hooks.rs @@ -73,10 +73,10 @@ async fn allowance(web3: Web3) { let order = OrderCreation { sell_token: cow.address(), - sell_amount: to_wei(4), - fee_amount: to_wei(1), + sell_amount: to_wei(4).into(), + fee_amount: to_wei(1).into(), buy_token: onchain.contracts().weth.address(), - buy_amount: to_wei(3), + buy_amount: to_wei(3).into(), valid_to: model::time::now_in_epoch_seconds() + 300, kind: OrderKind::Sell, app_data: OrderCreationAppData::Full { @@ -120,7 +120,7 @@ async fn allowance(web3: Web3) { .call() .await .unwrap(); - assert!(balance >= order.buy_amount); + assert!(balance >= *order.buy_amount); tracing::info!("Waiting for auction to be cleared."); let auction_is_empty = || async { services.get_auction().await.auction.orders.is_empty() }; @@ -244,10 +244,10 @@ async fn signature(web3: Web3) { let mut order = OrderCreation { from: Some(safe.address()), sell_token: token.address(), - sell_amount: to_wei(4), - fee_amount: to_wei(1), + sell_amount: to_wei(4).into(), + fee_amount: to_wei(1).into(), buy_token: onchain.contracts().weth.address(), - buy_amount: to_wei(3), + buy_amount: to_wei(3).into(), valid_to: model::time::now_in_epoch_seconds() + 300, kind: OrderKind::Sell, app_data: OrderCreationAppData::Full { @@ -295,7 +295,7 @@ async fn signature(web3: Web3) { .call() .await .unwrap(); - assert!(balance >= order.buy_amount); + assert!(balance >= *order.buy_amount); // Check Safe was deployed let code = web3.eth().code(safe.address(), None).await.unwrap(); @@ -341,9 +341,9 @@ async fn partial_fills(web3: Web3) { tracing::info!("Placing order"); let order = OrderCreation { sell_token: onchain.contracts().weth.address(), - sell_amount: to_wei(2), + sell_amount: to_wei(2).into(), buy_token: token.address(), - buy_amount: to_wei(1), + buy_amount: to_wei(1).into(), valid_to: model::time::now_in_epoch_seconds() + 300, kind: OrderKind::Sell, partially_fillable: true, diff --git a/crates/e2e/tests/e2e/limit_orders.rs b/crates/e2e/tests/e2e/limit_orders.rs index 98a7138018..bbd0f69022 100644 --- a/crates/e2e/tests/e2e/limit_orders.rs +++ b/crates/e2e/tests/e2e/limit_orders.rs @@ -134,9 +134,9 @@ async fn single_limit_order_test(web3: Web3) { let order = OrderCreation { sell_token: token_a.address(), - sell_amount: to_wei(10), + sell_amount: to_wei(10).into(), buy_token: token_b.address(), - buy_amount: to_wei(5), + buy_amount: to_wei(5).into(), valid_to: model::time::now_in_epoch_seconds() + 300, kind: OrderKind::Sell, ..Default::default() @@ -232,9 +232,9 @@ async fn two_limit_orders_test(web3: Web3) { let order_a = OrderCreation { sell_token: token_a.address(), - sell_amount: to_wei(10), + sell_amount: to_wei(10).into(), buy_token: token_b.address(), - buy_amount: to_wei(5), + buy_amount: to_wei(5).into(), valid_to: model::time::now_in_epoch_seconds() + 300, kind: OrderKind::Sell, ..Default::default() @@ -251,9 +251,9 @@ async fn two_limit_orders_test(web3: Web3) { let order_b = OrderCreation { sell_token: token_b.address(), - sell_amount: to_wei(5), + sell_amount: to_wei(5).into(), buy_token: token_a.address(), - buy_amount: to_wei(2), + buy_amount: to_wei(2).into(), valid_to: model::time::now_in_epoch_seconds() + 300, kind: OrderKind::Sell, ..Default::default() @@ -357,9 +357,9 @@ async fn mixed_limit_and_market_orders_test(web3: Web3) { let order_a = OrderCreation { sell_token: token_a.address(), - sell_amount: to_wei(10), + sell_amount: to_wei(10).into(), buy_token: token_b.address(), - buy_amount: to_wei(5), + buy_amount: to_wei(5).into(), valid_to: model::time::now_in_epoch_seconds() + 300, kind: OrderKind::Sell, ..Default::default() @@ -376,10 +376,10 @@ async fn mixed_limit_and_market_orders_test(web3: Web3) { let order_b = OrderCreation { sell_token: token_b.address(), - sell_amount: to_wei(5), - fee_amount: to_wei(1), + sell_amount: to_wei(5).into(), + fee_amount: to_wei(1).into(), buy_token: token_a.address(), - buy_amount: to_wei(2), + buy_amount: to_wei(2).into(), valid_to: model::time::now_in_epoch_seconds() + 300, kind: OrderKind::Sell, ..Default::default() @@ -453,9 +453,9 @@ async fn too_many_limit_orders_test(web3: Web3) { let order = OrderCreation { sell_token: token_a.address(), - sell_amount: to_wei(1), + sell_amount: to_wei(1).into(), buy_token: onchain.contracts().weth.address(), - buy_amount: to_wei(1), + buy_amount: to_wei(1).into(), valid_to: model::time::now_in_epoch_seconds() + 300, kind: OrderKind::Sell, ..Default::default() @@ -471,9 +471,9 @@ async fn too_many_limit_orders_test(web3: Web3) { // one limit order per user. let order = OrderCreation { sell_token: token_a.address(), - sell_amount: to_wei(1), + sell_amount: to_wei(1).into(), buy_token: onchain.contracts().weth.address(), - buy_amount: to_wei(2), + buy_amount: to_wei(2).into(), valid_to: model::time::now_in_epoch_seconds() + 300, kind: OrderKind::Sell, ..Default::default() @@ -532,9 +532,9 @@ async fn forked_mainnet_single_limit_order_test(web3: Web3) { let order = OrderCreation { sell_token: token_usdc.address(), - sell_amount: to_wei_with_exp(1000, 6), + sell_amount: to_wei_with_exp(1000, 6).into(), buy_token: token_usdt.address(), - buy_amount: to_wei_with_exp(500, 6), + buy_amount: to_wei_with_exp(500, 6).into(), valid_to: model::time::now_in_epoch_seconds() + 300, kind: OrderKind::Sell, ..Default::default() @@ -644,9 +644,9 @@ async fn forked_gnosis_single_limit_order_test(web3: Web3) { let order = OrderCreation { sell_token: token_usdc.address(), - sell_amount: to_wei_with_exp(1000, 6), + sell_amount: to_wei_with_exp(1000, 6).into(), buy_token: token_wxdai.address(), - buy_amount: to_wei(500), + buy_amount: to_wei(500).into(), valid_to: model::time::now_in_epoch_seconds() + 300, kind: OrderKind::Sell, ..Default::default() diff --git a/crates/e2e/tests/e2e/onchain_settlement.rs b/crates/e2e/tests/e2e/onchain_settlement.rs index ebb54e834a..9ccc1fab2a 100644 --- a/crates/e2e/tests/e2e/onchain_settlement.rs +++ b/crates/e2e/tests/e2e/onchain_settlement.rs @@ -98,10 +98,10 @@ async fn onchain_settlement(web3: Web3) { let order_a = OrderCreation { sell_token: token_a.address(), - sell_amount: to_wei(100), - fee_amount: to_wei(1), + sell_amount: to_wei(100).into(), + fee_amount: to_wei(1).into(), buy_token: token_b.address(), - buy_amount: to_wei(80), + buy_amount: to_wei(80).into(), valid_to: model::time::now_in_epoch_seconds() + 300, kind: OrderKind::Sell, ..Default::default() @@ -115,10 +115,10 @@ async fn onchain_settlement(web3: Web3) { let order_b = OrderCreation { sell_token: token_b.address(), - sell_amount: to_wei(50), - fee_amount: to_wei(1), + sell_amount: to_wei(50).into(), + fee_amount: to_wei(1).into(), buy_token: token_a.address(), - buy_amount: to_wei(40), + buy_amount: to_wei(40).into(), valid_to: model::time::now_in_epoch_seconds() + 300, kind: OrderKind::Sell, ..Default::default() @@ -152,9 +152,9 @@ async fn onchain_settlement(web3: Web3) { // Check matching let balance = token_b.balance_of(trader_a.address()).call().await.unwrap(); - assert!(balance >= order_a.buy_amount); + assert!(balance >= *order_a.buy_amount); let balance = token_a.balance_of(trader_b.address()).call().await.unwrap(); - assert!(balance >= order_b.buy_amount); + assert!(balance >= *order_b.buy_amount); tracing::info!("Waiting for auction to be cleared."); let auction_is_empty = || async { services.get_auction().await.auction.orders.is_empty() }; diff --git a/crates/e2e/tests/e2e/order_cancellation.rs b/crates/e2e/tests/e2e/order_cancellation.rs index 33a2ec28c7..ad0e59abfd 100644 --- a/crates/e2e/tests/e2e/order_cancellation.rs +++ b/crates/e2e/tests/e2e/order_cancellation.rs @@ -97,7 +97,7 @@ async fn order_cancellation(web3: Web3) { sell_amount: quote.sell_amount, fee_amount: quote.fee_amount, buy_token: quote.buy_token, - buy_amount: (quote.buy_amount * 99) / 100, + buy_amount: number::U256::from((*quote.buy_amount * 99) / 100), valid_to: quote.valid_to, app_data: quote.app_data, ..Default::default() diff --git a/crates/e2e/tests/e2e/partial_fill.rs b/crates/e2e/tests/e2e/partial_fill.rs index f9b6aa8613..7721be774f 100644 --- a/crates/e2e/tests/e2e/partial_fill.rs +++ b/crates/e2e/tests/e2e/partial_fill.rs @@ -49,9 +49,9 @@ async fn test(web3: Web3) { assert_eq!(balance, 0.into()); let order = OrderCreation { sell_token: onchain.contracts().weth.address(), - sell_amount: to_wei(4), + sell_amount: to_wei(4).into(), buy_token: token.address(), - buy_amount: to_wei(3), + buy_amount: to_wei(3).into(), valid_to: model::time::now_in_epoch_seconds() + 300, partially_fillable: true, kind: OrderKind::Sell, @@ -92,7 +92,7 @@ async fn test(web3: Web3) { let settlement_event_processed = || async { onchain.mint_block().await; let order = services.get_order(&uid).await.unwrap(); - order.metadata.executed_surplus_fee > U256::zero() + order.metadata.executed_surplus_fee > U256::zero().into() }; wait_for_condition(TIMEOUT, settlement_event_processed) .await diff --git a/crates/e2e/tests/e2e/partially_fillable_balance.rs b/crates/e2e/tests/e2e/partially_fillable_balance.rs index fd5c2a15a0..25fb10ebec 100644 --- a/crates/e2e/tests/e2e/partially_fillable_balance.rs +++ b/crates/e2e/tests/e2e/partially_fillable_balance.rs @@ -74,9 +74,9 @@ async fn test(web3: Web3) { let order_a = OrderCreation { sell_token: token_a.address(), - sell_amount: to_wei(100), + sell_amount: to_wei(100).into(), buy_token: token_b.address(), - buy_amount: to_wei(50), + buy_amount: to_wei(50).into(), valid_to: model::time::now_in_epoch_seconds() + 300, kind: OrderKind::Sell, partially_fillable: true, diff --git a/crates/e2e/tests/e2e/partially_fillable_pool.rs b/crates/e2e/tests/e2e/partially_fillable_pool.rs index 913fd14ad1..88780feee8 100644 --- a/crates/e2e/tests/e2e/partially_fillable_pool.rs +++ b/crates/e2e/tests/e2e/partially_fillable_pool.rs @@ -74,9 +74,9 @@ async fn test(web3: Web3) { let order_a = OrderCreation { sell_token: token_a.address(), - sell_amount: to_wei(500), + sell_amount: to_wei(500).into(), buy_token: token_b.address(), - buy_amount: to_wei(390), + buy_amount: to_wei(390).into(), valid_to: model::time::now_in_epoch_seconds() + 300, kind: OrderKind::Sell, partially_fillable: true, diff --git a/crates/e2e/tests/e2e/protocol_fee.rs b/crates/e2e/tests/e2e/protocol_fee.rs index fd461a505d..579ece5129 100644 --- a/crates/e2e/tests/e2e/protocol_fee.rs +++ b/crates/e2e/tests/e2e/protocol_fee.rs @@ -305,9 +305,9 @@ async fn execute_test( let order = OrderCreation { sell_token: token_gno.address(), - sell_amount: to_wei(10), + sell_amount: to_wei(10).into(), buy_token: token_dai.address(), - buy_amount: to_wei(5), + buy_amount: to_wei(5).into(), valid_to: model::time::now_in_epoch_seconds() + 300, kind: order_kind, ..Default::default() @@ -332,7 +332,7 @@ async fn execute_test( let metadata_updated = || async { onchain.mint_block().await; let order = services.get_order(&uid).await.unwrap(); - is_approximately_equal(order.metadata.executed_surplus_fee, expected_surplus_fee) + is_approximately_equal(*order.metadata.executed_surplus_fee, expected_surplus_fee) }; wait_for_condition(TIMEOUT, metadata_updated).await.unwrap(); diff --git a/crates/e2e/tests/e2e/smart_contract_orders.rs b/crates/e2e/tests/e2e/smart_contract_orders.rs index 30d000d192..d4f5b5a02b 100644 --- a/crates/e2e/tests/e2e/smart_contract_orders.rs +++ b/crates/e2e/tests/e2e/smart_contract_orders.rs @@ -37,10 +37,10 @@ async fn smart_contract_orders(web3: Web3) { let order_template = OrderCreation { kind: OrderKind::Sell, sell_token: token.address(), - sell_amount: to_wei(4), - fee_amount: to_wei(1), + sell_amount: to_wei(4).into(), + fee_amount: to_wei(1).into(), buy_token: onchain.contracts().weth.address(), - buy_amount: to_wei(3), + buy_amount: to_wei(3).into(), valid_to: model::time::now_in_epoch_seconds() + 300, ..Default::default() }; diff --git a/crates/e2e/tests/e2e/solver_competition.rs b/crates/e2e/tests/e2e/solver_competition.rs index 07c2de1b90..839885e875 100644 --- a/crates/e2e/tests/e2e/solver_competition.rs +++ b/crates/e2e/tests/e2e/solver_competition.rs @@ -73,10 +73,10 @@ async fn solver_competition(web3: Web3) { // Place Order let order = OrderCreation { sell_token: token_a.address(), - sell_amount: to_wei(9), - fee_amount: to_wei(1), + sell_amount: to_wei(9).into(), + fee_amount: to_wei(1).into(), buy_token: onchain.contracts().weth.address(), - buy_amount: to_wei(5), + buy_amount: to_wei(5).into(), valid_to: model::time::now_in_epoch_seconds() + 300, kind: OrderKind::Sell, ..Default::default() diff --git a/crates/e2e/tests/e2e/tracking_insufficient_funds.rs b/crates/e2e/tests/e2e/tracking_insufficient_funds.rs index 3b60db83c1..f59bf9abc9 100644 --- a/crates/e2e/tests/e2e/tracking_insufficient_funds.rs +++ b/crates/e2e/tests/e2e/tracking_insufficient_funds.rs @@ -59,10 +59,10 @@ async fn test(web3: Web3) { tracing::info!("Placing order"); let order_a = OrderCreation { sell_token: onchain.contracts().weth.address(), - sell_amount: to_wei(2), - fee_amount: to_wei(1), + sell_amount: to_wei(2).into(), + fee_amount: to_wei(1).into(), buy_token: token.address(), - buy_amount: to_wei(1), + buy_amount: to_wei(1).into(), valid_to: model::time::now_in_epoch_seconds() + 300, kind: OrderKind::Buy, ..Default::default() @@ -74,10 +74,10 @@ async fn test(web3: Web3) { ); let order_b = OrderCreation { sell_token: onchain.contracts().weth.address(), - sell_amount: to_wei(2), - fee_amount: to_wei(1), + sell_amount: to_wei(2).into(), + fee_amount: to_wei(1).into(), buy_token: token.address(), - buy_amount: to_wei(1), + buy_amount: to_wei(1).into(), valid_to: model::time::now_in_epoch_seconds() + 300, kind: OrderKind::Buy, ..Default::default() diff --git a/crates/e2e/tests/e2e/univ2.rs b/crates/e2e/tests/e2e/univ2.rs index b23c7e2084..e29a4f3d65 100644 --- a/crates/e2e/tests/e2e/univ2.rs +++ b/crates/e2e/tests/e2e/univ2.rs @@ -49,10 +49,10 @@ async fn test(web3: Web3) { assert_eq!(balance, 0.into()); let order = OrderCreation { sell_token: onchain.contracts().weth.address(), - sell_amount: to_wei(2), - fee_amount: to_wei(1), + sell_amount: to_wei(2).into(), + fee_amount: to_wei(1).into(), buy_token: token.address(), - buy_amount: to_wei(1), + buy_amount: to_wei(1).into(), valid_to: model::time::now_in_epoch_seconds() + 300, kind: OrderKind::Buy, ..Default::default() diff --git a/crates/e2e/tests/e2e/vault_balances.rs b/crates/e2e/tests/e2e/vault_balances.rs index 93d280ed6f..6e81dd3ec2 100644 --- a/crates/e2e/tests/e2e/vault_balances.rs +++ b/crates/e2e/tests/e2e/vault_balances.rs @@ -48,11 +48,11 @@ async fn vault_balances(web3: Web3) { let order = OrderCreation { kind: OrderKind::Sell, sell_token: token.address(), - sell_amount: to_wei(9), + sell_amount: to_wei(9).into(), sell_token_balance: SellTokenSource::External, - fee_amount: to_wei(1), + fee_amount: to_wei(1).into(), buy_token: onchain.contracts().weth.address(), - buy_amount: to_wei(8), + buy_amount: to_wei(8).into(), valid_to: model::time::now_in_epoch_seconds() + 300, ..Default::default() } diff --git a/crates/model/src/auction.rs b/crates/model/src/auction.rs index f8d1df0669..c44a2b9be3 100644 --- a/crates/model/src/auction.rs +++ b/crates/model/src/auction.rs @@ -2,10 +2,9 @@ use { crate::order::Order, - number::serialization::HexOrDecimalU256, - primitive_types::{H160, U256}, + number::U256, + primitive_types::H160, serde::{Deserialize, Serialize}, - serde_with::serde_as, std::collections::BTreeMap, }; @@ -26,7 +25,6 @@ pub struct AuctionWithId { } /// A batch auction. -#[serde_as] #[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)] #[serde(rename_all = "camelCase")] pub struct Auction { @@ -47,7 +45,6 @@ pub struct Auction { pub orders: Vec, /// The reference prices for all traded tokens in the auction. - #[serde_as(as = "BTreeMap<_, HexOrDecimalU256>")] pub prices: BTreeMap, } diff --git a/crates/model/src/interaction.rs b/crates/model/src/interaction.rs index 526cbb9106..b9bb4e41f4 100644 --- a/crates/model/src/interaction.rs +++ b/crates/model/src/interaction.rs @@ -1,17 +1,14 @@ use { - number::serialization::HexOrDecimalU256, - primitive_types::{H160, U256}, + number::U256, + primitive_types::H160, serde::{Deserialize, Serialize}, - serde_with::serde_as, std::fmt::{self, Debug, Formatter}, }; -#[serde_as] #[derive(Eq, PartialEq, Clone, Hash, Default, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct InteractionData { pub target: H160, - #[serde_as(as = "HexOrDecimalU256")] pub value: U256, #[serde(with = "crate::bytes_hex")] pub call_data: Vec, diff --git a/crates/model/src/order.rs b/crates/model/src/order.rs index 9646d9b270..db8c263e03 100644 --- a/crates/model/src/order.rs +++ b/crates/model/src/order.rs @@ -16,7 +16,6 @@ use { derivative::Derivative, hex_literal::hex, num::BigUint, - number::serialization::HexOrDecimalU256, primitive_types::{H160, H256, U256}, serde::{de, Deserialize, Deserializer, Serialize, Serializer}, serde_with::{serde_as, DisplayFromStr}, @@ -153,12 +152,12 @@ impl OrderBuilder { } pub fn with_sell_amount(mut self, sell_amount: U256) -> Self { - self.0.data.sell_amount = sell_amount; + self.0.data.sell_amount = sell_amount.into(); self } pub fn with_buy_amount(mut self, buy_amount: U256) -> Self { - self.0.data.buy_amount = buy_amount; + self.0.data.buy_amount = buy_amount.into(); self } @@ -178,12 +177,12 @@ impl OrderBuilder { } pub fn with_fee_amount(mut self, fee_amount: U256) -> Self { - self.0.data.fee_amount = fee_amount; + self.0.data.fee_amount = fee_amount.into(); self } pub fn with_full_fee_amount(mut self, full_fee_amount: U256) -> Self { - self.0.metadata.full_fee_amount = full_fee_amount; + self.0.metadata.full_fee_amount = full_fee_amount.into(); self } @@ -245,7 +244,7 @@ impl OrderBuilder { } pub fn with_solver_fee(mut self, fee: U256) -> Self { - self.0.metadata.solver_fee = fee; + self.0.metadata.solver_fee = fee.into(); self } @@ -263,7 +262,6 @@ impl OrderBuilder { /// /// These are the exact fields that get signed and verified by the settlement /// contract. -#[serde_as] #[derive(Clone, Copy, Debug, Default, Deserialize, Eq, Hash, PartialEq, Serialize)] #[serde(rename_all = "camelCase")] pub struct OrderData { @@ -271,10 +269,8 @@ pub struct OrderData { pub buy_token: H160, #[serde(default)] pub receiver: Option, - #[serde_as(as = "HexOrDecimalU256")] - pub sell_amount: U256, - #[serde_as(as = "HexOrDecimalU256")] - pub buy_amount: U256, + pub sell_amount: number::U256, + pub buy_amount: number::U256, pub valid_to: u32, pub app_data: AppDataHash, /// Fees that will be taken in terms of `sell_token`. @@ -284,8 +280,7 @@ pub struct OrderData { /// This is 0 for limit orders as their fee gets taken from the surplus. /// This is equal to `OrderMetadata::full_fee_amount` except for old orders /// where the subsidy was applied (at the time when we used the subsidies). - #[serde_as(as = "HexOrDecimalU256")] - pub fee_amount: U256, + pub fee_amount: number::U256, pub kind: OrderKind, pub partially_fillable: bool, #[serde(default)] @@ -344,8 +339,8 @@ impl OrderData { /// Checks if the order is a market order. pub fn within_market(&self, quote: QuoteAmounts) -> bool { - (self.sell_amount + self.fee_amount).full_mul(quote.buy) - >= (quote.sell + quote.fee).full_mul(self.buy_amount) + (*self.sell_amount + *self.fee_amount).full_mul(quote.buy) + >= (quote.sell + quote.fee).full_mul(self.buy_amount.into()) } } @@ -359,7 +354,6 @@ pub struct QuoteAmounts { } /// An order as provided to the POST order endpoint. -#[serde_as] #[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] #[serde(rename_all = "camelCase")] pub struct OrderCreation { @@ -368,13 +362,10 @@ pub struct OrderCreation { pub buy_token: H160, #[serde(default)] pub receiver: Option, - #[serde_as(as = "HexOrDecimalU256")] - pub sell_amount: U256, - #[serde_as(as = "HexOrDecimalU256")] - pub buy_amount: U256, + pub sell_amount: number::U256, + pub buy_amount: number::U256, pub valid_to: u32, - #[serde_as(as = "HexOrDecimalU256")] - pub fee_amount: U256, + pub fee_amount: number::U256, pub kind: OrderKind, pub partially_fillable: bool, #[serde(default)] @@ -734,20 +725,16 @@ pub struct OrderMetadata { pub owner: H160, pub uid: OrderUid, /// deprecated, always set to null - #[serde_as(as = "Option")] - pub available_balance: Option, + pub available_balance: Option, #[derivative(Debug(format_with = "debug_biguint_to_string"))] #[serde_as(as = "DisplayFromStr")] pub executed_buy_amount: BigUint, #[derivative(Debug(format_with = "debug_biguint_to_string"))] #[serde_as(as = "DisplayFromStr")] pub executed_sell_amount: BigUint, - #[serde_as(as = "HexOrDecimalU256")] - pub executed_sell_amount_before_fees: U256, - #[serde_as(as = "HexOrDecimalU256")] - pub executed_fee_amount: U256, - #[serde_as(as = "HexOrDecimalU256")] - pub executed_surplus_fee: U256, + pub executed_sell_amount_before_fees: number::U256, + pub executed_fee_amount: number::U256, + pub executed_surplus_fee: number::U256, pub invalidated: bool, pub status: OrderStatus, #[serde(flatten)] @@ -761,8 +748,7 @@ pub struct OrderMetadata { /// Does not take partial fill into account. /// /// [TO BE DEPRECATED] - #[serde_as(as = "HexOrDecimalU256")] - pub full_fee_amount: U256, + pub full_fee_amount: number::U256, /// The fee amount that should be used for objective value computations. /// /// This is different than the actual signed fee in that it @@ -772,8 +758,7 @@ pub struct OrderMetadata { /// Does not take partial fill into account. /// /// [TO BE DEPRECATED] - #[serde_as(as = "HexOrDecimalU256")] - pub solver_fee: U256, + pub solver_fee: number::U256, #[serde(default, skip_serializing_if = "Option::is_none")] pub ethflow_data: Option, #[serde(default, skip_serializing_if = "Option::is_none")] @@ -1135,8 +1120,8 @@ mod tests { invalidated: true, status: OrderStatus::Open, settlement_contract: H160::from_low_u64_be(2), - full_fee_amount: U256::MAX, - solver_fee: U256::MAX, + full_fee_amount: U256::MAX.into(), + solver_fee: U256::MAX.into(), full_app_data: Some("123".to_string()), ..Default::default() }, @@ -1150,7 +1135,7 @@ mod tests { app_data: AppDataHash(hex!( "6000000000000000000000000000000000000000000000000000000000000007" )), - fee_amount: U256::MAX, + fee_amount: U256::MAX.into(), kind: OrderKind::Buy, partially_fillable: false, sell_token_balance: SellTokenSource::External, diff --git a/crates/model/src/quote.rs b/crates/model/src/quote.rs index 451d8dd426..b9d3bd1719 100644 --- a/crates/model/src/quote.rs +++ b/crates/model/src/quote.rs @@ -7,8 +7,8 @@ use { }, anyhow::bail, chrono::{DateTime, Utc}, - number::{nonzero::U256 as NonZeroU256, serialization::HexOrDecimalU256}, - primitive_types::{H160, U256}, + number::nonzero::U256 as NonZeroU256, + primitive_types::H160, serde::{de, ser::SerializeStruct as _, Deserialize, Deserializer, Serialize, Serializer}, serde_with::serde_as, }; @@ -268,22 +268,18 @@ pub enum SellAmount { } /// The quoted order by the service. -#[serde_as] #[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct OrderQuote { pub sell_token: H160, pub buy_token: H160, pub receiver: Option, - #[serde_as(as = "HexOrDecimalU256")] - pub sell_amount: U256, - #[serde_as(as = "HexOrDecimalU256")] - pub buy_amount: U256, + pub sell_amount: number::U256, + pub buy_amount: number::U256, pub valid_to: u32, #[serde(flatten)] pub app_data: OrderCreationAppData, - #[serde_as(as = "HexOrDecimalU256")] - pub fee_amount: U256, + pub fee_amount: number::U256, pub kind: OrderKind, pub partially_fillable: bool, pub sell_token_balance: SellTokenSource, diff --git a/crates/model/src/solver_competition.rs b/crates/model/src/solver_competition.rs index 0147871a1e..c879feeb69 100644 --- a/crates/model/src/solver_competition.rs +++ b/crates/model/src/solver_competition.rs @@ -1,7 +1,6 @@ use { crate::{auction::AuctionId, bytes_hex::BytesHex, order::OrderUid}, derivative::Derivative, - number::serialization::HexOrDecimalU256, primitive_types::{H160, H256, U256}, serde::{Deserialize, Serialize}, serde_with::serde_as, @@ -30,13 +29,11 @@ pub struct SolverCompetitionAPI { pub common: SolverCompetitionDB, } -#[serde_as] #[derive(Clone, Debug, Default, Deserialize, Serialize, Eq, PartialEq)] #[serde(rename_all = "camelCase")] pub struct CompetitionAuction { pub orders: Vec, - #[serde_as(as = "BTreeMap<_, HexOrDecimalU256>")] - pub prices: BTreeMap, + pub prices: BTreeMap, } #[serde_as] @@ -51,8 +48,7 @@ pub struct SolverSettlement { pub score: Option, #[serde(default)] pub ranking: usize, - #[serde_as(as = "BTreeMap<_, HexOrDecimalU256>")] - pub clearing_prices: BTreeMap, + pub clearing_prices: BTreeMap, pub orders: Vec, #[serde(skip_serializing_if = "Option::is_none")] #[serde_as(as = "Option")] @@ -64,25 +60,24 @@ pub struct SolverSettlement { pub uninternalized_call_data: Option>, } -#[serde_as] #[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq)] pub enum Score { /// The score is provided by the solver. #[serde(rename = "score")] - Solver(#[serde_as(as = "HexOrDecimalU256")] U256), + Solver(number::U256), /// The score is calculated by the protocol (and equal to the objective /// function). #[serde(rename = "scoreProtocol")] - Protocol(#[serde_as(as = "HexOrDecimalU256")] U256), + Protocol(number::U256), /// The score is calculated by the protocol and success_probability provided /// by solver is taken into account #[serde(rename = "scoreProtocolWithSolverRisk")] - ProtocolWithSolverRisk(#[serde_as(as = "HexOrDecimalU256")] U256), + ProtocolWithSolverRisk(number::U256), /// The score is calculated by the protocol, by applying a discount to the /// `Self::Protocol` value. /// [DEPRECATED] Kept to not brake the solver competition API. #[serde(rename = "scoreDiscounted")] - Discounted(#[serde_as(as = "HexOrDecimalU256")] U256), + Discounted(number::U256), } impl Default for Score { @@ -94,15 +89,14 @@ impl Default for Score { impl Score { pub fn score(&self) -> U256 { match self { - Self::Solver(score) => *score, - Self::Protocol(score) => *score, - Self::ProtocolWithSolverRisk(score) => *score, - Self::Discounted(score) => *score, + Self::Solver(score) => (*score).into(), + Self::Protocol(score) => (*score).into(), + Self::ProtocolWithSolverRisk(score) => (*score).into(), + Self::Discounted(score) => (*score).into(), } } } -#[serde_as] #[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq)] #[serde(untagged)] pub enum Order { @@ -110,17 +104,14 @@ pub enum Order { Colocated { id: OrderUid, /// The effective amount that left the user's wallet including all fees. - #[serde_as(as = "HexOrDecimalU256")] - sell_amount: U256, + sell_amount: number::U256, /// The effective amount the user received after all fees. - #[serde_as(as = "HexOrDecimalU256")] - buy_amount: U256, + buy_amount: number::U256, }, #[serde(rename_all = "camelCase")] Legacy { id: OrderUid, - #[serde_as(as = "HexOrDecimalU256")] - executed_amount: U256, + executed_amount: number::U256, }, } diff --git a/crates/number/Cargo.toml b/crates/number/Cargo.toml index b23587ca86..cf2119eae8 100644 --- a/crates/number/Cargo.toml +++ b/crates/number/Cargo.toml @@ -8,7 +8,9 @@ license = "MIT OR Apache-2.0" [dependencies] anyhow = { workspace = true } bigdecimal = { workspace = true } +derive_more = "0.99.0" num = { workspace = true } primitive-types = { workspace = true } serde_with = { workspace = true } serde = { workspace = true } +uint = "0.9.4" diff --git a/crates/number/src/lib.rs b/crates/number/src/lib.rs index 5d277018a1..c8c00067c9 100644 --- a/crates/number/src/lib.rs +++ b/crates/number/src/lib.rs @@ -1,3 +1,5 @@ pub mod conversions; pub mod nonzero; pub mod serialization; + +pub use serialization::U256; diff --git a/crates/number/src/nonzero.rs b/crates/number/src/nonzero.rs index 36408f3a58..dbeab2d45e 100644 --- a/crates/number/src/nonzero.rs +++ b/crates/number/src/nonzero.rs @@ -30,6 +30,14 @@ impl TryFrom for U256 { } } +impl TryFrom for U256 { + type Error = anyhow::Error; + + fn try_from(value: crate::U256) -> Result { + ZeroU256::from(value).try_into() + } +} + impl Serialize for U256 { fn serialize(&self, serializer: S) -> Result where diff --git a/crates/number/src/serialization.rs b/crates/number/src/serialization.rs index 3f57cffa11..1cb3228dcd 100644 --- a/crates/number/src/serialization.rs +++ b/crates/number/src/serialization.rs @@ -1,69 +1,165 @@ use { - primitive_types::U256, - serde::{de, Deserializer, Serializer}, - serde_with::{DeserializeAs, SerializeAs}, - std::fmt, + derive_more::{From, Into}, + primitive_types, + serde::{ + de::{self, Visitor}, + Deserialize, + Deserializer, + Serialize, + Serializer, + }, + serde_with::SerializeAs, + std::{ + cmp::Ordering, + fmt, + hash::{Hash, Hasher}, + ops::{Deref, DerefMut}, + }, + uint::FromDecStrErr, }; -pub struct HexOrDecimalU256; +/// Serialize [`U256`] as a decimal string a deserialize [`U256`] from a decimal +/// or a hex prefixed with 0x +#[derive(Debug, Clone, Copy, Default, From, Into, Eq)] +pub struct U256(primitive_types::U256); -impl<'de> DeserializeAs<'de, U256> for HexOrDecimalU256 { - fn deserialize_as(deserializer: D) -> Result +impl<'de> Deserialize<'de> for U256 { + fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { - deserialize(deserializer) + struct U256Visitor; + + impl<'de> Visitor<'de> for U256Visitor { + type Value = U256; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!( + formatter, + "a u256 encoded either as 0x hex prefixed or decimal encoded string" + ) + } + + fn visit_str(self, s: &str) -> Result + where + E: de::Error, + { + if s.trim().starts_with("0x") { + Ok(U256(primitive_types::U256::from_str_radix(s, 16).map_err( + |err| E::custom(format!("failed to decode {s:?} as hex u256: {err}")), + )?)) + } else { + Ok(U256(primitive_types::U256::from_dec_str(s).map_err( + |err| E::custom(format!("failed to decode {s:?} as decimal u256: {err}")), + )?)) + } + } + } + + deserializer.deserialize_str(U256Visitor) + } +} + +impl SerializeAs for U256 { + fn serialize_as( + source: &primitive_types::U256, + serializer: S, + ) -> Result { + serializer.serialize_str(&source.to_string()) } } -impl SerializeAs for HexOrDecimalU256 { - fn serialize_as(source: &U256, serializer: S) -> Result +impl Serialize for U256 { + fn serialize(&self, serializer: S) -> Result where S: Serializer, { - serialize(source, serializer) + U256::serialize_as(&self.0, serializer) + } +} + +impl U256 { + pub fn zero() -> Self { + Self(primitive_types::U256::zero()) + } + + pub fn from_dec_str(value: &str) -> Result { + Ok(Self(primitive_types::U256::from_dec_str(value)?)) } } -pub fn serialize(value: &U256, serializer: S) -> Result -where - S: Serializer, -{ - serializer.serialize_str(&value.to_string()) +impl PartialEq for U256 { + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } } -pub fn deserialize<'de, D>(deserializer: D) -> Result -where - D: Deserializer<'de>, -{ - struct Visitor {} - impl<'de> de::Visitor<'de> for Visitor { - type Value = U256; +impl PartialOrd for U256 { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!( - formatter, - "a u256 encoded either as 0x hex prefixed or decimal encoded string" - ) - } +impl Ord for U256 { + fn cmp(&self, other: &Self) -> Ordering { + self.0.cmp(&other.0) + } +} - fn visit_str(self, s: &str) -> Result - where - E: de::Error, - { - if s.trim().starts_with("0x") { - U256::from_str_radix(s, 16).map_err(|err| { - de::Error::custom(format!("failed to decode {s:?} as hex u256: {err}")) - }) - } else { - U256::from_dec_str(s).map_err(|err| { - de::Error::custom(format!("failed to decode {s:?} as decimal u256: {err}")) - }) - } - } +impl From for U256 { + fn from(value: u128) -> Self { + Self(primitive_types::U256::from(value)) } +} - deserializer.deserialize_str(Visitor {}) +impl From for U256 { + fn from(value: u64) -> Self { + Self(value.into()) + } +} + +impl From for U256 { + fn from(value: i32) -> Self { + Self(value.into()) + } +} + +impl From for U256 { + fn from(value: u32) -> Self { + Self(value.into()) + } +} + +impl From for U256 { + fn from(value: u8) -> Self { + Self(value.into()) + } +} + +impl From for U256 { + fn from(value: u16) -> Self { + Self(value.into()) + } +} + +impl Hash for U256 { + fn hash(&self, state: &mut H) { + self.0.hash(state); + } +} + +impl Deref for U256 { + type Target = primitive_types::U256; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for U256 { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } } #[cfg(test)] @@ -79,9 +175,9 @@ mod tests { #[test] fn test_deserialization() { let deserializer: StrDeserializer = "0x10".into_deserializer(); - assert_eq!(deserialize(deserializer), Ok(16.into())); + assert_eq!(U256::deserialize(deserializer), Ok(16.into())); let deserializer: StrDeserializer = "10".into_deserializer(); - assert_eq!(deserialize(deserializer), Ok(10.into())); + assert_eq!(U256::deserialize(deserializer), Ok(10.into())); } } diff --git a/crates/orderbook/src/database/orders.rs b/crates/orderbook/src/database/orders.rs index 4e8ebb0c67..03c0f1d0fb 100644 --- a/crates/orderbook/src/database/orders.rs +++ b/crates/orderbook/src/database/orders.rs @@ -442,23 +442,26 @@ fn full_order_into_model_order(order: FullOrder) -> Result { // order's fee and sell amounts, and thus can always fit in a `U256` // - as it is limited by the order format. executed_sell_amount_before_fees: big_decimal_to_u256(&(order.sum_sell - &order.sum_fee)) - .context( - "executed sell amount before fees does not fit in a u256", - )?, + .context("executed sell amount before fees does not fit in a u256")? + .into(), executed_fee_amount: big_decimal_to_u256(&order.sum_fee) - .context("executed fee amount is not a valid u256")?, + .context("executed fee amount is not a valid u256")? + .into(), executed_surplus_fee: big_decimal_to_u256(&order.executed_surplus_fee) - .context("executed surplus fee is not a valid u256")?, + .context("executed surplus fee is not a valid u256")? + .into(), invalidated: order.invalidated, status, is_liquidity_order: class == OrderClass::Liquidity, class, settlement_contract: H160(order.settlement_contract.0), full_fee_amount: big_decimal_to_u256(&order.full_fee_amount) - .context("full_fee_amount is not U256")?, + .context("full_fee_amount is not U256")? + .into(), // Initialize unscaled and scale later when required. solver_fee: big_decimal_to_u256(&order.full_fee_amount) - .context("solver_fee is not U256")?, + .context("solver_fee is not U256")? + .into(), ethflow_data, onchain_user, onchain_order_data, @@ -472,11 +475,17 @@ fn full_order_into_model_order(order: FullOrder) -> Result { sell_token: H160(order.sell_token.0), buy_token: H160(order.buy_token.0), receiver: order.receiver.map(|address| H160(address.0)), - sell_amount: big_decimal_to_u256(&order.sell_amount).context("sell_amount is not U256")?, - buy_amount: big_decimal_to_u256(&order.buy_amount).context("buy_amount is not U256")?, + sell_amount: big_decimal_to_u256(&order.sell_amount) + .context("sell_amount is not U256")? + .into(), + buy_amount: big_decimal_to_u256(&order.buy_amount) + .context("buy_amount is not U256")? + .into(), valid_to: order.valid_to.try_into().context("valid_to is not u32")?, app_data: AppDataHash(order.app_data.0), - fee_amount: big_decimal_to_u256(&order.fee_amount).context("fee_amount is not U256")?, + fee_amount: big_decimal_to_u256(&order.fee_amount) + .context("fee_amount is not U256")? + .into(), kind: order_kind_from(order.kind), partially_fillable: order.partially_fillable, sell_token_balance: sell_token_source_from(order.sell_token_balance), diff --git a/crates/orderbook/src/dto/auction.rs b/crates/orderbook/src/dto/auction.rs index c497314461..8d22537e1f 100644 --- a/crates/orderbook/src/dto/auction.rs +++ b/crates/orderbook/src/dto/auction.rs @@ -1,22 +1,19 @@ use { super::order::Order, - number::serialization::HexOrDecimalU256, - primitive_types::{H160, U256}, + primitive_types::H160, serde::{Deserialize, Serialize}, serde_with::serde_as, std::collections::BTreeMap, }; /// Replicates [`crate::model::Auction`]. -#[serde_as] #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Auction { pub block: u64, pub latest_settlement_block: u64, pub orders: Vec, - #[serde_as(as = "BTreeMap<_, HexOrDecimalU256>")] - pub prices: BTreeMap, + pub prices: BTreeMap, } pub type AuctionId = i64; diff --git a/crates/orderbook/src/dto/order.rs b/crates/orderbook/src/dto/order.rs index a50704125e..04e0383bbc 100644 --- a/crates/orderbook/src/dto/order.rs +++ b/crates/orderbook/src/dto/order.rs @@ -5,33 +5,27 @@ use { order::{BuyTokenDestination, OrderClass, OrderKind, OrderUid, SellTokenSource}, signature::Signature, }, - number::serialization::HexOrDecimalU256, - primitive_types::{H160, U256}, + primitive_types::H160, serde::{Deserialize, Serialize}, serde_with::serde_as, }; -#[serde_as] #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Order { pub uid: OrderUid, pub sell_token: H160, pub buy_token: H160, - #[serde_as(as = "HexOrDecimalU256")] - pub sell_amount: U256, - #[serde_as(as = "HexOrDecimalU256")] - pub buy_amount: U256, - #[serde_as(as = "HexOrDecimalU256")] - pub user_fee: U256, + pub sell_amount: number::U256, + pub buy_amount: number::U256, + pub user_fee: number::U256, pub protocol_fees: Vec, pub valid_to: u32, pub kind: OrderKind, pub receiver: Option, pub owner: H160, pub partially_fillable: bool, - #[serde_as(as = "HexOrDecimalU256")] - pub executed: U256, + pub executed: number::U256, pub pre_interactions: Vec, pub post_interactions: Vec, pub sell_token_balance: SellTokenSource, diff --git a/crates/orderbook/src/quoter.rs b/crates/orderbook/src/quoter.rs index c33c8f09b6..67576143de 100644 --- a/crates/orderbook/src/quoter.rs +++ b/crates/orderbook/src/quoter.rs @@ -113,8 +113,8 @@ impl QuoteHandler { sell_token: request.sell_token, buy_token: request.buy_token, receiver: request.receiver, - sell_amount: quote.sell_amount, - buy_amount: quote.buy_amount, + sell_amount: quote.sell_amount.into(), + buy_amount: quote.buy_amount.into(), valid_to, app_data: match &request.app_data { OrderCreationAppData::Full { full } => OrderCreationAppData::Both { @@ -123,7 +123,7 @@ impl QuoteHandler { }, app_data => app_data.clone(), }, - fee_amount: quote.fee_amount, + fee_amount: quote.fee_amount.into(), kind: quote.data.kind, partially_fillable: false, sell_token_balance: request.sell_token_balance, diff --git a/crates/shared/src/account_balances/simulation.rs b/crates/shared/src/account_balances/simulation.rs index 0571d10290..943fafe0f3 100644 --- a/crates/shared/src/account_balances/simulation.rs +++ b/crates/shared/src/account_balances/simulation.rs @@ -56,7 +56,7 @@ impl Balances { query .interactions .iter() - .map(|i| (i.target, i.value, Bytes(i.call_data.clone()))) + .map(|i| (i.target, i.value.into(), Bytes(i.call_data.clone()))) .collect(), ), ) diff --git a/crates/shared/src/balancer_sor_api.rs b/crates/shared/src/balancer_sor_api.rs index 02301c7312..214a48ab17 100644 --- a/crates/shared/src/balancer_sor_api.rs +++ b/crates/shared/src/balancer_sor_api.rs @@ -6,12 +6,10 @@ use { crate::price_estimation::PriceEstimationError, anyhow::{Context, Result}, - ethcontract::{H160, H256, U256}, + ethcontract::{H160, H256}, model::order::OrderKind, - number::serialization::HexOrDecimalU256, reqwest::{Client, IntoUrl, StatusCode, Url}, serde::{Deserialize, Serialize}, - serde_with::serde_as, }; /// Trait for mockable Balancer SOR API. @@ -82,7 +80,6 @@ impl BalancerSorApi for DefaultBalancerSorApi { } /// An SOR query. -#[serde_as] #[derive(Clone, Debug, Default, Eq, PartialEq, Serialize)] #[serde(rename_all = "camelCase")] pub struct Query { @@ -96,16 +93,13 @@ pub struct Query { /// /// For sell orders this is the exact amount of sell token to trade, for buy /// orders, this is the amount of buy tokens to buy. - #[serde_as(as = "HexOrDecimalU256")] - pub amount: U256, + pub amount: number::U256, /// The current gas price estimate used for determining how the trading /// route should be split. - #[serde_as(as = "HexOrDecimalU256")] - pub gas_price: U256, + pub gas_price: number::U256, } /// The swap route found by the Balancer SOR service. -#[serde_as] #[derive(Clone, Debug, Default, PartialEq, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Quote { @@ -116,13 +110,11 @@ pub struct Quote { /// The swapped token amount. /// /// In sell token for sell orders or buy token for buy orders. - #[serde_as(as = "HexOrDecimalU256")] - pub swap_amount: U256, + pub swap_amount: number::U256, /// The returned token amount. /// /// In buy token for sell orders or sell token for buy orders. - #[serde_as(as = "HexOrDecimalU256")] - pub return_amount: U256, + pub return_amount: number::U256, /// The input (sell) token. #[serde(with = "address_default_when_empty")] pub token_in: H160, @@ -132,7 +124,6 @@ pub struct Quote { } /// A swap included in a larger batched swap. -#[serde_as] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Swap { @@ -145,8 +136,7 @@ pub struct Swap { #[serde(with = "value_or_string")] pub asset_out_index: usize, /// The amount to swap. - #[serde_as(as = "HexOrDecimalU256")] - pub amount: U256, + pub amount: number::U256, /// Additional user data to pass to the pool. #[serde(with = "model::bytes_hex")] pub user_data: Vec, @@ -216,7 +206,7 @@ mod value_or_string { #[cfg(test)] mod tests { - use {super::*, hex_literal::hex, serde_json::json, std::env}; + use {super::*, hex_literal::hex, number::U256, serde_json::json, std::env}; #[test] fn serialize_query() { diff --git a/crates/shared/src/db_order_conversions.rs b/crates/shared/src/db_order_conversions.rs index 2efa5cee34..b37b61808a 100644 --- a/crates/shared/src/db_order_conversions.rs +++ b/crates/shared/src/db_order_conversions.rs @@ -85,20 +85,21 @@ pub fn full_order_into_model_order(order: database::orders::FullOrder) -> Result // order's fee and sell amounts, and thus can always fit in a `U256` // - as it is limited by the order format. executed_sell_amount_before_fees: big_decimal_to_u256(&(order.sum_sell - &order.sum_fee)) - .context( - "executed sell amount before fees does not fit in a u256", - )?, + .context("executed sell amount before fees does not fit in a u256")? + .into(), executed_fee_amount: big_decimal_to_u256(&order.sum_fee) - .context("executed fee amount is not a valid u256")?, + .context("executed fee amount is not a valid u256")? + .into(), executed_surplus_fee: big_decimal_to_u256(&order.executed_surplus_fee) - .context("executed surplus fee is not a valid u256")?, + .context("executed surplus fee is not a valid u256")? + .into(), invalidated: order.invalidated, status, is_liquidity_order: class == OrderClass::Liquidity, class, settlement_contract: H160(order.settlement_contract.0), - full_fee_amount, - solver_fee, + full_fee_amount: full_fee_amount.into(), + solver_fee: solver_fee.into(), ethflow_data, onchain_user, onchain_order_data, @@ -112,11 +113,15 @@ pub fn full_order_into_model_order(order: database::orders::FullOrder) -> Result sell_token: H160(order.sell_token.0), buy_token: H160(order.buy_token.0), receiver: order.receiver.map(|address| H160(address.0)), - sell_amount: big_decimal_to_u256(&order.sell_amount).context("sell_amount is not U256")?, - buy_amount: big_decimal_to_u256(&order.buy_amount).context("buy_amount is not U256")?, + sell_amount: big_decimal_to_u256(&order.sell_amount) + .context("sell_amount is not U256")? + .into(), + buy_amount: big_decimal_to_u256(&order.buy_amount) + .context("buy_amount is not U256")? + .into(), valid_to: order.valid_to.try_into().context("valid_to is not u32")?, app_data: AppDataHash(order.app_data.0), - fee_amount, + fee_amount: fee_amount.into(), kind: order_kind_from(order.kind), partially_fillable: order.partially_fillable, sell_token_balance: sell_token_source_from(order.sell_token_balance), @@ -149,7 +154,8 @@ pub fn extract_interactions( Ok(InteractionData { target: H160(interaction.0 .0), value: big_decimal_to_u256(&interaction.1) - .context("interaction value is not U256")?, + .context("interaction value is not U256")? + .into(), call_data: interaction.2.to_vec(), }) }) diff --git a/crates/shared/src/encoded_settlement.rs b/crates/shared/src/encoded_settlement.rs index a0646e843e..97ba22ac26 100644 --- a/crates/shared/src/encoded_settlement.rs +++ b/crates/shared/src/encoded_settlement.rs @@ -35,11 +35,11 @@ pub fn encode_trade( sell_token_index.into(), buy_token_index.into(), order.receiver.unwrap_or_else(H160::zero), - order.sell_amount, - order.buy_amount, + order.sell_amount.into(), + order.buy_amount.into(), order.valid_to, Bytes(order.app_data.0), - order.fee_amount, + order.fee_amount.into(), order_flags(order, signature), *executed_amount, Bytes(signature.encode_for_settlement(owner).to_vec()), diff --git a/crates/shared/src/http_solver/gas_model.rs b/crates/shared/src/http_solver/gas_model.rs index 3cd9bd52d4..4bdecbe081 100644 --- a/crates/shared/src/http_solver/gas_model.rs +++ b/crates/shared/src/http_solver/gas_model.rs @@ -12,7 +12,7 @@ pub struct GasModel { impl GasModel { pub fn cost_for_gas(&self, gas: U256) -> TokenAmount { TokenAmount { - amount: U256::from_f64_lossy(self.gas_price) * gas, + amount: (U256::from_f64_lossy(self.gas_price) * gas).into(), token: self.native_token, } } diff --git a/crates/shared/src/http_solver/model.rs b/crates/shared/src/http_solver/model.rs index de59281fd6..ecd7b35b3a 100644 --- a/crates/shared/src/http_solver/model.rs +++ b/crates/shared/src/http_solver/model.rs @@ -12,7 +12,6 @@ use { signature::Signature, }, num::BigRational, - number::serialization::HexOrDecimalU256, primitive_types::{H256, U256}, serde::{Deserialize, Deserializer, Serialize}, serde_json::Value, @@ -29,17 +28,14 @@ pub struct BatchAuctionModel { pub metadata: Option, } -#[serde_as] #[derive(Clone, Debug, Serialize)] pub struct OrderModel { #[serde(skip_serializing_if = "Option::is_none")] pub id: Option, pub sell_token: H160, pub buy_token: H160, - #[serde_as(as = "HexOrDecimalU256")] - pub sell_amount: U256, - #[serde_as(as = "HexOrDecimalU256")] - pub buy_amount: U256, + pub sell_amount: number::U256, + pub buy_amount: number::U256, pub allow_partial_fill: bool, pub is_sell_order: bool, /// Represents user_fee. Which is 0 for limit orders. @@ -83,18 +79,14 @@ pub enum AmmParameters { Concentrated(ConcentratedPoolParameters), } -#[serde_as] #[derive(Clone, Debug, Default, Serialize)] pub struct ConstantProductPoolParameters { - #[serde_as(as = "BTreeMap<_, HexOrDecimalU256>")] - pub reserves: BTreeMap, + pub reserves: BTreeMap, } -#[serde_as] #[derive(Clone, Debug, Serialize, Deserialize)] pub struct WeightedPoolTokenData { - #[serde_as(as = "HexOrDecimalU256")] - pub balance: U256, + pub balance: number::U256, #[serde(with = "ratio_as_decimal")] pub weight: BigRational, } @@ -104,13 +96,10 @@ pub struct WeightedProductPoolParameters { pub reserves: BTreeMap, } -#[serde_as] #[derive(Clone, Debug, Serialize)] pub struct StablePoolParameters { - #[serde_as(as = "BTreeMap<_, HexOrDecimalU256>")] - pub reserves: BTreeMap, - #[serde_as(as = "BTreeMap<_, HexOrDecimalU256>")] - pub scaling_rates: BTreeMap, + pub reserves: BTreeMap, + pub scaling_rates: BTreeMap, #[serde(with = "ratio_as_decimal")] pub amplification_parameter: BigRational, } @@ -121,52 +110,44 @@ pub struct ConcentratedPoolParameters { pub pool: PoolInfo, } -#[serde_as] #[derive(Clone, Debug, Default, Serialize)] pub struct TokenInfoModel { pub decimals: Option, pub alias: Option, pub external_price: Option, pub normalize_priority: Option, - #[serde_as(as = "Option")] - pub internal_buffer: Option, + pub internal_buffer: Option, /// Is token in the external list containing only safe tokens pub accepted_for_internalization: bool, } -#[serde_as] #[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] pub struct TokenAmount { - #[serde_as(as = "HexOrDecimalU256")] - pub amount: U256, + pub amount: number::U256, pub token: H160, } impl TokenAmount { pub fn new>(token: H160, amount: T) -> Self { Self { - amount: amount.into(), + amount: amount.into().into(), token, } } } -#[serde_as] #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] pub struct ApprovalModel { pub token: H160, pub spender: H160, - #[serde_as(as = "HexOrDecimalU256")] - pub amount: U256, + pub amount: number::U256, } -#[serde_as] #[derive(Clone, Derivative, Default, Deserialize, Eq, PartialEq, Serialize)] #[derivative(Debug)] pub struct InteractionData { pub target: H160, - #[serde_as(as = "HexOrDecimalU256")] - pub value: U256, + pub value: number::U256, #[derivative(Debug(format_with = "crate::debug_bytes"))] #[serde(with = "model::bytes_hex")] pub call_data: Vec, @@ -189,27 +170,26 @@ pub struct InteractionData { impl Interaction for InteractionData { fn encode(&self) -> Vec { - vec![(self.target, self.value, Bytes(self.call_data.clone()))] + vec![( + self.target, + self.value.into(), + Bytes(self.call_data.clone()), + )] } } -#[serde_as] #[derive(Copy, Clone, Debug, Deserialize, PartialEq, Serialize)] #[serde(untagged)] pub enum Score { /// The score value is provided as is from solver. /// Success probability is not incorporated into this value. - Solver { - #[serde_as(as = "HexOrDecimalU256")] - score: U256, - }, + Solver { score: number::U256 }, /// This option is used to indicate that the solver did not provide a score. /// Instead, the score should be computed by the protocol given the success /// probability and optionally the amount of gas this settlement will take. RiskAdjusted { success_probability: f64, - #[serde_as(as = "Option")] - gas_amount: Option, + gas_amount: Option, }, } @@ -237,7 +217,7 @@ impl Score { match (self, other) { (Score::Solver { score: left }, Score::Solver { score: right }) => { Some(Score::Solver { - score: left.checked_add(*right)?, + score: left.checked_add(**right)?.into(), }) } ( @@ -252,14 +232,14 @@ impl Score { ) => Some(Score::RiskAdjusted { success_probability: p_left * p_right, gas_amount: gas_left - .and_then(|left| gas_right.and_then(|right| left.checked_add(right))), + .and_then(|left| gas_right.and_then(|right| left.checked_add(*right))) + .map(Into::into), }), _ => None, } } } -#[serde_as] #[derive(Clone, Debug, Default, Deserialize, Serialize)] pub struct SettledBatchAuctionModel { pub orders: HashMap, @@ -268,8 +248,7 @@ pub struct SettledBatchAuctionModel { #[serde(default)] pub amms: HashMap, pub ref_token: Option, - #[serde_as(as = "HashMap<_, HexOrDecimalU256>")] - pub prices: HashMap, + pub prices: HashMap, #[serde(default)] pub approvals: Vec, #[serde(default)] @@ -315,15 +294,11 @@ pub struct SettledBatchAuctionMetadataModel { pub result: Option, } -#[serde_as] #[derive(Clone, Debug, Deserialize, Serialize)] pub struct ExecutedOrderModel { - #[serde_as(as = "HexOrDecimalU256")] - pub exec_sell_amount: U256, - #[serde_as(as = "HexOrDecimalU256")] - pub exec_buy_amount: U256, - #[serde_as(as = "Option")] - pub exec_fee_amount: Option, + pub exec_sell_amount: number::U256, + pub exec_buy_amount: number::U256, + pub exec_fee_amount: Option, pub cost: Option, pub fee: Option, // Orders which need to be executed in a specific order have an `exec_plan` (e.g. 0x limit @@ -331,14 +306,11 @@ pub struct ExecutedOrderModel { pub exec_plan: Option, } -#[serde_as] #[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)] pub struct ExecutedLiquidityOrderModel { pub order: NativeLiquidityOrder, - #[serde_as(as = "HexOrDecimalU256")] - pub exec_sell_amount: U256, - #[serde_as(as = "HexOrDecimalU256")] - pub exec_buy_amount: U256, + pub exec_sell_amount: number::U256, + pub exec_buy_amount: number::U256, } #[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)] @@ -358,22 +330,19 @@ pub struct UpdatedAmmModel { pub cost: Option, } -#[serde_as] #[derive(Clone, Debug, Default, Deserialize, Serialize)] pub struct ExecutedAmmModel { pub sell_token: H160, pub buy_token: H160, - #[serde_as(as = "HexOrDecimalU256")] - pub exec_sell_amount: U256, - #[serde_as(as = "HexOrDecimalU256")] - pub exec_buy_amount: U256, + pub exec_sell_amount: number::U256, + pub exec_buy_amount: number::U256, pub exec_plan: ExecutionPlan, } impl UpdatedAmmModel { /// Returns true there is at least one non-zero update. pub fn is_non_trivial(&self) -> bool { - let zero = &U256::zero(); + let zero = &number::U256::zero(); let has_non_trivial_execution = self .execution .iter() @@ -423,7 +392,6 @@ pub enum AuctionResult { type SimulationSucceededAtLeastOnce = bool; -#[serde_as] #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] pub enum SolverRejectionReason { @@ -465,10 +433,8 @@ pub enum SolverRejectionReason { /// Objective value is too low. #[serde(rename_all = "camelCase")] ObjectiveValueNonPositive { - #[serde_as(as = "HexOrDecimalU256")] - quality: U256, - #[serde_as(as = "HexOrDecimalU256")] - gas_cost: U256, + quality: number::U256, + gas_cost: number::U256, }, /// Success probability is out of the allowed range [0, 1] @@ -478,10 +444,8 @@ pub enum SolverRejectionReason { /// fees). #[serde(rename_all = "camelCase")] ScoreHigherThanQuality { - #[serde_as(as = "HexOrDecimalU256")] - score: U256, - #[serde_as(as = "HexOrDecimalU256")] - quality: U256, + score: number::U256, + quality: number::U256, }, /// Solver balance too low to cover the execution costs. @@ -516,7 +480,6 @@ pub struct TransactionWithError { } /// Transaction data used for simulation of the settlement -#[serde_as] #[derive(Clone, Serialize, Derivative)] #[derivative(Debug)] #[serde(rename_all = "camelCase")] @@ -542,10 +505,8 @@ pub struct SimulatedTransaction { pub data: Vec, /// Gas price can influence the success of simulation if sender balance /// is not enough for paying the costs of executing the transaction onchain - #[serde_as(as = "HexOrDecimalU256")] - pub max_fee_per_gas: U256, - #[serde_as(as = "HexOrDecimalU256")] - pub max_priority_fee_per_gas: U256, + pub max_fee_per_gas: number::U256, + pub max_priority_fee_per_gas: number::U256, } /// Whether or not internalizable interactions should be encoded as calldata @@ -591,12 +552,12 @@ mod tests { .is_non_trivial()); let execution_with_sell = ExecutedAmmModel { - exec_sell_amount: U256::one(), + exec_sell_amount: U256::one().into(), ..Default::default() }; let execution_with_buy = ExecutedAmmModel { - exec_buy_amount: U256::one(), + exec_buy_amount: U256::one().into(), ..Default::default() }; @@ -629,16 +590,16 @@ mod tests { id: Some(OrderUid::default()), sell_token, buy_token, - sell_amount: U256::from(1), - buy_amount: U256::from(2), + sell_amount: U256::from(1).into(), + buy_amount: U256::from(2).into(), allow_partial_fill: false, is_sell_order: true, fee: TokenAmount { - amount: U256::from(2), + amount: U256::from(2).into(), token: sell_token, }, cost: TokenAmount { - amount: U256::from(1), + amount: U256::from(1).into(), token: native_token, }, is_liquidity_order: false, @@ -650,13 +611,13 @@ mod tests { let constant_product_pool_model = AmmModel { parameters: AmmParameters::ConstantProduct(ConstantProductPoolParameters { reserves: btreemap! { - buy_token => U256::from(100), - sell_token => U256::from(200), + buy_token => U256::from(100).into(), + sell_token => U256::from(200).into(), }, }), fee: BigRational::new(3.into(), 1000.into()), cost: TokenAmount { - amount: U256::from(3), + amount: U256::from(3).into(), token: native_token, }, mandatory: false, @@ -666,18 +627,18 @@ mod tests { parameters: AmmParameters::WeightedProduct(WeightedProductPoolParameters { reserves: btreemap! { sell_token => WeightedPoolTokenData { - balance: U256::from(808), + balance: U256::from(808).into(), weight: BigRational::new(2.into(), 10.into()), }, buy_token => WeightedPoolTokenData { - balance: U256::from(64), + balance: U256::from(64).into(), weight: BigRational::new(8.into(), 10.into()), } }, }), fee: BigRational::new(2.into(), 1000.into()), cost: TokenAmount { - amount: U256::from(2), + amount: U256::from(2).into(), token: native_token, }, mandatory: true, @@ -686,18 +647,18 @@ mod tests { let stable_pool_model = AmmModel { parameters: AmmParameters::Stable(StablePoolParameters { reserves: btreemap! { - sell_token => U256::from(1000), - buy_token => U256::from(1_001_000_000), + sell_token => U256::from(1000).into(), + buy_token => U256::from(1_001_000_000).into(), }, scaling_rates: btreemap! { - sell_token => U256::from(1), - buy_token => U256::from(1_000_000), + sell_token => U256::from(1).into(), + buy_token => U256::from(1_000_000).into(), }, amplification_parameter: BigRational::new(1337.into(), 100.into()), }), fee: BigRational::new(3.into(), 1000.into()), cost: TokenAmount { - amount: U256::from(3), + amount: U256::from(3).into(), token: native_token, }, mandatory: true, @@ -722,7 +683,7 @@ mod tests { }), fee: BigRational::new(3.into(), 1000.into()), cost: TokenAmount { - amount: U256::from(3), + amount: U256::from(3).into(), token: native_token, }, mandatory: false, @@ -735,7 +696,7 @@ mod tests { alias: Some("CAT".to_string()), external_price: Some(1.2), normalize_priority: Some(1), - internal_buffer: Some(U256::from(1337)), + internal_buffer: Some(U256::from(1337).into()), accepted_for_internalization: true, }, sell_token => TokenInfoModel { @@ -743,7 +704,7 @@ mod tests { alias: Some("DOG".to_string()), external_price: Some(2345.0), normalize_priority: Some(0), - internal_buffer: Some(U256::from(42)), + internal_buffer: Some(U256::from(42).into()), accepted_for_internalization: true, } }, @@ -1192,8 +1153,8 @@ mod tests { to: H160::from_str("0x9008D19f58AAbD9eD0D60971565AA8510560ab41").unwrap(), data: vec![19, 250, 73], internalization: InternalizationStrategy::SkipInternalizableInteraction, - max_fee_per_gas: U256::from(100), - max_priority_fee_per_gas: U256::from(10), + max_fee_per_gas: U256::from(100).into(), + max_priority_fee_per_gas: U256::from(10).into(), }) .unwrap(), json!({ @@ -1247,8 +1208,8 @@ mod tests { fn serialize_objective_value_non_positive_colocated() { let auction_result = AuctionResult::Rejected(SolverRejectionReason::ObjectiveValueNonPositive { - quality: U256::from(1), - gas_cost: U256::from(2), + quality: U256::from(1).into(), + gas_cost: U256::from(2).into(), }); assert_eq!( @@ -1280,8 +1241,8 @@ mod tests { fn serialize_score_higher_than_quality() { let auction_result = AuctionResult::Rejected(SolverRejectionReason::ScoreHigherThanQuality { - score: U256::from(1), - quality: U256::from(2), + score: U256::from(1).into(), + quality: U256::from(2).into(), }); assert_eq!( diff --git a/crates/shared/src/interaction.rs b/crates/shared/src/interaction.rs index ef5735fc40..f476780f55 100644 --- a/crates/shared/src/interaction.rs +++ b/crates/shared/src/interaction.rs @@ -33,7 +33,7 @@ impl Interaction for EncodedInteraction { impl Interaction for InteractionData { fn encode(&self) -> Vec { - vec![(self.target, self.value, Bytes(self.call_data.clone()))] + vec![(self.target, *self.value, Bytes(self.call_data.clone()))] } } @@ -43,7 +43,7 @@ where { InteractionData { target: tx.to.unwrap(), - value: tx.value.unwrap_or_default(), + value: tx.value.unwrap_or_default().into(), call_data: tx.data.unwrap().0, } } diff --git a/crates/shared/src/oneinch_api.rs b/crates/shared/src/oneinch_api.rs index ae40a7d2f8..4a07ae956c 100644 --- a/crates/shared/src/oneinch_api.rs +++ b/crates/shared/src/oneinch_api.rs @@ -11,10 +11,8 @@ use { derivative::Derivative, ethcontract::{Bytes, H160, U256}, ethrpc::current_block::CurrentBlockStream, - number::serialization::HexOrDecimalU256, reqwest::{Client, IntoUrl, Url}, serde::{de::DeserializeOwned, Deserialize}, - serde_with::serde_as, std::{ fmt::{self, Display, Formatter}, future::Future, @@ -174,16 +172,13 @@ impl SellOrderQuoteQuery { } /// A sell order quote from 1Inch. -#[serde_as] #[derive(Clone, Debug, Deserialize, PartialEq, Default)] #[serde(rename_all = "camelCase")] pub struct SellOrderQuote { pub from_token: Token, pub to_token: Token, - #[serde_as(as = "HexOrDecimalU256")] - pub from_token_amount: U256, - #[serde_as(as = "HexOrDecimalU256")] - pub to_token_amount: U256, + pub from_token_amount: number::U256, + pub to_token_amount: number::U256, pub protocols: Vec>>, pub estimated_gas: u64, } @@ -387,23 +382,20 @@ pub struct RestError { pub description: String, } -#[serde_as] #[derive(Clone, Debug, Deserialize, PartialEq, Default)] #[serde(rename_all = "camelCase")] pub struct Swap { pub from_token: Token, pub to_token: Token, - #[serde_as(as = "HexOrDecimalU256")] - pub from_token_amount: U256, - #[serde_as(as = "HexOrDecimalU256")] - pub to_token_amount: U256, + pub from_token_amount: number::U256, + pub to_token_amount: number::U256, pub protocols: Vec>>, pub tx: Transaction, } impl Interaction for Swap { fn encode(&self) -> Vec { - vec![(self.tx.to, self.tx.value, Bytes(self.tx.data.clone()))] + vec![(self.tx.to, *self.tx.value, Bytes(self.tx.data.clone()))] } } @@ -427,7 +419,6 @@ pub struct ProtocolRouteSegment { } /// Swap transaction generated by the 1Inch API. -#[serde_as] #[derive(Clone, Deserialize, Eq, PartialEq, Default, Derivative)] #[derivative(Debug)] #[serde(rename_all = "camelCase")] @@ -437,10 +428,8 @@ pub struct Transaction { #[derivative(Debug(format_with = "crate::debug_bytes"))] #[serde(with = "model::bytes_hex")] pub data: Vec, - #[serde_as(as = "HexOrDecimalU256")] - pub value: U256, - #[serde_as(as = "HexOrDecimalU256")] - pub gas_price: U256, + pub value: number::U256, + pub gas_price: number::U256, pub gas: u64, } diff --git a/crates/shared/src/order_validation.rs b/crates/shared/src/order_validation.rs index 28c75582f9..3d8957e78d 100644 --- a/crates/shared/src/order_validation.rs +++ b/crates/shared/src/order_validation.rs @@ -370,7 +370,7 @@ impl OrderValidator { } else { vec![InteractionData { target: self.hooks.address(), - value: U256::zero(), + value: U256::zero().into(), call_data: self .hooks .execute( @@ -570,9 +570,9 @@ impl OrderValidating for OrderValidator { let quote_parameters = QuoteSearchParameters { sell_token: data.sell_token, buy_token: data.buy_token, - sell_amount: data.sell_amount, - buy_amount: data.buy_amount, - fee_amount: data.fee_amount, + sell_amount: *data.sell_amount, + buy_amount: *data.buy_amount, + fee_amount: *data.fee_amount, kind: data.kind, signing_scheme: convert_signing_scheme_into_quote_signing_scheme( order.signature.scheme(), @@ -585,9 +585,13 @@ impl OrderValidating for OrderValidator { let quote = match class { OrderClass::Market => { let fee = Some(data.fee_amount); - let quote = - get_quote_and_check_fee(&*self.quoter, "e_parameters, order.quote_id, fee) - .await?; + let quote = get_quote_and_check_fee( + &*self.quoter, + "e_parameters, + order.quote_id, + fee.map(Into::into), + ) + .await?; Some(quote) } OrderClass::Limit => { @@ -660,9 +664,9 @@ impl OrderValidating for OrderValidator { (OrderClass::Market, Some(quote)) if is_order_outside_market_price( &Amounts { - sell: data.sell_amount, - buy: data.buy_amount, - fee: data.fee_amount, + sell: *data.sell_amount, + buy: *data.buy_amount, + fee: *data.fee_amount, }, &Amounts { sell: quote.sell_amount, @@ -775,7 +779,7 @@ fn minimum_balance(order: &OrderData) -> Option { if order.partially_fillable { return Some(1.into()); } - order.sell_amount.checked_add(order.fee_amount) + (*order.sell_amount).checked_add(*order.fee_amount) } /// Retrieves the quote for an order that is being created and verify that its @@ -924,14 +928,14 @@ mod tests { #[test] fn minimum_balance_() { let order = OrderData { - sell_amount: U256::MAX, - fee_amount: U256::from(1), + sell_amount: U256::MAX.into(), + fee_amount: U256::from(1).into(), ..Default::default() }; assert_eq!(minimum_balance(&order), None); let order = OrderData { - sell_amount: U256::from(1), - fee_amount: U256::from(1), + sell_amount: U256::from(1).into(), + fee_amount: U256::from(1).into(), ..Default::default() }; assert_eq!(minimum_balance(&order), Some(U256::from(2))); @@ -1243,9 +1247,9 @@ mod tests { valid_to: time::now_in_epoch_seconds() + 2, sell_token: H160::from_low_u64_be(1), buy_token: H160::from_low_u64_be(2), - buy_amount: U256::from(1), - sell_amount: U256::from(1), - fee_amount: U256::from(1), + buy_amount: U256::from(1).into(), + sell_amount: U256::from(1).into(), + fee_amount: U256::from(1).into(), signature: Signature::Eip712(EcdsaSignature::non_zero()), app_data: OrderCreationAppData::Full { full: "{}".to_string(), @@ -1295,7 +1299,7 @@ mod tests { let pre_interactions = vec![InteractionData { target: hooks.address(), - value: U256::zero(), + value: U256::zero().into(), call_data: hooks .execute(vec![( addr!("1111111111111111111111111111111111111111"), @@ -1362,7 +1366,7 @@ mod tests { .is_ok()); let creation_ = OrderCreation { - fee_amount: U256::zero(), + fee_amount: U256::zero().into(), ..creation.clone() }; let (order, quote) = validator @@ -1373,7 +1377,7 @@ mod tests { assert!(order.metadata.class.is_limit()); let creation_ = OrderCreation { - fee_amount: U256::zero(), + fee_amount: U256::zero().into(), partially_fillable: true, app_data: OrderCreationAppData::Full { full: "{}".to_string(), @@ -1436,8 +1440,8 @@ mod tests { valid_to: model::time::now_in_epoch_seconds() + 2, sell_token: H160::from_low_u64_be(1), buy_token: H160::from_low_u64_be(2), - buy_amount: U256::from(1), - sell_amount: U256::from(1), + buy_amount: U256::from(1).into(), + sell_amount: U256::from(1).into(), signature: Signature::Eip712(EcdsaSignature::non_zero()), app_data: OrderCreationAppData::Full { full: "{}".to_string(), @@ -1493,9 +1497,9 @@ mod tests { valid_to: time::now_in_epoch_seconds() + 2, sell_token: H160::from_low_u64_be(1), buy_token: H160::from_low_u64_be(2), - buy_amount: U256::from(0), - sell_amount: U256::from(0), - fee_amount: U256::from(1), + buy_amount: U256::from(0).into(), + sell_amount: U256::from(0).into(), + fee_amount: U256::from(1).into(), signature: Signature::Eip712(EcdsaSignature::non_zero()), app_data: OrderCreationAppData::Full { full: "{}".to_string(), @@ -1550,9 +1554,9 @@ mod tests { valid_to: time::now_in_epoch_seconds() + 2, sell_token: H160::from_low_u64_be(1), buy_token: H160::from_low_u64_be(2), - buy_amount: expected_buy_amount + 1, // buy more than expected - sell_amount: U256::from(1), - fee_amount: U256::from(1), + buy_amount: (expected_buy_amount + 1).into(), // buy more than expected + sell_amount: U256::from(1).into(), + fee_amount: U256::from(1).into(), kind: OrderKind::Sell, signature: Signature::Eip712(EcdsaSignature::non_zero()), app_data: OrderCreationAppData::Full { @@ -1606,9 +1610,9 @@ mod tests { valid_to: time::now_in_epoch_seconds() + 2, sell_token: H160::from_low_u64_be(1), buy_token: H160::from_low_u64_be(2), - buy_amount: U256::from(1), - sell_amount: U256::from(1), - fee_amount: U256::from(1), + buy_amount: U256::from(1).into(), + sell_amount: U256::from(1).into(), + fee_amount: U256::from(1).into(), from: Some(Default::default()), signature: Signature::Eip712(EcdsaSignature::non_zero()), app_data: OrderCreationAppData::Full { @@ -1657,9 +1661,9 @@ mod tests { valid_to: time::now_in_epoch_seconds() + 2, sell_token: H160::from_low_u64_be(1), buy_token: H160::from_low_u64_be(2), - buy_amount: U256::from(1), - sell_amount: U256::from(1), - fee_amount: U256::from(1), + buy_amount: U256::from(1).into(), + sell_amount: U256::from(1).into(), + fee_amount: U256::from(1).into(), signature: Signature::Eip712(EcdsaSignature::non_zero()), app_data: OrderCreationAppData::Full { full: "{}".to_string(), @@ -1710,9 +1714,9 @@ mod tests { valid_to: time::now_in_epoch_seconds() + 2, sell_token: H160::from_low_u64_be(1), buy_token: H160::from_low_u64_be(2), - buy_amount: U256::from(1), - sell_amount: U256::from(1), - fee_amount: U256::from(1), + buy_amount: U256::from(1).into(), + sell_amount: U256::from(1).into(), + fee_amount: U256::from(1).into(), signature: Signature::Eip712(EcdsaSignature::non_zero()), app_data: OrderCreationAppData::Full { full: "{}".to_string(), @@ -1767,9 +1771,9 @@ mod tests { valid_to: time::now_in_epoch_seconds() + 2, sell_token: H160::from_low_u64_be(1), buy_token: H160::from_low_u64_be(2), - buy_amount: U256::from(1), - sell_amount: U256::MAX, - fee_amount: U256::from(1), + buy_amount: U256::from(1).into(), + sell_amount: U256::MAX.into(), + fee_amount: U256::from(1).into(), signature: Signature::Eip712(EcdsaSignature::non_zero()), app_data: OrderCreationAppData::Full { full: "{}".to_string(), @@ -1818,9 +1822,9 @@ mod tests { valid_to: time::now_in_epoch_seconds() + 2, sell_token: H160::from_low_u64_be(1), buy_token: H160::from_low_u64_be(2), - buy_amount: U256::from(1), - sell_amount: U256::from(1), - fee_amount: U256::from(1), + buy_amount: U256::from(1).into(), + sell_amount: U256::from(1).into(), + fee_amount: U256::from(1).into(), signature: Signature::Eip712(EcdsaSignature::non_zero()), app_data: OrderCreationAppData::Full { full: "{}".to_string(), @@ -1874,9 +1878,9 @@ mod tests { valid_to: time::now_in_epoch_seconds() + 2, sell_token: H160::from_low_u64_be(1), buy_token: H160::from_low_u64_be(2), - buy_amount: U256::from(1), - sell_amount: U256::from(1), - fee_amount: U256::from(1), + buy_amount: U256::from(1).into(), + sell_amount: U256::from(1).into(), + fee_amount: U256::from(1).into(), from: Some(H160([1; 20])), signature: Signature::Eip1271(vec![1, 2, 3]), app_data: OrderCreationAppData::Full { diff --git a/crates/shared/src/paraswap_api.rs b/crates/shared/src/paraswap_api.rs index b45e3d33c7..a82c0d5e93 100644 --- a/crates/shared/src/paraswap_api.rs +++ b/crates/shared/src/paraswap_api.rs @@ -4,7 +4,6 @@ use { derivative::Derivative, ethcontract::{Bytes, H160, U256}, ethrpc::current_block::CurrentBlockStream, - number::serialization::HexOrDecimalU256, reqwest::{Client, RequestBuilder, StatusCode, Url}, serde::{ de::{DeserializeOwned, Error}, @@ -247,10 +246,8 @@ impl<'de> Deserialize<'de> for PriceResponse { #[derive(Deserialize)] #[serde(rename_all = "camelCase")] struct PriceRoute { - #[serde_as(as = "HexOrDecimalU256")] - src_amount: U256, - #[serde_as(as = "HexOrDecimalU256")] - dest_amount: U256, + src_amount: number::U256, + dest_amount: number::U256, token_transfer_proxy: H160, #[serde_as(as = "DisplayFromStr")] gas_cost: u64, @@ -266,8 +263,8 @@ impl<'de> Deserialize<'de> for PriceResponse { .map_err(D::Error::custom)?; Ok(PriceResponse { price_route_raw: parsed.price_route, - src_amount, - dest_amount, + src_amount: *src_amount, + dest_amount: *dest_amount, token_transfer_proxy, gas_cost, }) @@ -296,7 +293,6 @@ pub struct TransactionBuilderQuery { } /// The amounts for buying and selling. -#[serde_as] #[derive(Clone, Debug, Eq, PartialEq, Serialize)] #[serde(untagged)] pub enum TradeAmount { @@ -305,8 +301,7 @@ pub enum TradeAmount { #[serde(rename_all = "camelCase")] Sell { /// The source amount - #[serde_as(as = "HexOrDecimalU256")] - src_amount: U256, + src_amount: number::U256, /// The maximum slippage in BPS. slippage: u32, }, @@ -315,8 +310,7 @@ pub enum TradeAmount { #[serde(rename_all = "camelCase")] Buy { /// The destination amount - #[serde_as(as = "HexOrDecimalU256")] - dest_amount: U256, + dest_amount: number::U256, /// The maximum slippage in BPS. slippage: u32, }, @@ -325,10 +319,8 @@ pub enum TradeAmount { /// on the initial `/price` query and the included `price_route`. #[serde(rename_all = "camelCase")] Exact { - #[serde_as(as = "HexOrDecimalU256")] - src_amount: U256, - #[serde_as(as = "HexOrDecimalU256")] - dest_amount: U256, + src_amount: number::U256, + dest_amount: number::U256, }, } @@ -361,7 +353,6 @@ impl TransactionBuilderQueryWithPartner<'_> { } /// Paraswap transaction builder response. -#[serde_as] #[derive(Clone, Derivative, Deserialize, Default)] #[derivative(Debug)] #[serde(rename_all = "camelCase")] @@ -373,20 +364,18 @@ pub struct TransactionBuilderResponse { /// the chain for which this transaction is valid pub chain_id: u64, /// the native token value to be set on the transaction - #[serde_as(as = "HexOrDecimalU256")] - pub value: U256, + pub value: number::U256, /// the calldata for the transaction #[derivative(Debug(format_with = "debug_bytes"))] #[serde(with = "model::bytes_hex")] pub data: Vec, /// the suggested gas price - #[serde_as(as = "HexOrDecimalU256")] - pub gas_price: U256, + pub gas_price: number::U256, } impl Interaction for TransactionBuilderResponse { fn encode(&self) -> Vec { - vec![(self.to, self.value, Bytes(self.data.clone()))] + vec![(self.to, *self.value, Bytes(self.data.clone()))] } } @@ -434,7 +423,7 @@ mod tests { src_token, dest_token, trade_amount: TradeAmount::Sell { - src_amount: price_response.src_amount, + src_amount: price_response.src_amount.into(), slippage: 1000, }, src_decimals: 18, @@ -497,7 +486,7 @@ mod tests { src_token, dest_token, trade_amount: TradeAmount::Buy { - dest_amount: price_response.dest_amount, + dest_amount: price_response.dest_amount.into(), slippage: 1000, }, src_decimals: 18, @@ -814,7 +803,7 @@ mod tests { src_token, dest_token, trade_amount: TradeAmount::Sell { - src_amount: price_response.src_amount, + src_amount: price_response.src_amount.into(), slippage: 1000, // 10% }, src_decimals: 18, diff --git a/crates/shared/src/price_estimation/balancer_sor.rs b/crates/shared/src/price_estimation/balancer_sor.rs index e403e607f2..d66ed9981c 100644 --- a/crates/shared/src/price_estimation/balancer_sor.rs +++ b/crates/shared/src/price_estimation/balancer_sor.rs @@ -56,8 +56,8 @@ impl BalancerSor { sell_token: query.sell_token, buy_token: query.buy_token, order_kind: query.kind, - amount: query.in_amount.get(), - gas_price: U256::from_f64_lossy(gas_price.effective_gas_price()), + amount: query.in_amount.get().into(), + gas_price: U256::from_f64_lossy(gas_price.effective_gas_price()).into(), }; let api = self.api.clone(); let future = async move { @@ -71,7 +71,7 @@ impl BalancerSor { let future = self.sharing.shared(query.clone(), future.boxed()); let quote = future.await?; Ok(Estimate { - out_amount: quote.return_amount, + out_amount: quote.return_amount.into(), gas: SETTLEMENT_SINGLE_TRADE + (quote.swaps.len() as u64) * GAS_PER_BALANCER_SWAP, solver: self.solver, verified: false, diff --git a/crates/shared/src/price_estimation/http.rs b/crates/shared/src/price_estimation/http.rs index 3b1fb9fb1a..388e8e3341 100644 --- a/crates/shared/src/price_estimation/http.rs +++ b/crates/shared/src/price_estimation/http.rs @@ -153,16 +153,16 @@ impl HttpTradeFinder { id: Default::default(), sell_token: query.sell_token, buy_token: query.buy_token, - sell_amount, - buy_amount, + sell_amount: sell_amount.into(), + buy_amount: buy_amount.into(), allow_partial_fill: false, is_sell_order: query.kind == OrderKind::Sell, fee: TokenAmount { - amount: U256::from(GAS_PER_ORDER) * gas_price, + amount: (U256::from(GAS_PER_ORDER) * gas_price).into(), token: self.native_token, }, cost: TokenAmount { - amount: U256::from(GAS_PER_ORDER) * gas_price, + amount: (U256::from(GAS_PER_ORDER) * gas_price).into(), token: self.native_token, }, is_liquidity_order: false, @@ -282,8 +282,8 @@ impl HttpTradeFinder { + ERC20_TRANSFER * 2; // transfer in and transfer out Ok(Trade { out_amount: match query.kind { - OrderKind::Buy => settlement.orders[&0].exec_sell_amount, - OrderKind::Sell => settlement.orders[&0].exec_buy_amount, + OrderKind::Buy => settlement.orders[&0].exec_sell_amount.into(), + OrderKind::Sell => settlement.orders[&0].exec_buy_amount.into(), }, gas_estimate, interactions: settlement @@ -291,7 +291,7 @@ impl HttpTradeFinder { .into_iter() .map(|i| Interaction { target: i.target, - value: i.value, + value: i.value.into(), data: i.call_data, }) .collect(), @@ -348,7 +348,7 @@ impl HttpTradeFinder { BigInt::from(*pool.state.fee.numer()), BigInt::from(*pool.state.fee.denom()), )), - cost: gas_model.cost_for_gas(pool.gas_stats.mean_gas), + cost: gas_model.cost_for_gas(pool.gas_stats.mean_gas.into()), address: pool.address, parameters: AmmParameters::Concentrated(ConcentratedPoolParameters { pool }), mandatory: false, @@ -382,7 +382,7 @@ impl HttpTradeFinder { ( token, WeightedPoolTokenData { - balance: state.common.balance, + balance: state.common.balance.into(), weight: BigRational::from(state.weight), }, ) @@ -402,12 +402,12 @@ impl HttpTradeFinder { parameters: AmmParameters::Stable(StablePoolParameters { reserves: pool .reserves_without_bpt() - .map(|(token, state)| (token, state.balance)) + .map(|(token, state)| (token, state.balance.into())) .collect(), scaling_rates: pool .reserves_without_bpt() .map(|(token, state)| { - Ok((token, compute_scaling_rate(state.scaling_factor)?)) + Ok((token, compute_scaling_rate(state.scaling_factor)?.into())) }) .collect::>() .with_context(|| "convert stable pool to solver model".to_string())?, @@ -434,7 +434,7 @@ impl HttpTradeFinder { cost.token ))) } else { - Ok(cost.amount) + Ok(*cost.amount) } } else { Ok(U256::zero()) @@ -719,7 +719,7 @@ mod tests { }, interaction_data: vec![InteractionData { target: H160::zero(), - value: U256::zero(), + value: U256::zero().into(), call_data: vec![], inputs: vec![], outputs: vec![], diff --git a/crates/shared/src/price_estimation/native/oneinch.rs b/crates/shared/src/price_estimation/native/oneinch.rs index 6d4bb6d090..1e792422eb 100644 --- a/crates/shared/src/price_estimation/native/oneinch.rs +++ b/crates/shared/src/price_estimation/native/oneinch.rs @@ -4,11 +4,9 @@ use { anyhow::{anyhow, Context, Result}, ethrpc::current_block::{into_stream, CurrentBlockStream}, futures::{future::BoxFuture, FutureExt, StreamExt}, - number::serialization::HexOrDecimalU256, primitive_types::{H160, U256}, reqwest::{header::AUTHORIZATION, Client}, serde::{Deserialize, Serialize}, - serde_with::serde_as, std::{ collections::HashMap, sync::{Arc, Mutex}, @@ -16,9 +14,8 @@ use { url::Url, }; -#[serde_as] #[derive(Debug, Deserialize, Serialize)] -struct Response(#[serde_as(as = "HashMap<_, HexOrDecimalU256>")] HashMap); +struct Response(HashMap); type Token = H160; type PriceInWei = U256; diff --git a/crates/shared/src/price_estimation/trade_verifier.rs b/crates/shared/src/price_estimation/trade_verifier.rs index 355120c9ce..1b56da380a 100644 --- a/crates/shared/src/price_estimation/trade_verifier.rs +++ b/crates/shared/src/price_estimation/trade_verifier.rs @@ -246,9 +246,9 @@ fn encode_settlement( }; let fake_order = OrderData { sell_token: query.sell_token, - sell_amount, + sell_amount: sell_amount.into(), buy_token: query.buy_token, - buy_amount, + buy_amount: buy_amount.into(), receiver: Some(verification.receiver), valid_to: u32::MAX, app_data: Default::default(), diff --git a/crates/shared/src/remaining_amounts.rs b/crates/shared/src/remaining_amounts.rs index a9b2a32a7f..0e1d5663c7 100644 --- a/crates/shared/src/remaining_amounts.rs +++ b/crates/shared/src/remaining_amounts.rs @@ -51,17 +51,17 @@ impl From<&ModelOrder> for Order { fn from(o: &ModelOrder) -> Self { Self { kind: o.data.kind, - buy_amount: o.data.buy_amount, - sell_amount: o.data.sell_amount, - fee_amount: o.data.fee_amount, + buy_amount: *o.data.buy_amount, + sell_amount: *o.data.sell_amount, + fee_amount: *o.data.fee_amount, executed_amount: match o.data.kind { // A real buy order cannot execute more than U256::MAX so in order to make this // function infallible we treat a larger amount as a full execution. OrderKind::Buy => { number::conversions::big_uint_to_u256(&o.metadata.executed_buy_amount) - .unwrap_or(o.data.buy_amount) + .unwrap_or(*o.data.buy_amount) } - OrderKind::Sell => o.metadata.executed_sell_amount_before_fees, + OrderKind::Sell => *o.metadata.executed_sell_amount_before_fees, }, partially_fillable: o.data.partially_fillable, } @@ -190,7 +190,7 @@ mod tests { let order = ModelOrder { data: OrderData { sell_amount: 1000.into(), - buy_amount: U256::MAX, + buy_amount: U256::MAX.into(), fee_amount: 337.into(), kind: OrderKind::Buy, partially_fillable: false, @@ -285,7 +285,7 @@ mod tests { data: OrderData { sell_amount: 1000.into(), fee_amount: 337.into(), - buy_amount: U256::MAX, + buy_amount: U256::MAX.into(), kind: OrderKind::Buy, partially_fillable: true, ..Default::default() @@ -298,7 +298,7 @@ mod tests { // Partially filled order overflowing executed amount. let order = ModelOrder { data: OrderData { - buy_amount: U256::MAX, + buy_amount: U256::MAX.into(), kind: OrderKind::Buy, partially_fillable: true, ..Default::default() @@ -421,7 +421,7 @@ mod tests { fn support_scaling_for_large_orders_with_partial_balance() { let order: Order = ModelOrder { data: OrderData { - sell_amount: U256::exp10(30), + sell_amount: U256::exp10(30).into(), buy_amount: 1.into(), kind: OrderKind::Sell, partially_fillable: true, diff --git a/crates/shared/src/signature_validator/simulation.rs b/crates/shared/src/signature_validator/simulation.rs index 82a80b063f..3546a8e497 100644 --- a/crates/shared/src/signature_validator/simulation.rs +++ b/crates/shared/src/signature_validator/simulation.rs @@ -47,7 +47,7 @@ impl Validator { check .interactions .iter() - .map(|i| (i.target, i.value, Bytes(i.call_data.clone()))) + .map(|i| (i.target, i.value.into(), Bytes(i.call_data.clone()))) .collect(), ), ) diff --git a/crates/shared/src/sources/uniswap_v3/graph_api.rs b/crates/shared/src/sources/uniswap_v3/graph_api.rs index df604e0de5..514496aa5c 100644 --- a/crates/shared/src/sources/uniswap_v3/graph_api.rs +++ b/crates/shared/src/sources/uniswap_v3/graph_api.rs @@ -7,9 +7,8 @@ use { subgraph::{ContainsId, SubgraphClient}, }, anyhow::{bail, Result}, - ethcontract::{H160, U256}, + ethcontract::H160, num::BigInt, - number::serialization::HexOrDecimalU256, reqwest::{Client, Url}, serde::{Deserialize, Serialize}, serde_json::{json, Map, Value}, @@ -240,12 +239,9 @@ pub struct PoolData { pub id: H160, pub token0: Token, pub token1: Token, - #[serde_as(as = "HexOrDecimalU256")] - pub fee_tier: U256, - #[serde_as(as = "HexOrDecimalU256")] - pub liquidity: U256, - #[serde_as(as = "HexOrDecimalU256")] - pub sqrt_price: U256, + pub fee_tier: number::U256, + pub liquidity: number::U256, + pub sqrt_price: number::U256, #[serde_as(as = "DisplayFromStr")] pub tick: BigInt, #[serde_as(as = "DisplayFromStr")] @@ -319,6 +315,7 @@ mod tests { use { super::*, crate::subgraph::{Data, QUERY_PAGE_SIZE}, + number::U256, serde_json::json, std::str::FromStr, }; diff --git a/crates/shared/src/sources/uniswap_v3/pool_fetching.rs b/crates/shared/src/sources/uniswap_v3/pool_fetching.rs index 208379a874..f41b50ea5a 100644 --- a/crates/shared/src/sources/uniswap_v3/pool_fetching.rs +++ b/crates/shared/src/sources/uniswap_v3/pool_fetching.rs @@ -17,7 +17,6 @@ use { itertools::{Either, Itertools}, model::TokenPair, num::{rational::Ratio, BigInt, Zero}, - number::serialization::HexOrDecimalU256, reqwest::{Client, Url}, serde::Serialize, serde_with::{serde_as, DisplayFromStr}, @@ -53,10 +52,8 @@ pub struct PoolInfo { #[serde_as] #[derive(Clone, Debug, Default, Eq, PartialEq, Serialize)] pub struct PoolState { - #[serde_as(as = "HexOrDecimalU256")] - pub sqrt_price: U256, - #[serde_as(as = "HexOrDecimalU256")] - pub liquidity: U256, + pub sqrt_price: number::U256, + pub liquidity: number::U256, #[serde_as(as = "DisplayFromStr")] pub tick: BigInt, // (tick_idx, liquidity_net) @@ -67,12 +64,10 @@ pub struct PoolState { } /// Pool stats in a format prepared for solvers -#[serde_as] #[derive(Clone, Debug, Default, Eq, PartialEq, Serialize)] pub struct PoolStats { - #[serde_as(as = "HexOrDecimalU256")] #[serde(rename = "mean")] - pub mean_gas: U256, + pub mean_gas: number::U256, } impl TryFrom for PoolInfo { @@ -101,7 +96,7 @@ impl TryFrom for PoolInfo { fee: Ratio::new(pool.fee_tier.as_u32(), 1_000_000u32), }, gas_stats: PoolStats { - mean_gas: U256::from(108_163), // as estimated by https://dune.com/queries/1044812 + mean_gas: U256::from(108_163).into(), /* as estimated by https://dune.com/queries/1044812 */ }, }) } @@ -384,7 +379,7 @@ impl PoolFetching for UniswapV3PoolFetcher { // return only pools which current liquidity is positive Ok(checkpoint .into_values() - .filter(|pool| pool.state.liquidity > U256::zero()) + .filter(|pool| pool.state.liquidity > U256::zero().into()) .collect()) } } @@ -405,7 +400,7 @@ fn append_events(pools: &mut HashMap, events: Vec, events: Vec, events: Vec { pool.tick = BigInt::from(swap.tick); pool.liquidity = swap.liquidity.into(); - pool.sqrt_price = swap.sqrt_price_x96; + pool.sqrt_price = swap.sqrt_price_x96.into(); } } } @@ -545,8 +540,10 @@ mod tests { }, ], state: PoolState { - sqrt_price: U256::from_dec_str("792216481398733702759960397").unwrap(), - liquidity: U256::from_dec_str("303015134493562686441").unwrap(), + sqrt_price: U256::from_dec_str("792216481398733702759960397") + .unwrap() + .into(), + liquidity: U256::from_dec_str("303015134493562686441").unwrap().into(), tick: BigInt::from_str("-92110").unwrap(), liquidity_net: BTreeMap::from([ ( @@ -565,7 +562,7 @@ mod tests { fee: Ratio::new(10_000u32, 1_000_000u32), }, gas_stats: PoolStats { - mean_gas: U256::from(300000), + mean_gas: U256::from(300000).into(), }, }; @@ -606,8 +603,8 @@ mod tests { append_events(&mut pools, vec![event]); assert_eq!(pools[&address].state.tick, BigInt::from(3)); - assert_eq!(pools[&address].state.liquidity, U256::from(2)); - assert_eq!(pools[&address].state.sqrt_price, U256::from(1)); + assert_eq!(pools[&address].state.liquidity, U256::from(2).into()); + assert_eq!(pools[&address].state.sqrt_price, U256::from(1).into()); } #[test] diff --git a/crates/shared/src/trade_finding.rs b/crates/shared/src/trade_finding.rs index 31129d4f4c..fc79731fc9 100644 --- a/crates/shared/src/trade_finding.rs +++ b/crates/shared/src/trade_finding.rs @@ -118,7 +118,7 @@ impl From for Interaction { fn from(interaction: InteractionData) -> Self { Self { target: interaction.target, - value: interaction.value, + value: *interaction.value, data: interaction.call_data, } } diff --git a/crates/shared/src/trade_finding/external.rs b/crates/shared/src/trade_finding/external.rs index 711743b306..6fa77581ac 100644 --- a/crates/shared/src/trade_finding/external.rs +++ b/crates/shared/src/trade_finding/external.rs @@ -46,7 +46,7 @@ impl ExternalTradeFinder { let order = dto::Order { sell_token: query.sell_token, buy_token: query.buy_token, - amount: query.in_amount.get(), + amount: query.in_amount.get().into(), kind: query.kind, deadline, }; @@ -111,14 +111,14 @@ impl From for Trade { const TRADE_GAS: u64 = 290_000; Self { - out_amount: quote.amount, + out_amount: *quote.amount, gas_estimate: TRADE_GAS, interactions: quote .interactions .into_iter() .map(|interaction| Interaction { target: interaction.target, - value: interaction.value, + value: *interaction.value, data: interaction.call_data, }) .collect(), @@ -156,31 +156,26 @@ impl TradeFinding for ExternalTradeFinder { mod dto { use { - ethcontract::{H160, U256}, + ethcontract::H160, model::{bytes_hex::BytesHex, order::OrderKind}, - number::serialization::HexOrDecimalU256, serde::{Deserialize, Serialize}, serde_with::serde_as, }; - #[serde_as] #[derive(Clone, Debug, Serialize)] #[serde(rename_all = "camelCase")] pub struct Order { pub sell_token: H160, pub buy_token: H160, - #[serde_as(as = "HexOrDecimalU256")] - pub amount: U256, + pub amount: number::U256, pub kind: OrderKind, pub deadline: chrono::DateTime, } - #[serde_as] #[derive(Clone, Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Quote { - #[serde_as(as = "HexOrDecimalU256")] - pub amount: U256, + pub amount: number::U256, pub interactions: Vec, pub solver: H160, } @@ -190,8 +185,7 @@ mod dto { #[serde(rename_all = "camelCase")] pub struct Interaction { pub target: H160, - #[serde_as(as = "HexOrDecimalU256")] - pub value: U256, + pub value: number::U256, #[serde_as(as = "BytesHex")] pub call_data: Vec, } diff --git a/crates/shared/src/trade_finding/oneinch.rs b/crates/shared/src/trade_finding/oneinch.rs index 82994f975d..00c84b7c99 100644 --- a/crates/shared/src/trade_finding/oneinch.rs +++ b/crates/shared/src/trade_finding/oneinch.rs @@ -98,7 +98,7 @@ impl OneInchTradeFinder { Some(spender), Interaction { target: swap.tx.to, - value: swap.tx.value, + value: swap.tx.value.into(), data: swap.tx.data, }, self.inner.solver, @@ -156,7 +156,7 @@ impl Inner { .await?; Ok(Quote { - out_amount: quote.to_token_amount, + out_amount: quote.to_token_amount.into(), gas_estimate: gas::SETTLEMENT_OVERHEAD + quote.estimated_gas, solver: self.solver, }) diff --git a/crates/shared/src/trade_finding/paraswap.rs b/crates/shared/src/trade_finding/paraswap.rs index e14712f217..ec0c848f5c 100644 --- a/crates/shared/src/trade_finding/paraswap.rs +++ b/crates/shared/src/trade_finding/paraswap.rs @@ -126,11 +126,11 @@ impl Inner { dest_token: query.buy_token, trade_amount: match query.kind { OrderKind::Buy => TradeAmount::Buy { - dest_amount: query.in_amount.get(), + dest_amount: query.in_amount.get().into(), slippage: Self::DEFAULT_SLIPPAGE, }, OrderKind::Sell => TradeAmount::Sell { - src_amount: query.in_amount.get(), + src_amount: query.in_amount.get().into(), slippage: Self::DEFAULT_SLIPPAGE, }, }, @@ -156,7 +156,7 @@ impl Inner { Some(quote.price.token_transfer_proxy), Interaction { target: tx.to, - value: tx.value, + value: tx.value.into(), data: tx.data, }, self.solver, diff --git a/crates/shared/src/trade_finding/zeroex.rs b/crates/shared/src/trade_finding/zeroex.rs index e37bd463e6..32a1be9d78 100644 --- a/crates/shared/src/trade_finding/zeroex.rs +++ b/crates/shared/src/trade_finding/zeroex.rs @@ -85,14 +85,14 @@ impl Inner { Ok(Trade::swap( query.sell_token, match query.kind { - OrderKind::Buy => swap.price.sell_amount, - OrderKind::Sell => swap.price.buy_amount, + OrderKind::Buy => swap.price.sell_amount.into(), + OrderKind::Sell => swap.price.buy_amount.into(), }, gas::SETTLEMENT_OVERHEAD + swap.price.estimated_gas, Some(swap.price.allowance_target), Interaction { target: swap.to, - value: swap.value, + value: swap.value.into(), data: swap.data, }, self.solver, diff --git a/crates/shared/src/zeroex_api.rs b/crates/shared/src/zeroex_api.rs index f8fa5225cd..d69e96355f 100644 --- a/crates/shared/src/zeroex_api.rs +++ b/crates/shared/src/zeroex_api.rs @@ -14,7 +14,6 @@ use { derivative::Derivative, ethcontract::{Bytes, H160, H256, U256}, ethrpc::current_block::{BlockInfo, CurrentBlockStream}, - number::serialization::HexOrDecimalU256, reqwest::{ header::{HeaderMap, HeaderValue}, Client, @@ -233,8 +232,7 @@ pub struct Order { pub pool: H256, /// A value that can be used to guarantee order uniqueness. Typically it is /// set to a random number. - #[serde_as(as = "HexOrDecimalU256")] - pub salt: U256, + pub salt: number::U256, /// It allows the maker to enforce that the order flow through some /// additional logic before it can be filled (e.g., a KYC whitelist). pub sender: H160, @@ -299,10 +297,8 @@ pub struct OrdersResponse { #[derivative(Debug)] #[serde(rename_all = "camelCase")] pub struct PriceResponse { - #[serde_as(as = "HexOrDecimalU256")] - pub sell_amount: U256, - #[serde_as(as = "HexOrDecimalU256")] - pub buy_amount: U256, + pub sell_amount: number::U256, + pub buy_amount: number::U256, pub allowance_target: H160, #[serde_as(as = "DisplayFromStr")] pub price: f64, @@ -322,13 +318,12 @@ pub struct SwapResponse { #[derivative(Debug(format_with = "debug_bytes"))] #[serde(with = "model::bytes_hex")] pub data: Vec, - #[serde_as(as = "HexOrDecimalU256")] - pub value: U256, + pub value: number::U256, } impl Interaction for SwapResponse { fn encode(&self) -> Vec { - vec![(self.to, self.value, Bytes(self.data.clone()))] + vec![(self.to, *self.value, Bytes(self.data.clone()))] } } @@ -810,8 +805,8 @@ mod tests { swap, SwapResponse { price: PriceResponse { - sell_amount: U256::from_dec_str("100000000000000000").unwrap(), - buy_amount: U256::from_dec_str("1312100257517027783").unwrap(), + sell_amount: U256::from_dec_str("100000000000000000").unwrap().into(), + buy_amount: U256::from_dec_str("1312100257517027783").unwrap().into(), allowance_target: crate::addr!("def1c0ded9bec7f1a1670819833240f027b25eff"), price: 13.121_002_575_170_278_f64, estimated_gas: 111000, @@ -820,7 +815,7 @@ mod tests { data: hex::decode( "d9627aa40000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000016345785d8a00000000000000000000000000000000000000000000000000001206e6c0056936e100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006810e776880c02933d47db1b9fc05908e5386b96869584cd0000000000000000000000001000000000000000000000000000000000000011000000000000000000000000000000000000000000000092415e982f60d431ba" ).unwrap(), - value: U256::from_dec_str("0").unwrap(), + value: U256::from_dec_str("0").unwrap().into(), } ); } diff --git a/crates/solver/src/interactions/allowances.rs b/crates/solver/src/interactions/allowances.rs index d16089a16a..9b1f4224c8 100644 --- a/crates/solver/src/interactions/allowances.rs +++ b/crates/solver/src/interactions/allowances.rs @@ -74,7 +74,7 @@ impl Allowances { .copied() .ok_or_else(|| anyhow!("missing allowance for token {:?}", token_amount.token))?; - Ok(if allowance < token_amount.amount { + Ok(if allowance < *token_amount.amount { Some(Approval { token: token_amount.token, spender: self.spender, diff --git a/crates/solver/src/interactions/balancer_v2.rs b/crates/solver/src/interactions/balancer_v2.rs index c97a746d86..f65178c79c 100644 --- a/crates/solver/src/interactions/balancer_v2.rs +++ b/crates/solver/src/interactions/balancer_v2.rs @@ -33,7 +33,7 @@ impl BalancerSwapGivenOutInteraction { 1, // GivenOut, self.asset_in_max.token, self.asset_out.token, - self.asset_out.amount, + *self.asset_out.amount, self.user_data.clone(), ), ( @@ -42,7 +42,7 @@ impl BalancerSwapGivenOutInteraction { self.settlement.address(), // recipient false, // toInternalBalance ), - self.asset_in_max.amount, + *self.asset_in_max.amount, *NEVER, ); let calldata = method.tx.data.expect("no calldata").0; diff --git a/crates/solver/src/interactions/uniswap_v3.rs b/crates/solver/src/interactions/uniswap_v3.rs index 5313fe6ece..f82a3db1d1 100644 --- a/crates/solver/src/interactions/uniswap_v3.rs +++ b/crates/solver/src/interactions/uniswap_v3.rs @@ -31,8 +31,8 @@ impl Interaction for UniswapV3Interaction { self.params.fee, self.params.recipient, self.params.deadline, - self.params.token_amount_out.amount, - self.params.token_amount_in_max.amount, + *self.params.token_amount_out.amount, + *self.params.token_amount_in_max.amount, self.params.sqrt_price_limit_x96, )); let calldata = method.tx.data.expect("no calldata").0; diff --git a/crates/solver/src/interactions/zeroex.rs b/crates/solver/src/interactions/zeroex.rs index 1c77e90652..eca505e6cd 100644 --- a/crates/solver/src/interactions/zeroex.rs +++ b/crates/solver/src/interactions/zeroex.rs @@ -29,7 +29,7 @@ impl Interaction for ZeroExInteraction { self.order.fee_recipient, Bytes(self.order.pool.0), self.order.expiry, - self.order.salt, + *self.order.salt, ), ( self.order.signature.signature_type, diff --git a/crates/solver/src/liquidity/order_converter.rs b/crates/solver/src/liquidity/order_converter.rs index ca48747a12..4546140478 100644 --- a/crates/solver/src/liquidity/order_converter.rs +++ b/crates/solver/src/liquidity/order_converter.rs @@ -63,8 +63,8 @@ impl OrderConverter { } OrderClass::Limit => LimitOrderId::Limit(order.metadata.uid), }; - let sell_amount = remaining.remaining(sell_amount)?; - let buy_amount = remaining.remaining(order.data.buy_amount)?; + let sell_amount = remaining.remaining(*sell_amount)?; + let buy_amount = remaining.remaining(*order.data.buy_amount)?; ensure!( !sell_amount.is_zero() && !buy_amount.is_zero(), "order with 0 amounts", @@ -78,7 +78,7 @@ impl OrderConverter { buy_amount, kind: order.data.kind, partially_fillable: order.data.partially_fillable, - user_fee: remaining.remaining(order.data.fee_amount)?, + user_fee: remaining.remaining(*order.data.fee_amount)?, settlement_handling: Arc::new(OrderSettlementHandler { order, native_token: self.native_token.clone(), diff --git a/crates/solver/src/liquidity/slippage.rs b/crates/solver/src/liquidity/slippage.rs index cae0517367..d013787915 100644 --- a/crates/solver/src/liquidity/slippage.rs +++ b/crates/solver/src/liquidity/slippage.rs @@ -105,7 +105,7 @@ impl<'a> SlippageContext<'a> { ); } - execution.input_max.amount = slippage.add_to_amount(execution.input_max.amount); + execution.input_max.amount = slippage.add_to_amount(*execution.input_max.amount).into(); Ok(execution) } diff --git a/crates/solver/src/liquidity/uniswap_v2.rs b/crates/solver/src/liquidity/uniswap_v2.rs index 21431723c3..efd961e74f 100644 --- a/crates/solver/src/liquidity/uniswap_v2.rs +++ b/crates/solver/src/liquidity/uniswap_v2.rs @@ -143,8 +143,8 @@ impl Inner { UniswapInteraction { router: self.router.clone(), settlement: self.gpv2_settlement.clone(), - amount_out: token_amount_out.amount, - amount_in_max: token_amount_in_max.amount, + amount_out: *token_amount_out.amount, + amount_in_max: *token_amount_in_max.amount, token_in: token_amount_in_max.token, token_out: token_amount_out.token, }, diff --git a/crates/solver/src/order_balance_filter.rs b/crates/solver/src/order_balance_filter.rs index 1bd1504a1b..f28417c3f4 100644 --- a/crates/solver/src/order_balance_filter.rs +++ b/crates/solver/src/order_balance_filter.rs @@ -156,8 +156,8 @@ fn sort_orders_for_balance_priority(orders: &mut [Order], external_prices: &Exte /// Returns `Err` on overflow. fn max_transfer_out_amount(order: &Order) -> Result { let remaining = shared::remaining_amounts::Remaining::from_order(&order.into())?; - let sell = remaining.remaining(order.data.sell_amount)?; - let fee = remaining.remaining(order.data.fee_amount)?; + let sell = remaining.remaining(*order.data.sell_amount)?; + let fee = remaining.remaining(*order.data.fee_amount)?; sell.checked_add(fee).context("add") } diff --git a/crates/solver/src/settlement.rs b/crates/solver/src/settlement.rs index 3df284f283..80701929bb 100644 --- a/crates/solver/src/settlement.rs +++ b/crates/solver/src/settlement.rs @@ -142,7 +142,7 @@ impl Trade { // Returns the executed fee amount (prorated of executed amount) // cf. https://github.com/cowprotocol/contracts/blob/v1.1.2/src/contracts/GPv2Settlement.sol#L383-L385 pub fn executed_fee(&self) -> Option { - self.scale_amount(self.order.data.fee_amount) + self.scale_amount(*self.order.data.fee_amount) } /// Returns the actual fees taken by the protocol. @@ -151,9 +151,9 @@ impl Trade { match self.order.solver_determines_fee() { true => { // Solvers already scale the `fee` for these orders. - self.scale_amount(user_fee)?.checked_add(self.fee) + self.scale_amount(*user_fee)?.checked_add(self.fee) } - false => self.scale_amount(user_fee), + false => self.scale_amount(*user_fee), } } @@ -162,10 +162,10 @@ impl Trade { match self.order.data.kind { model::order::OrderKind::Buy => amount .checked_mul(self.executed_amount)? - .checked_div(self.order.data.buy_amount), + .checked_div(*self.order.data.buy_amount), model::order::OrderKind::Sell => amount .checked_mul(self.executed_amount)? - .checked_div(self.order.data.sell_amount), + .checked_div(*self.order.data.sell_amount), } } @@ -645,12 +645,12 @@ pub mod tests { let trades = vec![ Trade { order: order1.clone(), - executed_amount: order1.data.sell_amount, + executed_amount: *order1.data.sell_amount, ..Default::default() }, Trade { order: order2.clone(), - executed_amount: order2.data.sell_amount, + executed_amount: *order2.data.sell_amount, ..Default::default() }, ]; @@ -779,7 +779,7 @@ pub mod tests { }; let mut trades = vec![Trade { order: order.clone(), - executed_amount: order.data.sell_amount, + executed_amount: *order.data.sell_amount, ..Default::default() }]; let clearing_prices = hashmap! {native_token => 1700.into(), usd => U256::one()}; @@ -806,7 +806,7 @@ pub mod tests { }; trades.push(Trade { order: counter_order.clone(), - executed_amount: counter_order.data.sell_amount, + executed_amount: *counter_order.data.sell_amount, ..Default::default() }); let settlement = test_settlement(clearing_prices, trades); @@ -1275,8 +1275,8 @@ pub mod tests { let large_amounts = Trade { order: Order { data: OrderData { - sell_amount: U256::max_value(), - fee_amount: U256::max_value(), + sell_amount: U256::max_value().into(), + fee_amount: U256::max_value().into(), kind: OrderKind::Sell, ..Default::default() }, @@ -1290,8 +1290,8 @@ pub mod tests { let zero_amounts = Trade { order: Order { data: OrderData { - sell_amount: U256::zero(), - fee_amount: U256::zero(), + sell_amount: U256::zero().into(), + fee_amount: U256::zero().into(), kind: OrderKind::Sell, ..Default::default() }, diff --git a/crates/solver/src/settlement/settlement_encoder.rs b/crates/solver/src/settlement/settlement_encoder.rs index bb3f522b07..6f0657a979 100644 --- a/crates/solver/src/settlement/settlement_encoder.rs +++ b/crates/solver/src/settlement/settlement_encoder.rs @@ -259,7 +259,7 @@ impl SettlementEncoder { OrderClass::Market => self.add_market_trade(order, executed_amount, fee)?, OrderClass::Liquidity => { let (sell_price, buy_price) = (order.data.buy_amount, order.data.sell_amount); - self.add_custom_price_trade(order, executed_amount, fee, sell_price, buy_price)? + self.add_custom_price_trade(order, executed_amount, fee, *sell_price, *buy_price)? } OrderClass::Limit => { let surplus_fee = fee; @@ -307,8 +307,8 @@ impl SettlementEncoder { OrderKind::Sell => order.data.sell_amount, }; anyhow::ensure!( - (order.data.partially_fillable && executed_amount <= target_amount) - || (!order.data.partially_fillable && executed_amount == target_amount), + (order.data.partially_fillable && executed_amount <= *target_amount) + || (!order.data.partially_fillable && executed_amount == *target_amount), "this function should only be called with valid executed amounts" ); @@ -725,10 +725,10 @@ impl PricedTrade<'_> { pub fn verify_executed_amount(order: &Order, executed: U256) -> Result<()> { let remaining = shared::remaining_amounts::Remaining::from_order(&order.into())?; let valid_executed_amount = match (order.data.partially_fillable, order.data.kind) { - (true, OrderKind::Sell) => executed <= remaining.remaining(order.data.sell_amount)?, - (true, OrderKind::Buy) => executed <= remaining.remaining(order.data.buy_amount)?, - (false, OrderKind::Sell) => executed == remaining.remaining(order.data.sell_amount)?, - (false, OrderKind::Buy) => executed == remaining.remaining(order.data.buy_amount)?, + (true, OrderKind::Sell) => executed <= remaining.remaining(*order.data.sell_amount)?, + (true, OrderKind::Buy) => executed <= remaining.remaining(*order.data.buy_amount)?, + (false, OrderKind::Sell) => executed == remaining.remaining(*order.data.sell_amount)?, + (false, OrderKind::Buy) => executed == remaining.remaining(*order.data.buy_amount)?, }; ensure!(valid_executed_amount, "invalid executed amount"); Ok(()) @@ -877,7 +877,10 @@ pub mod tests { assert_eq!(finished_settlement.tokens, vec![token(0), token(1)]); assert_eq!( finished_settlement.clearing_prices, - vec![order01.data.buy_amount, order01.data.sell_amount] + vec![ + order01.data.buy_amount.into(), + order01.data.sell_amount.into() + ] ); assert_eq!( finished_settlement.trades[0].0, // <-- is the sell token index of liquidity order @@ -1190,8 +1193,8 @@ pub mod tests { assert_eq!(encoder.pre_interactions, vec![i1.clone(), i1.clone()]); assert_eq!(encoder.post_interactions, vec![i2.clone(), i2.clone()]); - let i1 = (i1.target, i1.value, Bytes(i1.call_data)); - let i2 = (i2.target, i2.value, Bytes(i2.call_data)); + let i1 = (i1.target, i1.value.into(), Bytes(i1.call_data)); + let i2 = (i2.target, i2.value.into(), Bytes(i2.call_data)); let encoded = encoder.finish(InternalizationStrategy::EncodeAllInteractions); assert_eq!( encoded.interactions, @@ -1204,19 +1207,19 @@ pub mod tests { let mut encoder0 = SettlementEncoder::new(Default::default()); encoder0.post_interactions.push(InteractionData { target: H160([1; 20]), - value: U256::zero(), + value: U256::zero().into(), call_data: vec![0xa], }); let mut encoder1 = SettlementEncoder::new(Default::default()); encoder1.post_interactions.push(InteractionData { target: H160([1; 20]), - value: U256::zero(), + value: U256::zero().into(), call_data: vec![0xa], }); encoder1.post_interactions.push(InteractionData { target: H160([2; 20]), - value: U256::one(), + value: U256::one().into(), call_data: vec![0xb], }); @@ -1226,17 +1229,17 @@ pub mod tests { vec![ InteractionData { target: H160([1; 20]), - value: U256::zero(), + value: U256::zero().into(), call_data: vec![0xa], }, InteractionData { target: H160([1; 20]), - value: U256::zero(), + value: U256::zero().into(), call_data: vec![0xa], }, InteractionData { target: H160([2; 20]), - value: U256::one(), + value: U256::one().into(), call_data: vec![0xb], }, ] @@ -1248,19 +1251,19 @@ pub mod tests { let mut encoder0 = SettlementEncoder::new(Default::default()); encoder0.pre_interactions.push(InteractionData { target: H160([1; 20]), - value: U256::zero(), + value: U256::zero().into(), call_data: vec![0xa], }); let mut encoder1 = SettlementEncoder::new(Default::default()); encoder1.pre_interactions.push(InteractionData { target: H160([1; 20]), - value: U256::zero(), + value: U256::zero().into(), call_data: vec![0xa], }); encoder1.pre_interactions.push(InteractionData { target: H160([2; 20]), - value: U256::one(), + value: U256::one().into(), call_data: vec![0xb], }); @@ -1270,17 +1273,17 @@ pub mod tests { vec![ InteractionData { target: H160([1; 20]), - value: U256::zero(), + value: U256::zero().into(), call_data: vec![0xa], }, InteractionData { target: H160([1; 20]), - value: U256::zero(), + value: U256::zero().into(), call_data: vec![0xa], }, InteractionData { target: H160([2; 20]), - value: U256::one(), + value: U256::one().into(), call_data: vec![0xb], }, ] diff --git a/crates/solver/src/solver/naive_solver/multi_order_solver.rs b/crates/solver/src/solver/naive_solver/multi_order_solver.rs index dc0fba6243..8e262cda16 100644 --- a/crates/solver/src/solver/naive_solver/multi_order_solver.rs +++ b/crates/solver/src/solver/naive_solver/multi_order_solver.rs @@ -489,8 +489,10 @@ mod tests { // Make sure the sell amounts cover the uniswap in, and min buy amounts are // covered by uniswap out - assert!(orders[0].sell_amount + orders[1].sell_amount >= interaction.input_max.amount); - assert!(interaction.output.amount >= orders[0].buy_amount + orders[1].buy_amount); + assert!(orders[0].sell_amount + orders[1].sell_amount >= *interaction.input_max.amount); + assert!( + interaction.output.amount >= ((orders[0].buy_amount + orders[1].buy_amount).into()) + ); // Make sure expected buy amounts (given prices) are also covered by uniswap out // amounts @@ -499,7 +501,7 @@ mod tests { let first_expected_buy = orders[0].sell_amount * price_a / price_b; let second_expected_buy = orders[1].sell_amount * price_a / price_b; - assert!(interaction.output.amount >= first_expected_buy + second_expected_buy); + assert!(interaction.output.amount >= (first_expected_buy + second_expected_buy).into()); } #[test] @@ -681,8 +683,8 @@ mod tests { data: OrderData { sell_token: token_a, buy_token: token_b, - sell_amount: to_wei(1), - buy_amount: to_wei(1000), + sell_amount: to_wei(1).into(), + buy_amount: to_wei(1000).into(), kind: OrderKind::Sell, partially_fillable: false, ..Default::default() @@ -695,8 +697,8 @@ mod tests { data: OrderData { sell_token: token_a, buy_token: token_b, - sell_amount: to_wei(1000), - buy_amount: to_wei(1000), + sell_amount: to_wei(1000).into(), + buy_amount: to_wei(1000).into(), kind: OrderKind::Sell, partially_fillable: false, ..Default::default() @@ -709,8 +711,8 @@ mod tests { data: OrderData { sell_token: token_b, buy_token: token_a, - sell_amount: to_wei(1000), - buy_amount: to_wei(1000), + sell_amount: to_wei(1000).into(), + buy_amount: to_wei(1000).into(), kind: OrderKind::Sell, partially_fillable: false, ..Default::default() @@ -723,8 +725,8 @@ mod tests { data: OrderData { sell_token: token_b, buy_token: token_a, - sell_amount: to_wei(2), - buy_amount: to_wei(1000), + sell_amount: to_wei(2).into(), + buy_amount: to_wei(1000).into(), kind: OrderKind::Sell, partially_fillable: false, ..Default::default() @@ -757,8 +759,8 @@ mod tests { data: OrderData { sell_token: token_a, buy_token: token_b, - sell_amount: to_wei(900), - buy_amount: to_wei(1000), + sell_amount: to_wei(900).into(), + buy_amount: to_wei(1000).into(), kind: OrderKind::Sell, partially_fillable: false, ..Default::default() @@ -770,8 +772,8 @@ mod tests { data: OrderData { sell_token: token_b, buy_token: token_a, - sell_amount: to_wei(900), - buy_amount: to_wei(1000), + sell_amount: to_wei(900).into(), + buy_amount: to_wei(1000).into(), kind: OrderKind::Sell, partially_fillable: false, ..Default::default() @@ -801,8 +803,8 @@ mod tests { data: OrderData { sell_token: token_a, buy_token: token_b, - sell_amount: to_wei(10), - buy_amount: to_wei(8), + sell_amount: to_wei(10).into(), + buy_amount: to_wei(8).into(), kind: OrderKind::Sell, partially_fillable: false, ..Default::default() @@ -813,8 +815,8 @@ mod tests { data: OrderData { sell_token: token_b, buy_token: token_a, - sell_amount: to_wei(10), - buy_amount: to_wei(9), + sell_amount: to_wei(10).into(), + buy_amount: to_wei(9).into(), kind: OrderKind::Sell, partially_fillable: false, ..Default::default() @@ -886,7 +888,7 @@ mod tests { data: OrderData { sell_token: token_a, buy_token: token_b, - sell_amount: U256::MAX, + sell_amount: U256::MAX.into(), buy_amount: 1.into(), kind: OrderKind::Sell, partially_fillable: false, diff --git a/crates/solvers/Cargo.toml b/crates/solvers/Cargo.toml index a20d616c99..b31c43b89f 100644 --- a/crates/solvers/Cargo.toml +++ b/crates/solvers/Cargo.toml @@ -25,6 +25,7 @@ humantime-serde = { workspace = true } hyper = "0.14" itertools = "0.11" num = "0.4" +number = { path = "../number" } prometheus = { workspace = true } prometheus-metric-storage = { workspace = true } rate-limit = { path = "../rate-limit" } diff --git a/crates/solvers/src/boundary/legacy.rs b/crates/solvers/src/boundary/legacy.rs index df0f706bb6..19df8cc0e3 100644 --- a/crates/solvers/src/boundary/legacy.rs +++ b/crates/solvers/src/boundary/legacy.rs @@ -166,7 +166,7 @@ fn to_boundary_auction( external_price: info .reference_price .map(|price| price.0 .0.to_f64_lossy() / 1e18), - internal_buffer: Some(info.available_balance), + internal_buffer: Some(info.available_balance.into()), accepted_for_internalization: info.trusted, // Quasimodo crashes when the reference token (i.e. WETH) doesn't // have decimals. So use a reasonable default if we don't get one. @@ -209,12 +209,12 @@ fn to_boundary_auction( id: Some(OrderUid(order.uid.0)), sell_token: order.sell.token.0, buy_token: order.buy.token.0, - sell_amount: order.sell.amount, - buy_amount: order.buy.amount, + sell_amount: order.sell.amount.into(), + buy_amount: order.buy.amount.into(), allow_partial_fill: order.partially_fillable, is_sell_order: order.side == order::Side::Sell, fee: TokenAmount { - amount: order.fee().amount, + amount: order.fee().amount.into(), token: order.fee().token.0, }, cost: gas.gp_order_cost(), @@ -229,7 +229,7 @@ fn to_boundary_auction( for liquidity in &auction.liquidity { let cost = TokenAmount { - amount: U256::from_f64_lossy(liquidity.gas.0.to_f64_lossy() * gas.gas_price), + amount: U256::from_f64_lossy(liquidity.gas.0.to_f64_lossy() * gas.gas_price).into(), token: weth.0, }; @@ -239,11 +239,11 @@ fn to_boundary_auction( reserves: [ ( state.reserves.get().0.token.0, - state.reserves.get().0.amount, + state.reserves.get().0.amount.into(), ), ( state.reserves.get().1.token.0, - state.reserves.get().1.amount, + state.reserves.get().1.amount.into(), ), ] .into_iter() @@ -260,7 +260,7 @@ fn to_boundary_auction( ( reserve.asset.token.0, WeightedPoolTokenData { - balance: reserve.asset.amount, + balance: reserve.asset.amount.into(), weight: to_big_rational(&reserve.weight), }, ) @@ -285,7 +285,12 @@ fn to_boundary_auction( }; let Some(scaling_rates) = reserves_without_bpt() - .map(|reserve| Some((reserve.asset.token.0, to_scaling_rate(&reserve.scale)?))) + .map(|reserve| { + Some(( + reserve.asset.token.0, + to_scaling_rate(&reserve.scale)?.into(), + )) + }) .collect() else { // A scaling factor that cannot be represented in the format @@ -296,7 +301,7 @@ fn to_boundary_auction( ( AmmParameters::Stable(StablePoolParameters { reserves: reserves_without_bpt() - .map(|reserve| (reserve.asset.token.0, reserve.asset.amount)) + .map(|reserve| (reserve.asset.token.0, reserve.asset.amount.into())) .collect(), scaling_rates, amplification_parameter: to_big_rational(&state.amplification_parameter), @@ -321,7 +326,7 @@ fn to_boundary_auction( address: liquidity.address, tokens: vec![token(state.tokens.get().0), token(state.tokens.get().1)], state: PoolState { - sqrt_price: state.sqrt_price.0, + sqrt_price: state.sqrt_price.0.into(), liquidity: state.liquidity.0.into(), tick: num::BigInt::from(state.tick.0), liquidity_net: state @@ -337,7 +342,7 @@ fn to_boundary_auction( ), }, gas_stats: PoolStats { - mean_gas: liquidity.gas.0, + mean_gas: liquidity.gas.0.into(), }, }, }), @@ -353,12 +358,12 @@ fn to_boundary_auction( id: None, sell_token: state.maker.token.0, buy_token: state.taker.token.0, - sell_amount: state.maker.amount, - buy_amount: state.taker.amount, + sell_amount: state.maker.amount.into(), + buy_amount: state.taker.amount.into(), allow_partial_fill: true, is_sell_order: false, fee: TokenAmount { - amount: state.fee().amount, + amount: state.fee().amount.into(), token: state.fee().token.0, }, cost, @@ -403,13 +408,13 @@ fn to_domain_solution( signature: jit.order.signature.clone().into(), sell: eth::Asset { token: eth::TokenAddress(jit.order.data.sell_token), - amount: jit.order.data.sell_amount, + amount: *jit.order.data.sell_amount, }, buy: eth::Asset { token: eth::TokenAddress(jit.order.data.buy_token), - amount: jit.order.data.buy_amount, + amount: *jit.order.data.buy_amount, }, - fee: order::Fee(jit.order.data.fee_amount), + fee: order::Fee(*jit.order.data.fee_amount), side: match jit.order.data.kind { OrderKind::Buy => order::Side::Buy, OrderKind::Sell => order::Side::Sell, @@ -421,8 +426,8 @@ fn to_domain_solution( valid_to: jit.order.data.valid_to, }, executed: match jit.order.data.kind { - model::order::OrderKind::Buy => jit.exec_buy_amount, - model::order::OrderKind::Sell => jit.exec_sell_amount, + model::order::OrderKind::Buy => *jit.exec_buy_amount, + model::order::OrderKind::Sell => *jit.exec_sell_amount, }, })); } @@ -437,12 +442,13 @@ fn to_domain_solution( solution::Fulfillment::new( (*order).clone(), match order.side { - order::Side::Buy => execution.exec_buy_amount, - order::Side::Sell => execution.exec_sell_amount, + order::Side::Buy => *execution.exec_buy_amount, + order::Side::Sell => *execution.exec_sell_amount, }, match order.solver_determines_fee() { true => execution .exec_fee_amount + .map(Into::into) .map(solution::Fee::Surplus) .context("no surplus fee")?, false => solution::Fee::Protocol, @@ -457,11 +463,11 @@ fn to_domain_solution( liquidity: (*liquidity).clone(), input: eth::Asset { token: state.taker.token, - amount: execution.exec_buy_amount, + amount: *execution.exec_buy_amount, }, output: eth::Asset { token: state.maker.token, - amount: execution.exec_sell_amount, + amount: *execution.exec_sell_amount, }, internalize: execution .exec_plan @@ -486,11 +492,11 @@ fn to_domain_solution( liquidity: (*liquidity).clone(), input: eth::Asset { token: eth::TokenAddress(interaction.buy_token), - amount: interaction.exec_buy_amount, + amount: *interaction.exec_buy_amount, }, output: eth::Asset { token: eth::TokenAddress(interaction.sell_token), - amount: interaction.exec_sell_amount, + amount: *interaction.exec_sell_amount, }, internalize: interaction.exec_plan.internal, }); @@ -502,14 +508,14 @@ fn to_domain_solution( let coordinate = interaction.exec_plan.as_ref().map(|e| &e.coordinates); let interaction = solution::Interaction::Custom(solution::CustomInteraction { target: interaction.target, - value: eth::Ether(interaction.value), + value: eth::Ether(*interaction.value), calldata: interaction.call_data.clone(), inputs: interaction .inputs .iter() .map(|i| eth::Asset { token: eth::TokenAddress(i.token), - amount: i.amount, + amount: *i.amount, }) .collect(), outputs: interaction @@ -517,7 +523,7 @@ fn to_domain_solution( .iter() .map(|i| eth::Asset { token: eth::TokenAddress(i.token), - amount: i.amount, + amount: *i.amount, }) .collect(), internalize: interaction @@ -541,7 +547,7 @@ fn to_domain_solution( spender: approval.spender, asset: eth::Asset { token: eth::TokenAddress(approval.token), - amount: approval.amount, + amount: *approval.amount, }, }) .collect(); @@ -565,7 +571,7 @@ fn to_domain_solution( model .prices .iter() - .map(|(address, price)| (eth::TokenAddress(*address), *price)) + .map(|(address, price)| (eth::TokenAddress(*address), (*price).into())) .collect(), ), trades, @@ -574,7 +580,7 @@ fn to_domain_solution( .map(|(interaction, _)| interaction) .collect(), score: match model.score { - Score::Solver { score } => solution::Score::Solver(score), + Score::Solver { score } => solution::Score::Solver(*score), Score::RiskAdjusted { success_probability, .. @@ -615,8 +621,8 @@ fn to_boundary_auction_result(notification: ¬ification::Notification) -> (i64 } Kind::ScoringFailed(ScoreKind::ObjectiveValueNonPositive(quality, gas_cost)) => { AuctionResult::Rejected(SolverRejectionReason::ObjectiveValueNonPositive { - quality: quality.0, - gas_cost: gas_cost.0, + quality: quality.0.into(), + gas_cost: gas_cost.0.into(), }) } Kind::ScoringFailed(ScoreKind::ZeroScore) => { @@ -624,8 +630,8 @@ fn to_boundary_auction_result(notification: ¬ification::Notification) -> (i64 } Kind::ScoringFailed(ScoreKind::ScoreHigherThanQuality(score, quality)) => { AuctionResult::Rejected(SolverRejectionReason::ScoreHigherThanQuality { - score: score.0, - quality: quality.0, + score: score.0.into(), + quality: quality.0.into(), }) } Kind::ScoringFailed(ScoreKind::SuccessProbabilityOutOfRange(_)) => { diff --git a/crates/solvers/src/boundary/naive.rs b/crates/solvers/src/boundary/naive.rs index 3e47ef1ac0..e2f21821a1 100644 --- a/crates/solvers/src/boundary/naive.rs +++ b/crates/solvers/src/boundary/naive.rs @@ -80,15 +80,15 @@ pub fn solve( order::Class::Limit => OrderClass::Limit, order::Class::Liquidity => OrderClass::Liquidity, }, - solver_fee: order.fee().amount, + solver_fee: order.fee().amount.into(), ..Default::default() }, data: OrderData { sell_token: order.sell.token.0, buy_token: order.buy.token.0, - sell_amount: order.sell.amount, - buy_amount: order.buy.amount, - fee_amount: order.fee().amount, + sell_amount: order.sell.amount.into(), + buy_amount: order.buy.amount.into(), + fee_amount: order.fee().amount.into(), kind: match order.side { order::Side::Buy => OrderKind::Buy, order::Side::Sell => OrderKind::Sell, @@ -236,11 +236,11 @@ impl SettlementHandling for PoolHandler { *self.swap.lock().unwrap() = Some(( eth::Asset { token: eth::TokenAddress(execution.input_max.token), - amount: execution.input_max.amount, + amount: *execution.input_max.amount, }, eth::Asset { token: eth::TokenAddress(execution.output.token), - amount: execution.output.amount, + amount: *execution.output.amount, }, )); Ok(())