From 709c30ecf074f3917f800740971b41caa8f4737c Mon Sep 17 00:00:00 2001 From: devfoma Date: Fri, 29 May 2026 20:53:13 -0700 Subject: [PATCH 1/2] fix(stream_contract): remove duplicate stream.paused check in withdraw The withdraw function contained an unreachable second if stream.paused guard immediately after an identical first check. Since validate_stream_active and the first paused guard already cause an early return, the second block was dead code. Remove it to improve readability and reduce WASM size. --- contracts/stream_contract/src/lib.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/contracts/stream_contract/src/lib.rs b/contracts/stream_contract/src/lib.rs index f0d482c1..eaa35296 100644 --- a/contracts/stream_contract/src/lib.rs +++ b/contracts/stream_contract/src/lib.rs @@ -433,9 +433,6 @@ impl StreamContract { if stream.paused { return Err(StreamError::StreamInactive); } - if stream.paused { - return Err(StreamError::StreamInactive); - } let now = env.ledger().timestamp(); let claimable = Self::calculate_claimable(&stream, now); From bd83e6297680ab7100cd1a1acbe16c09951cb10d Mon Sep 17 00:00:00 2001 From: devfoma Date: Fri, 29 May 2026 20:54:01 -0700 Subject: [PATCH 2/2] chore(stream_contract): delete orphaned nested stream_contract/src/ directory Remove the stale contracts/stream_contract/src/stream_contract/ subtree. This nested directory was never wired into the crate module tree (lib.rs declares mod test; which resolves to src/test.rs, not this path), so the 61-line fuzz_stream_invariants stub it contained was never compiled or run. The four arithmetic invariants it tested (withdrawn<=deposited, claimable<= remaining, non-negative accrual, cancel_refund+withdrawn<=deposited) are already covered by test_fuzz_withdrawn_never_exceeds_deposited, test_fuzz_claimable_never_exceeds_remaining, test_fuzz_cancel_early_refunds, and test_fuzz_claimable_overflow_and_cancel_invariants in src/test.rs. --- .../src/stream_contract/src/test.rs | 62 ------------------- 1 file changed, 62 deletions(-) delete mode 100644 contracts/stream_contract/src/stream_contract/src/test.rs diff --git a/contracts/stream_contract/src/stream_contract/src/test.rs b/contracts/stream_contract/src/stream_contract/src/test.rs deleted file mode 100644 index 6fc42805..00000000 --- a/contracts/stream_contract/src/stream_contract/src/test.rs +++ /dev/null @@ -1,62 +0,0 @@ -#![cfg(test)] - -use super::*; -use soroban_sdk::{testutils::Address as _, Address, Env}; - -/// Simple deterministic pseudo-random generator (no external deps) -fn pseudo_rand(seed: &mut u64) -> u64 { - *seed = seed.wrapping_mul(6364136223846793005).wrapping_add(1); - *seed -} - -#[test] -fn fuzz_stream_invariants() { - let env = Env::default(); - let mut seed: u64 = 42; - - for _ in 0..10_000 { - // Generate random actors - let _sender = Address::generate(&env); - let _recipient = Address::generate(&env); - - // Generate random values (bounded to avoid overflow) - let deposited = (pseudo_rand(&mut seed) % 1_000_000) as i128; - let withdrawn = (pseudo_rand(&mut seed) % deposited.max(1) as u64) as i128; - - let elapsed_seconds = (pseudo_rand(&mut seed) % 10_000) as i128; - let rate_per_second = (pseudo_rand(&mut seed) % 1_000) as i128; - - let claimable = (rate_per_second * elapsed_seconds) - .min(deposited - withdrawn) - .max(0); - - let withdrawn_before_cancel = withdrawn; - let cancel_refund = (deposited - withdrawn_before_cancel).max(0); - - // 🧠 Invariants - - // 1. withdrawn <= deposited - assert!( - withdrawn <= deposited, - "Invariant failed: withdrawn > deposited" - ); - - // 2. claimable <= (deposited - withdrawn) - assert!( - claimable <= (deposited - withdrawn), - "Invariant failed: claimable exceeds remaining balance" - ); - - // 3. rate_per_second * elapsed_seconds >= 0 - assert!( - rate_per_second * elapsed_seconds >= 0, - "Invariant failed: negative accrual" - ); - - // 4. cancel_refund + withdrawn_before_cancel <= deposited - assert!( - cancel_refund + withdrawn_before_cancel <= deposited, - "Invariant failed: total payout exceeds deposit" - ); - } -} \ No newline at end of file