-
Instance storage TTL extension (Closes #38): Added
env.storage().instance().extend_ttl(100_000, 500_000)to all state-changing entrypoints across all three contracts (escrow,milestones,maintenance-pool). Previously, instance storage (holding Admin, Treasury, FeeBps, MaxSponsors) was never extended, risking full contract archival — unlike per-record persistent TTL which was already handled. Now every mutating call keeps the instance alive alongside individual records. -
Identifier reuse after terminal state (Closes #41):
escrow::fundandmilestones::create_milestonenow allow re-funding/re-creation when the existing record is in a terminal state (Paid/Refunded for escrow, closed for milestones). Previously, once anissue_idormilestone_idreached any terminal state, the identifier was permanently retired with no recovery path. The existing record is overwritten with fresh state on reuse. Active (Funded/open) records still reject duplicates as before. -
Milestone deadline + permissionless cancel (Closes #42): Added a
deadlinefield toMilestone(set atcreate_milestone) and a newcancel_milestone_after_deadlineentrypoint that mirrors escrow's permissionlessrefund— anyone can trigger it afterdeadline + GRACE_PERIOD(14 days), but funds only go to contributors on record. For maintenance-pool, added a per-depositreclaim_depositentrypoint: sponsors can reclaim individual deposits after a 90-day inactivity window (INACTIVITY_WINDOW) if nowithdrawhas occurred against the pool. Both mechanisms provide non-admin-gated recovery paths for sponsors whose admin goes permanently unresponsive. -
Deallocate mechanism (Closes #43): Added
deallocate(milestone_id, issue_id)to milestones — admin-only, moves an Allocated (not yet Released) issue's amount back intoremaining_budget, removes the allocation entry, and clears itsIssueStatus. This prevents the scenario where #5's fix (blockingrelease_issueon closed milestones) would strand allocated-but-unreleased funds permanently. A deallocated issue can be re-allocated with corrected amounts. -
Merge-conflict syntax fixes: Resolved stray merge markers in
contracts/escrow/src/lib.rsandcontracts/milestones/src/lib.rsthat were introduced during themax_sponsorsfeature integration, causing build failures on a clean clone. -
Panic avoidance — deposit count ceiling (Closes #45): Replaced the unchecked
deposit_count += 1incontracts/maintenance-pool/src/lib.rswithchecked_add, returning the newDepositCountOverflowerror variant instead of panicking atu32::MAX. Companion regression testtest_deposit_rejects_when_deposit_count_would_overflowadded. -
Atomic payout revert risk documented & tested (partial mitigation, #47): Added
MockPanicTokencontract doubles and two new tests —test_release_all_or_nothing_revert_with_blocked_recipient(escrow) andtest_release_issue_all_or_nothing_revert_with_blocked_recipient(milestones) — that prove the all-or-nothing payout semantics when a frozen/unauthorized trustline blocks one recipient. The security model section in README now documents this risk and the required backend-side pre-flight trustline check. -
Milestones budget-conservation fuzz harness (partial coverage, #54): Added
test_milestones_invariant_fuzzing— a 300-step deterministic property-based test running random sequences ofcreate_milestone,contribute,allocate,release_issue,deallocate, andcancel_milestone. After every operation it asserts: (a) for open milestonestotal_budget == remaining_budget + Σallocations, and (b) every issue_id inallocationshas a liveIssueStatus. Confirmed the invariant holds across all generated sequences. -
Real-network integration test design doc (progress on #50): Added
docs/real-network-integration-testing.mddocumenting the full Testnet/Mainnet integration harness: environment variables, Friendbot provisioning, WASM compilation +soroban-clideployment, liveness test sequence (fund → contribute → release), and post-run verification steps.
cargo test --workspace— all 94 tests pass (51 escrow · 16 maintenance-pool · 27 milestones)- New escrow tests:
test_fund_allows_reuse_after_refund,test_fund_allows_reuse_after_paid,test_fund_still_rejects_reuse_of_funded_escrow,test_release_all_or_nothing_revert_with_blocked_recipient - New maintenance-pool test:
test_deposit_rejects_when_deposit_count_would_overflow - New milestones tests:
test_release_issue_all_or_nothing_revert_with_blocked_recipient,test_milestones_invariant_fuzzing