Skip to content

Commit

Permalink
Indexing order cancellations (#786)
Browse files Browse the repository at this point in the history
closes #708.

Finishes the indexing of the onchain order invalidations.

Unfortunately, we needed to redeploy the contracts, hence the new contract version. We needed to redeploy, as we had the order_uids marked as "indexed" in the smart contract and then the order_uid was not readable from the logs. See here for more information.
  • Loading branch information
josojo authored Nov 16, 2022
1 parent e5dacdf commit 13b1f8d
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 7 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 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

0 comments on commit 13b1f8d

Please sign in to comment.