Skip to content

Security/persistent ttl bump#369

Open
Harbduls wants to merge 3 commits into
Talenttrust:mainfrom
Harbduls:security/persistent-ttl-bump
Open

Security/persistent ttl bump#369
Harbduls wants to merge 3 commits into
Talenttrust:mainfrom
Harbduls:security/persistent-ttl-bump

Conversation

@Harbduls
Copy link
Copy Markdown
Contributor

Closes #334

Harbduls added 3 commits May 28, 2026 13:18
…ites

## Summary
Migrated 4 orphaned test suites from crate root to test/ subdirectory and updated all function signatures to match the current EscrowClient API with authorization hardening.

## Changes

### Test Suite Migration
- Moved `src/deposit.rs` → `src/test/deposit.rs`
- Moved `src/release.rs` → `src/test/release.rs`
- Moved `src/refund.rs` → `src/test/refund.rs`
- Moved `src/create_contract.rs` → `src/test/create_contract.rs`

### API Signature Updates
All test suites updated to match current EscrowClient API:

**deposit_funds:**
- Old: `deposit_funds(&contract_id, &amount)`
- New: `deposit_funds(&contract_id, &caller, &amount)`

**release_milestone:**
- Old: `release_milestone(&contract_id, &milestone_index)`
- New: `approve_milestone_release(&contract_id, &caller, &milestone_index)` + `release_milestone(&contract_id, &caller, &milestone_index)`

**create_contract:**
- Old: `create_contract(&client, &freelancer, &milestones)`
- New: `create_contract(&client, &freelancer, &arbiter, &milestones, &release_authorization)`

### Security Enhancements
- Added comprehensive rustdoc comments documenting security assumptions
- All tests now properly test authorization with caller parameter
- Approval workflow tested (approve before release)
- ReleaseAuthorization mode explicitly specified

### Test Coverage
**deposit.rs (4 tests):**
- Deposit accumulation and state transitions
- Zero deposit rejection
- Overfunding prevention
- Post-refund deposit rejection

**release.rs (5 tests):**
- Sequential milestone release and completion
- Insufficient balance rejection
- Invalid milestone index rejection
- Refunded milestone release rejection
- Double-release prevention

**refund.rs (7 tests):**
- Partial refund with balance preservation
- Full refund state transition
- Empty refund request rejection
- Duplicate milestone rejection
- Released milestone refund rejection
- Double-refund prevention
- Insufficient balance rejection

**create_contract.rs (4 tests):**
- Contract creation and milestone persistence
- Empty milestones rejection
- Zero-amount milestone rejection
- Same participant rejection

### Documentation
Updated `docs/escrow/tests.md`:
- Added test organization section with module descriptions
- Documented all migrated test suites with detailed descriptions
- Updated version to 0.3.0
- Added migration notes explaining API changes

## Security Validation
✅ Authorization checks: All tests use proper caller authentication
✅ Overflow prevention: Amount validation tested
✅ Fail-closed state machine: Invalid state transitions rejected
✅ Storage TTL: Approval expiry workflow tested
✅ Fee accounting: Balance tracking validated in all scenarios
✅ Double-spending prevention: Release/refund idempotency tested
✅ Input sanitization: Empty/duplicate/invalid inputs rejected

## Test Execution
All tests compile and are now discoverable by `cargo test`.
Previously: 31 tests discovered (only emergency_controls and pause_controls)
Now: 31+ tests discovered (includes all migrated suites)

## Acceptance Criteria Met
✅ Orphaned test files moved to contracts/escrow/src/test/
✅ Module declarations already present in test.rs
✅ Function signatures updated to match current EscrowClient API
✅ Authorization hardening applied (caller parameter)
✅ Approval workflow integrated
✅ Comprehensive rustdoc comments added
✅ Documentation updated in docs/escrow/tests.md
✅ No orphaned .rs test files remain at crate root
✅ Security assumptions validated and documented
Add explicit TTL extension on all persistent storage reads and writes
to prevent DataKey::Contract(id) and milestone entries from being
evicted by the Soroban ledger, which would strand active escrow
fund-state.

Changes:
- ttl.rs: Add PERSISTENT_MAX_TTL_LEDGERS (1yr), PERSISTENT_BUMP_THRESHOLD
  (180d), MIN_PERSISTENT_TTL (30d) constants and four helper functions:
  extend_contract_ttl, extend_milestone_ttl, extend_next_contract_id_ttl,
  extend_contract_and_milestones_ttl
- lib.rs: Call extend_ttl helpers on every persistent read/write in
  create_contract, deposit_funds, approve_milestone_release,
  release_milestone, refund_unreleased_milestones, get_contract,
  get_milestones, get_refundable_balance
- approvals.rs: Call extend_contract_ttl and extend_milestone_ttl when
  reading contract and milestone data during approval
- test/persistence.rs: 13 new TTL-specific tests covering all mutating
  and read operations, long-running contract simulation, lifecycle
  completeness, constant sanity checks, and independent contract TTLs
- test/performance.rs: Update read_entries baselines (+1) to account
  for the additional extend_ttl storage operations
- docs/escrow/storage-ttl.md: Document TTL policy, constants, security
  assumptions, coverage table, and performance impact

Security:
- Fail-closed: TTL extension only occurs on successful transactions;
  panics roll back the extension along with state changes
- No overflow: all TTL values are well within u32::MAX
- No auth required: extend_ttl is a storage op, not a contract call
- Invariant: any contract touched within its TTL window remains live;
  eviction cannot strand active escrow accounting
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bump persistent storage TTL for active escrow contracts to prevent eviction

1 participant