Skip to content

Commit

Permalink
Indexing order cancellations
Browse files Browse the repository at this point in the history
  • Loading branch information
josojo committed Nov 16, 2022
1 parent cd5c349 commit bfcf712
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 9 deletions.
2 changes: 1 addition & 1 deletion crates/autopilot/src/arguments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub struct Arguments {
#[clap(
long,
env,
default_value = "0x26c3801b4840dab317cedfd7aeaf9f45fdd22830"
default_value = "0x76aAf674848311C7F21fc691B0b952f016dA49F3"
)]
pub ethflow_contract: H160,

Expand Down
2 changes: 1 addition & 1 deletion crates/autopilot/src/database/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ pub fn meta_to_event_index(meta: &EventMetadata) -> EventIndex {
}
}

fn bytes_to_order_uid(bytes: &[u8]) -> Result<OrderUid> {
pub fn bytes_to_order_uid(bytes: &[u8]) -> Result<OrderUid> {
bytes
.try_into()
.context("order_uid has wrong number of bytes")
Expand Down
73 changes: 71 additions & 2 deletions crates/autopilot/src/database/onchain_order_events.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
pub mod ethflow_events;

use super::{events::meta_to_event_index, Metrics, Postgres};
use super::{
events::{bytes_to_order_uid, meta_to_event_index},
Metrics, Postgres,
};
use anyhow::{anyhow, bail, Context, Result};
use contracts::cowswap_onchain_orders::{
event_data::OrderPlacement as ContractOrderPlacement, Event as ContractEvent,
event_data::{OrderInvalidation, OrderPlacement as ContractOrderPlacement},
Event as ContractEvent,
};
use database::{
byte_array::ByteArray,
Expand Down Expand Up @@ -134,11 +138,14 @@ impl<T: Sync + Send + Clone, W: Sync + Send + Clone> EventStoring<ContractEvent>
range: RangeInclusive<u64>,
) -> Result<()> {
let order_placement_events = events
.clone()
.into_iter()
.filter(|EthContractEvent { data, .. }| {
matches!(data, ContractEvent::OrderPlacement(_))
})
.collect();
let invalidation_events = get_invalidation_events(events)?;
let invalided_order_uids = extract_invalidated_order_uids(invalidation_events)?;
let (custom_onchain_data, quotes, broadcasted_order_data, orders) = self
.extract_custom_and_general_order_data(order_placement_events)
.await?;
Expand All @@ -157,6 +164,20 @@ impl<T: Sync + Send + Clone, W: Sync + Send + Clone> EventStoring<ContractEvent>
.await
.context("mark_onchain_order_events failed")?;

database::onchain_invalidations::delete_invalidations(
&mut transaction,
*range.start() as i64,
)
.await
.context("invalidating_onchain_order_events failed")?;

database::onchain_invalidations::insert_onchain_invalidations(
&mut transaction,
invalided_order_uids.as_slice(),
)
.await
.context("insert_onchain_invalidations failed")?;

self.custom_onchain_data_parser
.append_custom_order_info_to_db(&mut transaction, custom_onchain_data)
.await
Expand All @@ -182,11 +203,14 @@ impl<T: Sync + Send + Clone, W: Sync + Send + Clone> EventStoring<ContractEvent>

async fn append_events(&mut self, events: Vec<EthContractEvent<ContractEvent>>) -> Result<()> {
let order_placement_events = events
.clone()
.into_iter()
.filter(|EthContractEvent { data, .. }| {
matches!(data, ContractEvent::OrderPlacement(_))
})
.collect();
let invalidation_events = get_invalidation_events(events)?;
let invalided_order_uids = extract_invalidated_order_uids(invalidation_events)?;
let (custom_order_data, quotes, broadcasted_order_data, orders) = self
.extract_custom_and_general_order_data(order_placement_events)
.await?;
Expand All @@ -197,6 +221,12 @@ impl<T: Sync + Send + Clone, W: Sync + Send + Clone> EventStoring<ContractEvent>
.start_timer();
let mut transaction = self.db.0.begin().await?;

database::onchain_invalidations::insert_onchain_invalidations(
&mut transaction,
invalided_order_uids.as_slice(),
)
.await
.context("insert_onchain_invalidations failed")?;
database::onchain_broadcasted_orders::append(
&mut transaction,
broadcasted_order_data.as_slice(),
Expand Down Expand Up @@ -294,6 +324,45 @@ impl<T: Send + Sync + Clone, W: Send + Sync> OnchainOrderParser<T, W> {
}
}

fn get_invalidation_events(
events: Vec<EthContractEvent<ContractEvent>>,
) -> Result<Vec<(EventIndex, OrderInvalidation)>> {
events
.into_iter()
.filter_map(|EthContractEvent { data, meta }| {
let meta = match meta {
Some(meta) => meta,
None => return Some(Err(anyhow!("invalidation event without metadata"))),
};
let data = match data {
ContractEvent::OrderInvalidation(event) => event,
_ => {
return None;
}
};
Some(Ok((meta_to_event_index(&meta), data)))
})
.collect()
}

fn extract_invalidated_order_uids(
invalidations: Vec<(EventIndex, OrderInvalidation)>,
) -> Result<Vec<(EventIndex, database::OrderUid)>> {
invalidations
.into_iter()
.map(|(event_index, invalidation)| {
Ok((
event_index,
// The following conversion should not error, as the contract
// enforces that the enough bytes are send.
// If the error hpapens anyways, we want to stop indexing and
// hence escalate the error
bytes_to_order_uid(invalidation.order_uid.0.as_slice())?,
))
})
.collect()
}

type GeneralOnchainOrderPlacementData = (
EventIndex,
database::orders::Quote,
Expand Down
2 changes: 1 addition & 1 deletion crates/contracts/artifacts/CoWSwapEthFlow.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"abi":[{"inputs":[{"internalType":"contract ICoWSwapSettlement","name":"_cowSwapSettlement","type":"address"},{"internalType":"contract IWrappedNativeToken","name":"_wrappedNativeToken","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"EthTransferFailed","type":"error"},{"inputs":[],"name":"IncorrectEthAmount","type":"error"},{"inputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"NotAllowedToInvalidateOrder","type":"error"},{"inputs":[],"name":"NotAllowedZeroSellAmount","type":"error"},{"inputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"OrderIsAlreadyOwned","type":"error"},{"inputs":[],"name":"ReceiverMustBeSet","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes","name":"orderUid","type":"bytes"}],"name":"OrderInvalidation","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"components":[{"internalType":"contract IERC20","name":"sellToken","type":"address"},{"internalType":"contract IERC20","name":"buyToken","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"uint256","name":"buyAmount","type":"uint256"},{"internalType":"uint32","name":"validTo","type":"uint32"},{"internalType":"bytes32","name":"appData","type":"bytes32"},{"internalType":"uint256","name":"feeAmount","type":"uint256"},{"internalType":"bytes32","name":"kind","type":"bytes32"},{"internalType":"bool","name":"partiallyFillable","type":"bool"},{"internalType":"bytes32","name":"sellTokenBalance","type":"bytes32"},{"internalType":"bytes32","name":"buyTokenBalance","type":"bytes32"}],"indexed":false,"internalType":"struct GPv2Order.Data","name":"order","type":"tuple"},{"components":[{"internalType":"enum ICoWSwapOnchainOrders.OnchainSigningScheme","name":"scheme","type":"uint8"},{"internalType":"bytes","name":"data","type":"bytes"}],"indexed":false,"internalType":"struct ICoWSwapOnchainOrders.OnchainSignature","name":"signature","type":"tuple"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"OrderPlacement","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes","name":"orderUid","type":"bytes"},{"indexed":true,"internalType":"address","name":"refunder","type":"address"}],"name":"OrderRefund","type":"event"},{"inputs":[],"name":"cowSwapSettlement","outputs":[{"internalType":"contract ICoWSwapSettlement","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"buyToken","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"uint256","name":"buyAmount","type":"uint256"},{"internalType":"bytes32","name":"appData","type":"bytes32"},{"internalType":"uint256","name":"feeAmount","type":"uint256"},{"internalType":"uint32","name":"validTo","type":"uint32"},{"internalType":"bool","name":"partiallyFillable","type":"bool"},{"internalType":"int64","name":"quoteId","type":"int64"}],"internalType":"struct EthFlowOrder.Data","name":"order","type":"tuple"}],"name":"createOrder","outputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"buyToken","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"uint256","name":"buyAmount","type":"uint256"},{"internalType":"bytes32","name":"appData","type":"bytes32"},{"internalType":"uint256","name":"feeAmount","type":"uint256"},{"internalType":"uint32","name":"validTo","type":"uint32"},{"internalType":"bool","name":"partiallyFillable","type":"bool"},{"internalType":"int64","name":"quoteId","type":"int64"}],"internalType":"struct EthFlowOrder.Data","name":"order","type":"tuple"}],"name":"invalidateOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"buyToken","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"uint256","name":"buyAmount","type":"uint256"},{"internalType":"bytes32","name":"appData","type":"bytes32"},{"internalType":"uint256","name":"feeAmount","type":"uint256"},{"internalType":"uint32","name":"validTo","type":"uint32"},{"internalType":"bool","name":"partiallyFillable","type":"bool"},{"internalType":"int64","name":"quoteId","type":"int64"}],"internalType":"struct EthFlowOrder.Data[]","name":"orderArray","type":"tuple[]"}],"name":"invalidateOrdersIgnoringNotAllowed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"isValidSignature","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"orders","outputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint32","name":"validTo","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"unwrap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"wrap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"wrapAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"wrappedNativeToken","outputs":[{"internalType":"contract IWrappedNativeToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]}
{"abi":[{"inputs":[{"internalType":"contract ICoWSwapSettlement","name":"_cowSwapSettlement","type":"address"},{"internalType":"contract IWrappedNativeToken","name":"_wrappedNativeToken","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"EthTransferFailed","type":"error"},{"inputs":[],"name":"IncorrectEthAmount","type":"error"},{"inputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"NotAllowedToInvalidateOrder","type":"error"},{"inputs":[],"name":"NotAllowedZeroSellAmount","type":"error"},{"inputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"OrderIsAlreadyOwned","type":"error"},{"inputs":[],"name":"ReceiverMustBeSet","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"orderUid","type":"bytes"}],"name":"OrderInvalidation","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"components":[{"internalType":"contract IERC20","name":"sellToken","type":"address"},{"internalType":"contract IERC20","name":"buyToken","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"uint256","name":"buyAmount","type":"uint256"},{"internalType":"uint32","name":"validTo","type":"uint32"},{"internalType":"bytes32","name":"appData","type":"bytes32"},{"internalType":"uint256","name":"feeAmount","type":"uint256"},{"internalType":"bytes32","name":"kind","type":"bytes32"},{"internalType":"bool","name":"partiallyFillable","type":"bool"},{"internalType":"bytes32","name":"sellTokenBalance","type":"bytes32"},{"internalType":"bytes32","name":"buyTokenBalance","type":"bytes32"}],"indexed":false,"internalType":"struct GPv2Order.Data","name":"order","type":"tuple"},{"components":[{"internalType":"enum ICoWSwapOnchainOrders.OnchainSigningScheme","name":"scheme","type":"uint8"},{"internalType":"bytes","name":"data","type":"bytes"}],"indexed":false,"internalType":"struct ICoWSwapOnchainOrders.OnchainSignature","name":"signature","type":"tuple"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"OrderPlacement","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"orderUid","type":"bytes"},{"indexed":true,"internalType":"address","name":"refunder","type":"address"}],"name":"OrderRefund","type":"event"},{"inputs":[],"name":"cowSwapSettlement","outputs":[{"internalType":"contract ICoWSwapSettlement","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"buyToken","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"uint256","name":"buyAmount","type":"uint256"},{"internalType":"bytes32","name":"appData","type":"bytes32"},{"internalType":"uint256","name":"feeAmount","type":"uint256"},{"internalType":"uint32","name":"validTo","type":"uint32"},{"internalType":"bool","name":"partiallyFillable","type":"bool"},{"internalType":"int64","name":"quoteId","type":"int64"}],"internalType":"struct EthFlowOrder.Data","name":"order","type":"tuple"}],"name":"createOrder","outputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"buyToken","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"uint256","name":"buyAmount","type":"uint256"},{"internalType":"bytes32","name":"appData","type":"bytes32"},{"internalType":"uint256","name":"feeAmount","type":"uint256"},{"internalType":"uint32","name":"validTo","type":"uint32"},{"internalType":"bool","name":"partiallyFillable","type":"bool"},{"internalType":"int64","name":"quoteId","type":"int64"}],"internalType":"struct EthFlowOrder.Data","name":"order","type":"tuple"}],"name":"invalidateOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"buyToken","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"uint256","name":"buyAmount","type":"uint256"},{"internalType":"bytes32","name":"appData","type":"bytes32"},{"internalType":"uint256","name":"feeAmount","type":"uint256"},{"internalType":"uint32","name":"validTo","type":"uint32"},{"internalType":"bool","name":"partiallyFillable","type":"bool"},{"internalType":"int64","name":"quoteId","type":"int64"}],"internalType":"struct EthFlowOrder.Data[]","name":"orderArray","type":"tuple[]"}],"name":"invalidateOrdersIgnoringNotAllowed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"isValidSignature","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"orders","outputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint32","name":"validTo","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"unwrap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"wrap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"wrapAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"wrappedNativeToken","outputs":[{"internalType":"contract IWrappedNativeToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]}
Loading

0 comments on commit bfcf712

Please sign in to comment.