diff --git a/src/client/trades.rs b/src/client/trades.rs index d7eaf2f..2ebe11c 100644 --- a/src/client/trades.rs +++ b/src/client/trades.rs @@ -3,7 +3,7 @@ use alloy::primitives::{Address, B256, Bytes, I256, U256}; use alloy::sol_types::SolEvent; -use crate::constants::{MIN_OPENING_MARGIN, TICK_SPACING}; +use crate::constants::{MAX_TICK, MIN_OPENING_MARGIN, MIN_TICK, TICK_SPACING}; use crate::contracts::{IERC20, Perp}; use crate::convert::{scale_from_6dec, scale_to_6dec}; use crate::errors::{ContractError, Result, ValidationError}; @@ -161,7 +161,7 @@ impl PerpClient { let tick_lower = align_tick_down(price_to_tick(params.price_lower)?, TICK_SPACING); let tick_upper = align_tick_up(price_to_tick(params.price_upper)?, TICK_SPACING); - if tick_lower >= tick_upper { + if tick_lower < MIN_TICK || tick_upper > MAX_TICK || tick_lower >= tick_upper { return Err(ValidationError::InvalidTickRange { lower: tick_lower, upper: tick_upper, diff --git a/src/constants.rs b/src/constants.rs index 89c271b..e779de4 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -40,17 +40,17 @@ pub const MIN_OPENING_MARGIN: u32 = 5_000_000; /// Funding interval in seconds (1 day). pub const INTERVAL: u64 = 86_400; -/// sqrt(0.001) * 2^96 — the minimum allowed sqrtPriceX96. -pub const MIN_SQRT_PRICE_X96: U256 = uint!(2505414483750479311864138016_U256); +/// sqrt(1e-6) * 2^96 — the minimum starting sqrtPriceX96 accepted by the factory. +pub const MIN_SQRT_PRICE_X96: U256 = uint!(79228162514264337593543951_U256); -/// sqrt(1000) * 2^96 — the maximum allowed sqrtPriceX96. -pub const MAX_SQRT_PRICE_X96: U256 = uint!(2505414483750479311864138015696_U256); +/// sqrt(1e6) * 2^96 — the maximum starting sqrtPriceX96 accepted by the factory. +pub const MAX_SQRT_PRICE_X96: U256 = uint!(79228162514264337593543950336000_U256); -/// Minimum tick (~= TickMath.getTickAtSqrtPrice(MIN_SQRT_PRICE_X96)). -pub const MIN_TICK: i32 = -69_090; +/// Minimum allowed maker tick, slightly below the factory's minimum starting price. +pub const MIN_TICK: i32 = -138_180; -/// Maximum tick (~= TickMath.getTickAtSqrtPrice(MAX_SQRT_PRICE_X96)). -pub const MAX_TICK: i32 = 69_090; +/// Maximum allowed maker tick, slightly above the factory's maximum starting price. +pub const MAX_TICK: i32 = 138_180; /// Total supply of the internal accounting token: type(uint120).max. pub const ACCOUNTING_TOKEN_SUPPLY: U256 = U256::from_limbs([u64::MAX, u64::MAX >> 8, 0, 0]); // 2^120 - 1 @@ -125,13 +125,13 @@ mod tests { #[test] fn min_sqrt_price_x96_matches_contract() { - let expected = U256::from_str_radix("2505414483750479311864138016", 10).unwrap(); + let expected = U256::from_str_radix("79228162514264337593543951", 10).unwrap(); assert_eq!(MIN_SQRT_PRICE_X96, expected); } #[test] fn max_sqrt_price_x96_matches_contract() { - let expected = U256::from_str_radix("2505414483750479311864138015696", 10).unwrap(); + let expected = U256::from_str_radix("79228162514264337593543950336000", 10).unwrap(); assert_eq!(MAX_SQRT_PRICE_X96, expected); } } diff --git a/src/convert.rs b/src/convert.rs index 7b1166b..85a7eda 100644 --- a/src/convert.rs +++ b/src/convert.rs @@ -286,7 +286,7 @@ pub fn sqrt_price_x96_to_price(sqrt_price_x96: U256) -> Result 0.0); assert!(max_price > min_price); - // MIN_TICK ≈ -69090 → price ≈ 0.001 - assert!((min_price - 0.001).abs() < 0.0005, "min_price={min_price}"); - // MAX_TICK ≈ 69090 → price ≈ 1000 - assert!((max_price - 1000.0).abs() < 1.0, "max_price={max_price}"); + assert!( + (min_price - 1e-6).abs() / 1e-6 < 0.01, + "min_price={min_price}" + ); + assert!( + (max_price - 1e6).abs() / 1e6 < 0.01, + "max_price={max_price}" + ); } }