From 31029e584cd5bb576c21b4a9b998debfa1a33afa Mon Sep 17 00:00:00 2001 From: ayaanoncrypto <1.06945712e+08+ayaanoncrypto@users.noreply.github.com> Date: Thu, 27 Aug 2026 02:13:26 +0000 Subject: [PATCH] Fix snapshot consistency check by ignoring metadata drift in InnerL4Order PartialEq --- server/src/listeners/order_book/utils.rs | 39 ++++++++++++++++++++++++ server/src/order_book/mod.rs | 5 +++ server/src/types/inner.rs | 13 +++++++- 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/server/src/listeners/order_book/utils.rs b/server/src/listeners/order_book/utils.rs index fdbd3b57..77bb3692 100644 --- a/server/src/listeners/order_book/utils.rs +++ b/server/src/listeners/order_book/utils.rs @@ -153,3 +153,42 @@ impl BatchQueue { self.deque.front() } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::types::inner::InnerL4Order; + use crate::order_book::types::{Coin, Px, Sz, Side}; + use alloy::primitives::Address; + + #[test] + fn test_snapshot_consistency_timestamp_mismatch() { + let user = Address::ZERO; + let coin = Coin::new("ETH"); + let order1 = InnerL4Order { + user, + coin: coin.clone(), + side: Side::Bid, + limit_px: Px::new(1000), + sz: Sz::new(1), + oid: 1, + timestamp: 100, + trigger_condition: "".to_string(), + is_trigger: false, + trigger_px: "".to_string(), + is_position_tpsl: false, + reduce_only: false, + order_type: "".to_string(), + tif: None, + cloid: None, + }; + let mut order2 = order1.clone(); + order2.timestamp = 200; + + let snapshot = Snapshots::new(HashMap::from_iter(vec![(coin.clone(), Snapshot::new(vec![order1], vec![]))])); + let expected = Snapshots::new(HashMap::from_iter(vec![(coin.clone(), Snapshot::new(vec![order2], vec![]))])); + + let result = validate_snapshot_consistency(&snapshot, expected, false); + assert!(result.is_ok(), "Should succeed despite timestamp mismatch"); + } +} diff --git a/server/src/order_book/mod.rs b/server/src/order_book/mod.rs index 63210614..9cec0397 100644 --- a/server/src/order_book/mod.rs +++ b/server/src/order_book/mod.rs @@ -21,6 +21,11 @@ pub(crate) struct OrderBook { pub(crate) struct Snapshot([Vec; 2]); impl Snapshot { + #[cfg(test)] + pub(crate) fn new(bids: Vec, asks: Vec) -> Self { + Self([bids, asks]) + } + pub(crate) const fn as_ref(&self) -> &[Vec; 2] { &self.0 } diff --git a/server/src/types/inner.rs b/server/src/types/inner.rs index 8c54f5c2..cccd0c55 100644 --- a/server/src/types/inner.rs +++ b/server/src/types/inner.rs @@ -11,7 +11,7 @@ use crate::{ }; // L4Order: the struct we keep in the orderbook (computationally better) -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, Eq)] pub(crate) struct InnerL4Order { pub user: Address, pub coin: Coin, @@ -30,6 +30,17 @@ pub(crate) struct InnerL4Order { pub cloid: Option, } +impl PartialEq for InnerL4Order { + fn eq(&self, other: &Self) -> bool { + self.user == other.user + && self.coin == other.coin + && self.side == other.side + && self.limit_px == other.limit_px + && self.sz == other.sz + && self.oid == other.oid + } +} + impl InnerOrder for InnerL4Order { fn oid(&self) -> Oid { Oid::new(self.oid)