test(escrow-fuzz): cover refund_escrow and circuit-breaker interaction - #33
Merged
Meshmulla merged 1 commit intoAug 29, 2026
Conversation
The escrow fuzz suite added in stellar-kracken#5 covers create_escrow, release_escrow, and batch_release, but refund_escrow — the other half of the settlement path, where value also moves — had zero fuzz coverage. The circuit breaker guarding release/refund (053a3f8) landed after stellar-kracken#5 merged, so its interaction with both paths was never fuzzed either. Adds fuzz_release_refund_sequences_respect_circuit_breaker_and_never_double_pay to the existing escrow_contract_fuzz.rs, mirroring its established pattern: randomized sequences of sync_verification/release_escrow/refund_escrow/ trip_circuit_breaker/reset_circuit_breaker against a fresh escrow per round, asserting after every op that released_amount never goes negative or exceeds the releasable total, that an escrow can never reach both Released and Refunded (no double payout), that Released implies the full total was drained (no residue), and that a tripped breaker blocks both settlement paths with CircuitBreakerTripped specifically. A deterministic tail nails down the exact trip/block/reset/restore behavior beyond the randomized loop's statistical sampling. Uses a fresh Env per round (capped at fuzz_iterations().min(20), independent of the CI job's FUZZ_ITERATIONS override) rather than one shared Env across all rounds: escrow_contract keys escrows under instance storage, a single footprint shared by every escrow the contract has created, so reusing one Env while creating a new escrow each round made per-round storage I/O scale with every escrow created so far — quadratic overall, ~94s at FUZZ_ITERATIONS=200 before this was caught in testing. The fresh-env-per-round pattern already used by threshold_window_fuzz's max-windows test avoids this; same fix here. No CI change needed — .github/workflows/ci.yml already runs `cargo test --test escrow_contract_fuzz -p escrow-contract`, which picks up the new test automatically. Verified: cargo test (whole workspace, 553+ tests), cargo fmt --check, cargo clippy --all-targets --all-features -- -D warnings, cargo build --release --target wasm32-unknown-unknown, and FUZZ_ITERATIONS=200 (exact CI config, 1.56s) all pass. FUZZ_ITERATIONS=2000 --release local stress run (47s) found no invariant violation. Claude-Session: https://claude.ai/code/session_01GZ272ySgw1zd9m5ELwpS2g
Contributor
|
Good codes. Thanks |
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
closes #31
Context
#5 added fuzz coverage for escrow_contract's settlement path (create_escrow, release_escrow, batch_release) and wired it into the bounded fuzz CI job. That coverage is solid but has a real gap: refund_escrow — the other half of the settlement path, where value also moves — has zero fuzz coverage, and the circuit breaker added afterward in 053a3f8 (which guards release_escrow, batch_release, and refund_escrow) was never fuzzed at all, since it landed after #5 merged. This PR closes that specific gap. It does not re-litigate #5's scope — it's a follow-up, not a fix for something broken.
What needs to be done (from the original ask, re-verified against the current gap)
Extends escrow_contract/tests/escrow_contract_fuzz.rs (doesn't add a new file — the target already exists per Extend fuzz testing beyond the relay contract (escrow, threshold_window) #5; this adds one more #[test] to it, following the same seeded-xorshift-RNG / try_* client / capped-iteration conventions as the other three tests in the file).
fuzz_release_refund_sequences_respect_circuit_breaker_and_never_double_pay randomly interleaves sync_verification, release_escrow, refund_escrow, trip_circuit_breaker, and reset_circuit_breaker against the same escrow per round — the "record usage/lock, then settle/release" sequencing the issue asked for, applied to the one path (refund_escrow + breaker) the existing suite didn't touch.
No CI change needed — .github/workflows/ci.yml's existing cargo test --test escrow_contract_fuzz -p escrow-contract line already picks up the new #[test] automatically. Round count is capped at fuzz_iterations().min(20), independent of the job's FUZZ_ITERATIONS=200, mirroring the same cap already used by threshold_window_fuzz::fuzz_max_windows_cap_and_removal_keep_state_consistent.
Acceptance criteria
Evidence
Known gaps
Scope
Single file touched: escrow_contract/tests/escrow_contract_fuzz.rs, plus its auto-generated test_snapshots/*.json fixtures (21 files, one per capped round + one for the deterministic tail — same convention as the pre-existing fuzz_max_windows_cap_and_removal_keep_state_consistent test). No contract logic changed; no CI file changed.