test: concurrency guard and vesting timestamp edge cases - #452
Merged
maugauwi-hash merged 1 commit intoAug 31, 2026
Conversation
Duplicate vault prevention — concurrency tests (contracts/ttl_vault/src/duplicate_vault_concurrency_tests.rs) - test_concurrent_same_params_only_first_succeeds: fires N rapid calls with identical (owner, beneficiary, interval) at incrementing timestamps; asserts exactly one succeeds and the vault-ID counter does not advance for rejected calls. - test_same_block_ordering_deterministically_rejects_second_call: two calls at the same ledger timestamp with no state change between them; confirms the guard fires even within the same block. - test_colliding_near_simultaneous_calls_different_params_both_succeed: same owner+interval, different beneficiary — both must succeed without cross-contaminating each other's fingerprint. - test_different_interval_same_owner_beneficiary_is_not_duplicate: changing only the interval creates a distinct triple; neither vault blocks the other. - test_fingerprint_cleared_after_cancel_allows_recreation: cancel_vault removes the VaultDuplicate key; same triple is accepted again. - test_fingerprint_cleared_after_release_allows_recreation: trigger_release removes the VaultDuplicate key; same triple is accepted again. - test_multiple_owners_same_beneficiary_interval_all_succeed: three different owners sharing the same beneficiary+interval all get distinct vault IDs. Vesting schedule — timestamp edge-case tests (contracts/ttl_vault/src/vesting_timestamp_edge_case_tests.rs) - test_installment_claimable_at_exact_start_timestamp: now == start_time is immediately claimable (>= boundary, not >). - test_nothing_claimable_one_second_before_start: now == start_time - 1 returns an error. - test_claim_succeeds_at_exact_cliff_boundary: now == start_time + cliff_period exactly succeeds. - test_claim_fails_one_second_before_cliff_boundary: now == start_time + cliff_period - 1 returns CliffNotReached (error 55). - test_installment_claimable_at_exact_interval_boundary: now == start + n * interval is claimable. - test_no_installment_one_second_before_interval_boundary: one second before an interval boundary is not claimable. - test_vesting_interval_crossing_leap_year_2000: 1-year regular interval starting 2000-01-01 crosses Feb 29; both installments claim correctly. - test_vesting_interval_uses_leap_year_length: leap-year interval (31_622_400 s) starting on 2000-02-29; total equals vault balance. - test_cliff_spanning_leap_year_boundary: cliff of one leap year crossing Feb 29; exact boundary succeeds, one second before fails. - test_multi_year_schedule_spanning_year_2000_leap: 4-installment annual schedule from Y2K; all installments claim at correct offsets and sum to full vault balance. - test_zero_cliff_claimable_from_epoch_zero: cliff_period=0, start_time=0 is claimable at Unix epoch. - test_large_unix_timestamp_no_overflow: start_time near u32::MAX does not overflow u64 arithmetic. Documentation - docs/duplicate-vault-prevention.md: added Concurrency Guarantee section (same-block ordering, atomic check-then-write, guard properties table, test coverage table). - docs/vesting-schedules.md: added Timestamp Edge Cases section (inclusive boundary semantics, leap-year transparency, large-timestamp safety, test coverage table). Modules registered in contracts/ttl_vault/src/lib.rs.
|
@agnesadah3-jpg Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
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.
Summary
Two test suites and accompanying doc updates addressing gaps identified in the duplicate-vault prevention and vesting schedule logic.
Duplicate vault prevention — concurrency tests
New file:
contracts/ttl_vault/src/duplicate_vault_concurrency_tests.rsThe existing
test_duplicate_vault_errorintest.rscovered the basic happy-path rejection, but there was no load/concurrency scenario confirming the guard holds under near-simultaneous creation attempts.Tests added (7):
test_concurrent_same_params_only_first_succeedstest_same_block_ordering_deterministically_rejects_second_calltest_colliding_near_simultaneous_calls_different_params_both_succeedtest_different_interval_same_owner_beneficiary_is_not_duplicatetest_fingerprint_cleared_after_cancel_allows_recreationcancel_vaultremoves fingerprint → same triple reusabletest_fingerprint_cleared_after_release_allows_recreationtrigger_releaseremoves fingerprint → same triple reusabletest_multiple_owners_same_beneficiary_interval_all_succeedVesting schedule — timestamp edge-case tests
New file:
contracts/ttl_vault/src/vesting_timestamp_edge_case_tests.rsLedger timestamps are UNIX seconds (
u64). The tests confirm all boundary checks use>=(inclusive), no calendar conversions occur, and leap-year crossings are transparent.Tests added (10+2 off-by-one = 12):
test_installment_claimable_at_exact_start_timestampnow == start_time→ immediately claimabletest_nothing_claimable_one_second_before_startnow == start_time - 1→ errortest_claim_succeeds_at_exact_cliff_boundarynow == start_time + cliff_period→ succeedstest_claim_fails_one_second_before_cliff_boundarynow == start_time + cliff_period - 1→CliffNotReached(55)test_installment_claimable_at_exact_interval_boundarynow == start + n * interval→ succeedstest_no_installment_one_second_before_interval_boundarytest_vesting_interval_crossing_leap_year_2000test_vesting_interval_uses_leap_year_lengthtest_cliff_spanning_leap_year_boundarytest_multi_year_schedule_spanning_year_2000_leaptest_zero_cliff_claimable_from_epoch_zerocliff_period=0, start_time=0at Unix epochtest_large_unix_timestamp_no_overflowstart_time ≈ u32::MAX→ no u64 overflowDocumentation
docs/duplicate-vault-prevention.md— added Concurrency Guarantee section: same-block ordering, atomic check-then-write, guard properties table, full test coverage table.docs/vesting-schedules.md— added Timestamp Edge Cases section: inclusive boundary semantics, leap-year transparency, large-timestamp safety, test coverage table.What was tested
DuplicateVault(error 57) path throughcreate_vault,cancel_vault, andtrigger_release.set_beneficiary_vesting/claim_beneficiary_vestingwith explicit ledger timestamp manipulation.beneficiary_vesting_tests.rsandlifecycle_tests.rs.closes #426
closes #427