Skip to content

[CRITICAL] Persistent storage TTLs can expire before claims/refunds — user funds permanently locked #166

Closed

Description

@grantfox-oss

Summary

All four contracts store user-claimable state (bet entries, refund records, claim windows, referral earnings) in persistent storage entries with fixed TTLs that are never extended on the read path. If a market resolves or a payout window extends beyond the original TTL, the storage entry expires and the data is permanently lost — the user can no longer claim their refund or payout.

Impact

  • Permanent fund lock: expired BetEntry or RefundRecord storage means users lose access to their XLM.
  • No read-bump: view-only operations (e.g., checking claimable amounts) do not extend the TTL, so merely querying state accelerates expiry.
  • Keeper-dependent: only an external keeper can refresh TTLs before they expire; if the keeper is offline, funds are at risk.

Fix

  • Extend the TTL on every read path (Soroban's extend_ttl or equivalent) for entries that hold claimable state.
  • Set TTLs relative to the longest possible claim window, not the creation time.
  • Add a bump_ttl public function callable by anyone for entries close to expiry.

Activity

  1. GauravKarakoti commented on Aug 23, 2026

    @GauravKarakoti

    Allow me to work on this one

  2. samjay8 commented on Aug 23, 2026

    @samjay8
    Contributor

    Hi team,

    I'd like to work on resolving this issue. Here is my proposed plan of approach to prevent user funds from becoming locked due to expiring persistent storage TTLs:

    Plan of Approach

    1. Implement Read-Path TTL Bumping:

      • Update all four contracts (BetEntry, RefundRecord, claim windows, and referral earnings) to invoke Soroban's extend_ttl on every read/query path.
      • Ensure TTLs are dynamically extended upon interaction to prevent active entries from expiring during resolution or payout windows.
    2. Align TTL Thresholds with Claim Lifecycles:

      • Adjust storage TTL initial values to be relative to the maximum possible claim window duration rather than a fixed creation-time value.
    3. Expose Public bump_ttl Function:

      • Implement a permissionless bump_ttl entrypoint across contracts, allowing any user or keeper to refresh TTLs for storage entries approaching expiration.
    4. Testing & Validation:

      • Add unit tests simulating market resolution extensions to verify storage entries remain accessible throughout the entire claim window.
      • Verify that read operations and public bump_ttl calls correctly extend storage lifetimes without corrupting state.

    I can implement these TTL updates and test cases promptly.

  3. grantfox-oss commented on Aug 23, 2026

    @grantfox-oss
    Author

    🦊 GrantFox — @samjay8 has been assigned to this issue as part of the Third Campaign campaign!

    Next steps:

    1. Open a Pull Request referencing this issue (e.g., Closes #166)
    2. Your PR will be reviewed by the SPulse-Org maintainers

    Good luck! Track your progress on GrantFox.

  4. grantfox-oss commented on Aug 30, 2026

    @grantfox-oss
    Author

    🎉 This issue has been marked as completed on GrantFox!

    @samjay8's PR #191 was approved and merged by @Muyideen-js.

    🏆 @samjay8: You earned 40 FoxPoints for this contribution! Your current tier: Builder (2,220 total points). Track your full progress on GrantFox.

    👏 Great work, @samjay8! Keep contributing to SPulse-Org.

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

Metadata

Metadata

Assignees

Labels

GrantFox OSSIssue tracked in GrantFox OSSThird CampaignCampaign: Third CampaigncriticalCritical severity - funds at riskttl-storageTTL / storage lifecycle

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions