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

Indexing order cancellations #786

Merged
merged 3 commits into from
Nov 16, 2022
Merged
Show file tree
Hide file tree
Changes from all 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
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 sent
// If the error happens 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

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion crates/contracts/artifacts/CoWSwapOnchainOrders.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"abi":[{"inputs":[{"internalType":"address","name":"settlementContractAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"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"}]}
{"abi":[{"inputs":[{"internalType":"address","name":"settlementContractAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"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"}]}
5 changes: 5 additions & 0 deletions crates/contracts/src/bin/vendor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,11 @@ fn run() -> Result<()> {
"balancer-labs/balancer-v2-monorepo/903d34e491a5e9c5d59dabf512c7addf1ccf9bbd/\
pkg/deployments/tasks/20220609-stable-pool-v2/abi/StablePoolFactory.json",
)?
.github(
"CoWSwapOnchainOrders",
"cowprotocol/ethflowcontract/0.0.0-rc.2\
-artifacts/artifacts/CoWSwapOnchainOrders.sol/CoWSwapOnchainOrders.json"
)?
.npm(
"ERC20",
"@openzeppelin/[email protected]/build/contracts/ERC20.json",
Expand Down
2 changes: 1 addition & 1 deletion crates/refunder/src/arguments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pub struct Arguments {
#[clap(
long,
env,
default_value = "0x26c3801b4840dab317cedfd7aeaf9f45fdd22830"
default_value = "0x76aAf674848311C7F21fc691B0b952f016dA49F3"
)]
pub ethflow_contract: H160,

Expand Down