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

Executed total fee token #2966

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
23 changes: 20 additions & 3 deletions crates/autopilot/src/domain/settlement/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,27 @@ impl Settlement {
}

/// Per order fees breakdown. Contains all orders from the settlement
pub fn fee_breakdown(&self) -> HashMap<domain::OrderUid, Option<trade::FeeBreakdown>> {
pub fn fee_breakdown(&self) -> HashMap<domain::OrderUid, trade::FeeBreakdown> {
self.trades
.iter()
.map(|trade| (*trade.uid(), trade.fee_breakdown(&self.auction).ok()))
.map(|trade| {
let fee_breakdown = trade.fee_breakdown(&self.auction).unwrap_or_else(|err| {
tracing::warn!(
?err,
trade = %trade.uid(),
"possible incomplete fee breakdown calculation",
);
trade::FeeBreakdown {
total: eth::Asset {
// TODO surplus token
token: trade.sell_token(),
amount: num::zero(),
},
protocol: vec![],
}
});
(*trade.uid(), fee_breakdown)
})
.collect()
}

Expand Down Expand Up @@ -339,7 +356,7 @@ mod tests {
trade.surplus_in_ether(&auction.prices).unwrap().0,
eth::U256::from(52937525819789126u128)
);
// fee read from "executedSurplusFee" https://api.cow.fi/mainnet/api/v1/orders/0x10dab31217bb6cc2ace0fe601c15d342f7626a1ee5ef0495449800e73156998740a50cf069e992aa4536211b23f286ef88752187ffffffff
// fee read from "executedTotalFee" https://api.cow.fi/mainnet/api/v1/orders/0x10dab31217bb6cc2ace0fe601c15d342f7626a1ee5ef0495449800e73156998740a50cf069e992aa4536211b23f286ef88752187ffffffff
assert_eq!(
trade.fee_in_ether(&auction.prices).unwrap().0,
eth::U256::from(6890975030480504u128)
Expand Down
14 changes: 10 additions & 4 deletions crates/autopilot/src/domain/settlement/trade/math.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,9 @@ impl Trade {
pub fn fee_in_ether(&self, prices: &auction::Prices) -> Result<eth::Ether, Error> {
let total_fee = self.fee_in_sell_token()?;
let price = prices
.get(&self.sell.token)
.ok_or(Error::MissingPrice(self.sell.token))?;
Ok(price.in_eth(total_fee.into()))
.get(&total_fee.token)
.ok_or(Error::MissingPrice(total_fee.token))?;
Ok(price.in_eth(total_fee.amount))
}

/// Converts given surplus fee into sell token fee.
Expand All @@ -134,9 +134,15 @@ impl Trade {

/// Total fee (protocol fee + network fee). Equal to a surplus difference
/// before and after applying the fees.
pub fn fee_in_sell_token(&self) -> Result<eth::SellTokenAmount, Error> {
///
/// Denominated in SELL token
Comment on lines +137 to +138
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need this clarification here since the function name is self-explanatory already?

pub fn fee_in_sell_token(&self) -> Result<eth::Asset, Error> {
let fee = self.fee()?;
self.fee_into_sell_token(fee.amount)
.map(|amount| eth::Asset {
token: self.sell.token,
amount: amount.into(),
})
}

/// Total fee (protocol fee + network fee). Equal to a surplus difference
Expand Down
11 changes: 9 additions & 2 deletions crates/autopilot/src/domain/settlement/trade/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,13 @@ impl Trade {
Ok(FeeBreakdown { total, protocol })
}

pub fn sell_token(&self) -> eth::TokenAddress {
match self {
Self::Fulfillment(trade) => trade.sell.token,
Self::Jit(trade) => trade.sell.token,
}
}

pub fn new(trade: transaction::EncodedTrade, auction: &super::Auction, created: u32) -> Self {
if auction.orders.contains_key(&trade.uid) {
Trade::Fulfillment(Fulfillment {
Expand Down Expand Up @@ -150,8 +157,8 @@ pub struct Jit {
#[derive(Debug, Clone)]
pub struct FeeBreakdown {
/// Total fee the trade was charged (network fee + protocol fee)
// TODO: express in surplus token
pub total: eth::SellTokenAmount,
// TODO surplus token
pub total: eth::Asset,
/// Breakdown of protocol fees.
pub protocol: Vec<ExecutedProtocolFee>,
}
Expand Down
29 changes: 12 additions & 17 deletions crates/autopilot/src/infra/persistence/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -645,28 +645,23 @@ impl Persistence {
.await;

for (order, order_fee) in fee_breakdown {
let total_fee = order_fee
.as_ref()
.map(|fee| u256_to_big_decimal(&fee.total.0))
.unwrap_or_default();
let executed_protocol_fees = order_fee
.map(|fee| {
fee.protocol
.into_iter()
.map(|executed| Asset {
token: ByteArray(executed.fee.token.0 .0),
amount: u256_to_big_decimal(&executed.fee.amount.0),
})
.collect::<Vec<_>>()
})
.unwrap_or_default();
database::order_execution::save(
&mut ex,
&ByteArray(order.0),
auction_id,
block_number,
&total_fee,
&executed_protocol_fees,
Asset {
token: ByteArray(order_fee.total.token.0 .0),
Copy link
Contributor

@m-lord-renkse m-lord-renkse Sep 12, 2024

Choose a reason for hiding this comment

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

Maybe worth having From<TokenAddress> for ByteArray as it appears in more occurrences 🤔

amount: u256_to_big_decimal(&order_fee.total.amount.0),
},
&order_fee
.protocol
.into_iter()
.map(|executed| Asset {
token: ByteArray(executed.fee.token.0 .0),
amount: u256_to_big_decimal(&executed.fee.amount.0),
})
.collect::<Vec<_>>(),
)
.await?;
}
Expand Down
3 changes: 2 additions & 1 deletion crates/database/src/jit_orders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ ARRAY[]::record[] AS post_interactions,
NULL AS ethflow_data,
NULL AS onchain_user,
NULL AS onchain_placement_error,
COALESCE((SELECT SUM(surplus_fee) FROM order_execution oe WHERE oe.order_uid = o.uid), 0) as executed_surplus_fee,
COALESCE((SELECT SUM(total_fee) FROM order_execution oe WHERE oe.order_uid = o.uid), 0) as executed_total_fee,
COALESCE((SELECT total_fee_token FROM order_execution oe WHERE oe.order_uid = o.uid), o.sell_token) as executed_total_fee_token, -- TODO surplus token
NULL AS full_app_data
"#;

Expand Down
36 changes: 25 additions & 11 deletions crates/database/src/order_execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,26 @@ pub async fn save(
order: &OrderUid,
auction: AuctionId,
block_number: i64,
executed_fee: &BigDecimal,
executed_protocol_fees: &[Asset],
total_fee: Asset,
protocol_fees: &[Asset],
) -> Result<(), sqlx::Error> {
let (protocol_fee_tokens, protocol_fee_amounts): (Vec<_>, Vec<_>) = executed_protocol_fees
let (protocol_fee_tokens, protocol_fee_amounts): (Vec<_>, Vec<_>) = protocol_fees
.iter()
.map(|entry| (entry.token, entry.amount.clone()))
.unzip();

const QUERY: &str = r#"
INSERT INTO order_execution (order_uid, auction_id, reward, surplus_fee, block_number, protocol_fee_tokens, protocol_fee_amounts)
VALUES ($1, $2, $3, $4, $5, $6, $7)
INSERT INTO order_execution (order_uid, auction_id, reward, total_fee, total_fee_token, block_number, protocol_fee_tokens, protocol_fee_amounts)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
ON CONFLICT (order_uid, auction_id)
DO UPDATE SET reward = $3, surplus_fee = $4, block_number = $5, protocol_fee_tokens = $6, protocol_fee_amounts = $7
DO UPDATE SET reward = $3, total_fee = $4, total_fee_token = $5, block_number = $6, protocol_fee_tokens = $7, protocol_fee_amounts = $8
;"#;
sqlx::query(QUERY)
.bind(order)
.bind(auction)
.bind(0.) // reward is deprecated but saved for historical analysis
.bind(Some(executed_fee))
.bind(Some(total_fee.amount))
sunce86 marked this conversation as resolved.
Show resolved Hide resolved
.bind(total_fee.token)
.bind(block_number)
.bind(protocol_fee_tokens)
.bind(protocol_fee_amounts)
Expand Down Expand Up @@ -123,17 +124,30 @@ mod tests {
&Default::default(),
1,
0,
&Default::default(),
Asset {
amount: BigDecimal::from(3),
token: Default::default(),
},
protocol_fees.as_slice(),
)
.await
.unwrap();

// save entry without protocol fees (simulate case when we are still not
sunce86 marked this conversation as resolved.
Show resolved Hide resolved
// calculating them)
save(&mut db, &Default::default(), 2, 0, &Default::default(), &[])
.await
.unwrap();
save(
&mut db,
&Default::default(),
2,
0,
Asset {
amount: BigDecimal::from(3),
token: Default::default(),
},
&[],
)
.await
.unwrap();

let keys: Vec<(AuctionId, OrderUid)> = vec![
(1, Default::default()),
Expand Down
47 changes: 36 additions & 11 deletions crates/database/src/orders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,8 @@ pub struct FullOrder {
pub ethflow_data: Option<(Option<TransactionHash>, i64)>,
pub onchain_user: Option<Address>,
pub onchain_placement_error: Option<OnchainOrderPlacementError>,
pub executed_surplus_fee: BigDecimal,
pub executed_total_fee: BigDecimal,
pub executed_total_fee_token: Address,
pub full_app_data: Option<Vec<u8>>,
}

Expand Down Expand Up @@ -548,7 +549,8 @@ array(Select (p.target, p.value, p.data) from interactions p where p.order_uid =
where eth_o.uid = o.uid limit 1) as ethflow_data,
(SELECT onchain_o.sender from onchain_placed_orders onchain_o where onchain_o.uid = o.uid limit 1) as onchain_user,
(SELECT onchain_o.placement_error from onchain_placed_orders onchain_o where onchain_o.uid = o.uid limit 1) as onchain_placement_error,
COALESCE((SELECT SUM(surplus_fee) FROM order_execution oe WHERE oe.order_uid = o.uid), 0) as executed_surplus_fee,
COALESCE((SELECT SUM(total_fee) FROM order_execution oe WHERE oe.order_uid = o.uid), 0) as executed_total_fee,
sunce86 marked this conversation as resolved.
Show resolved Hide resolved
COALESCE((SELECT total_fee_token FROM order_execution oe WHERE oe.order_uid = o.uid), o.sell_token) as executed_total_fee_token, -- TODO surplus token
(SELECT full_app_data FROM app_data ad WHERE o.app_data = ad.contract_app_data LIMIT 1) as full_app_data
"#;

Expand Down Expand Up @@ -776,6 +778,7 @@ mod tests {
events::{Event, EventIndex, Invalidation, PreSignature, Settlement, Trade},
onchain_broadcasted_orders::{insert_onchain_order, OnchainOrderPlacement},
onchain_invalidations::insert_onchain_invalidation,
order_execution::Asset,
PgTransaction,
},
bigdecimal::num_bigint::{BigInt, ToBigInt},
Expand Down Expand Up @@ -1764,18 +1767,28 @@ mod tests {
.await
.unwrap()
.unwrap();
assert_eq!(order.executed_surplus_fee, fee);
assert_eq!(order.executed_total_fee, fee);

let fee: BigDecimal = 1.into();
crate::order_execution::save(&mut db, &order_uid, 1, 0, &fee, &[])
.await
.unwrap();
crate::order_execution::save(
&mut db,
&order_uid,
1,
0,
Asset {
amount: fee.clone(),
token: Default::default(),
},
&[],
)
.await
.unwrap();

let order = single_full_order(&mut db, &order_uid)
.await
.unwrap()
.unwrap();
assert_eq!(order.executed_surplus_fee, fee);
assert_eq!(order.executed_total_fee, fee);
}

#[tokio::test]
Expand Down Expand Up @@ -1889,7 +1902,10 @@ mod tests {
&ByteArray([1u8; 56]),
1,
1,
&BigDecimal::from(1),
Asset {
amount: BigDecimal::from(1),
token: Default::default(),
},
Default::default(),
)
.await
Expand All @@ -1899,7 +1915,10 @@ mod tests {
&ByteArray([1u8; 56]),
2,
2,
&BigDecimal::from(2),
Asset {
amount: BigDecimal::from(2),
token: Default::default(),
},
Default::default(),
)
.await
Expand All @@ -1909,7 +1928,10 @@ mod tests {
&ByteArray([1u8; 56]),
3,
0,
&BigDecimal::from(4),
Asset {
amount: BigDecimal::from(4),
token: Default::default(),
},
Default::default(),
)
.await
Expand All @@ -1919,7 +1941,10 @@ mod tests {
&ByteArray([3u8; 56]),
2,
3,
&BigDecimal::from(4),
Asset {
amount: BigDecimal::from(4),
token: Default::default(),
},
Default::default(),
)
.await
Expand Down
2 changes: 1 addition & 1 deletion crates/e2e/tests/e2e/ethflow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ async fn eth_flow_tx(web3: Web3) {
.get_order(&ethflow_order.uid(onchain.contracts()).await)
.await
.unwrap();
order.metadata.executed_surplus_fee > U256::zero()
order.metadata.executed_total_fee > U256::zero()
};
wait_for_condition(TIMEOUT, fee_charged).await.unwrap();

Expand Down
2 changes: 1 addition & 1 deletion crates/e2e/tests/e2e/partial_fill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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_total_fee > U256::zero()
};
wait_for_condition(TIMEOUT, settlement_event_processed)
.await
Expand Down
2 changes: 1 addition & 1 deletion crates/e2e/tests/e2e/partially_fillable_pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ async fn test(web3: Web3) {
let metadata_updated = || async {
onchain.mint_block().await;
let order = services.get_order(&uid).await.unwrap();
!order.metadata.executed_surplus_fee.is_zero()
!order.metadata.executed_total_fee.is_zero()
&& order.metadata.executed_buy_amount != Default::default()
&& order.metadata.executed_sell_amount != Default::default()
};
Expand Down
Loading
Loading