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

Merged
merged 21 commits into from
Dec 24, 2024
Merged
Show file tree
Hide file tree
Changes from 18 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
28 changes: 24 additions & 4 deletions crates/autopilot/src/domain/settlement/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,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 @@ -329,7 +346,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 "executedFee" https://api.cow.fi/mainnet/api/v1/orders/0x10dab31217bb6cc2ace0fe601c15d342f7626a1ee5ef0495449800e73156998740a50cf069e992aa4536211b23f286ef88752187ffffffff
// but not equal to 6890975030480504 anymore, since after this tx we switched to
// convert the fee from surplus token directly to ether
assert_eq!(
Expand Down Expand Up @@ -810,7 +827,10 @@ mod tests {
let jit_trade = super::trade::Trade::new(transaction.trades[1].clone(), &auction, 0);
assert_eq!(jit_trade.fee_in_ether(&auction.prices).unwrap().0, 0.into());
assert_eq!(jit_trade.score(&auction).unwrap().0, 0.into());
assert_eq!(jit_trade.fee_breakdown(&auction).unwrap().total.0, 0.into());
assert_eq!(
jit_trade.fee_breakdown(&auction).unwrap().total.amount.0,
0.into()
);
assert!(jit_trade
.fee_breakdown(&auction)
.unwrap()
Expand Down
6 changes: 5 additions & 1 deletion crates/autopilot/src/domain/settlement/trade/math.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,13 @@ 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> {
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 @@ -161,8 +168,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 @@ -701,28 +701,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(executed_fee) FROM order_execution oe WHERE oe.order_uid = o.uid), 0) as executed_fee,
COALESCE((SELECT executed_fee_token FROM order_execution oe WHERE oe.order_uid = o.uid), o.sell_token) as executed_fee_token, -- TODO surplus token
NULL AS full_app_data
"#;

Expand Down
39 changes: 26 additions & 13 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],
executed_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, executed_fee, executed_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, executed_fee = $4, executed_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(executed_fee.amount)
.bind(executed_fee.token)
.bind(block_number)
.bind(protocol_fee_tokens)
.bind(protocol_fee_amounts)
Expand Down Expand Up @@ -126,17 +127,29 @@ 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
// calculating them)
save(&mut db, &Default::default(), 2, 0, &Default::default(), &[])
.await
.unwrap();
// save entry for an order without protocol fees
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 @@ -493,7 +493,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_fee: BigDecimal,
pub executed_fee_token: Address,
pub full_app_data: Option<Vec<u8>>,
}

Expand Down Expand Up @@ -570,7 +571,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(executed_fee) FROM order_execution oe WHERE oe.order_uid = o.uid), 0) as executed_fee,
COALESCE((SELECT executed_fee_token FROM order_execution oe WHERE oe.order_uid = o.uid), o.sell_token) as executed_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 @@ -820,6 +822,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 @@ -1917,18 +1920,28 @@ mod tests {
.await
.unwrap()
.unwrap();
assert_eq!(order.executed_surplus_fee, fee);
assert_eq!(order.executed_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_fee, fee);
}

#[tokio::test]
Expand Down Expand Up @@ -2042,7 +2055,10 @@ mod tests {
&ByteArray([1u8; 56]),
1,
1,
&BigDecimal::from(1),
Asset {
amount: BigDecimal::from(1),
token: Default::default(),
},
Default::default(),
)
.await
Expand All @@ -2052,7 +2068,10 @@ mod tests {
&ByteArray([1u8; 56]),
2,
2,
&BigDecimal::from(2),
Asset {
amount: BigDecimal::from(2),
token: Default::default(),
},
Default::default(),
)
.await
Expand All @@ -2062,7 +2081,10 @@ mod tests {
&ByteArray([1u8; 56]),
3,
0,
&BigDecimal::from(4),
Asset {
amount: BigDecimal::from(4),
token: Default::default(),
},
Default::default(),
)
.await
Expand All @@ -2072,7 +2094,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_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 @@ -95,7 +95,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_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 @@ -118,7 +118,7 @@ async fn test(web3: Web3) {
let metadata_updated = || async {
let order = services.get_order(&uid).await.unwrap();
onchain.mint_block().await;
!order.metadata.executed_surplus_fee.is_zero()
!order.metadata.executed_fee.is_zero()
&& order.metadata.executed_buy_amount != Default::default()
&& order.metadata.executed_sell_amount != Default::default()
};
Expand Down
Loading
Loading