Skip to content

stealth-vault time-locked stealth payments contract #14

@truthixify

Description

@truthixify

Labels: Stellar Wave, stellar, feature, drips, help-wanted
Tier: L (1–2 weeks)
Type: feature

Context

Today every Wraith payment is unlocked the moment it lands at the stealth address — the recipient can spend it as soon as they scan and derive the private key. There's no concept of "send now, recipient can claim after N ledgers" or "send with a refund window."

These primitives are useful for: escrow, time-released payroll, payment links with a "claim by" deadline (after which funds return to sender), and conditional invoicing. Several Drips program partners have asked for them.

This is not in scope of stealth-sender — we want a separate Soroban contract that doesn't expand the audit surface of the existing simple sender.

Scope

Build a new crate contracts/stellar/stealth-vault/:

  1. deposit(sender, recipient_meta_address, amount, asset, unlock_ledger, refund_after, ephemeral_pub_key):
    • Transfers amount of asset from sender into the contract.
    • Records the deposit with unlock_ledger (recipient can withdraw at or after) and refund_after (sender can claw back at or after — must be > unlock_ledger + some grace).
    • Emits an announcement so the recipient can find it during a normal scan.
  2. claim(deposit_id, signature):
    • Recipient proves ownership of the stealth address (signature over deposit_id || claim_nonce).
    • Requires current ledger ≥ unlock_ledger.
    • Transfers funds to a destination of recipient's choice.
  3. refund(deposit_id):
    • Only the original sender may call.
    • Requires current ledger ≥ refund_after AND the deposit is unclaimed.
    • Returns funds to sender.
  4. Each deposit gets a deterministic deposit_id so recipients can index efficiently.

Open design questions

  • Should unlock_ledger == current be allowed (= immediate-claim with refund window)? Argue.
  • Refund window grace — pick a minimum (e.g., 100 ledgers ≈ 8 min) so a malicious sender can't set refund_after == unlock_ledger and race the recipient.
  • Should the deposit emit a modified announcement schema that includes unlock_ledger? Or is the standard announcement plus a separate read-by-ID call sufficient? (Affects SDK scan logic — flag SDK follow-up issue.)

Acceptance criteria

  • New crate with full unit and property tests.
  • Adversarial tests: sender tries to claim before refund window, recipient tries to claim before unlock, double-claim attempts.
  • Deploy script integration (issue #07).
  • SDK follow-up issue filed for buildVaultDeposit / buildVaultClaim.
  • Demo follow-up issue filed for the UI surface.

Why this matters

Time-locked stealth is the smallest possible step from "private payment" to "private escrow." Once it exists, a wide range of products (invoicing with deadlines, vesting, conditional disbursements) become buildable on Wraith without leaving the privacy envelope.

Metadata

Metadata

Assignees

Labels

Stellar WaveIssues in the Stellar wave programdripsFunded via Drips NetworkfeatureNew feature workhelp wantedExtra attention is neededstellarTouches Stellar / Soroban code

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