Skip to content

Implement per-payer payment cooldown with sliding window rate limiting #162

@Kingsman-99

Description

@Kingsman-99

Description

Implement a sliding-window rate limiter for invoice payments. Each payer has a configurable cooldown period between payments on the same invoice. Additionally, implement a global per-invoice payment rate limit (max N payments within any rolling time window) to prevent coordinated payment flooding.

Acceptance Criteria

  • InvoiceOptions accepts payment_cooldown_secs: Option<u64> and max_payments_per_window: Option<u32> and payment_window_secs: Option<u64>
  • Per-payer cooldown: _pay stores last payment timestamp at key (symbol_short!("pcd"), invoice_id, payer) and panics with "payment cooldown active" if within window
  • Global rate limit: _pay maintains a ring-buffer of recent payment timestamps in persistent storage, evicts entries older than payment_window_secs, and panics with "payment rate limit exceeded" if count >= max_payments_per_window
  • Ring buffer must not grow unbounded — cap storage at 50 entries with eviction
  • Cooldown and rate limit fields are stored in InvoiceExt (not InvoiceCore) to keep storage efficient
  • get_invoice_ext returns both fields correctly
  • Test test_cooldown_blocks_same_payer_within_window — same payer blocked, different payer succeeds
  • Test test_rate_limit_blocks_after_n_payments — Nth+1 payment blocked regardless of payer
  • Test test_rate_limit_window_resets — payments succeed again after window expires
  • Test test_cooldown_and_rate_limit_independent — both can be active simultaneously

Context

  • _pay is in contracts/split/src/lib.rs (~line 1313)
  • InvoiceOptions, InvoiceCore, InvoiceExt are in contracts/split/src/types.rs
  • Nonce storage pattern at nonce_key(invoice_id, payer) is a reference for per-payer keys
  • env.ledger().timestamp() provides current time
  • The ring buffer must use soroban_sdk::Vec (not std) and fit within Soroban storage constraints

Metadata

Metadata

Labels

GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardOfficial CampaignCampaign: Official CampaignenhancementNew feature or requestgrantfoxIssue for GrantFox program

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions