From 725763654215e3574dd820f897b0c310755f2407 Mon Sep 17 00:00:00 2001 From: die-herdplatte <173669014+die-herdplatte@users.noreply.github.com> Date: Fri, 27 Mar 2026 11:57:20 +0100 Subject: [PATCH] Mirror EVM logic of stored truncated timestamp in TWAMM Fixes #16 --- src/chain/evm.rs | 8 +++++ src/chain/mod.rs | 5 ++++ src/chain/starknet.rs | 8 +++++ src/quoting/pools/twamm.rs | 61 ++++++++++++++++++++++++++++++-------- 4 files changed, 69 insertions(+), 13 deletions(-) diff --git a/src/chain/evm.rs b/src/chain/evm.rs index 3e0c49a..63232ea 100644 --- a/src/chain/evm.rs +++ b/src/chain/evm.rs @@ -1,5 +1,6 @@ use crate::alloy_primitives::{aliases::B32, fixed_bytes, Address, FixedBytes, B256, U256}; use crate::alloy_primitives::{uint, Keccak256}; +use crate::quoting::util::real_last_time; use derive_more::From; use num_traits::Zero as _; use thiserror::Error; @@ -327,6 +328,13 @@ impl Chain for Evm { }, ) } + + fn real_last_virtual_order_execution_time( + block_timestamp: u64, + last_execution_time: u64, + ) -> u64 { + real_last_time(block_timestamp, last_execution_time as u32) + } } impl EvmPoolKey { diff --git a/src/chain/mod.rs b/src/chain/mod.rs index 393f8cc..e6df2cf 100644 --- a/src/chain/mod.rs +++ b/src/chain/mod.rs @@ -48,6 +48,11 @@ pub trait Chain: sqrt_ratio: U256, active_liquidity: u128, ) -> Result; + + fn real_last_virtual_order_execution_time( + block_timestamp: u64, + last_execution_time: u64, + ) -> u64; } #[cfg(test)] diff --git a/src/chain/starknet.rs b/src/chain/starknet.rs index b8f5a3f..ce6dfee 100644 --- a/src/chain/starknet.rs +++ b/src/chain/starknet.rs @@ -236,6 +236,14 @@ impl Chain for Starknet { } type Address = Felt; + + fn real_last_virtual_order_execution_time( + _block_timestamp: u64, + last_execution_time: u64, + ) -> u64 { + // We store the untruncated u64 on Starknet + last_execution_time + } } impl private::Sealed for Starknet {} diff --git a/src/quoting/pools/twamm.rs b/src/quoting/pools/twamm.rs index 8c8bca1..2a1e992 100644 --- a/src/quoting/pools/twamm.rs +++ b/src/quoting/pools/twamm.rs @@ -214,16 +214,14 @@ impl Pool for TwammPool { } = params; let current_time = meta; - let initial_state = override_state.unwrap_or_else(|| self.state()); - - let mut next_sqrt_ratio = initial_state.full_range_pool_state.sqrt_ratio(); - let mut token0_sale_rate = initial_state.token0_sale_rate; - let mut token1_sale_rate = initial_state.token1_sale_rate; - let last_execution_time = initial_state.last_execution_time; + let TwammPoolState { + full_range_pool_state, + mut token0_sale_rate, + mut token1_sale_rate, + last_execution_time, + } = override_state.unwrap_or_else(|| self.state()); - if current_time < last_execution_time { - return Err(TwammPoolQuoteError::ExecutionTimeExceedsBlockTime); - } + let mut next_sqrt_ratio = full_range_pool_state.sqrt_ratio(); let mut virtual_order_delta_times_crossed = 0; let mut full_range_pool_state_override = override_state.map(|s| s.full_range_pool_state); @@ -236,6 +234,13 @@ impl Pool for TwammPool { config: PoolConfig { fee, .. }, } = self.full_range_pool.key(); + let last_execution_time = + C::real_last_virtual_order_execution_time(current_time, last_execution_time); + + if current_time < last_execution_time { + return Err(TwammPoolQuoteError::ExecutionTimeExceedsBlockTime); + } + let mut time = last_execution_time; for sale_rate_delta in self @@ -362,13 +367,11 @@ impl Pool for TwammPool { full_range: full_range_pool_execution_resources + final_quote.execution_resources, twamm: TwammStandalonePoolResources { extra_distinct_bitmap_lookups: approximate_extra_distinct_time_bitmap_lookups( - initial_state.last_execution_time, + last_execution_time, current_time, ), virtual_order_delta_times_crossed, - virtual_orders_executed: u32::from( - current_time > initial_state.last_execution_time, - ), + virtual_orders_executed: u32::from(current_time > last_execution_time), }, }, state_after: TwammPoolState { @@ -1654,6 +1657,38 @@ mod tests { .unwrap(); }); + #[test] + fn evm_quote_uses_truncated_last_execution_time() { + let last_execution_time = 100; + let current_time = last_execution_time + (1u64 << 32); + + let pool = build_pool::( + to_sqrt_ratio::(1).unwrap(), + 0, + last_execution_time, + 0, + 0, + vec![], + ); + + let quote = pool + .quote(QuoteParams { + token_amount: TokenAmount { + amount: 0, + token: Evm::zero_address(), + }, + sqrt_ratio_limit: None, + meta: current_time, + override_state: None, + }) + .unwrap(); + + // The untruncated time is updated... + assert_eq!(quote.state_after.last_execution_time, current_time); + // ...but since the u32 suffix of the last_execution_time and the current_time match, orders aren't executed + assert_eq!(quote.execution_resources.twamm.virtual_orders_executed, 0); + } + #[test] fn example_from_production_sepolia() { let pool = TwammPool::::new(