From 6332bc39dbd9ce12685af84212f9cd94ec4f55f3 Mon Sep 17 00:00:00 2001 From: fadesany Date: Thu, 23 Jul 2026 11:47:49 +0000 Subject: [PATCH] feat(pool): add deadline guard to swap entrypoint - Added parameter to to reject stale transactions - Added guard before , consistent with other entrypoints - Added integration test mirroring - Updated all existing test callers of to pass Closes #107 --- contracts/pool/src/lib.rs | 4 ++++ contracts/pool/tests/integration_tests.rs | 17 +++++++++++++---- contracts/pool/tests/unit_tests.rs | 2 +- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/contracts/pool/src/lib.rs b/contracts/pool/src/lib.rs index 59c25b3..01fa1ab 100644 --- a/contracts/pool/src/lib.rs +++ b/contracts/pool/src/lib.rs @@ -366,9 +366,13 @@ impl NodusAmm { to: Address, amount_0_out: i128, amount_1_out: i128, + deadline: u64, ) -> Result<(), Error> { require_initialized(&env)?; require_not_paused(&env)?; + if env.ledger().timestamp() > deadline { + return Err(Error::Expired); + } lock(&env)?; env.storage() .instance() diff --git a/contracts/pool/tests/integration_tests.rs b/contracts/pool/tests/integration_tests.rs index d187fd4..8980bc9 100644 --- a/contracts/pool/tests/integration_tests.rs +++ b/contracts/pool/tests/integration_tests.rs @@ -26,7 +26,7 @@ mod integration { let (env, contract, _, _) = setup_initialized(); let client = NodusAmmClient::new(&env, &contract); let to = Address::generate(&env); - assert!(client.try_swap(&to, &100, &0).is_err()); + assert!(client.try_swap(&to, &100, &0, &u64::MAX).is_err()); } #[test] @@ -34,7 +34,7 @@ mod integration { let (env, contract, _, _) = setup_initialized(); let client = NodusAmmClient::new(&env, &contract); let to = Address::generate(&env); - assert!(client.try_swap(&to, &0, &0).is_err()); + assert!(client.try_swap(&to, &0, &0, &u64::MAX).is_err()); } #[test] @@ -57,6 +57,15 @@ mod integration { .is_err()); } + #[test] + fn expired_swap_rejected() { + let (env, contract, _, _) = setup_initialized(); + let client = NodusAmmClient::new(&env, &contract); + env.ledger().set_timestamp(5_000); + let to = Address::generate(&env); + assert!(client.try_swap(&to, &100, &0, &1_000).is_err()); + } + #[test] fn not_initialized_token_query_fails() { let env = Env::default(); @@ -123,7 +132,7 @@ mod integration { client.pause(&admin); let to = Address::generate(&env); assert_eq!( - client.try_swap(&to, &100, &0), + client.try_swap(&to, &100, &0, &u64::MAX), Err(Ok(nodus_protocol_amm::Error::ContractPaused)) ); } @@ -196,7 +205,7 @@ mod integration { let to = Address::generate(&env); // No longer blocked by pause; fails for the ordinary reason (no reserves) instead. assert_eq!( - client.try_swap(&to, &100, &0), + client.try_swap(&to, &100, &0, &u64::MAX), Err(Ok(nodus_protocol_amm::Error::InsufficientLiquidity)) ); } diff --git a/contracts/pool/tests/unit_tests.rs b/contracts/pool/tests/unit_tests.rs index f648efa..0adcf4c 100644 --- a/contracts/pool/tests/unit_tests.rs +++ b/contracts/pool/tests/unit_tests.rs @@ -201,7 +201,7 @@ mod soroban_contract_tests { let (env, contract) = setup(); let client = NodusAmmClient::new(&env, &contract); let to = Address::generate(&env); - assert!(client.try_swap(&to, &100, &0).is_err()); + assert!(client.try_swap(&to, &100, &0, &u64::MAX).is_err()); } #[test]