Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Solvers solution pre/post interactions #2679

Merged
merged 14 commits into from
May 13, 2024
6 changes: 3 additions & 3 deletions crates/driver/src/domain/competition/solution/encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ pub fn tx(
let mut clearing_prices =
Vec::with_capacity(solution.prices.len() + (solution.trades().len() * 2));
let mut trades: Vec<Trade> = Vec::with_capacity(solution.trades().len());
let mut pre_interactions = Vec::new();
let mut pre_interactions = solution.pre_interactions.clone();
let mut interactions =
Vec::with_capacity(approvals.size_hint().0 + solution.interactions().len());
let mut post_interactions = Vec::new();
let mut post_interactions = solution.post_interactions.clone();
let mut native_unwrap = eth::TokenAmount(eth::U256::zero());

// Encode uniform clearing price vector
Expand Down Expand Up @@ -183,7 +183,7 @@ pub fn tx(
interactions.push(match interaction {
competition::solution::Interaction::Custom(interaction) => eth::Interaction {
value: interaction.value,
target: interaction.target.0.into(),
target: interaction.target.into(),
call_data: interaction.call_data.clone(),
},
competition::solution::Interaction::Liquidity(liquidity) => {
Expand Down
18 changes: 18 additions & 0 deletions crates/driver/src/domain/competition/solution/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ pub struct Solution {
id: Id,
trades: Vec<Trade>,
prices: Prices,
pre_interactions: Vec<eth::Interaction>,
interactions: Vec<Interaction>,
post_interactions: Vec<eth::Interaction>,
solver: Solver,
weth: eth::WethAddress,
gas: Option<eth::Gas>,
Expand All @@ -56,7 +58,9 @@ impl Solution {
id: Id,
trades: Vec<Trade>,
prices: Prices,
pre_interactions: Vec<eth::Interaction>,
interactions: Vec<Interaction>,
post_interactions: Vec<eth::Interaction>,
solver: Solver,
weth: eth::WethAddress,
gas: Option<eth::Gas>,
Expand All @@ -66,7 +70,9 @@ impl Solution {
id,
trades,
prices,
pre_interactions,
interactions,
post_interactions,
solver,
weth,
gas,
Expand Down Expand Up @@ -246,7 +252,17 @@ impl Solution {
id: Id::Merged([self.id.ids(), other.id.ids()].concat()),
trades: [self.trades.clone(), other.trades.clone()].concat(),
prices,
pre_interactions: [
self.pre_interactions.clone(),
other.pre_interactions.clone(),
]
.concat(),
interactions: [self.interactions.clone(), other.interactions.clone()].concat(),
post_interactions: [
self.post_interactions.clone(),
other.post_interactions.clone(),
]
.concat(),
solver: self.solver.clone(),
weth: self.weth,
// Same solver are guaranteed to have the same fee handler
Expand Down Expand Up @@ -393,7 +409,9 @@ impl std::fmt::Debug for Solution {
.field("id", &self.id)
.field("trades", &self.trades)
.field("prices", &self.prices)
.field("pre_interactions", &self.pre_interactions)
.field("interactions", &self.interactions)
.field("post_interactions", &self.post_interactions)
.field("solver", &self.solver.name())
.finish()
}
Expand Down
25 changes: 24 additions & 1 deletion crates/driver/src/infra/solver/dto/solution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ use {
crate::{
domain::{competition, competition::order, eth, liquidity},
infra::{solver::Config, Solver},
util::serialize,
util::{serialize, Bytes},
},
itertools::Itertools,
model::interaction::InteractionData,
serde::Deserialize,
serde_with::serde_as,
std::collections::HashMap,
Expand Down Expand Up @@ -121,6 +122,15 @@ impl Solutions {
.into_iter()
.map(|(address, price)| (address.into(), price))
.collect(),
solution
.pre_interactions
.into_iter()
.map(|interaction| eth::Interaction {
target: interaction.target.into(),
value: interaction.value.into(),
call_data: Bytes(interaction.call_data),
})
.collect(),
solution
.interactions
.into_iter()
Expand Down Expand Up @@ -188,6 +198,15 @@ impl Solutions {
}
})
.try_collect()?,
solution
.post_interactions
.into_iter()
.map(|interaction| eth::Interaction {
target: interaction.target.into(),
value: interaction.value.into(),
call_data: Bytes(interaction.call_data),
})
.collect(),
solver.clone(),
weth,
solution.gas.map(|gas| eth::Gas(gas.into())),
Expand Down Expand Up @@ -221,7 +240,11 @@ pub struct Solution {
#[serde_as(as = "HashMap<_, serialize::U256>")]
prices: HashMap<eth::H160, eth::U256>,
trades: Vec<Trade>,
#[serde(default)]
pre_interactions: Vec<InteractionData>,
interactions: Vec<Interaction>,
#[serde(default)]
post_interactions: Vec<InteractionData>,
// TODO: remove this once all solvers are updated to not return the score
// https://github.com/cowprotocol/services/issues/2588
#[allow(dead_code)]
Expand Down
12 changes: 12 additions & 0 deletions crates/solvers-dto/src/solution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ pub struct Solution {
#[serde_as(as = "HashMap<_, HexOrDecimalU256>")]
pub prices: HashMap<H160, U256>,
pub trades: Vec<Trade>,
#[serde(default)]
pub pre_interactions: Vec<InteractionData>,
pub interactions: Vec<Interaction>,
#[serde(default)]
pub post_interactions: Vec<InteractionData>,
#[serde(skip_serializing_if = "Option::is_none")]
pub gas: Option<u64>,
}
Expand Down Expand Up @@ -94,6 +98,14 @@ pub enum Interaction {
Custom(CustomInteraction),
}

#[derive(Debug, Serialize)]
#[serde(tag = "kind", rename_all = "camelCase")]
pub struct InteractionData {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: maybe

Suggested change
pub struct InteractionData {
pub struct Call {

to avoid confusion with existing Interaction struct?

It would be nice to reuse this type on the CustomInteraction struct, but it seems like that would be a breaking change 😢

pub target: H160,
pub value: U256,
pub calldata: Vec<u8>,
}

#[serde_as]
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
Expand Down
28 changes: 28 additions & 0 deletions crates/solvers/openapi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -861,12 +861,40 @@ components:
type: array
items:
$ref: "#/components/schemas/Trade"
preInteractions:
description: |
Interactions to encode before a settlement.
type: array
items:
$ref: "#/components/schemas/InteractionData"
interactions:
description: |
Interactions to encode within a settlement.
type: array
items:
$ref: "#/components/schemas/InteractionData"
postInteractions:
description: |
Interactions to encode after a settlement.
type: array
items:
$ref: "#/components/schemas/Interaction"
gas:
type: integer
description: How many units of gas this solution is estimated to cost.
InteractionData:
type: object
properties:
target:
$ref: "#/components/schemas/Address"
value:
$ref: "#/components/schemas/TokenAmount"
callData:
type: array
items:
$ref: "#/components/schemas/CallData"
description: The call data to be used for the interaction.
CallData:
description: Some `calldata` sent to a contract in a transaction encoded as a hex with `0x` prefix.
type: string
example: "0xca11da7a"
15 changes: 15 additions & 0 deletions crates/solvers/src/api/routes/solve/dto/solution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ pub fn from_domain(solutions: &[solution::Solution]) -> super::Solutions {
}
})
.collect(),
pre_interactions: interaction_data_from_domain(&solution.pre_interactions),
post_interactions: interaction_data_from_domain(&solution.post_interactions),
interactions: solution
.interactions
.iter()
Expand Down Expand Up @@ -118,3 +120,16 @@ pub fn from_domain(solutions: &[solution::Solution]) -> super::Solutions {
.collect(),
}
}

fn interaction_data_from_domain(
interaction_data: &[solution::InteractionData],
) -> Vec<InteractionData> {
interaction_data
.iter()
.map(|interaction| InteractionData {
target: interaction.target,
value: interaction.value.0,
calldata: interaction.calldata.clone(),
})
.collect()
}
2 changes: 2 additions & 0 deletions crates/solvers/src/boundary/legacy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -563,10 +563,12 @@ fn to_domain_solution(
.collect(),
),
trades,
pre_interactions: Default::default(),
interactions: interactions
.into_iter()
.map(|(interaction, _)| interaction)
.collect(),
post_interactions: Default::default(),
gas: None,
})
}
Expand Down
2 changes: 2 additions & 0 deletions crates/solvers/src/boundary/naive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ pub fn solve(
// auctions (which is how we model a /quote request) it can not be used for
// quoting anyway.
gas: None,
pre_interactions: vec![],
interactions: swap
.into_iter()
.map(|(input, output)| {
Expand All @@ -154,6 +155,7 @@ pub fn solve(
})
})
.collect(),
post_interactions: vec![],
})
}

Expand Down
13 changes: 13 additions & 0 deletions crates/solvers/src/domain/solution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ pub struct Solution {
pub id: Id,
pub prices: ClearingPrices,
pub trades: Vec<Trade>,
pub pre_interactions: Vec<InteractionData>,
pub interactions: Vec<Interaction>,
pub post_interactions: Vec<InteractionData>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would lead to this:

Suggested change
pub post_interactions: Vec<InteractionData>,
pub post_interactions: Vec<eth::Interaction>,

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But eth::Interaction is part of the driver crate, and the solver crate should not depend on the driver, right? Do you want me to extract this type into a shared crate, like model?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, you are completely right (I missed that this was a different create). We could still add this type in the eth module of the solvers crate but not super important.

pub gas: Option<eth::Gas>,
}

Expand Down Expand Up @@ -187,7 +189,9 @@ impl Single {
(order.buy.token, sell.checked_sub(surplus_fee)?),
]),
trades: vec![Trade::Fulfillment(Fulfillment::new(order, executed, fee)?)],
pre_interactions: Default::default(),
interactions,
post_interactions: Default::default(),
gas: Some(gas),
})
}
Expand Down Expand Up @@ -357,6 +361,15 @@ pub struct CustomInteraction {
pub allowances: Vec<Allowance>,
}

/// An arbitrary ethereum interaction that is required for the settlement
/// execution.
#[derive(Debug)]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can maybe reuse this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't get it. To reuse something from the driver crate in what sense?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are redifining a struct in the domain which already exists in the domain. Now, we might not want to overload structs that happen to have the same fields (generally defining new structs for different semantics is good), but here this is similar to re-defining TokenAmount (which arguably is never going to change).

pub struct InteractionData {
pub target: Address,
pub value: eth::Ether,
pub calldata: Vec<u8>,
}

/// Approval required to make some `[CustomInteraction]` possible.
#[derive(Debug)]
pub struct Allowance {
Expand Down
10 changes: 10 additions & 0 deletions crates/solvers/src/tests/baseline/bal_liquidity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ async fn weighted() {
"executedAmount": "1000000000000000000"
}
],
"preInteractions": [],
"interactions": [
{
"kind": "liquidity",
Expand All @@ -128,6 +129,7 @@ async fn weighted() {
"outputAmount": "1657855325872947866705"
},
],
"postInteractions": [],
"gas": 206391,
}]
}),
Expand Down Expand Up @@ -258,6 +260,7 @@ async fn weighted_v3plus() {
"executedAmount": "1000000000000000000"
}
],
"preInteractions": [],
"interactions": [
{
"kind": "liquidity",
Expand All @@ -269,6 +272,7 @@ async fn weighted_v3plus() {
"outputAmount": "1663373703594405548696"
},
],
"postInteractions": [],
"gas": 206391,
}]
}),
Expand Down Expand Up @@ -417,6 +421,7 @@ async fn stable() {
"executedAmount": "10000000000000000000"
}
],
"preInteractions": [],
"interactions": [
{
"kind": "liquidity",
Expand All @@ -428,6 +433,7 @@ async fn stable() {
"outputAmount": "9999475"
},
],
"postInteractions": [],
"gas": 289911,
},
{
Expand All @@ -445,6 +451,7 @@ async fn stable() {
"executedAmount": "10000000"
}
],
"preInteractions": [],
"interactions": [
{
"kind": "liquidity",
Expand All @@ -456,6 +463,7 @@ async fn stable() {
"outputAmount": "10000000"
},
],
"postInteractions": [],
"gas": 289911,
},
]
Expand Down Expand Up @@ -588,6 +596,7 @@ async fn composable_stable_v4() {
"executedAmount": "10000000000000000000"
}
],
"preInteractions": [],
"interactions": [
{
"kind": "liquidity",
Expand All @@ -599,6 +608,7 @@ async fn composable_stable_v4() {
"outputAmount": "10029862202766050434"
},
],
"postInteractions": [],
"gas": 289911,
},
]
Expand Down
Loading
Loading