Difficulty: Expert. Scope: multi-week epic. Contract + keeper service + SDK.
Problem
Payments are one-shot: a human must sign each pay. Subscriptions, retainers, and scheduled payroll need "pay split #7 100 USDC on the 1st of every month" to run without a human signing every time. Soroban has no native cron, so this needs a contract-level authorization primitive plus an off-chain keeper that submits the transactions.
Proposal
Two parts:
- On-chain mandate. A payer authorizes a recurring pull:
create_mandate(payer, split_id, token, amount, interval, max_runs, expiry). The contract stores it and enforces that execute_mandate(mandate_id) can only move funds once per interval, up to the amount, until expiry or max_runs, and can be revoked by the payer at any time.
- Off-chain keeper. A service that watches due mandates and calls
execute_mandate.
Why this is hard
- The security model is the whole problem. A mandate is a standing authorization to pull a payer's funds. It must be impossible for a keeper (or anyone) to over-pull: enforce per-interval rate limiting on-chain, not in the keeper. Research how Soroban authorization (
require_auth, auth entries, or an allowance held by the contract) can represent "the contract may pull up to X per interval from the payer" without the payer signing each run.
- Replay and idempotency:
execute_mandate must be safe to call by anyone (keepers are untrusted) and must not double-execute within an interval even under races.
- Revocation and expiry must be immediate and final.
- Keeper liveness and incentives: what happens if no keeper runs it on time (catch-up vs skip)? Who pays the keeper's fees?
Deliverables
- Threat-model-first design RFC.
- Contract: mandate lifecycle (create, execute, revoke, view) with on-chain interval enforcement and events.
- Keeper service (Node) with due-detection, submission, backoff, and a dry-run mode.
- SDK helpers and tests, including adversarial tests (double execute, early execute, over-amount, post-revoke, post-expiry).
Acceptance criteria
- Maintainer-approved RFC with an explicit threat model before implementation.
- On-chain enforcement makes over-pulling and early execution impossible regardless of keeper behavior; adversarial tests prove it.
- Revocation and expiry take effect immediately and are tested.
- The keeper is stateless-recoverable (can crash and resume without missing or duplicating runs).
- Fee responsibility for execution is defined and documented.
Related
Distinct from streaming (continuous release of locked funds). This pulls from the payer's live balance on a schedule.
Difficulty: Expert. Scope: multi-week epic. Contract + keeper service + SDK.
Problem
Payments are one-shot: a human must sign each
pay. Subscriptions, retainers, and scheduled payroll need "pay split #7 100 USDC on the 1st of every month" to run without a human signing every time. Soroban has no native cron, so this needs a contract-level authorization primitive plus an off-chain keeper that submits the transactions.Proposal
Two parts:
create_mandate(payer, split_id, token, amount, interval, max_runs, expiry). The contract stores it and enforces thatexecute_mandate(mandate_id)can only move funds once per interval, up to the amount, until expiry ormax_runs, and can be revoked by the payer at any time.execute_mandate.Why this is hard
require_auth, auth entries, or an allowance held by the contract) can represent "the contract may pull up to X per interval from the payer" without the payer signing each run.execute_mandatemust be safe to call by anyone (keepers are untrusted) and must not double-execute within an interval even under races.Deliverables
Acceptance criteria
Related
Distinct from streaming (continuous release of locked funds). This pulls from the payer's live balance on a schedule.