Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 61 additions & 29 deletions crates/driver/src/domain/competition/order/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,18 @@ use {
derive_more::{From, Into},
eth_domain_types as eth,
model::order::{BuyTokenDestination, SellTokenSource},
std::sync::Arc,
};
pub use {fees::FeePolicy, signature::Signature};

pub mod app_data;
pub mod fees;
pub mod signature;

/// An order in the auction.
#[derive(Debug, Clone)]
pub struct Order {
/// The immutable, auction-independent data of an order. Wrapped in [`Arc`] so
/// that per-solver copies of [`Order`] share a single allocation.
#[derive(Debug)]
pub struct OrderData {
pub uid: Uid,
/// The user specified a custom address to receive the output of this order.
pub receiver: Option<eth::Address>,
Expand All @@ -29,8 +31,6 @@ pub struct Order {
pub sell: eth::Asset,
pub side: Side,
pub kind: Kind,
pub app_data: app_data::AppData,
pub partial: Partial,
/// The onchain calls to run before sending user funds to the settlement
/// contract.
/// These are set by the user and included in the settlement transaction.
Expand All @@ -50,6 +50,32 @@ pub struct Order {
pub quote: Option<Quote>,
}

/// An order in the auction.
///
/// Designed to be cheap to clone. Most of the data is immutable and is
/// reference counted. Solvers only get individual copies of data they
/// have need to update during the pre-processing phase.
#[derive(Debug, Clone)]
pub struct Order {
/// Immutable order data shared across all per-solver copies.
pub data: Arc<OrderData>,
/// Per-solver mutable as the data may only become available after
/// assembling the orders.
pub app_data: app_data::AppData,
/// Per-solver mutable as the driver may allocated different amounts of
/// the user's available balance based on the solver's order prioritization
/// logic.
pub partial: Partial,
}

impl std::ops::Deref for Order {
type Target = OrderData;

fn deref(&self) -> &Self::Target {
&self.data
}
}

/// An amount denominated in the sell token of an [`Order`].
#[derive(Clone, Copy, Debug, Default, Eq, Ord, PartialEq, PartialOrd, From, Into)]
pub struct SellAmount(pub eth::U256);
Expand Down Expand Up @@ -433,37 +459,43 @@ mod tests {
amount: eth::U256::from(amount).into(),
};

let order = |sell_amount: u64, buy_amount: u64, available: Option<eth::Asset>| Order {
uid: Default::default(),
receiver: Default::default(),
created: util::Timestamp(100),
valid_to: util::Timestamp(u32::MAX),
buy: buy(buy_amount),
sell: sell(sell_amount),
side: match available {
let order = |sell_amount: u64, buy_amount: u64, available: Option<eth::Asset>| {
let side = match available {
None => Side::Sell,
Some(executed) if executed.token == sell(0).token => Side::Sell,
Some(executed) if executed.token == buy(0).token => Side::Buy,
_ => panic!(),
},
kind: Kind::Limit,
app_data: Default::default(),
partial: available
};
let partial = available
.map(|available| Partial::Yes {
available: available.amount.into(),
})
.unwrap_or(Partial::No),
pre_interactions: Default::default(),
post_interactions: Default::default(),
sell_token_balance: SellTokenBalance::Erc20,
buy_token_balance: BuyTokenBalance::Erc20,
signature: Signature {
scheme: signature::Scheme::PreSign,
data: Default::default(),
signer: Default::default(),
},
protocol_fees: Default::default(),
quote: Default::default(),
.unwrap_or(Partial::No);
Order {
data: Arc::new(OrderData {
uid: Default::default(),
receiver: Default::default(),
created: util::Timestamp(100),
valid_to: util::Timestamp(u32::MAX),
buy: buy(buy_amount),
sell: sell(sell_amount),
side,
kind: Kind::Limit,
pre_interactions: Default::default(),
post_interactions: Default::default(),
sell_token_balance: SellTokenBalance::Erc20,
buy_token_balance: BuyTokenBalance::Erc20,
signature: Signature {
scheme: signature::Scheme::PreSign,
data: Default::default(),
signer: Default::default(),
},
protocol_fees: Default::default(),
quote: Default::default(),
}),
app_data: Default::default(),
partial,
}
};

assert_eq!(
Expand Down
84 changes: 46 additions & 38 deletions crates/driver/src/domain/competition/pre_processing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -463,47 +463,17 @@ impl Utilities {
let orders: Vec<_> = results
.into_iter()
.filter_map(|(amm, result)| match result {
Ok(template) => Some(Order {
uid: template.order.uid(&domain_separator, amm).0.into(),
receiver: template.order.receiver,
created: u32::try_from(Utc::now().timestamp())
.unwrap_or(u32::MIN)
.into(),
valid_to: template.order.valid_to.into(),
buy: eth::Asset {
amount: template.order.buy_amount.into(),
token: template.order.buy_token.into(),
},
sell: eth::Asset {
amount: template.order.sell_amount.into(),
token: template.order.sell_token.into(),
},
kind: order::Kind::Limit,
side: template.order.kind.into(),
app_data: order::app_data::AppDataHash(FixedBytes(template.order.app_data.0))
.into(),
buy_token_balance: template.order.buy_token_balance.into(),
sell_token_balance: template.order.sell_token_balance.into(),
partial: match template.order.partially_fillable {
Ok(template) => {
let partial = match template.order.partially_fillable {
true => order::Partial::Yes {
available: match template.order.kind {
OrderKind::Sell => order::TargetAmount(template.order.sell_amount),
OrderKind::Buy => order::TargetAmount(template.order.buy_amount),
},
},
false => order::Partial::No,
},
pre_interactions: template
.pre_interactions
.into_iter()
.map(Into::into)
.collect(),
post_interactions: template
.post_interactions
.into_iter()
.map(Into::into)
.collect(),
signature: match template.signature {
};
let signature = match template.signature {
Signature::Eip1271(bytes) => order::Signature {
scheme: order::signature::Scheme::Eip1271,
data: Bytes::from(bytes),
Expand All @@ -517,10 +487,48 @@ impl Utilities {
);
return None;
}
},
protocol_fees: vec![],
quote: None,
}),
};
Some(Order {
data: Arc::new(order::OrderData {
uid: template.order.uid(&domain_separator, amm).0.into(),
receiver: template.order.receiver,
created: u32::try_from(Utc::now().timestamp())
.unwrap_or(u32::MIN)
.into(),
valid_to: template.order.valid_to.into(),
buy: eth::Asset {
amount: template.order.buy_amount.into(),
token: template.order.buy_token.into(),
},
sell: eth::Asset {
amount: template.order.sell_amount.into(),
token: template.order.sell_token.into(),
},
kind: order::Kind::Limit,
side: template.order.kind.into(),
buy_token_balance: template.order.buy_token_balance.into(),
sell_token_balance: template.order.sell_token_balance.into(),
pre_interactions: template
.pre_interactions
.into_iter()
.map(Into::into)
.collect(),
post_interactions: template
.post_interactions
.into_iter()
.map(Into::into)
.collect(),
signature,
protocol_fees: vec![],
quote: None,
}),
app_data: order::app_data::AppDataHash(FixedBytes(
template.order.app_data.0,
))
.into(),
partial,
})
}
Err(err) => {
tracing::warn!(?err, ?amm, "failed to generate template order for cow amm");
None
Expand Down
36 changes: 19 additions & 17 deletions crates/driver/src/domain/competition/solution/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,25 +112,27 @@ impl Solution {
*trade = Trade::Fulfillment(
Fulfillment::new(
competition::Order {
uid: jit.order().uid,
kind: order::Kind::Limit,
side: jit.order().side,
sell: jit.order().sell,
buy: jit.order().buy,
signature: jit.order().signature.clone(),
receiver: Some(jit.order().receiver),
created: u32::try_from(Utc::now().timestamp())
.unwrap_or(u32::MIN)
.into(),
valid_to: jit.order().valid_to,
data: std::sync::Arc::new(order::OrderData {
uid: jit.order().uid,
kind: order::Kind::Limit,
side: jit.order().side,
sell: jit.order().sell,
buy: jit.order().buy,
signature: jit.order().signature.clone(),
receiver: Some(jit.order().receiver),
created: u32::try_from(Utc::now().timestamp())
.unwrap_or(u32::MIN)
.into(),
valid_to: jit.order().valid_to,
pre_interactions: vec![],
post_interactions: vec![],
sell_token_balance: jit.order().sell_token_balance,
buy_token_balance: jit.order().buy_token_balance,
protocol_fees: vec![],
quote: None,
}),
app_data: jit.order().app_data.into(),
partial: jit.order().partially_fillable(),
pre_interactions: vec![],
post_interactions: vec![],
sell_token_balance: jit.order().sell_token_balance,
buy_token_balance: jit.order().buy_token_balance,
protocol_fees: vec![],
quote: None,
},
jit.executed(),
Fee::Dynamic(jit.fee()),
Expand Down
1 change: 0 additions & 1 deletion crates/driver/src/domain/competition/solution/trade.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use {

/// A trade which executes an order as part of this solution.
#[derive(Debug, Clone)]
#[expect(clippy::large_enum_variant)]
pub enum Trade {
Fulfillment(Fulfillment),
Jit(Jit),
Expand Down
52 changes: 27 additions & 25 deletions crates/driver/src/domain/quote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,33 +177,35 @@ impl Order {
competition::Auction::new(
None,
vec![competition::Order {
uid: Default::default(),
receiver: None,
created: u32::try_from(Utc::now().timestamp())
.unwrap_or(u32::MIN)
.into(),
valid_to: util::Timestamp::MAX,
buy: self.buy(),
sell: self.sell(),
side: self.side,
kind: if quote_using_limit_orders {
competition::order::Kind::Limit
} else {
competition::order::Kind::Market
},
data: std::sync::Arc::new(competition::order::OrderData {
uid: Default::default(),
receiver: None,
created: u32::try_from(Utc::now().timestamp())
.unwrap_or(u32::MIN)
.into(),
valid_to: util::Timestamp::MAX,
buy: self.buy(),
sell: self.sell(),
side: self.side,
kind: if quote_using_limit_orders {
competition::order::Kind::Limit
} else {
competition::order::Kind::Market
},
pre_interactions: Default::default(),
post_interactions: Default::default(),
sell_token_balance: competition::order::SellTokenBalance::Erc20,
buy_token_balance: competition::order::BuyTokenBalance::Erc20,
signature: competition::order::Signature {
scheme: competition::order::signature::Scheme::Eip1271,
data: Default::default(),
signer: Default::default(),
},
protocol_fees: Default::default(),
quote: Default::default(),
}),
app_data: Default::default(),
partial: competition::order::Partial::No,
pre_interactions: Default::default(),
post_interactions: Default::default(),
sell_token_balance: competition::order::SellTokenBalance::Erc20,
buy_token_balance: competition::order::BuyTokenBalance::Erc20,
signature: competition::order::Signature {
scheme: competition::order::signature::Scheme::Eip1271,
data: Default::default(),
signer: Default::default(),
},
protocol_fees: Default::default(),
quote: Default::default(),
}],
[
auction::Token {
Expand Down
Loading
Loading