--- title: PRD - Decentralized Custody and Smart-Contract Escrow Roadmap tags: [prd, escrow, custody, smart-contracts, governance, payments, roadmap] created: 2026-05-28 status: draft-for-review owner: payments + security + operations --- # PRD - Decentralized Custody and Smart-Contract Escrow Roadmap ## Executive decision Do **not** move the whole Amanat escrow flow into a custom smart contract as the next step. The current architecture already uses on-chain settlement through Request Network, in-house wallet checkout, derived destination wallets, Transaction Safety Provider checks, and an internal funds ledger. The bigger risk is not "lack of blockchain"; it is **custody and administration centralization**: one backend/admin path can still become too powerful if hot keys, release/refund confirmation, sweep authority, and dispute decisions are not split across independent signers and delayed controls. Recommended path: 1. Harden the current hybrid escrow. 2. Move custody to multisig/hardware signers. 3. Add timelocked governance for global settings. 4. Pilot a minimal on-chain escrow only for opt-in/high-value flows after the above is stable. ## Current baseline | Area | Current state | Risk | |---|---|---| | Pay-in | Request Network in-house checkout, direct wallet txs, signed webhooks, transaction-safety checks | Still depends on webhook durability and reconciliation | | Funds tracking | `FundsLedgerEntry` exists and is append-only | Release/refund ledger enforcement is env-gated by `PAYMENT_LEDGER_ENFORCEMENT` | | Deposit routing | Derived destinations per `(buyer, sellerOffer, chainId)` | Live divergent-destination probe still needs production-grade evidence | | Sweep custody | Build-only / hot-key signer abstraction | Production must avoid hot-key signing | | Release/refund | Admin endpoints build and confirm instructions | Needs mandatory multisig/hardware proof and stronger dispute gating | | Disputes | Model/service/routes exist with legacy status enum | Needs alignment with canonical dispute/escrow state machine | | Admin control | App RBAC plus optional Trezor proof | No non-centralized admin quorum yet | ## Goals - Remove single-admin and backend-hot-key custody risk. - Make release/refund/sweep authority require independent signers. - Preserve the marketplace's human dispute workflow. - Keep buyer UX close to the current Request Network in-house checkout. - Add on-chain escrow only where it creates trust benefit larger than audit and UX cost. ## Non-goals - No token-voting DAO for individual buyer/seller disputes. - No full rewrite of payments into Solidity before ledger, signing, and webhook controls are stable. - No custom bridge, cross-chain settlement contract, or generalized DeFi protocol. - No removal of the internal funds ledger; the ledger remains the application accounting source even if custody moves on-chain. ## Target trust model ```mermaid flowchart LR Buyer["Buyer wallet"] --> PayIn["Request Network / in-house checkout"] PayIn --> Dest["Per-payment derived destination"] Dest --> Safety["Transaction Safety Provider\nconfirmations + token/recipient/amount + AML"] Safety --> Ledger["Internal append-only funds ledger"] Ledger --> Policy["Release/refund policy engine"] Policy --> Safe["Safe multisig custody"] Safe --> Seller["Seller wallet"] Safe --> BuyerRefund["Buyer refund wallet"] Admin["Admin UI"] --> Policy Arb["Arbitrator quorum"] --> Safe Guardian["Guardian"] --> Pause["Pause / cancel dangerous ops"] Timelock["Timelock / AccessManager"] --> Policy ``` ## Phase 0 - Stabilize The Hybrid Escrow **Timebox:** 1-2 weeks **Purpose:** Make the current system safe enough that decentralizing custody does not hide application bugs under contract ceremony. | Work | Owner | Exit criteria | |---|---|---| | Turn on `PAYMENT_LEDGER_ENFORCEMENT=true` in dev, then staging | Backend | Release/refund cannot exceed ledger available balance | | Backfill/verify ledger entries for active Request Network payments | Backend | Reconciliation report has no unexplained funded payments without ledger rows | | Enforce dispute hold in every release/refund path | Backend | Opening a dispute blocks release and refund until explicit resolution/override | | Require Trezor proof in staging with `TREZOR_SAFEKEEPING_REQUIRED=true` | Backend + frontend | Release/refund without proof is rejected; valid Trezor proof succeeds | | Add audit entries for release/refund/sweep instruction build and confirm | Backend | Each operation records actor, before/after state, tx hash, signer, and reason | | Complete RN durable webhook ingress design | Platform | Worker storage/replay design approved; backend remains the trust oracle | **Decision gate:** no Safe migration until release/refund is ledger-gated and dispute-gated in staging. ## Phase 1 - Move Custody To Safe Multisig **Timebox:** 2-4 weeks **Purpose:** Remove single-key custody without changing core escrow semantics. | Work | Owner | Exit criteria | |---|---|---| | Create Safe accounts per supported chain | Ops + security | 2-of-3 minimum for dev/staging, 3-of-5 preferred for production | | Register hardware-backed owners | Ops | At least two owners use Trezor or equivalent hardware wallets | | Route release/refund/sweep builds to Safe transaction proposals | Backend + frontend | Admin UI builds a Safe transaction instead of direct hot-key tx | | Confirm Safe execution before ledger release/refund append | Backend | Ledger terminal entry requires verified Safe tx hash | | Remove production hot-key sweep mode | Ops | `DERIVED_DESTINATION_SWEEP_SIGNER=build-only` in production | | Add break-glass policy | Security | Time-limited, alarmed, documented; cannot silently bypass quorum | **Administration model:** admins can propose, but custody owners execute. A compromised app admin cannot move funds alone. ## Phase 2 - Durable Payment Evidence And Quarantine **Timebox:** parallel with Phase 1 **Purpose:** Make payment evidence durable and make tainted-funds isolation real. | Work | Owner | Exit criteria | |---|---|---| | Cloudflare Worker receives RN webhooks first | Platform | Raw body, headers, delivery ID, payment reference, timestamp durably stored | | Replay endpoint/tool for stored webhook deliveries | Backend + ops | Operator can replay by delivery ID/time window/payment reference | | AML provider behind Transaction Safety Provider | Backend + compliance | `clean` allows funding; sanctions/mixer verdict blocks or quarantines | | Derived destination quarantine workflow | Backend + admin UI | Failed AML or transfer mismatch prevents sweep into treasury/Safe | | Live divergent-destination probe | Payments | Two real paid intents to two derived addresses both complete and reconcile | **Decision gate:** no custom escrow contract until webhook replay and per-payment quarantine work operationally. ## Phase 3 - Decentralize Administrative Control **Timebox:** 4-6 weeks **Purpose:** Split operational permissions without making daily support impossible. | Control | Recommended design | |---|---| | Custody movement | Safe multisig threshold | | Global escrow settings | Timelock or OpenZeppelin AccessManager-managed roles | | Contract upgrades, if any | Timelocked multisig, no instant admin upgrade | | Emergency pause | Guardian role can pause, not withdraw | | Dispute financial outcome | App records decision; Safe quorum executes release/refund/split | | Confirmation thresholds | App admin can propose; high-risk decreases require timelock or second approval | | Break-glass | Time-limited, high-severity alert, postmortem required | Use token/DAO voting only for protocol-level parameters if the platform later has a real governance community. Do not use broad token voting for individual disputes; it leaks private commercial facts and is slow/manipulable. ## Phase 4 - Minimal Smart-Contract Escrow Pilot **Timebox:** 6-10 weeks after Phases 0-3 **Purpose:** Test whether on-chain escrow improves trust enough for a specific cohort. Pilot only when one of these is true: - Average escrow value is high enough that users ask for contract custody. - Sellers/buyers explicitly demand on-chain proof that funds cannot be swept. - The platform wants a premium "contract escrow" mode. - Regulated partners require provable segregation of funds. Minimal contract shape: | Function | Notes | |---|---| | `fund(orderId, token, amount, buyer, seller, deadline)` | Buyer funds ERC-20 escrow; order ID is app-generated and hashed | | `confirmDelivery(orderId)` | Buyer can release without admin | | `openDispute(orderId)` | Either party can pause auto-release before deadline | | `resolve(orderId, releaseAmount, refundAmount, reasonHash)` | Arbitrator/multisig executes split | | `claimAfterTimeout(orderId)` | Seller can claim after timeout if no dispute | | `refundAfterExpiry(orderId)` | Buyer can recover if seller never starts/accepts | | `pause()` / `unpause()` | Guardian pause only; no fund extraction | Security requirements: - Use audited libraries for `SafeERC20`, reentrancy protection, pausing, and access control. - Avoid upgradeability unless the timelock and upgrade policy are production-ready. - External audit before mainnet funds. - Formal state-transition tests mirroring [[Funds Ledger and Escrow State Machine Specification]]. - Fuzz tests for double release, split math, fee rounding, pausing, and timeout races. ## Phase 5 - Go / No-Go Criteria Proceed from hybrid multisig custody to custom escrow only if all are true: - Safe/Trezor flow has processed real releases/refunds without operational pain. - Ledger enforcement has run for at least one complete payment cycle. - Dispute hold cannot be bypassed in tests or manual review. - Durable webhook ingress and replay are live. - Per-payment destination quarantine is live. - Contract audit budget and maintenance owner are approved. - The user trust/compliance benefit is explicitly documented. If these are not true, continue improving the hybrid model. A contract that encodes immature off-chain policy will make the system harder to fix, not safer. ## Stale documentation corrected in this pass This roadmap was created together with a focused documentation alignment pass: - [[System Overview]] now reflects Request Network as the primary payment rail, derived destinations, ledger, and existing dispute service. - [[System Architecture]] now shows Request Network webhooks and durable ingress as the target, instead of SHKeeper-only webhook flow. - [[Backend Architecture]] no longer lists removed SHKeeper service folders/routes as the current module map. - [[Escrow Flow]] now reflects hybrid custody, ledger gates, derived destinations, and the recommended multisig-before-contract direction. - [[Dispute Flow]] no longer says the backend dispute service/model/routes do not exist. - [[Request Network Integration Constraints]] now marks the in-house checkout and derived-destination work as implemented/partially implemented rather than only designed. ## External references - Safe threshold custody model: - OpenZeppelin AccessManager and timelock guidance: - Request Network payment contracts overview: