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

Define protocol fee params and forward to driver #2098

Merged
merged 25 commits into from
Dec 12, 2023
Merged
Changes from 1 commit
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
Prev Previous commit
Next Next commit
cr fixes
sunce86 committed Dec 6, 2023
commit 484ca6beb638783c275ab41c727f209a0ecfbc96
89 changes: 53 additions & 36 deletions crates/autopilot/src/arguments.rs
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@ use {
std::{
net::SocketAddr,
num::{NonZeroUsize, ParseFloatError},
str::FromStr,
time::Duration,
},
url::Url,
@@ -208,7 +209,9 @@ pub struct Arguments {
)]
pub solve_deadline: Duration,

/// Describes how the protocol fee should be calculated.
/// Describes how the protocol fee should be calculated. Examples:
/// price_improvement:<price_improvement_factor>:<max_volume_factor>
/// volume:<volume_factor>
#[clap(flatten)]
pub fee_policy: FeePolicy,

@@ -288,7 +291,7 @@ impl std::fmt::Display for Arguments {
writeln!(f, "score_cap: {}", self.score_cap)?;
display_option(f, "shadow", &self.shadow)?;
writeln!(f, "solve_deadline: {:?}", self.solve_deadline)?;
writeln!(f, "fee_policy: {}", self.fee_policy)?;
writeln!(f, "fee_policy: {:?}", self.fee_policy)?;
writeln!(
f,
"order_events_cleanup_interval: {:?}",
@@ -303,48 +306,62 @@ impl std::fmt::Display for Arguments {
}
}

#[derive(clap::Parser, Clone)]
#[derive(clap::Parser, Debug, Clone)]
pub struct FeePolicy {
/// How much of the order's price improvement over max(limit price,
/// best_bid) should be taken as a protocol fee.
#[clap(
long,
env,
default_value = None,
value_parser = shared::arguments::parse_percentage_factor
)]
pub price_improvement_factor: Option<f64>,

/// How much of the order's volume should be taken as a protocol fee.
#[clap(
long,
env,
default_value = None,
value_parser = shared::arguments::parse_percentage_factor
)]
pub volume_factor: Option<f64>,
/// Type of fee policy to use.
pub fee_policy_kind: FeePolicyKind,

/// Should protocol fees be collected or skipped for limit orders with
/// in-market price at the time of order creation.
#[clap(long, env, action = clap::ArgAction::Set, default_value = "true")]
pub skip_in_market_orders: bool,
pub fee_policy_skip_market_orders: bool,
}

/// Should protocol fees be collected or skipped for TWAP limit orders.
#[clap(long, env, action = clap::ArgAction::Set, default_value = "true")]
pub skip_twap_orders: bool,
#[derive(clap::Parser, Debug, Clone)]
pub enum FeePolicyKind {
/// How much of the order's price improvement over max(limit price,
/// best_bid) should be taken as a protocol fee.
PriceImprovement {
price_improvement_factor: f64,
max_volume_factor: f64,
},
/// How much of the order's volume should be taken as a protocol fee.
Volume { volume_factor: f64 },
}

impl std::fmt::Display for FeePolicy {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"price_improvement_factor: {:?}, volume_factor: {:?}, skip_in_market_orders: {}, \
skip_twap_orders: {}",
self.price_improvement_factor,
self.volume_factor,
self.skip_in_market_orders,
self.skip_twap_orders
)
impl FromStr for FeePolicyKind {
type Err = String;

fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut parts = s.split(':');
let kind = parts.next().ok_or("missing fee policy kind")?;
match kind {
"price_improvement" => {
let price_improvement_factor = parts
.next()
.ok_or("missing price improvement factor")?
.parse::<f64>()
.map_err(|e| format!("invalid price improvement factor: {}", e))?;
let max_volume_factor = parts
.next()
.ok_or("missing max volume factor")?
.parse::<f64>()
.map_err(|e| format!("invalid max volume factor: {}", e))?;
Ok(Self::PriceImprovement {
price_improvement_factor,
max_volume_factor,
})
}
"volume" => {
let volume_factor = parts
.next()
.ok_or("missing volume factor")?
.parse::<f64>()
.map_err(|e| format!("invalid volume factor: {}", e))?;
Ok(Self::Volume { volume_factor })
}
_ => Err(format!("invalid fee policy kind: {}", kind)),
}
}
}

4 changes: 2 additions & 2 deletions crates/autopilot/src/driver_model.rs
Original file line number Diff line number Diff line change
@@ -160,7 +160,7 @@ pub mod solve {
/// quoted amounts) pay the protocol a factor of the achieved
/// improvement. The fee is taken in `sell` token for `buy`
/// orders and in `buy` token for `sell` orders.
QuoteDeviation {
PriceImprovement {
sunce86 marked this conversation as resolved.
Show resolved Hide resolved
/// Factor of price improvement the protocol charges as a fee.
/// Price improvement is the difference between executed price and
/// limit price or quoted price (whichever is better)
@@ -171,7 +171,7 @@ pub mod solve {
/// the protocol for settling this order.
factor: f64,
/// Cap protocol fee with a percentage of the order's volume.
volume_cap_factor: Option<f64>,
volume_cap_factor: f64,
},
/// How much of the order's volume should be taken as a protocol fee.
/// The fee is taken in `sell` token for `sell` orders and in `buy`
24 changes: 13 additions & 11 deletions crates/autopilot/src/run_loop.rs
Original file line number Diff line number Diff line change
@@ -517,16 +517,18 @@ pub fn solve_request(
.collect()
};
let order_is_untouched = remaining_order.executed_amount.is_zero();
let fee_policy = match (
fee_policy.price_improvement_factor,
fee_policy.volume_factor,
) {
(Some(factor), volume_cap_factor) => Some(FeePolicy::QuoteDeviation {
factor,
volume_cap_factor,
}),
(None, Some(factor)) => Some(FeePolicy::Volume { factor }),
(_, _) => None,

let fee_policy = match fee_policy.fee_policy_kind {
arguments::FeePolicyKind::PriceImprovement {
price_improvement_factor,
max_volume_factor,
} => FeePolicy::PriceImprovement {
factor: price_improvement_factor,
volume_cap_factor: max_volume_factor,
},
arguments::FeePolicyKind::Volume { volume_factor } => FeePolicy::Volume {
factor: volume_factor,
},
};

let fee_policies = match order.metadata.class {
@@ -537,7 +539,7 @@ pub fn solve_request(

// todo https://github.com/cowprotocol/services/issues/2115
// skip protocol fee for TWAP limit orders
OrderClass::Limit(_) => fee_policy.map(|policy| vec![policy]).unwrap_or(vec![]),
OrderClass::Limit(_) => vec![fee_policy],
};
solve::Order {
uid: order.metadata.uid,
2 changes: 1 addition & 1 deletion crates/driver/src/domain/competition/order/fees.rs
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ pub enum FeePolicy {
/// amounts) pay the protocol a factor of the achieved improvement.
/// The fee is taken in `sell` token for `buy` orders and in `buy`
/// token for `sell` orders.
QuoteDeviation {
PriceImprovement {
/// Factor of price improvement the protocol charges as a fee.
/// Price improvement is the difference between executed price and
/// limit price or quoted price (whichever is better)
6 changes: 3 additions & 3 deletions crates/driver/src/infra/api/routes/solve/dto/auction.rs
Original file line number Diff line number Diff line change
@@ -119,10 +119,10 @@ impl Auction {
.fee_policies
.into_iter()
.map(|policy| match policy {
FeePolicy::QuoteDeviation {
FeePolicy::PriceImprovement {
factor,
volume_cap_factor,
} => competition::order::FeePolicy::QuoteDeviation {
} => competition::order::FeePolicy::PriceImprovement {
factor,
volume_cap_factor,
},
@@ -308,6 +308,6 @@ enum Class {
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
enum FeePolicy {
QuoteDeviation { factor: f64, volume_cap_factor: f64 },
PriceImprovement { factor: f64, volume_cap_factor: f64 },
Volume { factor: f64 },
}
2 changes: 1 addition & 1 deletion crates/driver/src/tests/setup/driver.rs
Original file line number Diff line number Diff line change
@@ -101,7 +101,7 @@ pub fn solve_req(test: &Test) -> serde_json::Value {
"signingScheme": "eip712",
"signature": format!("0x{}", hex::encode(quote.order_signature(&test.blockchain))),
"feePolicies": [{
"quoteDeviation": {
"priceImprovement": {
"factor": 0.5,
"volume_cap_factor": 0.06,
}