Skip to content

maintenance-pool::reclaim_deposit's inactivity window is measured from last_withdraw_at = 0 for never-withdrawn pools, so deposits are reclaimable immediately #414

Description

@chonilius

Problem

MaintenancePool.last_withdraw_at is initialized to 0 when a pool is created in deposit(), and only withdraw() ever updates it. reclaim_deposit gates on:

let now = env.ledger().timestamp();
if now < pool.last_withdraw_at + INACTIVITY_WINDOW {   // 0 + 90 days
    return Err(Error::InactivityWindowNotElapsed);
}

For any pool that hasn't had a withdrawal yet, this compares the current ledger time with Unix epoch + 90 days (1970-04-01). On any real network, now is decades past that, so the check always passes. A sponsor can deposit and call reclaim_deposit in the next transaction. The "90-day inactivity" guarantee that #42 and the README describe doesn't apply to new pools.

This undermines the pool's purpose. Maintainers and the oracle plan rewards around a funded pool, but the funds can be pulled at any moment until the first withdraw. And with the separate "reclaim never marks the deposit as consumed" issue, a fresh pool can be drained immediately.

The test suite doesn't catch this because Soroban's test ledger starts at timestamp 0. #346's boundary test advances time from 0, so "0 + window" and "created_at + window" give the same result there.

Suggested fix

Measure inactivity from the most recent activity:

let last_activity = pool.last_withdraw_at.max(pool.created_at);
// or per-deposit: .max(deposit.timestamp)
if now < last_activity.saturating_add(INACTIVITY_WINDOW) { ... }
  • Using deposit.timestamp as well stops a late deposit into a long-idle pool from being instantly reclaimable.
  • Add a test that first moves the ledger to a realistic timestamp, such as 1_700_000_000, and then creates and deposits: an immediate reclaim must fail.

Related: #42, #346.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Stellar WaveIssues in the Stellar wave programbugSomething isn't workingsecuritySecurity-related issuevery hardVery difficult task, expert-level effort required

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions