<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>OrcaRail API Blog</title>
        <link>https://docs.orcarail.com/blog/</link>
        <description>OrcaRail API Blog</description>
        <lastBuildDate>Mon, 20 Apr 2026 00:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <item>
            <title><![CDATA[The OrcaRail Non-Custodial Roadmap]]></title>
            <link>https://docs.orcarail.com/blog/non-custodial-roadmap/</link>
            <guid>https://docs.orcarail.com/blog/non-custodial-roadmap/</guid>
            <pubDate>Mon, 20 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[An eight-phase roadmap moving OrcaRail from an HD-wallet sweep model to on-chain payment-link contracts, allowance-pull subscriptions on EVM and Solana, reduced custody on Bitcoin, and optional decentralized keepers.]]></description>
            <content:encoded><![CDATA[<p><strong>April 20, 2026</strong> — Today we are publishing the full roadmap for moving OrcaRail from its current <strong>custodial sweep model</strong> (we generate a deposit address per payment link, then sweep and split funds) to a <strong>non-custodial smart-contract model</strong> (funds land in a per-link contract that splits and settles atomically, and subscriptions pull from a payer-controlled allowance).</p>
<p>This post is the index. Each phase has its own deep-dive post and a living docs page, so you can deep-link to exactly the part you care about.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-we-are-doing-this">Why we are doing this<a href="https://docs.orcarail.com/blog/non-custodial-roadmap/#why-we-are-doing-this" class="hash-link" aria-label="Direct link to Why we are doing this" title="Direct link to Why we are doing this" translate="no">​</a></h2>
<p>The current flow works, but it has a simple structural problem: between deposit and settlement, <strong>OrcaRail holds the funds</strong>. That is true even though we never hold merchant operating balances — the in-flight moment between "payer sent" and "merchant received" is custodial. Removing that moment is a security, compliance, and reliability win.</p>
<p>Concretely, the legacy path looks like:</p>
<div class="wrapper_vprU"><button type="button" class="expandBtn_RmxB" aria-label="Show diagram fullscreen" title="Fullscreen"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7" stroke-linecap="round" stroke-linejoin="round"></path></svg></button></div>
<p>The target is:</p>
<div class="wrapper_vprU"><button type="button" class="expandBtn_RmxB" aria-label="Show diagram fullscreen" title="Fullscreen"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7" stroke-linecap="round" stroke-linejoin="round"></path></svg></button></div>
<p>Funds never pass through a wallet we control. Splits happen on-chain. Subscriptions pull from an allowance the payer can revoke at any time.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-is-changing-in-one-page">What is changing, in one page<a href="https://docs.orcarail.com/blog/non-custodial-roadmap/#what-is-changing-in-one-page" class="hash-link" aria-label="Direct link to What is changing, in one page" title="Direct link to What is changing, in one page" translate="no">​</a></h2>
<table><thead><tr><th>Area</th><th>Before</th><th>After</th></tr></thead><tbody><tr><td>Payment link addresses</td><td>HD-derived EOA or Alchemy smart account per link</td><td>Deterministic CREATE2 on EVM; PDA on Solana — no key material stored by OrcaRail</td></tr><tr><td>Settlement</td><td>Sweep transaction after observation</td><td>Atomic split inside the receiver on the pay transaction</td></tr><tr><td>Subscriptions</td><td>Custodial pull from merchant-funded wallet</td><td>Payer signs ERC-20 <code>approve</code> or SPL delegate; keeper calls <code>charge(id)</code></td></tr><tr><td>Keeper</td><td>Single NestJS scheduler</td><td>NestJS primary + Chainlink Automation or Gelato fallback (+ optional EigenLayer)</td></tr><tr><td>Cross-chain</td><td>Relay bridge executed by keeper</td><td>Same Relay route, but as an on-chain call from a non-custodial receiver</td></tr><tr><td>Bitcoin</td><td>Hot wallet with server-held xpub</td><td>2-of-2 taproot multisig per link (merchant + platform) with pre-signed refunds</td></tr></tbody></table>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-roadmap">The roadmap<a href="https://docs.orcarail.com/blog/non-custodial-roadmap/#the-roadmap" class="hash-link" aria-label="Direct link to The roadmap" title="Direct link to The roadmap" translate="no">​</a></h2>
<p>Each phase is self-contained and shippable. Early phases remove custody for the largest volumes (EVM payments and subscriptions) and later phases tackle the harder chains and optional decentralization.</p>
<ul>
<li class=""><strong><a class="" href="https://docs.orcarail.com/blog/phase-0-design-and-audit-strategy/">Phase 0: Designing a non-custodial payment stack</a></strong> — fee/split spec freeze, chain selection, audit vendor, deployer multisig, the subscription-model decision matrix.</li>
<li class=""><strong><a class="" href="https://docs.orcarail.com/blog/phase-1-evm-payment-link-contracts/">Phase 1: Contract-based payment links on EVM</a></strong> — <code>PaymentLinkFactory</code> + <code>PaymentLinkReceiver</code> + <code>FeeSplitter</code>, deterministic addresses, event indexer.</li>
<li class=""><strong><a class="" href="https://docs.orcarail.com/blog/phase-2-allowance-pull-subscriptions/">Phase 2: Allowance-pull subscriptions</a></strong> — <code>SubscriptionHub</code>, new payer flow, keeper replacing the custodial auto-charge processor.</li>
<li class=""><strong><a class="" href="https://docs.orcarail.com/blog/phase-3-multi-evm-and-keeper-redundancy/">Phase 3: Multi-EVM rollout and keeper redundancy</a></strong> — Ethereum, Arbitrum, Optimism, Polygon + Chainlink/Gelato fallback.</li>
<li class=""><strong><a class="" href="https://docs.orcarail.com/blog/phase-4-solana-pda-programs/">Phase 4: Non-custodial Solana with Anchor PDAs</a></strong> — <code>payment_link</code> and <code>subscription</code> Anchor programs, SPL delegate auto-charge.</li>
<li class=""><strong><a class="" href="https://docs.orcarail.com/blog/phase-5-bitcoin-reduced-custody/">Phase 5: Bitcoin — taproot 2-of-2 and honest scope</a></strong> — reduced custody, pre-signed refunds, Lightning BOLT12 as future work.</li>
<li class=""><strong><a class="" href="https://docs.orcarail.com/blog/phase-6-eigenlayer-keeper-avs/">Phase 6: Decentralized scheduler and EigenLayer</a></strong> — when an AVS helps and when it does not.</li>
<li class=""><strong><a class="" href="https://docs.orcarail.com/blog/phase-7-retiring-custody/">Phase 7: Retiring the custody infrastructure</a></strong> — dropping <code>hd_wallet_seed</code>, removing sweep paths, updating TOS.</li>
</ul>
<p>A companion post, <strong><a class="" href="https://docs.orcarail.com/blog/why-allowance-pull-subscriptions/">Why allowance-pull beats escrow and session keys</a></strong>, explains how we picked the subscription model.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-this-means-in-practice">What this means in practice<a href="https://docs.orcarail.com/blog/non-custodial-roadmap/#what-this-means-in-practice" class="hash-link" aria-label="Direct link to What this means in practice" title="Direct link to What this means in practice" translate="no">​</a></h2>
<p><strong>For merchants</strong>: after Phase 1, nothing changes in the API — payment-link URLs and webhooks behave the same. Withdrawal rules move from "settle after sweep" to "emit on pay". You get a faster, cheaper, more auditable path without code changes. Phase 2 adds a new public endpoint for payers to register their on-chain <code>approve</code>, matching the flow documented in <a class="" href="https://docs.orcarail.com/docs/subscriptions/auto-charge/">Auto-charge</a>.</p>
<p><strong>For payers</strong>: one-off payments feel identical. Subscriptions add one extra signature at setup (the on-chain <code>approve</code>) and a clearer "revoke" path: revoke on-chain, and OrcaRail stops trying. Your funds never leave your wallet until the contract pulls them, and never sit in a wallet we control.</p>
<p><strong>For integrators</strong>: API shape stays stable. New fields (contract addresses, deployment chain, allowance metadata) are additive, behind a feature flag per chain. Existing integrations keep working through their current renewal cycle and migrate on opt-in.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-stays-custodial-for-now">What stays custodial (for now)<a href="https://docs.orcarail.com/blog/non-custodial-roadmap/#what-stays-custodial-for-now" class="hash-link" aria-label="Direct link to What stays custodial (for now)" title="Direct link to What stays custodial (for now)" translate="no">​</a></h2>
<p>Bitcoin. We will reduce custody materially in <a class="" href="https://docs.orcarail.com/blog/phase-5-bitcoin-reduced-custody/">Phase 5</a> by moving every link to a 2-of-2 taproot multisig with a merchant signer, plus pre-signed refund PSBTs. But Bitcoin L1 does not have the contract expressiveness to eliminate custody outright today. BTC subscriptions remain out of scope until Lightning BOLT12 recurring payments are ready.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="timeline-and-status">Timeline and status<a href="https://docs.orcarail.com/blog/non-custodial-roadmap/#timeline-and-status" class="hash-link" aria-label="Direct link to Timeline and status" title="Direct link to Timeline and status" translate="no">​</a></h2>
<p>The full plan is tracked at <a class="" href="https://docs.orcarail.com/docs/non-custodial/roadmap/">/docs/non-custodial/roadmap</a> and each phase has a status page:</p>
<ul>
<li class="">Planned: <strong>0 — 7</strong></li>
<li class="">In progress: none yet</li>
<li class="">Shipped: none yet</li>
</ul>
<p>We will publish a dated update post each time a phase ships.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="read-the-architecture-docs">Read the architecture docs<a href="https://docs.orcarail.com/blog/non-custodial-roadmap/#read-the-architecture-docs" class="hash-link" aria-label="Direct link to Read the architecture docs" title="Direct link to Read the architecture docs" translate="no">​</a></h2>
<p>For the reference version of all of this — architecture diagrams, contract surface, migration guide, security model — start at <a class="" href="https://docs.orcarail.com/docs/non-custodial/overview/">/docs/non-custodial/overview</a>.</p>
<hr>
<p><strong><a href="https://app.orcarail.com/" target="_blank" rel="noopener noreferrer" class="">OrcaRail App</a></strong> · <strong><a href="https://docs.orcarail.com/" target="_blank" rel="noopener noreferrer" class="">Docs</a></strong> · <strong><a class="" href="https://docs.orcarail.com/docs/non-custodial/overview/">Non-custodial docs</a></strong></p>]]></content:encoded>
            <category>Announcement</category>
            <category>Payments</category>
            <category>Multi-Chain</category>
            <category>Web3</category>
            <category>Stablecoins</category>
            <category>Crypto</category>
        </item>
        <item>
            <title><![CDATA[OrcaRail Protocol: A Whitepaper for Non-Custodial, Non-Stop, Web2-to-Web3 Payment Rails]]></title>
            <link>https://docs.orcarail.com/blog/orcarail-protocol-whitepaper/</link>
            <guid>https://docs.orcarail.com/blog/orcarail-protocol-whitepaper/</guid>
            <pubDate>Mon, 20 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[The OrcaRail Protocol whitepaper. Four invariants (non-custodial, non-stop, credibly neutral, web2-compatible), a two-track roadmap, governance that decentralizes over time, and a reserved option — not a commitment — for a future governance token post-decentralization.]]></description>
            <content:encoded><![CDATA[<p><strong>April 20, 2026</strong> — This is the OrcaRail Protocol whitepaper. It is the canonical statement of what OrcaRail is becoming: an open, credibly neutral, non-custodial, non-stop payment rail that a Web2 merchant can integrate using familiar HTTP APIs and webhooks, and a Web3 payer can use with any wallet — and that keeps settling even if OrcaRail, the company, disappears.</p>
<p>It extends — it does <strong>not</strong> replace — the <a class="" href="https://docs.orcarail.com/blog/non-custodial-roadmap/">non-custodial roadmap</a> and the <a class="" href="https://docs.orcarail.com/blog/protocol-debate-non-custodial-futures/">protocol debate</a>. The non-custodial roadmap (Track N, Phases 0-7) removes custody. This whitepaper adds a parallel Track P that decentralizes the rest: indexers, frontends, standards, keepers, and governance.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="abstract">Abstract<a href="https://docs.orcarail.com/blog/orcarail-protocol-whitepaper/#abstract" class="hash-link" aria-label="Direct link to Abstract" title="Direct link to Abstract" translate="no">​</a></h2>
<p>OrcaRail Protocol is a set of on-chain primitives — payment-link factories and receivers, allowance-pull subscription hubs, fee splitters, Anchor programs on Solana, and taproot multisig descriptors on Bitcoin — together with public specifications for indexers, keepers, frontends, and SDKs that operate on top of those primitives. The protocol satisfies four invariants: <strong>non-custodial</strong> (no party holds funds in transit), <strong>non-stop</strong> (legitimate settlement continues without OrcaRail), <strong>credibly neutral</strong> (no single party can censor a well-formed paid transaction), and <strong>web2-compatible</strong> (merchants keep API keys, webhooks, and dashboards). The rollout is two parallel tracks: <strong>Track N</strong> removes custody in seven phases; <strong>Track P</strong> decentralizes indexing, frontends, standards, and settlement routing in five phases. No token exists at launch and none is planned as part of this whitepaper; a future governance token is explicitly <strong>reserved</strong> as an option for post-decentralization and would, if introduced, ship under its own whitepaper.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-introduction--why-a-protocol-not-just-a-product">1. Introduction — Why a protocol, not just a product<a href="https://docs.orcarail.com/blog/orcarail-protocol-whitepaper/#1-introduction--why-a-protocol-not-just-a-product" class="hash-link" aria-label="Direct link to 1. Introduction — Why a protocol, not just a product" title="Direct link to 1. Introduction — Why a protocol, not just a product" translate="no">​</a></h2>
<p>OrcaRail ships today as a hosted payments product with self-hosted options on the way. That is a product, not a protocol. Products can be improved; protocols can be <strong>trusted in absentia</strong>.</p>
<p>The <a class="" href="https://docs.orcarail.com/blog/non-custodial-roadmap/">non-custodial roadmap</a> takes custody out of the path. That is necessary but not sufficient. Even without custody, a payment rail can still break if the company running it stops paying AWS bills, gets sanctioned, or simply pivots. A protocol has to keep working when those things happen.</p>
<p>The <a class="" href="https://docs.orcarail.com/blog/protocol-debate-non-custodial-futures/">protocol debate</a> walked through five architectures. The synthesis was: ship the Pragmatist path, enforce Maximalist pressure against it, adopt intents for payer UX, write standards along the way, keep own-chain as an optional future. This whitepaper is that synthesis written as commitments.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-design-goals">2. Design goals<a href="https://docs.orcarail.com/blog/orcarail-protocol-whitepaper/#2-design-goals" class="hash-link" aria-label="Direct link to 2. Design goals" title="Direct link to 2. Design goals" translate="no">​</a></h2>
<p>Each goal is stated with a precise, testable definition. "Does the design satisfy this?" must have a yes-or-no answer.</p>
<ol>
<li class=""><strong>Non-custodial</strong> — At no point during a payment or subscription charge does a wallet or account controlled by OrcaRail, a merchant's processor, or any intermediary hold the payer's funds. <strong>Test</strong>: can a regulator freeze in-flight funds by serving OrcaRail alone? No.</li>
<li class=""><strong>Non-stop</strong> — If OrcaRail's servers go dark indefinitely, a legitimate due subscription charge still settles on-chain, and a payer can still complete a one-off payment. <strong>Test</strong>: after a 30-day OrcaRail outage, has any correctly-configured subscription missed a charge? No.</li>
<li class=""><strong>Credibly neutral</strong> — The on-chain rules are public, immutable per-link, and applied equally. OrcaRail cannot selectively deny service at the settlement layer (only at its own frontend). <strong>Test</strong>: can an unwelcome merchant still be paid through a third-party frontend? Yes.</li>
<li class=""><strong>Web2-compatible</strong> — Merchants retain the ergonomics they already have (REST endpoints, webhooks, API keys, dashboards, email). Protocolization does not require a merchant to run Ethereum tooling to accept a payment. <strong>Test</strong>: can a non-crypto-native merchant integrate in under an hour? Yes.</li>
<li class=""><strong>Real P2P</strong> — Defined precisely in the next section.</li>
</ol>
<p>A design that misses any goal is incomplete.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-what-real-p2p-means-here">3. What "real P2P" means here<a href="https://docs.orcarail.com/blog/orcarail-protocol-whitepaper/#3-what-real-p2p-means-here" class="hash-link" aria-label="Direct link to 3. What &quot;real P2P&quot; means here" title="Direct link to 3. What &quot;real P2P&quot; means here" translate="no">​</a></h2>
<p>Peer-to-peer is overloaded. In this protocol it has three concrete layers.</p>
<ul>
<li class=""><strong>Settlement P2P</strong> — Payer signs; funds flow payer → on-chain contract (EVM) or program-owned PDA (Solana) or 2-of-2 multisig (Bitcoin) → merchant and fee recipients, atomically. No OrcaRail wallet is in the path. This is enforced by Track N.</li>
<li class=""><strong>Discovery P2P</strong> — A payment link or subscription is fully resolvable from its on-chain data plus (optionally) IPFS-pinned metadata. Any wallet, any frontend, any third-party processor can render and complete it. OrcaRail's hosted dashboard is <strong>one</strong> implementation of the rendering layer, not the registry.</li>
<li class=""><strong>Liveness P2P</strong> — <code>SubscriptionHub.charge(id)</code> and the Anchor <code>charge</code> instruction are public. Any EOA or solver can call them. OrcaRail's scheduler is one participant among several (Chainlink, Gelato, merchant-run, solver-run).</li>
</ul>
<p>What "real P2P" does <strong>not</strong> mean here: we are not Lightning; we are not a direct wallet-to-wallet channel layer; we are not replacing a payment app with a DHT. OrcaRail is an <strong>on-chain protocol with off-chain UX</strong>. The P2P property comes from the impossibility of a middleman interposing on settlement, discovery, or liveness — not from avoiding on-chain rails.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-system-architecture">4. System architecture<a href="https://docs.orcarail.com/blog/orcarail-protocol-whitepaper/#4-system-architecture" class="hash-link" aria-label="Direct link to 4. System architecture" title="Direct link to 4. System architecture" translate="no">​</a></h2>
<p>At the highest level, the protocol is five layers.</p>
<div class="wrapper_vprU"><button type="button" class="expandBtn_RmxB" aria-label="Show diagram fullscreen" title="Fullscreen"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7" stroke-linecap="round" stroke-linejoin="round"></path></svg></button></div>
<p>The <strong>settlement layer</strong> is immutable-per-link on EVM and Solana, and per-link descriptor-derived on Bitcoin. The other four layers are swappable. A reader who wants the full technical diagram should go to <a class="" href="https://docs.orcarail.com/docs/non-custodial/architecture/">/docs/non-custodial/architecture</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-settlement-primitives">5. Settlement primitives<a href="https://docs.orcarail.com/blog/orcarail-protocol-whitepaper/#5-settlement-primitives" class="hash-link" aria-label="Direct link to 5. Settlement primitives" title="Direct link to 5. Settlement primitives" translate="no">​</a></h2>
<p>Full reference: <a class="" href="https://docs.orcarail.com/docs/non-custodial/contract-reference/">/docs/non-custodial/contract-reference</a>. Summary:</p>
<ul>
<li class=""><strong>EVM</strong> — <code>PaymentLinkFactory</code> (CREATE2 deterministic addresses), <code>PaymentLinkReceiver</code> (EIP-1167 minimal clone, immutable per link), <code>FeeSplitter</code> (basis-points atomic split), <code>SubscriptionHub</code> (allowance-pull with monotonic <code>lastChargedAt</code>).</li>
<li class=""><strong>Solana</strong> — <code>payment_link</code> Anchor program (PDA per link, CPI splits) and <code>subscription</code> Anchor program (SPL delegate authority, identical <code>charge</code> semantics to the EVM hub).</li>
<li class=""><strong>Bitcoin</strong> — 2-of-2 taproot multisig per link (merchant signer + platform signer from HSM/MPC) with pre-signed refund PSBTs. No recurring BTC until Lightning BOLT12 recurrence matures.</li>
</ul>
<p>Every primitive is designed so that the same <code>linkId</code> or <code>subscriptionId</code> resolves to the same deterministic address on the same chain forever — no address rotation, no re-issuance, no server-held mapping.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="6-cross-chain-as-intents">6. Cross-chain as intents<a href="https://docs.orcarail.com/blog/orcarail-protocol-whitepaper/#6-cross-chain-as-intents" class="hash-link" aria-label="Direct link to 6. Cross-chain as intents" title="Direct link to 6. Cross-chain as intents" translate="no">​</a></h2>
<p>A protocol that treats cross-chain as "our backend calls Relay" is still a product. A protocol treats cross-chain as a <strong>payer intent</strong>:</p>
<ul>
<li class="">The payer signs: "pay merchant X, $50 USDC, from any of my wallets on any supported chain, within 1 hour, with fees up to Y."</li>
<li class="">Existing solver networks — <strong>Across, Relay, deBridge, CoW-style</strong> — compete to fulfill the intent. Solvers are paid a bounty embedded in the intent.</li>
<li class="">For un-economic long-tail routes (small amounts, obscure chains) OrcaRail runs a <strong>fallback solver at cost</strong> so the tail still settles. The fallback is public and anyone else can run one too.</li>
</ul>
<p>The payer signature is bounded by amount, recipient, deadline, and max fee. Worst case a malicious solver is slow; they cannot redirect funds. This is the "Intents Believer" synthesis from the <a class="" href="https://docs.orcarail.com/blog/protocol-debate-non-custodial-futures/">protocol debate</a>, written as a commitment.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="7-standards-and-interoperability">7. Standards and interoperability<a href="https://docs.orcarail.com/blog/orcarail-protocol-whitepaper/#7-standards-and-interoperability" class="hash-link" aria-label="Direct link to 7. Standards and interoperability" title="Direct link to 7. Standards and interoperability" translate="no">​</a></h2>
<p>OrcaRail's payment-link and subscription primitives are a generic rail. Their value compounds only if other processors, wallets, and indexers implement them natively.</p>
<p>Commitments:</p>
<ul>
<li class=""><strong>Draft an EIP for non-custodial payment links</strong> using <code>PaymentLinkFactory</code> and <code>PaymentLinkReceiver</code> as the reference surface. Co-author with at least one other processor or wallet team to avoid the "EIP from one vendor" pattern.</li>
<li class=""><strong>Draft an EIP for allowance-pull subscriptions</strong> using <code>SubscriptionHub</code> as the reference. Monotonic <code>lastChargedAt</code> and the <code>ChargeSkipped(reason)</code> reason set are standardization targets.</li>
<li class=""><strong>Publish a Solana mirror</strong> via Anchor IDL and a written spec, so any Solana wallet or indexer can render a payment link from first principles.</li>
<li class=""><strong>Publish the canonical subgraph schema</strong> so any indexer (The Graph, Goldsky, Envio, self-hosted) can be drop-in compatible.</li>
</ul>
<p>Writing the EIP does not reduce our moat. As argued in the <a class="" href="https://docs.orcarail.com/blog/protocol-debate-non-custodial-futures/">debate</a>, the moat is in integrations, compliance, SLAs, and merchant trust — none of which an EIP copies.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="8-governance">8. Governance<a href="https://docs.orcarail.com/blog/orcarail-protocol-whitepaper/#8-governance" class="hash-link" aria-label="Direct link to 8. Governance" title="Direct link to 8. Governance" translate="no">​</a></h2>
<p>Governance sits on two horizons.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="today-and-near-term">Today and near-term<a href="https://docs.orcarail.com/blog/orcarail-protocol-whitepaper/#today-and-near-term" class="hash-link" aria-label="Direct link to Today and near-term" title="Direct link to Today and near-term" translate="no">​</a></h3>
<ul>
<li class=""><strong>EVM</strong>: 3-of-5 Safe multisig on each deployed chain. Hardware-wallet signers. Annual rotation. 48-hour timelock on proxy upgrades. Per-link <code>PaymentLinkReceiver</code> instances are <strong>immutable</strong>.</li>
<li class=""><strong>Solana</strong>: 3-of-5 Squads multisig with the same signer set and rotation policy.</li>
<li class=""><strong>Upgrade scope</strong>: factories and hubs sit behind UUPS proxies; per-link receivers and per-subscription records do not move under upgrades.</li>
<li class=""><strong>Publicly auditable</strong>: every deploy and upgrade runs as an announced multisig ceremony with signed transactions recorded.</li>
</ul>
<p>This is the governance described in <a class="" href="https://docs.orcarail.com/docs/non-custodial/security-model/">/docs/non-custodial/security-model</a>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="post-decentralization">Post-decentralization<a href="https://docs.orcarail.com/blog/orcarail-protocol-whitepaper/#post-decentralization" class="hash-link" aria-label="Direct link to Post-decentralization" title="Direct link to Post-decentralization" translate="no">​</a></h3>
<p>Over time the signer set stops being exclusively OrcaRail employees and becomes a <strong>public council</strong> drawn from integrators, audit firms, keeper operators, and independent contributors. Upgrade authority migrates to the council. On-chain governance becomes a live option at this point — but only as a governance mechanism, not as a speculation vehicle.</p>
<p>The threshold for "post-decentralization" is explicit: at least three independent production frontends hosting the rail, at least three independent keepers firing charges, and at least one non-OrcaRail processor shipping integrations. Until those are real, the protocol is not yet decentralized regardless of what governance mechanism sits on top.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="9-future-governance-token-explicit-reservation">9. Future governance token (explicit reservation)<a href="https://docs.orcarail.com/blog/orcarail-protocol-whitepaper/#9-future-governance-token-explicit-reservation" class="hash-link" aria-label="Direct link to 9. Future governance token (explicit reservation)" title="Direct link to 9. Future governance token (explicit reservation)" translate="no">​</a></h2>
<p>This section is deliberately short and deliberately specific.</p>
<ul>
<li class=""><strong>No token at launch.</strong> No presale. No allocation. No points. No retroactive claims.</li>
<li class=""><strong>A future governance token is reserved as an option</strong>, not as a commitment. It becomes appropriate only <strong>after</strong> the post-decentralization threshold in section 8 is met and a live base of integrators, keepers, and frontends exists that would benefit from formal signaling rights.</li>
<li class=""><strong>If we ever introduce one</strong>, it ships under its own whitepaper, with complete transparency on distribution, lockups, supply, and governance surface. The token whitepaper would be debated publicly before issuance.</li>
<li class=""><strong>The token would be governance-first, not speculation-first.</strong> Mechanisms that make sense: signaling upgrade votes, parameter setting within safe bounds, keeper operator reputation. Mechanisms that do not: fee discounts tied to holdings, pay-to-pay, yield farming.</li>
<li class=""><strong>We will not claim the protocol is decentralized because a token exists.</strong> Decentralization is measured by the things in section 8. A token is an instrument that can formalize already-achieved decentralization; it cannot manufacture it.</li>
</ul>
<p>This reservation is recorded in the protocol whitepaper — this document — and nowhere else. Any future change to this stance is a change to this whitepaper, published publicly, not a unilateral announcement.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="10-economics-and-fees--how-the-protocol-sustains-itself-without-a-token">10. Economics and fees — how the protocol sustains itself without a token<a href="https://docs.orcarail.com/blog/orcarail-protocol-whitepaper/#10-economics-and-fees--how-the-protocol-sustains-itself-without-a-token" class="hash-link" aria-label="Direct link to 10. Economics and fees — how the protocol sustains itself without a token" title="Direct link to 10. Economics and fees — how the protocol sustains itself without a token" translate="no">​</a></h2>
<p>The protocol's revenue model is the same as the product's, just encoded on-chain.</p>
<ul>
<li class=""><strong>Fee split</strong> lives in the <code>FeeSplitter</code> basis-points configuration per payment. Same buckets the <a class="" href="https://docs.orcarail.com/docs/withdrawals/strategy/">withdrawals</a> page describes today: merchant, platform (OrcaRail's hosted share), referral/affiliate, bridge fee.</li>
<li class=""><strong>OrcaRail-hosted surface</strong> (dashboard, email, paymaster gas, customer support) is paid for by OrcaRail's share of the split.</li>
<li class=""><strong>Alternative hosts</strong> — third-party processors, self-hosted operators, IPFS-pinned frontends — can ship with a zero-platform-bps split, or configure their own fee recipient. The protocol does not privilege OrcaRail's fee over anyone else's.</li>
<li class=""><strong>No emission, no subsidy, no staking yield.</strong> Costs are cash costs and cash revenues. The only way the protocol gets cheaper is if gas gets cheaper or a host accepts a smaller margin — not by issuing tokens to paper over running costs.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="11-security-model">11. Security model<a href="https://docs.orcarail.com/blog/orcarail-protocol-whitepaper/#11-security-model" class="hash-link" aria-label="Direct link to 11. Security model" title="Direct link to 11. Security model" translate="no">​</a></h2>
<p>Full statement: <a class="" href="https://docs.orcarail.com/docs/non-custodial/security-model/">/docs/non-custodial/security-model</a>. Core posture:</p>
<ul>
<li class="">Per-link receivers and per-subscription records are immutable.</li>
<li class="">Factories and hubs are upgradeable only through multisig + timelock.</li>
<li class="">Keepers are gas-only EOAs with no fund-movement authority.</li>
<li class="">BTC signing uses an HSM or MPC service on the platform side, plus a merchant key; no server holds unilateral spend authority.</li>
</ul>
<p>One addition specific to protocolization: <strong>independent frontend hosts must verify contract addresses against an on-chain registry</strong> (or a signed release manifest) before rendering a payment link. A malicious clone frontend that points payments at a look-alike contract is the most likely phishing vector once the ecosystem has multiple hosts. The canonical registry lives on-chain and the verification flow is documented as part of P2.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="12-roadmap--two-parallel-tracks">12. Roadmap — two parallel tracks<a href="https://docs.orcarail.com/blog/orcarail-protocol-whitepaper/#12-roadmap--two-parallel-tracks" class="hash-link" aria-label="Direct link to 12. Roadmap — two parallel tracks" title="Direct link to 12. Roadmap — two parallel tracks" translate="no">​</a></h2>
<p>The protocol rollout runs as two tracks at once.</p>
<div class="wrapper_vprU"><button type="button" class="expandBtn_RmxB" aria-label="Show diagram fullscreen" title="Fullscreen"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7" stroke-linecap="round" stroke-linejoin="round"></path></svg></button></div>
<p>Track N is the <a class="" href="https://docs.orcarail.com/blog/non-custodial-roadmap/">existing roadmap</a>, unchanged. Track P formalizes the M1-M5 commitments from the <a class="" href="https://docs.orcarail.com/blog/protocol-debate-non-custodial-futures/">debate post</a> as phases. Both tracks target the same end state: a rail that keeps running if OrcaRail steps away.</p>
<p>Track P never blocks Track N and Track N never blocks Track P. Either track can ship a phase before the other.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="13-track-p-phases">13. Track P phases<a href="https://docs.orcarail.com/blog/orcarail-protocol-whitepaper/#13-track-p-phases" class="hash-link" aria-label="Direct link to 13. Track P phases" title="Direct link to 13. Track P phases" translate="no">​</a></h2>
<p>Five phases, each a natural extension of an M-commitment from the debate post.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="p1--public-subgraph-and-open-indexer">P1 — Public subgraph and open indexer<a href="https://docs.orcarail.com/blog/orcarail-protocol-whitepaper/#p1--public-subgraph-and-open-indexer" class="hash-link" aria-label="Direct link to P1 — Public subgraph and open indexer" title="Direct link to P1 — Public subgraph and open indexer" translate="no">​</a></h3>
<p><strong>Scope</strong>: a canonical subgraph (The Graph, Envio, or equivalent) that indexes every <code>Paid</code>, <code>SubscriptionCreated</code>, <code>Charged</code>, <code>ChargeSkipped</code>, <code>Canceled</code>, and <code>Refunded</code> event from <code>PaymentLinkReceiver</code> and <code>SubscriptionHub</code> across every deployed chain. Schema published. Self-host instructions shipped so anyone can run the same index.</p>
<p><strong>Status checklist</strong></p>
<ul class="contains-task-list containsTaskList_mC6p">
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Subgraph manifest + mappings for EVM chains live in Phase 1 and Phase 3</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Solana equivalent (Helius webhooks or Triton stream) with same event shapes</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Schema documented and stable-versioned</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->One external indexer demonstrated running the same schema against live events</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="p2--decentralized-frontends-ipfs--ens">P2 — Decentralized frontends (IPFS / ENS)<a href="https://docs.orcarail.com/blog/orcarail-protocol-whitepaper/#p2--decentralized-frontends-ipfs--ens" class="hash-link" aria-label="Direct link to P2 — Decentralized frontends (IPFS / ENS)" title="Direct link to P2 — Decentralized frontends (IPFS / ENS)" translate="no">​</a></h3>
<p><strong>Scope</strong>: pin the OrcaRail pay app and merchant dashboard to IPFS with content-addressed release bundles. Resolve via ENS (<code>pay.orcarail.eth</code>, <code>app.orcarail.eth</code>). Reproducible builds so any reader can verify the bundle matches the source. A malicious clone has to impersonate both the contract addresses and the ENS record, not just the hostname.</p>
<p><strong>Status checklist</strong></p>
<ul class="contains-task-list containsTaskList_mC6p">
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Pay app builds reproducibly</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Dashboard builds reproducibly</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->ENS records pointing to IPFS CIDs</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Release-signing ceremony from the Safe multisig</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->On-chain contract-address registry frontends verify against before rendering</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="p3--standards-draft-eip">P3 — Standards (draft EIP)<a href="https://docs.orcarail.com/blog/orcarail-protocol-whitepaper/#p3--standards-draft-eip" class="hash-link" aria-label="Direct link to P3 — Standards (draft EIP)" title="Direct link to P3 — Standards (draft EIP)" translate="no">​</a></h3>
<p><strong>Scope</strong>: draft and submit an EIP for non-custodial payment links and a companion EIP for allowance-pull subscriptions. Co-author with at least one other processor or wallet team. Reference implementation is the OrcaRail contracts. Solana mirror spec published alongside the EIPs.</p>
<p><strong>Status checklist</strong></p>
<ul class="contains-task-list containsTaskList_mC6p">
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Co-author confirmed</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Payment-link EIP draft in discussion-thread state</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Subscription EIP draft in discussion-thread state</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Solana spec published alongside Anchor IDLs</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->EIP editor feedback incorporated through Last Call</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="p4--intent-based-payer-sdk">P4 — Intent-based payer SDK<a href="https://docs.orcarail.com/blog/orcarail-protocol-whitepaper/#p4--intent-based-payer-sdk" class="hash-link" aria-label="Direct link to P4 — Intent-based payer SDK" title="Direct link to P4 — Intent-based payer SDK" translate="no">​</a></h3>
<p><strong>Scope</strong>: an SDK surface (<code>orcarail.pay(intent)</code>) that accepts a payer-signed intent and routes it through existing solver networks (Across, Relay, deBridge) with an OrcaRail-run fallback solver for long-tail routes. Intent schema standardized in sync with P3.</p>
<p><strong>Status checklist</strong></p>
<ul class="contains-task-list containsTaskList_mC6p">
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Intent schema finalized</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->SDK adapter for at least two solver networks</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Fallback solver deployed and metered</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Payer UX in the pay app supports same-intent + cross-chain</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Spec published as part of the Node SDK reference</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="p5--self-host--reference-implementation-kit">P5 — Self-host / reference implementation kit<a href="https://docs.orcarail.com/blog/orcarail-protocol-whitepaper/#p5--self-host--reference-implementation-kit" class="hash-link" aria-label="Direct link to P5 — Self-host / reference implementation kit" title="Direct link to P5 — Self-host / reference implementation kit" translate="no">​</a></h3>
<p><strong>Scope</strong>: a Docker-compose (and Helm chart) that lets anyone run an OrcaRail-compatible processor end-to-end from the public contracts. Includes subgraph, keeper, indexer, optional dashboard, and an OpenAPI specification of the processor API that others can conform to.</p>
<p><strong>Status checklist</strong></p>
<ul class="contains-task-list containsTaskList_mC6p">
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Docker-compose that boots against a live chain and services a test merchant</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->OpenAPI spec for the processor API</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Helm chart for Kubernetes operators</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->End-to-end test that a self-hosted operator can process payments identical to the hosted version</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Documentation in <code>/docs/non-custodial/</code> (added in a future docs-only change; out of scope for this whitepaper)</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="14-optional-p6--own-chain-evaluation">14. Optional P6 — Own-chain evaluation<a href="https://docs.orcarail.com/blog/orcarail-protocol-whitepaper/#14-optional-p6--own-chain-evaluation" class="hash-link" aria-label="Direct link to 14. Optional P6 — Own-chain evaluation" title="Direct link to 14. Optional P6 — Own-chain evaluation" translate="no">​</a></h2>
<p>P6 mirrors the <a class="" href="https://docs.orcarail.com/docs/non-custodial/eigenlayer-evaluation/">EigenLayer evaluation</a> pattern. It is <strong>not</strong> a commitment. It is a quarterly review with specific triggers.</p>
<p>Current recommendation: <strong>defer</strong>.</p>
<p>Triggers that would open a design doc for a Phase P6 build:</p>
<ol>
<li class="">Payment volume on a single chain exceeds a threshold where gas becomes a material line-item of the platform fee.</li>
<li class="">A canonical L2/L3 toolchain offers specialized precompiles for payment-split semantics at near-zero cost.</li>
<li class="">Merchant demand for sub-cent settlement latency that mainnet / L2 consistently cannot meet.</li>
<li class="">A partner rollup-as-a-service lets OrcaRail ship with shared sequencing on day one.</li>
</ol>
<p>If triggered, the build would prefer OP Stack with shared-sequencing (Espresso, Astria) and a credible exit bridge to the canonical chains we already support. Even then, Phases N0-N7 and P1-P5 must be mature enough that an own chain is an <strong>optimization</strong>, not a dependency.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="15-what-orcarail-is-today-vs-what-it-becomes">15. What OrcaRail is today vs. what it becomes<a href="https://docs.orcarail.com/blog/orcarail-protocol-whitepaper/#15-what-orcarail-is-today-vs-what-it-becomes" class="hash-link" aria-label="Direct link to 15. What OrcaRail is today vs. what it becomes" title="Direct link to 15. What OrcaRail is today vs. what it becomes" translate="no">​</a></h2>
<p>A before/after at the rail level.</p>
<table><thead><tr><th>Dimension</th><th>Today</th><th>After Tracks N and P</th></tr></thead><tbody><tr><td>Custody during a payment</td><td>OrcaRail holds the deposit wallet's key</td><td>No custody. Payer → contract → merchant atomic splits</td></tr><tr><td>Subscription spender</td><td>OrcaRail-controlled smart account</td><td>Public <code>SubscriptionHub</code> contract; any caller</td></tr><tr><td>Keeper</td><td>Sole NestJS scheduler</td><td>NestJS + Chainlink + Gelato + optional EigenLayer AVS</td></tr><tr><td>Indexer</td><td>Internal</td><td>Public subgraph with a documented schema</td></tr><tr><td>Pay app / dashboard</td><td>Hosted by OrcaRail</td><td>Hosted + IPFS/ENS copies; third-party hosts welcome</td></tr><tr><td>Payment-link primitive</td><td>Internal API shape</td><td>Draft EIP with reference implementation</td></tr><tr><td>Cross-chain settlement</td><td>OrcaRail keeper calls Relay</td><td>Payer intents routed by a solver market + OrcaRail fallback</td></tr><tr><td>Governance</td><td>OrcaRail multisig (founders + team)</td><td>Public council; on-chain governance as a real option</td></tr><tr><td>Regulatory surface</td><td>"OrcaRail is the processor"</td><td>"OrcaRail is one processor among many on the same rail"</td></tr><tr><td>Merchant-visible API</td><td>REST + webhooks</td><td><strong>Same REST + webhooks</strong> (stable)</td></tr><tr><td>Token</td><td>None</td><td>None; reserved as a future option (section 9)</td></tr></tbody></table>
<p>The Web2-facing surface stays stable on purpose. Merchants that integrated against the REST API in 2026 do not break in 2028.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="16-threat-model">16. Threat model<a href="https://docs.orcarail.com/blog/orcarail-protocol-whitepaper/#16-threat-model" class="hash-link" aria-label="Direct link to 16. Threat model" title="Direct link to 16. Threat model" translate="no">​</a></h2>
<p>The threats we are explicit about, with their mitigations:</p>
<ul>
<li class=""><strong>Contract bug</strong> → multiple audits per contract; immutable per-link receivers; UUPS upgrades behind 48-hour timelock on factories and hubs; public bug bounty.</li>
<li class=""><strong>Keeper outage</strong> → Track N Phase 3 keeper redundancy (Chainlink/Gelato) + Track P P4 solver network + public manual <code>charge()</code> fallback.</li>
<li class=""><strong>Frontend phishing</strong> → Track P P2 on-chain contract registry + ENS content-addressing + release-signing ceremony from the Safe multisig.</li>
<li class=""><strong>Governance capture</strong> → Multisig signer rotation; 3-of-5 threshold; post-decentralization council drawn from independent operators; public ceremonies.</li>
<li class=""><strong>Regulatory action against one host</strong> → Track P P5 self-host kit + multiple independent frontends so merchants have alternate rails.</li>
<li class=""><strong>Subgraph or indexer drift</strong> → Canonical schema + reproducibility tests; multiple independent indexers.</li>
<li class=""><strong>Solver market thinness</strong> → OrcaRail fallback solver at cost; permissionless entry for new solvers.</li>
<li class=""><strong>BTC key loss</strong> → Backup xpub at merchant onboarding; HSM failover; pre-signed refund PSBTs keep payer recovery possible.</li>
<li class=""><strong>EVM reorgs</strong> → Monotonic <code>lastChargedAt</code> in <code>SubscriptionHub</code>; Solana equivalent in <code>last_charged_at</code>.</li>
<li class=""><strong>Token-induced distortion</strong> → No token at launch; explicit reservation; any future token gated on independent-operator thresholds before it can claim a governance role.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="17-open-questions-we-are-honest-about">17. Open questions we are honest about<a href="https://docs.orcarail.com/blog/orcarail-protocol-whitepaper/#17-open-questions-we-are-honest-about" class="hash-link" aria-label="Direct link to 17. Open questions we are honest about" title="Direct link to 17. Open questions we are honest about" translate="no">​</a></h2>
<p>Writing this document does not solve every question it raises.</p>
<ul>
<li class=""><strong>When does "post-decentralization" start, precisely?</strong> Section 8 gives a threshold (three independent frontends, three independent keepers, one non-OrcaRail processor). Whether that threshold is the right one is an open debate.</li>
<li class=""><strong>Who pays for the public subgraph at scale?</strong> The Graph has a market; self-hosted is free but operationally heavy. Economics are not yet settled.</li>
<li class=""><strong>What is the exit story for a merchant whose primary frontend host disappears?</strong> P5 makes self-hosting possible; it does not make it automatic. A "migrate-my-store-to-another-host" flow is future work.</li>
<li class=""><strong>What does governance actually decide in a protocol with immutable per-link contracts?</strong> Upgrades to factories, parameter-setting on hubs (paused token lists, new chain deployments), fee-split defaults for OrcaRail-hosted traffic — but not much more. Whether that is enough scope to justify on-chain governance is part of the post-decentralization conversation.</li>
<li class=""><strong>What happens to the protocol if OrcaRail, the company, changes its mind about the reservation in section 9?</strong> Any change is a published change to this whitepaper. No unilateral, quiet pivot.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="18-conclusion--a-call-to-builders">18. Conclusion — A call to builders<a href="https://docs.orcarail.com/blog/orcarail-protocol-whitepaper/#18-conclusion--a-call-to-builders" class="hash-link" aria-label="Direct link to 18. Conclusion — A call to builders" title="Direct link to 18. Conclusion — A call to builders" translate="no">​</a></h2>
<p>The <a class="" href="https://docs.orcarail.com/blog/non-custodial-roadmap/">non-custodial roadmap</a> gets the rail off custody. This whitepaper gets the rail off OrcaRail. Both need to ship for either to matter.</p>
<p>If you are building a wallet, a dashboard, an indexer, a solver, a compliance tool, or a rival processor — the protocol is designed to accept your contribution without asking permission. Co-author the EIP. Run the subgraph. Pin your own frontend. Run a keeper or a solver. File issues against the reference implementation. The more of Track P is done by people who do not work at OrcaRail, the more the protocol earns the word <em>protocol</em>.</p>
<p>The Web2 merchants we work with today will not notice any of this — their API keys, webhooks, and dashboards keep working. That stability is the point. We are changing the foundation of the rail, not the surface the merchants touched when they signed up.</p>
<hr>
<p><strong>References</strong></p>
<ul>
<li class=""><a class="" href="https://docs.orcarail.com/blog/non-custodial-roadmap/">The OrcaRail Non-Custodial Roadmap</a> — Track N</li>
<li class=""><a class="" href="https://docs.orcarail.com/blog/protocol-debate-non-custodial-futures/">The Protocol Debate: Five Visions for a Fully Non-Custodial OrcaRail</a> — origin of Track P</li>
<li class=""><a class="" href="https://docs.orcarail.com/blog/why-allowance-pull-subscriptions/">Why allowance-pull beats escrow and session keys</a> — subscription-model decision</li>
<li class=""><a class="" href="https://docs.orcarail.com/docs/non-custodial/architecture/">Architecture</a> — full technical architecture</li>
<li class=""><a class="" href="https://docs.orcarail.com/docs/non-custodial/contract-reference/">Contract reference</a> — ABIs, events, and addresses</li>
<li class=""><a class="" href="https://docs.orcarail.com/docs/non-custodial/security-model/">Security model</a> — trust assumptions and key custody</li>
<li class=""><a class="" href="https://docs.orcarail.com/docs/non-custodial/roadmap/">Roadmap</a> — Track N phase status</li>
<li class=""><a class="" href="https://docs.orcarail.com/docs/non-custodial/eigenlayer-evaluation/">EigenLayer evaluation</a> — pattern reused for P6</li>
</ul>]]></content:encoded>
            <category>Announcement</category>
            <category>Payments</category>
            <category>Multi-Chain</category>
            <category>Web3</category>
            <category>Stablecoins</category>
            <category>Subscriptions</category>
            <category>Crypto</category>
        </item>
        <item>
            <title><![CDATA[Phase 0: Designing a Non-Custodial Payment Stack]]></title>
            <link>https://docs.orcarail.com/blog/phase-0-design-and-audit-strategy/</link>
            <guid>https://docs.orcarail.com/blog/phase-0-design-and-audit-strategy/</guid>
            <pubDate>Mon, 20 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Phase 0 of the OrcaRail non-custodial roadmap. Fee split spec, chain selection, audit vendor choice, deployer multisig, upgrade policy, and the subscription-model decision matrix.]]></description>
            <content:encoded><![CDATA[<p><strong>April 20, 2026</strong> — Before we write a line of Solidity, we freeze the spec. Phase 0 is the design and sign-off phase of the <a class="" href="https://docs.orcarail.com/blog/non-custodial-roadmap/">non-custodial roadmap</a>: what moves on-chain, what does not, which chain ships first, who audits the contracts, and who holds the deployer keys.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="tldr">TL;DR<a href="https://docs.orcarail.com/blog/phase-0-design-and-audit-strategy/#tldr" class="hash-link" aria-label="Direct link to TL;DR" title="Direct link to TL;DR" translate="no">​</a></h2>
<ul>
<li class="">Fee split is frozen to four buckets: <strong>merchant, platform, referral/affiliate, bridge fee</strong>. Everything in the on-chain splitter is expressible in basis points; no off-chain fix-ups.</li>
<li class=""><strong>Base</strong> is the launch chain for Phase 1. Cheap, fast, already in the <a href="https://github.com/orcarail/orcarail/tree/main/api/src/payments/wallet.service.ts" target="_blank" rel="noopener noreferrer" class="">wallet service</a> chain list, and USDC-native.</li>
<li class="">Subscriptions adopt <strong>ERC-20 approve + pull</strong> (EVM) and <strong>SPL delegate</strong> (Solana). Escrow and session-key designs were rejected — see the decision matrix below.</li>
<li class="">Contracts are deployed by a <strong>3-of-5 Safe multisig</strong> (EVM) and <strong>3-of-5 Squads multisig</strong> (Solana). Per-link receivers are immutable. Factories and <code>SubscriptionHub</code> sit behind a small proxy with a 48-hour timelock.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-this-phase-changes">What this phase changes<a href="https://docs.orcarail.com/blog/phase-0-design-and-audit-strategy/#what-this-phase-changes" class="hash-link" aria-label="Direct link to What this phase changes" title="Direct link to What this phase changes" translate="no">​</a></h2>
<p>Nothing in production. Phase 0 is a written spec, three audit proposals, a deployer-key ceremony, and a couple of merged ADRs.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-fee-split-spec-frozen">The fee split spec (frozen)<a href="https://docs.orcarail.com/blog/phase-0-design-and-audit-strategy/#the-fee-split-spec-frozen" class="hash-link" aria-label="Direct link to The fee split spec (frozen)" title="Direct link to The fee split spec (frozen)" translate="no">​</a></h2>
<p>Today, <code>SmartAccountWalletService.drainSmartAccountWallet</code> in <a href="https://github.com/orcarail/orcarail/tree/main/api/src/withdrawals/services/smart-account-wallet.service.ts" target="_blank" rel="noopener noreferrer" class="">api/src/withdrawals/services/smart-account-wallet.service.ts</a> composes transfers into a UserOperation with three recipients: the merchant (<code>toAddress</code>), the support wallet (<code>supportWalletAddress</code>), and the commission wallet. The contract version mirrors this exactly:</p>
<div class="language-solidity codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-solidity codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">struct Split {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    address merchant;   // main receiver</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    address platform;   // support / platform fee</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    address referral;   // commission / affiliate (optional, zero = skip)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    address bridgeFee;  // Relay bridge fee carrier (optional, zero = skip)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    uint16 platformBps;</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    uint16 referralBps;</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    uint16 bridgeFeeBps;</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">}</span><br></div></code></pre></div></div>
<p>Everything the keeper does today in TypeScript is computable from this struct and the payment amount. Anything the current keeper cannot express (e.g. dynamic taxes, merchant-level holdbacks) is out of scope for Phase 1 — we add it in a later phase if needed.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="chain-selection">Chain selection<a href="https://docs.orcarail.com/blog/phase-0-design-and-audit-strategy/#chain-selection" class="hash-link" aria-label="Direct link to Chain selection" title="Direct link to Chain selection" translate="no">​</a></h2>
<p>Launch chain for Phase 1 is <strong>Base</strong>:</p>
<ul>
<li class="">Already in our chainId map (<code>8453 → base</code>, <code>84532 → baseSepolia</code>) in <code>api/src/payments/wallet.service.ts</code>.</li>
<li class="">Gas is cheap enough that <code>PaymentLinkReceiver</code> deploy + split on first pay is pennies per transaction.</li>
<li class="">Alchemy paymaster policy already supports it, which gives us an escape hatch if we want the keeper on <code>SubscriptionHub.charge()</code> sponsored.</li>
<li class="">Native USDC (not bridged), which matters for subscription allowances.</li>
</ul>
<p>Ethereum mainnet, Arbitrum, Optimism, and Polygon follow in <a class="" href="https://docs.orcarail.com/blog/phase-3-multi-evm-and-keeper-redundancy/">Phase 3</a>. Solana is a separate program, tracked in <a class="" href="https://docs.orcarail.com/blog/phase-4-solana-pda-programs/">Phase 4</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="subscription-model-the-decision-matrix">Subscription model: the decision matrix<a href="https://docs.orcarail.com/blog/phase-0-design-and-audit-strategy/#subscription-model-the-decision-matrix" class="hash-link" aria-label="Direct link to Subscription model: the decision matrix" title="Direct link to Subscription model: the decision matrix" translate="no">​</a></h2>
<p>We evaluated three designs. Only one works for us.</p>
<table><thead><tr><th>Model</th><th>Custody</th><th>Payer UX</th><th>Wallet compatibility</th><th>Keeper requirement</th><th>Verdict</th></tr></thead><tbody><tr><td><strong>ERC-20 approve + pull</strong> (chosen)</td><td>None</td><td>One-time <code>approve</code></td><td>MetaMask, Phantom, Ledger, Safe — native</td><td>Any caller; keeper is optional</td><td>Ship this</td></tr><tr><td>Escrow deposit</td><td>None</td><td>Deposit N months</td><td>All wallets</td><td>Any caller</td><td>Worse UX; funds locked</td></tr><tr><td>Smart-wallet + session keys</td><td>None</td><td>Onboard to 4337</td><td>4337 wallets only</td><td>Session-key signer</td><td>Too narrow compatibility</td></tr></tbody></table>
<p>Approve + pull is the only one that works with the wallets payers already use (MetaMask, Phantom, hardware wallets, Safes). It is also the design we already publish in <a class="" href="https://docs.orcarail.com/docs/subscriptions/auto-charge/">Auto-charge</a>, which documents <code>approve(spender, amount)</code> and SPL delegation. Phase 2 replaces the <strong>pull side</strong> with a smart contract and leaves the payer side unchanged.</p>
<p>The long-form argument is in <a class="" href="https://docs.orcarail.com/blog/why-allowance-pull-subscriptions/">Why allowance-pull beats escrow and session keys</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="deployer-key-custody">Deployer key custody<a href="https://docs.orcarail.com/blog/phase-0-design-and-audit-strategy/#deployer-key-custody" class="hash-link" aria-label="Direct link to Deployer key custody" title="Direct link to Deployer key custody" translate="no">​</a></h2>
<ul>
<li class=""><strong>EVM</strong>: Safe (formerly Gnosis Safe) on Base with <strong>3-of-5 threshold</strong>. Signers: two founders, one ops lead, one advisor, one cold backup. Each signer uses a hardware wallet; no key on a server.</li>
<li class=""><strong>Solana</strong>: Squads multisig with the same 3-of-5 setup and the same signers.</li>
<li class=""><strong>Rotation</strong>: every signer rotates annually or on departure; any single rotation is a Safe/Squads transaction.</li>
<li class=""><strong>No hot keeper can deploy</strong>. The NestJS keeper EOA (used to call <code>charge()</code> in Phase 2) has no deploy authority, no upgrade authority, and no fee address.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="upgrade-policy">Upgrade policy<a href="https://docs.orcarail.com/blog/phase-0-design-and-audit-strategy/#upgrade-policy" class="hash-link" aria-label="Direct link to Upgrade policy" title="Direct link to Upgrade policy" translate="no">​</a></h2>
<ul>
<li class=""><strong>Per-link <code>PaymentLinkReceiver</code></strong>: immutable. No upgrade. This is a trust win for payers — the code they are paying into can't change after the fact.</li>
<li class=""><strong><code>PaymentLinkFactory</code></strong>: small UUPS proxy owned by the multisig, 48-hour timelock on <code>upgradeTo</code>. Upgrades cannot change already-deployed receivers.</li>
<li class=""><strong><code>SubscriptionHub</code></strong>: same pattern. <code>charge()</code> and <code>cancel()</code> semantics are stable between versions; if we ever need a breaking change, we deploy <code>SubscriptionHubV2</code> and migrate instead of upgrading.</li>
<li class=""><strong>Refund and dispute semantics</strong>: on-chain <code>refund(txId)</code> callable by the merchant signer (via their API key → keeper EOA) or the deployer multisig. Payer cannot self-refund (matches today's product).</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="audit-vendor-strategy">Audit vendor strategy<a href="https://docs.orcarail.com/blog/phase-0-design-and-audit-strategy/#audit-vendor-strategy" class="hash-link" aria-label="Direct link to Audit vendor strategy" title="Direct link to Audit vendor strategy" translate="no">​</a></h2>
<p>We will shortlist three firms and run one primary audit + one competitive review:</p>
<ul>
<li class=""><strong>Primary candidates (EVM)</strong>: Spearbit, Trail of Bits, Zellic.</li>
<li class=""><strong>Secondary candidates (Solana)</strong>: OtterSec, Neodyme.</li>
<li class=""><strong>Scope</strong>: <code>PaymentLinkFactory</code>, <code>PaymentLinkReceiver</code>, <code>FeeSplitter</code>, <code>SubscriptionHub</code>. The Anchor programs get their own audit in Phase 4.</li>
<li class=""><strong>Budget</strong>: treat the audit as a hard prerequisite for Base mainnet launch. No mainnet before the fix-all report.</li>
<li class=""><strong>Public disclosure</strong>: audit reports land in the repo and link from <a class="" href="https://docs.orcarail.com/docs/non-custodial/security-model/">/docs/non-custodial/security-model</a>.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="risks-and-mitigations">Risks and mitigations<a href="https://docs.orcarail.com/blog/phase-0-design-and-audit-strategy/#risks-and-mitigations" class="hash-link" aria-label="Direct link to Risks and mitigations" title="Direct link to Risks and mitigations" translate="no">​</a></h2>
<ul>
<li class=""><strong>Spec scope creep</strong>. Mitigation: everything not expressible as basis-points-split is deferred to a later phase. Phase 1 does not block on dynamic taxation or per-merchant overrides.</li>
<li class=""><strong>Multisig signer availability</strong>. Mitigation: 3-of-5, not 2-of-3, so any two signers can be unavailable without freezing deploys.</li>
<li class=""><strong>Audit timing</strong>. Mitigation: start vendor conversations now; ship contracts to testnet during audit; mainnet deploy is gated.</li>
<li class=""><strong>Forgotten fee case</strong>. Mitigation: reproduce every path in <code>drainSmartAccountWallet</code> today (native + ERC-20, with/without support, with/without commission) as a Foundry invariant test before audit.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="status-checklist">Status checklist<a href="https://docs.orcarail.com/blog/phase-0-design-and-audit-strategy/#status-checklist" class="hash-link" aria-label="Direct link to Status checklist" title="Direct link to Status checklist" translate="no">​</a></h2>
<ul class="contains-task-list containsTaskList_mC6p">
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Fee split struct approved and tagged</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Base selected as Phase 1 launch chain</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Three audit vendors shortlisted</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Safe (Base) and Squads (Solana) deployer multisigs created and tested</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->ADR merged covering upgrade policy and timelock</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->ADR merged covering subscription model decision</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Refund / dispute semantics documented</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-is-next">What is next<a href="https://docs.orcarail.com/blog/phase-0-design-and-audit-strategy/#what-is-next" class="hash-link" aria-label="Direct link to What is next" title="Direct link to What is next" translate="no">​</a></h2>
<p>Phase 1 implements the spec: <strong><a class="" href="https://docs.orcarail.com/blog/phase-1-evm-payment-link-contracts/">Contract-based payment links on EVM</a></strong>.</p>
<hr>
<p>Reference docs: <strong><a class="" href="https://docs.orcarail.com/docs/non-custodial/phases/phase-0-design/">Phase 0 status</a></strong> · <strong><a class="" href="https://docs.orcarail.com/docs/non-custodial/security-model/">Security model</a></strong> · <strong><a class="" href="https://docs.orcarail.com/docs/non-custodial/architecture/">Architecture</a></strong></p>]]></content:encoded>
            <category>Payments</category>
            <category>Web3</category>
            <category>Multi-Chain</category>
            <category>Announcement</category>
        </item>
        <item>
            <title><![CDATA[Phase 1: Contract-Based Payment Links on EVM]]></title>
            <link>https://docs.orcarail.com/blog/phase-1-evm-payment-link-contracts/</link>
            <guid>https://docs.orcarail.com/blog/phase-1-evm-payment-link-contracts/</guid>
            <pubDate>Mon, 20 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Phase 1 of the OrcaRail non-custodial roadmap. PaymentLinkFactory, PaymentLinkReceiver clone, and FeeSplitter replace the HD-wallet sweep model on EVM with atomic on-chain splits.]]></description>
            <content:encoded><![CDATA[<p><strong>April 20, 2026</strong> — Phase 1 is the real engineering start of the <a class="" href="https://docs.orcarail.com/blog/non-custodial-roadmap/">non-custodial roadmap</a>. We replace per-link HD-derived EOAs and Alchemy smart accounts with a <strong>factory + minimal-clone receiver</strong> pattern on EVM. Funds are split atomically on the pay transaction; no sweep, no custody.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="tldr">TL;DR<a href="https://docs.orcarail.com/blog/phase-1-evm-payment-link-contracts/#tldr" class="hash-link" aria-label="Direct link to TL;DR" title="Direct link to TL;DR" translate="no">​</a></h2>
<ul>
<li class=""><code>PaymentLinkFactory.computeAddress(linkId)</code> returns a deterministic CREATE2 address. We show that address to the payer <strong>before</strong> anything is deployed.</li>
<li class=""><code>PaymentLinkReceiver</code> is an EIP-1167 minimal clone. It accepts native or ERC-20, emits <code>Paid</code>, and calls <code>FeeSplitter.split()</code> in the same transaction.</li>
<li class=""><a href="https://github.com/orcarail/orcarail/tree/main/api/src/payments/wallet.service.ts" target="_blank" rel="noopener noreferrer" class="">api/src/payments/wallet.service.ts</a> stops generating HD wallets for EVM links; it calls the factory view instead.</li>
<li class="">The sweep path (<code>drainSmartAccountWallet</code>, <code>getSmartAccountClientForDepositWallet</code>) is bypassed for links created under the <code>useOnChainReceiver</code> flag.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-this-phase-changes">What this phase changes<a href="https://docs.orcarail.com/blog/phase-1-evm-payment-link-contracts/#what-this-phase-changes" class="hash-link" aria-label="Direct link to What this phase changes" title="Direct link to What this phase changes" translate="no">​</a></h2>
<div class="wrapper_vprU"><button type="button" class="expandBtn_RmxB" aria-label="Show diagram fullscreen" title="Fullscreen"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7" stroke-linecap="round" stroke-linejoin="round"></path></svg></button></div>
<p>The "after" side has no box we control sitting on the funds.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="contracts-introduced">Contracts introduced<a href="https://docs.orcarail.com/blog/phase-1-evm-payment-link-contracts/#contracts-introduced" class="hash-link" aria-label="Direct link to Contracts introduced" title="Direct link to Contracts introduced" translate="no">​</a></h2>
<p>All under a new package <code>contracts/evm/</code>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="paymentlinkfactory">PaymentLinkFactory<a href="https://docs.orcarail.com/blog/phase-1-evm-payment-link-contracts/#paymentlinkfactory" class="hash-link" aria-label="Direct link to PaymentLinkFactory" title="Direct link to PaymentLinkFactory" translate="no">​</a></h3>
<ul>
<li class=""><code>computeAddress(bytes32 linkId) view returns (address)</code> — deterministic CREATE2 address derived from <code>linkId</code> (the existing payment-link UUID, hashed to <code>bytes32</code>).</li>
<li class=""><code>deployAndPay(bytes32 linkId, Split split, address token, uint256 amount)</code> — lazy deploy + pay in one transaction. The factory clones the <code>PaymentLinkReceiver</code> implementation, initializes it with the <code>Split</code>, and forwards funds.</li>
<li class=""><code>isDeployed(bytes32 linkId) view returns (bool)</code> — helper used by the indexer and UI.</li>
<li class="">Upgradeable behind a UUPS proxy, owned by the deployer multisig (3-of-5 Safe), 48-hour timelock on <code>upgradeTo</code>.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="paymentlinkreceiver-clone">PaymentLinkReceiver (clone)<a href="https://docs.orcarail.com/blog/phase-1-evm-payment-link-contracts/#paymentlinkreceiver-clone" class="hash-link" aria-label="Direct link to PaymentLinkReceiver (clone)" title="Direct link to PaymentLinkReceiver (clone)" translate="no">​</a></h3>
<ul>
<li class="">Immutable after initialization. Stores the <code>Split</code> struct and the <code>FeeSplitter</code> address.</li>
<li class=""><code>pay(address token, uint256 amount)</code> — handles native and ERC-20 in one entry point. Uses <code>SafeERC20</code> so non-standard tokens (USDT) work. Emits <code>Paid(linkId, payer, token, amount)</code>.</li>
<li class="">Calls <code>FeeSplitter.split()</code> atomically. If the split reverts, the pay reverts.</li>
<li class="">Explicit <code>refund(bytes32 txId)</code> callable only by the merchant keeper EOA or deployer multisig.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="feesplitter">FeeSplitter<a href="https://docs.orcarail.com/blog/phase-1-evm-payment-link-contracts/#feesplitter" class="hash-link" aria-label="Direct link to FeeSplitter" title="Direct link to FeeSplitter" translate="no">​</a></h3>
<ul>
<li class=""><code>split(Split s, address token, uint256 amount)</code> — distributes by basis points. Remaining wei goes to the merchant (no dust loss).</li>
<li class="">Emits <code>Split(txId, merchant, platform, referral, bridgeFee)</code> for indexer parity with legacy webhook payloads.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="api-changes">API changes<a href="https://docs.orcarail.com/blog/phase-1-evm-payment-link-contracts/#api-changes" class="hash-link" aria-label="Direct link to API changes" title="Direct link to API changes" translate="no">​</a></h2>
<p>The single biggest code change is in <a href="https://github.com/orcarail/orcarail/tree/main/api/src/payments/wallet.service.ts" target="_blank" rel="noopener noreferrer" class="">api/src/payments/wallet.service.ts</a>. Today, <code>getOrCreateAddressForPaymentLink</code> derives from <code>hd_wallet_seed</code>, computes the Alchemy counterfactual address, and stores it in <code>wallet_address</code>. After Phase 1, for EVM chains under the feature flag, that function becomes:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getOrCreateAddressForPaymentLink</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">paymentLinkId</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> network</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">isEvm</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">network</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> featureFlags</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">useOnChainReceiver</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">network</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">chainId</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> address </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> factory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">computeAddress</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">hashLinkId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">paymentLinkId</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> address</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> walletAddressId</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> derivationPath</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// legacy path unchanged</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>No HD derivation. No private material in the database for new links.</p>
<p>A new service, <code>payments/indexer/evm-paid-event.service.ts</code>, subscribes to <code>Paid</code> events on each enabled chain via <code>viem.watchContractEvent</code>. On match, it:</p>
<ol>
<li class="">Looks up the <code>paymentLinkId</code> from the event (indexed in <code>bytes32</code>).</li>
<li class="">Upserts a <code>PaymentTransaction</code> row — same shape as today.</li>
<li class="">Emits the same webhooks today's sweep-completion path does (<a href="https://github.com/orcarail/orcarail/tree/main/api/src/webhooks/webhooks.service.ts" target="_blank" rel="noopener noreferrer" class="">api/src/webhooks/webhooks.service.ts</a>).</li>
</ol>
<p>The feature flag <code>useOnChainReceiver</code> is scoped per chain id. A link created while the flag is off stays on the legacy sweep path forever — we do not migrate in-flight links.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="deprecations">Deprecations<a href="https://docs.orcarail.com/blog/phase-1-evm-payment-link-contracts/#deprecations" class="hash-link" aria-label="Direct link to Deprecations" title="Direct link to Deprecations" translate="no">​</a></h2>
<p>Inside this phase we <strong>bypass</strong> but do not delete:</p>
<ul>
<li class=""><code>SmartAccountWalletService.drainSmartAccountWallet</code> — no longer called for flagged chains.</li>
<li class=""><code>SmartAccountWalletService.getSmartAccountClientForDepositWallet</code> — not needed when addresses come from the factory.</li>
<li class="">Rows in <code>wallet_address</code> — not written for flagged EVM chains.</li>
</ul>
<p>Actual deletion happens in <a class="" href="https://docs.orcarail.com/blog/phase-7-retiring-custody/">Phase 7</a>, once all legacy links on the chain are settled.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="migration-plan">Migration plan<a href="https://docs.orcarail.com/blog/phase-1-evm-payment-link-contracts/#migration-plan" class="hash-link" aria-label="Direct link to Migration plan" title="Direct link to Migration plan" translate="no">​</a></h2>
<ul>
<li class=""><strong>New links on Base</strong>: get a factory-computed CREATE2 address. The UI displays it the same as today.</li>
<li class=""><strong>Existing open links on Base</strong>: stay on the legacy sweep path until they expire or settle. No forced migration.</li>
<li class=""><strong>Other EVM chains</strong>: legacy until <a class="" href="https://docs.orcarail.com/blog/phase-3-multi-evm-and-keeper-redundancy/">Phase 3</a> flips their flag.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="risks-and-mitigations">Risks and mitigations<a href="https://docs.orcarail.com/blog/phase-1-evm-payment-link-contracts/#risks-and-mitigations" class="hash-link" aria-label="Direct link to Risks and mitigations" title="Direct link to Risks and mitigations" translate="no">​</a></h2>
<ul>
<li class=""><strong>CREATE2 address shown before any code exists</strong>. Mitigation: document that recoverability depends on the factory deployer. Cap <code>maxLinkValue</code> in the factory for the first 30 days.</li>
<li class=""><strong>USDT and other non-standard ERC-20s</strong>. Mitigation: <code>SafeERC20</code> in both <code>PaymentLinkReceiver</code> and <code>FeeSplitter</code>; Foundry fuzz tests against a USDT mainnet fork.</li>
<li class=""><strong>Fee-on-transfer tokens</strong>. Mitigation: token allowlist; tokens outside it fall back to legacy path.</li>
<li class=""><strong>Chain indexer lag</strong>. Mitigation: dual-subscribe (Alchemy + fallback public RPC); reconcile jobs run hourly; idempotent upsert.</li>
<li class=""><strong>Audit finding during development</strong>. Mitigation: audit gated; no mainnet deploy before fix-all report.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="status-checklist">Status checklist<a href="https://docs.orcarail.com/blog/phase-1-evm-payment-link-contracts/#status-checklist" class="hash-link" aria-label="Direct link to Status checklist" title="Direct link to Status checklist" translate="no">​</a></h2>
<ul class="contains-task-list containsTaskList_mC6p">
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Foundry project scaffolded at <code>contracts/evm/</code></li>
<li class="task-list-item"><input type="checkbox" disabled=""> <code>PaymentLinkFactory</code> + <code>PaymentLinkReceiver</code> + <code>FeeSplitter</code> implemented</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Fuzz + invariant tests for split math (merchant always gets ≥ expected minus fees)</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->USDT / non-standard ERC-20 fork tests passing</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <code>useOnChainReceiver</code> feature flag wired in <code>api/src/payments</code></li>
<li class="task-list-item"><input type="checkbox" disabled=""> <code>evm-paid-event.service.ts</code> indexer shipping and emitting existing webhooks</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Audit kicked off, fixes landed</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Base mainnet deploy from multisig</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Canary cohort of merchants on the flag</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-is-next">What is next<a href="https://docs.orcarail.com/blog/phase-1-evm-payment-link-contracts/#what-is-next" class="hash-link" aria-label="Direct link to What is next" title="Direct link to What is next" translate="no">​</a></h2>
<p>With Base merchants on contract receivers, Phase 2 does the same for subscriptions: <strong><a class="" href="https://docs.orcarail.com/blog/phase-2-allowance-pull-subscriptions/">Allowance-pull subscriptions</a></strong>.</p>
<hr>
<p>Reference docs: <strong><a class="" href="https://docs.orcarail.com/docs/non-custodial/phases/phase-1-evm-payment-links/">Phase 1 status</a></strong> · <strong><a class="" href="https://docs.orcarail.com/docs/non-custodial/contract-reference/">Contract reference</a></strong> · <strong><a class="" href="https://docs.orcarail.com/docs/non-custodial/architecture/">Architecture</a></strong></p>]]></content:encoded>
            <category>Payments</category>
            <category>Web3</category>
            <category>Multi-Chain</category>
            <category>Stablecoins</category>
        </item>
        <item>
            <title><![CDATA[Phase 2: Allowance-Pull Subscriptions]]></title>
            <link>https://docs.orcarail.com/blog/phase-2-allowance-pull-subscriptions/</link>
            <guid>https://docs.orcarail.com/blog/phase-2-allowance-pull-subscriptions/</guid>
            <pubDate>Mon, 20 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Phase 2 of the OrcaRail non-custodial roadmap. The SubscriptionHub contract replaces the custodial auto-charge processor; payers sign one ERC-20 approve and any caller can trigger charge(id) on schedule.]]></description>
            <content:encoded><![CDATA[<p><strong>April 20, 2026</strong> — Phase 2 moves recurring billing to an on-chain <code>SubscriptionHub</code>. The payer signs one <code>approve</code> in their wallet, and anyone (including our keeper) can call <code>charge(id)</code> when a period is due. Funds move directly from the payer to the merchant splits — OrcaRail never holds them.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="tldr">TL;DR<a href="https://docs.orcarail.com/blog/phase-2-allowance-pull-subscriptions/#tldr" class="hash-link" aria-label="Direct link to TL;DR" title="Direct link to TL;DR" translate="no">​</a></h2>
<ul>
<li class=""><code>SubscriptionHub.createSubscription(...)</code> records the schedule on-chain.</li>
<li class="">Payer signs <code>approve(USDC, hub, cap)</code> once in their normal wallet. That is the same step we already document in <a class="" href="https://docs.orcarail.com/docs/subscriptions/auto-charge/">Auto-charge</a>.</li>
<li class="">Any EOA can call <code>charge(id)</code>. Our NestJS scheduler does it by default; Chainlink/Gelato will back it up from <a class="" href="https://docs.orcarail.com/blog/phase-3-multi-evm-and-keeper-redundancy/">Phase 3</a> onward.</li>
<li class="">Reorg protection via monotonic <code>lastChargedAt</code>. No double-charges.</li>
<li class="">Existing subscribers migrate <strong>opt-in</strong>, at renewal.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-this-phase-changes">What this phase changes<a href="https://docs.orcarail.com/blog/phase-2-allowance-pull-subscriptions/#what-this-phase-changes" class="hash-link" aria-label="Direct link to What this phase changes" title="Direct link to What this phase changes" translate="no">​</a></h2>
<p>Today, <a href="https://github.com/orcarail/orcarail/tree/main/api/src/scheduler/processors/subscription-auto-charge.processor.ts" target="_blank" rel="noopener noreferrer" class="">api/src/scheduler/processors/subscription-auto-charge.processor.ts</a> uses an OrcaRail-controlled smart account to pull from the payer via existing <code>approve</code>. It works, but the smart account is ours — trust flows through us.</p>
<p>After Phase 2:</p>
<div class="wrapper_vprU"><button type="button" class="expandBtn_RmxB" aria-label="Show diagram fullscreen" title="Fullscreen"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7" stroke-linecap="round" stroke-linejoin="round"></path></svg></button></div>
<p>The allowance is <strong>still from the payer to a contract</strong>, but the contract is auditable and immutable, and anyone — not just us — can be the keeper.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="contracts-introduced">Contracts introduced<a href="https://docs.orcarail.com/blog/phase-2-allowance-pull-subscriptions/#contracts-introduced" class="hash-link" aria-label="Direct link to Contracts introduced" title="Direct link to Contracts introduced" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="subscriptionhub">SubscriptionHub<a href="https://docs.orcarail.com/blog/phase-2-allowance-pull-subscriptions/#subscriptionhub" class="hash-link" aria-label="Direct link to SubscriptionHub" title="Direct link to SubscriptionHub" translate="no">​</a></h3>
<p>One instance per chain. Minimal surface:</p>
<div class="language-solidity codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-solidity codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">function createSubscription(</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    bytes32 id,</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    address payer,</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    IERC20 token,</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    uint256 amount,</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    uint64 interval,</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    uint256 cap,</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    Split calldata split</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">) external;</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">function charge(bytes32 id) external;        // any caller</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">function cancel(bytes32 id) external;        // payer only</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">function subscription(bytes32 id) view returns (Subscription memory);</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">event SubscriptionCreated(bytes32 indexed id, address indexed payer, ...);</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">event Charged(bytes32 indexed id, uint256 amount, uint64 nextChargeAt);</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">event ChargeSkipped(bytes32 indexed id, bytes32 reason);</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">event Canceled(bytes32 indexed id);</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="invariants-enforced-in-charge">Invariants enforced in <code>charge()</code><a href="https://docs.orcarail.com/blog/phase-2-allowance-pull-subscriptions/#invariants-enforced-in-charge" class="hash-link" aria-label="Direct link to invariants-enforced-in-charge" title="Direct link to invariants-enforced-in-charge" translate="no">​</a></h3>
<ul>
<li class=""><code>block.timestamp &gt;= nextChargeAt</code> — cannot charge early.</li>
<li class=""><code>block.timestamp &gt; lastChargedAt</code> — monotonic, so reorgs cannot double-charge.</li>
<li class=""><code>amountCharged + amount &lt;= cap</code> — enforces the approval limit in addition to ERC-20 allowance.</li>
<li class=""><code>token.allowance(payer, hub) &gt;= amount</code> — explicit revert with <code>InsufficientAllowance</code> for clean webhook copy.</li>
<li class=""><code>token.balanceOf(payer) &gt;= amount</code> — same, with <code>InsufficientBalance</code>.</li>
</ul>
<p>The <code>Split</code> is reused from <a class="" href="https://docs.orcarail.com/blog/phase-1-evm-payment-link-contracts/">Phase 1</a> — same <code>FeeSplitter</code>, same basis-points semantics.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="api-changes">API changes<a href="https://docs.orcarail.com/blog/phase-2-allowance-pull-subscriptions/#api-changes" class="hash-link" aria-label="Direct link to API changes" title="Direct link to API changes" translate="no">​</a></h2>
<p>The big change is that <a href="https://github.com/orcarail/orcarail/tree/main/api/src/scheduler/processors/subscription-auto-charge.processor.ts" target="_blank" rel="noopener noreferrer" class="">api/src/scheduler/processors/subscription-auto-charge.processor.ts</a> stops pulling from our smart account and starts calling <code>SubscriptionHub.charge(id)</code> with a keeper EOA.</p>
<p>Concretely:</p>
<ul>
<li class="">Keeper EOA is a per-chain hot wallet with only gas. It has zero authority over merchant funds.</li>
<li class="">If the chain has an Alchemy paymaster policy (see <a href="https://github.com/orcarail/orcarail/tree/main/api/src/withdrawals/services/gas-strategy" target="_blank" rel="noopener noreferrer" class="">api/src/withdrawals/services/gas-strategy</a>), the keeper uses the sponsored path; otherwise it self-funds from its gas balance.</li>
<li class="">On revert, the processor parses the error selector and updates the same <a href="https://github.com/orcarail/orcarail/tree/main/api/src/subscriptions/infrastructure/persistence/relational/entities/subscription-auto-charge.entity.ts" target="_blank" rel="noopener noreferrer" class="">SubscriptionAutoChargeEntity</a> states we use today (<code>past_due</code>, <code>insufficient_balance</code>, etc.).</li>
<li class="">Webhooks and emails from <code>api/src/mail/mail-templates/subscription-*.hbs</code> fire unchanged.</li>
</ul>
<p>Payer UX in <a href="https://github.com/orcarail/orcarail/tree/main/pay" target="_blank" rel="noopener noreferrer" class="">pay</a> gets two adjustments, both minor:</p>
<ol>
<li class="">The <code>approve()</code> step now points spender to the <code>SubscriptionHub</code> address instead of our hot wallet. That is one copy change and one config value — the flow the payer sees is identical.</li>
<li class="">A "revoke" button that calls <code>SubscriptionHub.cancel(id)</code> then prompts an on-chain <code>approve(hub, 0)</code> for full cleanup. Today's <a class="" href="https://docs.orcarail.com/docs/subscriptions/auto-charge/">Auto-charge revoke docs</a> remain accurate.</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="deprecations">Deprecations<a href="https://docs.orcarail.com/blog/phase-2-allowance-pull-subscriptions/#deprecations" class="hash-link" aria-label="Direct link to Deprecations" title="Direct link to Deprecations" translate="no">​</a></h2>
<ul>
<li class="">The custodial pull path in <code>subscription-auto-charge.processor.ts</code> — behind the flag, only the <code>SubscriptionHub.charge</code> branch runs.</li>
<li class="">OrcaRail-owned smart account as <code>approval_spender_address</code> — new subs store the hub address instead.</li>
<li class="">The <code>approval_spender_address</code> field stays in the API response, it just points somewhere new and auditable.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="migration-plan">Migration plan<a href="https://docs.orcarail.com/blog/phase-2-allowance-pull-subscriptions/#migration-plan" class="hash-link" aria-label="Direct link to Migration plan" title="Direct link to Migration plan" translate="no">​</a></h2>
<p>Existing subscribers are <strong>never force-migrated</strong>. We offer two paths:</p>
<ol>
<li class=""><strong>Renewal-triggered</strong>: at the next cycle, the dashboard banner asks the payer to resign <code>approve(hub, cap)</code> on the new <code>SubscriptionHub</code>. One click. Old allowance to the legacy hot wallet can be left or revoked; it no longer matters.</li>
<li class=""><strong>User-initiated</strong>: a "Move to non-custodial" button in the subscription detail page does the same thing immediately.</li>
</ol>
<p>Subs that never migrate stay on the custodial path until cancellation. That path is turned off in <a class="" href="https://docs.orcarail.com/blog/phase-7-retiring-custody/">Phase 7</a>, with plenty of notice.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="risks-and-mitigations">Risks and mitigations<a href="https://docs.orcarail.com/blog/phase-2-allowance-pull-subscriptions/#risks-and-mitigations" class="hash-link" aria-label="Direct link to Risks and mitigations" title="Direct link to Risks and mitigations" translate="no">​</a></h2>
<ul>
<li class=""><strong>Payer confusion at migration</strong>. Mitigation: email template mirrors existing <code>subscription-auto-charge-approved.hbs</code> language; banner in dashboard; FAQ entry at <a class="" href="https://docs.orcarail.com/docs/non-custodial/migration-guide/">/docs/non-custodial/migration-guide</a>.</li>
<li class=""><strong>Keeper outage misses a charge</strong>. Mitigation: <code>charge()</code> is permissionless — any Chainlink Automation or Gelato instance can be a fallback; manual merchant-initiated <code>charge()</code> is also possible. Full plan in <a class="" href="https://docs.orcarail.com/blog/phase-3-multi-evm-and-keeper-redundancy/">Phase 3</a>.</li>
<li class=""><strong>Reorg double-charge</strong>. Mitigation: <code>lastChargedAt</code> monotonic invariant; unit test with fork reorgs.</li>
<li class=""><strong>Payer revokes between cycles</strong>. Mitigation: <code>charge()</code> emits <code>ChargeSkipped(AllowanceRevoked)</code>; the existing <code>subscription-insufficient-allowance.hbs</code> email template fires; sub moves to <code>past_due</code>.</li>
<li class=""><strong>Token allowlist drift</strong>. Mitigation: hub only accepts tokens on <code>SubscriptionHub.isAllowed(token)</code>; changes are multisig-gated.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="status-checklist">Status checklist<a href="https://docs.orcarail.com/blog/phase-2-allowance-pull-subscriptions/#status-checklist" class="hash-link" aria-label="Direct link to Status checklist" title="Direct link to Status checklist" translate="no">​</a></h2>
<ul class="contains-task-list containsTaskList_mC6p">
<li class="task-list-item"><input type="checkbox" disabled=""> <code>SubscriptionHub</code> implemented with all invariants</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Fuzz tests for cap, allowance, reorg, and skip cases</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Audit delta covering <code>SubscriptionHub</code> landed</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Keeper EOA provisioned per chain, gas monitored via Sentry + Datadog</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Pay app migrated <code>approve</code> target to <code>SubscriptionHub</code></li>
<li class="task-list-item"><input type="checkbox" disabled=""> <code>approve-auto-charge</code> endpoint updated to accept hub-spender allowances</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Dashboard banner for existing subs</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Canary cohort migrated and stable for 14 days</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-is-next">What is next<a href="https://docs.orcarail.com/blog/phase-2-allowance-pull-subscriptions/#what-is-next" class="hash-link" aria-label="Direct link to What is next" title="Direct link to What is next" translate="no">​</a></h2>
<p>Multi-chain rollout and a second keeper: <strong><a class="" href="https://docs.orcarail.com/blog/phase-3-multi-evm-and-keeper-redundancy/">Phase 3</a></strong>.</p>
<hr>
<p>Reference docs: <strong><a class="" href="https://docs.orcarail.com/docs/non-custodial/phases/phase-2-evm-subscriptions/">Phase 2 status</a></strong> · <strong><a class="" href="https://docs.orcarail.com/docs/non-custodial/migration-guide/">Migration guide</a></strong> · <strong><a class="" href="https://docs.orcarail.com/docs/non-custodial/contract-reference/">Contract reference</a></strong> · <strong><a class="" href="https://docs.orcarail.com/blog/why-allowance-pull-subscriptions/">Why allowance-pull</a></strong></p>]]></content:encoded>
            <category>Subscriptions</category>
            <category>Payments</category>
            <category>Web3</category>
            <category>Stablecoins</category>
        </item>
        <item>
            <title><![CDATA[Phase 3: Multi-EVM Rollout and Keeper Redundancy]]></title>
            <link>https://docs.orcarail.com/blog/phase-3-multi-evm-and-keeper-redundancy/</link>
            <guid>https://docs.orcarail.com/blog/phase-3-multi-evm-and-keeper-redundancy/</guid>
            <pubDate>Mon, 20 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Phase 3 of the OrcaRail non-custodial roadmap. Deploy the payment-link factory and SubscriptionHub to Ethereum, Arbitrum, Optimism, and Polygon; add Chainlink Automation or Gelato as a second keeper.]]></description>
            <content:encoded><![CDATA[<p><strong>April 20, 2026</strong> — Phase 3 takes the contract surface from <a class="" href="https://docs.orcarail.com/blog/phase-1-evm-payment-link-contracts/">Phase 1</a> and <a class="" href="https://docs.orcarail.com/blog/phase-2-allowance-pull-subscriptions/">Phase 2</a> and puts it on every EVM chain we support. It also adds a second keeper, so a NestJS outage cannot skip a subscription charge.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="tldr">TL;DR<a href="https://docs.orcarail.com/blog/phase-3-multi-evm-and-keeper-redundancy/#tldr" class="hash-link" aria-label="Direct link to TL;DR" title="Direct link to TL;DR" translate="no">​</a></h2>
<ul>
<li class="">Deploy <code>PaymentLinkFactory</code>, <code>PaymentLinkReceiver</code> implementation, <code>FeeSplitter</code>, and <code>SubscriptionHub</code> to <strong>Ethereum mainnet, Arbitrum, Optimism, and Polygon</strong>.</li>
<li class="">Same CREATE2 salt scheme everywhere — the factory address is the same on every chain (clean for docs, clean for integrations, clean for <code>computeAddress</code> from the client).</li>
<li class="">Register <strong>Chainlink Automation</strong> (preferred) and/or <strong>Gelato Web3 Functions</strong> as a second keeper calling the same <code>charge(ids[])</code>.</li>
<li class="">Publish SLOs: <strong>99.5% of charges within 10 minutes of due time</strong>, measured.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-this-phase-changes">What this phase changes<a href="https://docs.orcarail.com/blog/phase-3-multi-evm-and-keeper-redundancy/#what-this-phase-changes" class="hash-link" aria-label="Direct link to What this phase changes" title="Direct link to What this phase changes" translate="no">​</a></h2>
<div class="wrapper_vprU"><button type="button" class="expandBtn_RmxB" aria-label="Show diagram fullscreen" title="Fullscreen"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7" stroke-linecap="round" stroke-linejoin="round"></path></svg></button></div>
<p>Multiple keepers calling the same public <code>charge()</code> is the liveness story. None of them has custody; any of them can save a due charge.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="deployment-plan">Deployment plan<a href="https://docs.orcarail.com/blog/phase-3-multi-evm-and-keeper-redundancy/#deployment-plan" class="hash-link" aria-label="Direct link to Deployment plan" title="Direct link to Deployment plan" translate="no">​</a></h2>
<p>Deploy order (one chain per week, canary per chain):</p>
<ol>
<li class="">Ethereum mainnet (chainId <code>1</code>)</li>
<li class="">Arbitrum One (<code>42161</code>)</li>
<li class="">Optimism (<code>10</code>)</li>
<li class="">Polygon PoS (<code>137</code>)</li>
</ol>
<p>Addresses on each chain are published in <a class="" href="https://docs.orcarail.com/docs/non-custodial/contract-reference/">/docs/non-custodial/contract-reference</a>. The deployer key is the same 3-of-5 Safe multisig defined in <a class="" href="https://docs.orcarail.com/blog/phase-0-design-and-audit-strategy/">Phase 0</a>, redeployed per chain from the same ceremony.</p>
<p>All four chains share the same <code>useOnChainReceiver</code> feature flag scoped by <code>chainId</code> inside <a href="https://github.com/orcarail/orcarail/tree/main/api/src/payments/wallet.service.ts" target="_blank" rel="noopener noreferrer" class="">api/src/payments/wallet.service.ts</a>. Merchants opt in chain-by-chain; defaults flip to on once the canary week is clean.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="gas-strategy-for-charge">Gas strategy for <code>charge()</code><a href="https://docs.orcarail.com/blog/phase-3-multi-evm-and-keeper-redundancy/#gas-strategy-for-charge" class="hash-link" aria-label="Direct link to gas-strategy-for-charge" title="Direct link to gas-strategy-for-charge" translate="no">​</a></h2>
<p>The keeper's <code>charge()</code> transactions need gas. We reuse the existing paymaster plumbing in <a href="https://github.com/orcarail/orcarail/tree/main/api/src/withdrawals/services/gas-strategy" target="_blank" rel="noopener noreferrer" class="">api/src/withdrawals/services/gas-strategy</a>:</p>
<ul>
<li class=""><strong>Alchemy paymaster enabled (Base, Arbitrum, Optimism, Polygon)</strong>: keeper calls <code>SubscriptionHub.charge()</code> as a UserOperation with policy sponsorship. Zero gas cost for the keeper EOA.</li>
<li class=""><strong>Ethereum mainnet (no paymaster)</strong>: keeper self-funds from its hot-gas balance. Funded daily by the platform wallet; monitored with a Datadog alert for low balance.</li>
<li class=""><strong>Merchant-subsidized gas (optional)</strong>: merchants can set a <code>gas_refund_address</code> and the keeper pulls reimbursement from there, matching the existing support/commission pattern. Out of scope for initial rollout.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="second-keeper-chainlink-and-gelato">Second keeper: Chainlink and Gelato<a href="https://docs.orcarail.com/blog/phase-3-multi-evm-and-keeper-redundancy/#second-keeper-chainlink-and-gelato" class="hash-link" aria-label="Direct link to Second keeper: Chainlink and Gelato" title="Direct link to Second keeper: Chainlink and Gelato" translate="no">​</a></h2>
<p>The second keeper is a redundancy play, not a replacement. It runs alongside the NestJS scheduler.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="chainlink-automation-preferred-on-evm">Chainlink Automation (preferred on EVM)<a href="https://docs.orcarail.com/blog/phase-3-multi-evm-and-keeper-redundancy/#chainlink-automation-preferred-on-evm" class="hash-link" aria-label="Direct link to Chainlink Automation (preferred on EVM)" title="Direct link to Chainlink Automation (preferred on EVM)" translate="no">​</a></h3>
<ul>
<li class="">Register an <strong>Upkeep</strong> per <code>SubscriptionHub</code>.</li>
<li class=""><code>checkUpkeep()</code> returns <code>performData = abi.encode(ids[])</code> for all <code>id</code> with <code>block.timestamp &gt;= nextChargeAt</code> (read from a view function).</li>
<li class=""><code>performUpkeep(performData)</code> calls <code>charge(ids)</code> in a batch.</li>
<li class="">Funded with LINK from the platform treasury; balance monitored.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="gelato-web3-functions-alternative">Gelato Web3 Functions (alternative)<a href="https://docs.orcarail.com/blog/phase-3-multi-evm-and-keeper-redundancy/#gelato-web3-functions-alternative" class="hash-link" aria-label="Direct link to Gelato Web3 Functions (alternative)" title="Direct link to Gelato Web3 Functions (alternative)" translate="no">​</a></h3>
<ul>
<li class="">A JS Web3 Function polls the hub, finds due IDs, and submits a <code>charge(ids[])</code> transaction.</li>
<li class="">Pricing is post-paid from Gelato's <code>1Balance</code>.</li>
</ul>
<p>Either one is sufficient on its own; we will pick based on operational experience during Phase 3. Running both is fine — <code>charge()</code> is idempotent within a period thanks to <code>lastChargedAt</code>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="slos-and-monitoring">SLOs and monitoring<a href="https://docs.orcarail.com/blog/phase-3-multi-evm-and-keeper-redundancy/#slos-and-monitoring" class="hash-link" aria-label="Direct link to SLOs and monitoring" title="Direct link to SLOs and monitoring" translate="no">​</a></h2>
<p>Published SLO targets:</p>
<table><thead><tr><th>Metric</th><th>Target</th></tr></thead><tbody><tr><td><code>charge()</code> within 10 minutes of <code>nextChargeAt</code></td><td>99.5%</td></tr><tr><td><code>charge()</code> within 1 hour of <code>nextChargeAt</code></td><td>99.9%</td></tr><tr><td>Keeper EOA hot-gas balance above alert threshold</td><td>99.99%</td></tr><tr><td>Events indexed within 2 minutes of block finality</td><td>99.5%</td></tr></tbody></table>
<p>Monitoring hooks into the existing Sentry setup documented in the repo's <a href="https://github.com/orcarail/orcarail/tree/main/.cursor/plugins" target="_blank" rel="noopener noreferrer" class="">Sentry workflow skill</a>. Alerts:</p>
<ul>
<li class=""><code>charge()</code> reverts per hour &gt; threshold → PagerDuty</li>
<li class="">Keeper EOA native balance below N gwei × gasLimit × 100 → PagerDuty</li>
<li class="">Chainlink/Gelato upkeep unhealthy → warning</li>
<li class=""><code>Paid</code> event indexer lag &gt; 5 min → warning</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="deprecations">Deprecations<a href="https://docs.orcarail.com/blog/phase-3-multi-evm-and-keeper-redundancy/#deprecations" class="hash-link" aria-label="Direct link to Deprecations" title="Direct link to Deprecations" translate="no">​</a></h2>
<p>Same as Phase 1 and 2, but on more chains. Nothing is deleted yet — deletion waits for <a class="" href="https://docs.orcarail.com/blog/phase-7-retiring-custody/">Phase 7</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="migration-plan">Migration plan<a href="https://docs.orcarail.com/blog/phase-3-multi-evm-and-keeper-redundancy/#migration-plan" class="hash-link" aria-label="Direct link to Migration plan" title="Direct link to Migration plan" translate="no">​</a></h2>
<ul>
<li class=""><strong>New payment links</strong>: use contract receivers on any chain with the flag on.</li>
<li class=""><strong>New subscriptions</strong>: use <code>SubscriptionHub</code> on any chain with the flag on.</li>
<li class=""><strong>Existing customers</strong>: opt-in migration at renewal, same as Phase 2.</li>
<li class=""><strong>Cross-chain settlement (Relay)</strong>: unchanged surface; the keeper still calls Relay executors in <a href="https://github.com/orcarail/orcarail/tree/main/api/src/withdrawals/services/bridge" target="_blank" rel="noopener noreferrer" class="">api/src/withdrawals/services/bridge</a>, just from an EOA that has no custody.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="risks-and-mitigations">Risks and mitigations<a href="https://docs.orcarail.com/blog/phase-3-multi-evm-and-keeper-redundancy/#risks-and-mitigations" class="hash-link" aria-label="Direct link to Risks and mitigations" title="Direct link to Risks and mitigations" translate="no">​</a></h2>
<ul>
<li class=""><strong>Multi-chain address drift</strong>. Mitigation: deterministic CREATE2 deployer (e.g. <code>0x4e59b44847b379578588920cA78FbF26c0B4956C</code>) with a locked init-code hash; factories share an address across all four chains.</li>
<li class=""><strong>Per-chain paymaster policy limits</strong>. Mitigation: per-chain monitoring and policy quota alerts at 70% usage.</li>
<li class=""><strong>Chainlink upkeep registration churn</strong>. Mitigation: one upkeep per chain; the list of IDs is read on-chain, so merchant onboarding does not require Chainlink config changes.</li>
<li class=""><strong>Double-charge across keepers</strong>. Mitigation: <code>lastChargedAt</code> monotonic plus <code>ChargeSkipped</code> for duplicates; both keepers are idempotent by design.</li>
<li class=""><strong>Mainnet gas spikes</strong>. Mitigation: per-chain batch size tuning; a gas-price ceiling above which <code>charge()</code> is deferred one block.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="status-checklist">Status checklist<a href="https://docs.orcarail.com/blog/phase-3-multi-evm-and-keeper-redundancy/#status-checklist" class="hash-link" aria-label="Direct link to Status checklist" title="Direct link to Status checklist" translate="no">​</a></h2>
<ul class="contains-task-list containsTaskList_mC6p">
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Deploys completed on Ethereum, Arbitrum, Optimism, Polygon</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Factory + hub addresses published in contract reference</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Paymaster policies validated per chain</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Chainlink Automation upkeep live on at least 2 chains</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->SLO dashboard in Datadog</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Runbook for keeper outage (manual <code>charge()</code> from merchant CLI)</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Canary merchants rolled per chain</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-is-next">What is next<a href="https://docs.orcarail.com/blog/phase-3-multi-evm-and-keeper-redundancy/#what-is-next" class="hash-link" aria-label="Direct link to What is next" title="Direct link to What is next" translate="no">​</a></h2>
<p>Solana is the other big chain we must make non-custodial: <strong><a class="" href="https://docs.orcarail.com/blog/phase-4-solana-pda-programs/">Phase 4</a></strong>.</p>
<hr>
<p>Reference docs: <strong><a class="" href="https://docs.orcarail.com/docs/non-custodial/phases/phase-3-multi-evm-rollout/">Phase 3 status</a></strong> · <strong><a class="" href="https://docs.orcarail.com/docs/non-custodial/keeper-strategy/">Keeper strategy</a></strong> · <strong><a class="" href="https://docs.orcarail.com/docs/non-custodial/contract-reference/">Contract reference</a></strong></p>]]></content:encoded>
            <category>Payments</category>
            <category>Multi-Chain</category>
            <category>Web3</category>
            <category>Stablecoins</category>
        </item>
        <item>
            <title><![CDATA[Phase 4: Non-Custodial Solana with Anchor PDAs]]></title>
            <link>https://docs.orcarail.com/blog/phase-4-solana-pda-programs/</link>
            <guid>https://docs.orcarail.com/blog/phase-4-solana-pda-programs/</guid>
            <pubDate>Mon, 20 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Phase 4 of the OrcaRail non-custodial roadmap. Anchor programs replace HD-wallet sweeps on Solana with PDA-based payment-link vaults and SPL delegate subscriptions.]]></description>
            <content:encoded><![CDATA[<p><strong>April 20, 2026</strong> — Phase 4 brings the non-custodial model to Solana. Two Anchor programs replace the per-link HD-wallet + sweep flow: <code>payment_link</code> for one-off payments and <code>subscription</code> for SPL-delegate auto-charge. No mnemonic lives on our servers for new Solana links.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="tldr">TL;DR<a href="https://docs.orcarail.com/blog/phase-4-solana-pda-programs/#tldr" class="hash-link" aria-label="Direct link to TL;DR" title="Direct link to TL;DR" translate="no">​</a></h2>
<ul>
<li class=""><code>payment_link</code> program owns a PDA per payment link, derived from <code>seeds = [b"pl", link_id]</code>. No keypair, no seed, no sweep.</li>
<li class=""><code>subscription</code> program uses SPL <strong>delegate</strong> authority — the same primitive we already rely on in <a class="" href="https://docs.orcarail.com/docs/subscriptions/auto-charge/">Auto-charge</a> — as an explicit allowance granted by the payer.</li>
<li class="">Splits are done via CPI to the same <code>fee_splitter</code> logic we built on EVM, adapted to Solana accounts.</li>
<li class="">Sweep service <a href="https://github.com/orcarail/orcarail/tree/main/api/src/withdrawals/services/solana-withdrawal-transfer.service.ts" target="_blank" rel="noopener noreferrer" class="">api/src/withdrawals/services/solana-withdrawal-transfer.service.ts</a> is bypassed for flagged links and removed in <a class="" href="https://docs.orcarail.com/blog/phase-7-retiring-custody/">Phase 7</a>.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-this-phase-changes">What this phase changes<a href="https://docs.orcarail.com/blog/phase-4-solana-pda-programs/#what-this-phase-changes" class="hash-link" aria-label="Direct link to What this phase changes" title="Direct link to What this phase changes" translate="no">​</a></h2>
<div class="wrapper_vprU"><button type="button" class="expandBtn_RmxB" aria-label="Show diagram fullscreen" title="Fullscreen"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7" stroke-linecap="round" stroke-linejoin="round"></path></svg></button></div>
<p>The "after" side replaces the HD seed in <a href="https://github.com/orcarail/orcarail/tree/main/api/src/payments/wallet.service.ts" target="_blank" rel="noopener noreferrer" class="">api/src/payments/wallet.service.ts</a> (the <code>m/44'/501'/i'/0'</code> branch) with a pure deterministic PDA computation.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="programs-introduced">Programs introduced<a href="https://docs.orcarail.com/blog/phase-4-solana-pda-programs/#programs-introduced" class="hash-link" aria-label="Direct link to Programs introduced" title="Direct link to Programs introduced" translate="no">​</a></h2>
<p>New package <code>contracts/solana/</code> (Anchor).</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="payment_link-program"><code>payment_link</code> program<a href="https://docs.orcarail.com/blog/phase-4-solana-pda-programs/#payment_link-program" class="hash-link" aria-label="Direct link to payment_link-program" title="Direct link to payment_link-program" translate="no">​</a></h3>
<p>Accounts per link:</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token attribute attr-name" style="color:#00a4db">#[account]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">struct</span><span class="token plain"> </span><span class="token type-definition class-name">PaymentLink</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> link_id</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token keyword" style="color:#00009f">u8</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">32</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> expected_mint</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Pubkey</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// e.g. USDC on SOL</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> expected_amount</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">u64</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> split</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Split</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> created_at</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">i64</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> status</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">PaymentStatus</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>Instructions:</p>
<ul>
<li class=""><code>initialize(link_id, expected_mint, expected_amount, split)</code> — lazy; called on first deposit by the factory-style wrapper.</li>
<li class=""><code>pay(link_id, amount)</code> — validates mint + amount, CPI-transfers into the PDA's ATA, then CPI-splits atomically. Emits <code>PaymentReceived { link_id, payer, amount }</code>.</li>
<li class=""><code>refund(link_id)</code> — multisig-gated, mirrors EVM refund.</li>
</ul>
<p>PDA seeds: <code>[b"pl", link_id]</code>. PDA has <strong>no private key</strong> — it signs via <code>invoke_signed</code>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="subscription-program"><code>subscription</code> program<a href="https://docs.orcarail.com/blog/phase-4-solana-pda-programs/#subscription-program" class="hash-link" aria-label="Direct link to subscription-program" title="Direct link to subscription-program" translate="no">​</a></h3>
<p>Leverages SPL <strong>Approve / Revoke</strong> for authority delegation. The payer signs <code>spl_token::approve</code> designating the program's PDA as delegate for up to <code>cap</code> tokens. Then:</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">charge</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ctx</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Context</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">Charge</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> id</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token keyword" style="color:#00009f">u8</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">32</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">Result</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">&gt;</span><br></div></code></pre></div></div>
<p>Can be called by anyone, checks:</p>
<ul>
<li class=""><code>clock.unix_timestamp &gt;= next_charge_at</code></li>
<li class=""><code>clock.unix_timestamp &gt; last_charged_at</code>  // monotonic</li>
<li class=""><code>amount_charged + period_amount &lt;= cap</code></li>
<li class="">delegate authority still present on payer ATA</li>
</ul>
<p>On pass, CPI <code>spl_token::transfer_checked</code> pulls from the payer's ATA (as delegate) and CPI-splits.</p>
<p>Events: <code>SubscriptionCreated</code>, <code>Charged</code>, <code>ChargeSkipped</code>, <code>Canceled</code>. Same shapes the EVM indexer produces, so <code>api/src/webhooks</code> is agnostic.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="api-changes">API changes<a href="https://docs.orcarail.com/blog/phase-4-solana-pda-programs/#api-changes" class="hash-link" aria-label="Direct link to API changes" title="Direct link to API changes" translate="no">​</a></h2>
<ul>
<li class="">The Solana branch of <code>WalletService.generateAddressForNetwork</code> stops deriving keypairs and returns <code>findProgramAddressSync(["pl", linkId], programId)</code> instead. No <code>encryptedSeed</code> row written for new Solana links.</li>
<li class="">A new indexer service watches program logs (Helius webhooks or Triton streams) and emits existing webhook events.</li>
<li class=""><a href="https://github.com/orcarail/orcarail/tree/main/api/src/scheduler/processors/subscription-auto-charge.processor.ts" target="_blank" rel="noopener noreferrer" class="">api/src/scheduler/processors/subscription-auto-charge.processor.ts</a> adds a SOL branch: build a <code>charge</code> transaction, sign with the keeper (gasless path via sponsor tx, similar to Phase 2 paymaster).</li>
<li class=""><code>withdrawals/services/solana-withdrawal-transfer.service.ts</code> is not called for flagged links.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="gas-on-solana">Gas on Solana<a href="https://docs.orcarail.com/blog/phase-4-solana-pda-programs/#gas-on-solana" class="hash-link" aria-label="Direct link to Gas on Solana" title="Direct link to Gas on Solana" translate="no">​</a></h2>
<p>Solana fees are small (typically 5000 lamports per sig, 0.000005 SOL). The keeper uses a hot-SOL balance with the same alerting pattern as Phase 3. Because Solana does not have an Alchemy-style paymaster, sponsored transactions use a simple co-signer pattern: the keeper signs as fee payer, payer does not need SOL at all.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="deprecations">Deprecations<a href="https://docs.orcarail.com/blog/phase-4-solana-pda-programs/#deprecations" class="hash-link" aria-label="Direct link to Deprecations" title="Direct link to Deprecations" translate="no">​</a></h2>
<ul>
<li class="">SOL HD derivation (<code>m/44'/501'/i'/0'</code>) for new links — not called when flag is on.</li>
<li class=""><code>solana-withdrawal-transfer.service.ts</code> — bypassed for flagged links.</li>
<li class=""><code>SolanaRelayBridgeExecutorService</code> in <a href="https://github.com/orcarail/orcarail/tree/main/api/src/withdrawals/services/bridge/solana-relay-bridge-executor.service.ts" target="_blank" rel="noopener noreferrer" class="">api/src/withdrawals/services/bridge/solana-relay-bridge-executor.service.ts</a> stays: bridging from SOL to EVM when the merchant lives on EVM still uses Relay, but the trigger moves to the program.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="migration-plan">Migration plan<a href="https://docs.orcarail.com/blog/phase-4-solana-pda-programs/#migration-plan" class="hash-link" aria-label="Direct link to Migration plan" title="Direct link to Migration plan" translate="no">​</a></h2>
<p>Same opt-in model as Phase 2:</p>
<ul>
<li class="">New payment links: PDA-addressed.</li>
<li class="">New subscriptions: SPL-delegate-based.</li>
<li class="">Existing active subscriptions: banner + email at next renewal to re-delegate to the new program.</li>
<li class="">In-flight deposits on legacy addresses keep settling on the legacy path.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="risks-and-mitigations">Risks and mitigations<a href="https://docs.orcarail.com/blog/phase-4-solana-pda-programs/#risks-and-mitigations" class="hash-link" aria-label="Direct link to Risks and mitigations" title="Direct link to Risks and mitigations" translate="no">​</a></h2>
<ul>
<li class=""><strong>SPL delegate is overridable</strong>. Mitigation: <code>charge</code> double-checks <code>delegated_amount</code> before transferring; failed checks emit <code>ChargeSkipped(DelegateRevoked)</code> and follow the same email template as the EVM allowance-revoked case.</li>
<li class=""><strong>Anchor upgrade authority</strong>. Mitigation: 3-of-5 Squads multisig owns the upgrade authority, timelocked. Matches the EVM Safe posture from <a class="" href="https://docs.orcarail.com/blog/phase-0-design-and-audit-strategy/">Phase 0</a>.</li>
<li class=""><strong>Wrapped SOL vs native SOL</strong>. Mitigation: <code>payment_link</code> supports both, with explicit <code>expected_mint</code> per link to avoid ambiguity.</li>
<li class=""><strong>Priority fee spikes</strong>. Mitigation: dynamic priority fee calculation in the keeper; fallback retry with higher priority after one slot.</li>
<li class=""><strong>Audit</strong>. Mitigation: OtterSec or Neodyme audit of both programs before mainnet deploy.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="status-checklist">Status checklist<a href="https://docs.orcarail.com/blog/phase-4-solana-pda-programs/#status-checklist" class="hash-link" aria-label="Direct link to Status checklist" title="Direct link to Status checklist" translate="no">​</a></h2>
<ul class="contains-task-list containsTaskList_mC6p">
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Anchor workspace <code>contracts/solana/</code> scaffolded</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <code>payment_link</code> program with all instructions + tests</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <code>subscription</code> program with all instructions + tests</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Helius webhook indexer shipping</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Keeper SOL branch in <code>subscription-auto-charge.processor.ts</code></li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Audit report landed</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Mainnet deploy from Squads multisig</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Canary merchant cohort</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-is-next">What is next<a href="https://docs.orcarail.com/blog/phase-4-solana-pda-programs/#what-is-next" class="hash-link" aria-label="Direct link to What is next" title="Direct link to What is next" translate="no">​</a></h2>
<p>Bitcoin. The hardest chain for non-custody, and the one where we have to be honest about the limits: <strong><a class="" href="https://docs.orcarail.com/blog/phase-5-bitcoin-reduced-custody/">Phase 5</a></strong>.</p>
<hr>
<p>Reference docs: <strong><a class="" href="https://docs.orcarail.com/docs/non-custodial/phases/phase-4-solana/">Phase 4 status</a></strong> · <strong><a class="" href="https://docs.orcarail.com/docs/non-custodial/contract-reference/">Contract reference</a></strong> · <strong><a class="" href="https://docs.orcarail.com/docs/non-custodial/architecture/">Architecture</a></strong></p>]]></content:encoded>
            <category>Payments</category>
            <category>Multi-Chain</category>
            <category>Web3</category>
            <category>Stablecoins</category>
            <category>Subscriptions</category>
        </item>
        <item>
            <title><![CDATA[Phase 5: Bitcoin — Taproot 2-of-2 and Honest Scope]]></title>
            <link>https://docs.orcarail.com/blog/phase-5-bitcoin-reduced-custody/</link>
            <guid>https://docs.orcarail.com/blog/phase-5-bitcoin-reduced-custody/</guid>
            <pubDate>Mon, 20 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Phase 5 of the OrcaRail non-custodial roadmap. Bitcoin cannot go fully non-custodial today, so we move to 2-of-2 taproot multisig per link with pre-signed refunds, and leave recurring payments to Lightning BOLT12 as future work.]]></description>
            <content:encoded><![CDATA[<p><strong>April 20, 2026</strong> — Bitcoin is the chain where we have to be honest. The L1 script surface does not have the expressiveness of EVM or Solana, so the "payment-link contract that splits atomically" pattern does not translate. What we can do is <strong>reduce custody</strong> from "OrcaRail holds the xpub" to "two-signer multisig with a merchant signer and a pre-signed refund," and push recurring payments to a future Lightning path.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="tldr">TL;DR<a href="https://docs.orcarail.com/blog/phase-5-bitcoin-reduced-custody/#tldr" class="hash-link" aria-label="Direct link to TL;DR" title="Direct link to TL;DR" translate="no">​</a></h2>
<ul>
<li class="">Every BTC payment link becomes a <strong>2-of-2 taproot multisig</strong>: one merchant signer, one platform signer. Platform cannot move funds unilaterally.</li>
<li class="">Every deposit gets a <strong>pre-signed refund PSBT</strong> stored off-chain so the payer is recoverable if the merchant disappears.</li>
<li class="">Master xpubs move off the API server to an <strong>HSM or MPC service</strong> (e.g. Lit, Turnkey). No mnemonic on disk.</li>
<li class=""><strong>Recurring payments on BTC are out of scope</strong> until Lightning BOLT12 is production-ready. Today, <a class="" href="https://docs.orcarail.com/docs/subscriptions/auto-charge/">Auto-charge</a> already states BTC is not supported for auto-charge — that stays true.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-this-phase-changes">What this phase changes<a href="https://docs.orcarail.com/blog/phase-5-bitcoin-reduced-custody/#what-this-phase-changes" class="hash-link" aria-label="Direct link to What this phase changes" title="Direct link to What this phase changes" translate="no">​</a></h2>
<p>Today, <code>BitcoinHotWalletService</code> in <a href="https://github.com/orcarail/orcarail/tree/main/api/src/withdrawals/services/bitcoin-hot-wallet.service.ts" target="_blank" rel="noopener noreferrer" class="">api/src/withdrawals/services/bitcoin-hot-wallet.service.ts</a> derives a unilateral p2wpkh address from a server-held mnemonic and sweeps it via <code>bitcoin-withdrawal-transfer.service.ts</code>. That is a single key we control.</p>
<p>After Phase 5:</p>
<div class="wrapper_vprU"><button type="button" class="expandBtn_RmxB" aria-label="Show diagram fullscreen" title="Fullscreen"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7" stroke-linecap="round" stroke-linejoin="round"></path></svg></button></div>
<p>No single party can spend. No server holds a unilateral seed.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-we-are-shipping">What we are shipping<a href="https://docs.orcarail.com/blog/phase-5-bitcoin-reduced-custody/#what-we-are-shipping" class="hash-link" aria-label="Direct link to What we are shipping" title="Direct link to What we are shipping" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-taproot-2-of-2-per-link">1. Taproot 2-of-2 per link<a href="https://docs.orcarail.com/blog/phase-5-bitcoin-reduced-custody/#1-taproot-2-of-2-per-link" class="hash-link" aria-label="Direct link to 1. Taproot 2-of-2 per link" title="Direct link to 1. Taproot 2-of-2 per link" translate="no">​</a></h3>
<ul>
<li class="">Descriptor wallet per link: <code>wsh(multi(2, merchant_pubkey, platform_pubkey))</code> or a taproot equivalent (<code>tr(NUMS, {pk(m), pk(p)})</code> with MuSig2 for a single-sig-looking output — nice for privacy and fees).</li>
<li class="">Merchant key lives in the merchant's browser or mobile extension. Merchant onboarding flow prompts for an xpub; per-link keys derive from it.</li>
<li class="">Platform key lives behind an HSM or MPC service. The API server never sees the private material.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-pre-signed-refund-psbt">2. Pre-signed refund PSBT<a href="https://docs.orcarail.com/blog/phase-5-bitcoin-reduced-custody/#2-pre-signed-refund-psbt" class="hash-link" aria-label="Direct link to 2. Pre-signed refund PSBT" title="Direct link to 2. Pre-signed refund PSBT" translate="no">​</a></h3>
<p>When a deposit is detected:</p>
<ol>
<li class="">API assembles a PSBT that returns the deposit minus gas to the payer's address (captured at pay-link creation when payer wallet is known; fallback is <code>sendback</code> policy).</li>
<li class="">Both signers sign the refund PSBT immediately and store it (encrypted) in the database.</li>
<li class="">Merchant can broadcast the refund at any time with one click; no further signing needed.</li>
</ol>
<p>This is the BTC analog of an on-chain <code>refund()</code> function.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-mpc-key-rotation">3. MPC key rotation<a href="https://docs.orcarail.com/blog/phase-5-bitcoin-reduced-custody/#3-mpc-key-rotation" class="hash-link" aria-label="Direct link to 3. MPC key rotation" title="Direct link to 3. MPC key rotation" translate="no">​</a></h3>
<ul>
<li class="">Master xpubs for platform keys rotate annually.</li>
<li class="">All derived per-link keys roll with rotations — old links keep working because their multisig is already on-chain with the specific pubkey.</li>
<li class="">Rotation is logged in the same audit trail as the multisig deploys from <a class="" href="https://docs.orcarail.com/blog/phase-0-design-and-audit-strategy/">Phase 0</a>.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-we-are-not-shipping">What we are not shipping<a href="https://docs.orcarail.com/blog/phase-5-bitcoin-reduced-custody/#what-we-are-not-shipping" class="hash-link" aria-label="Direct link to What we are not shipping" title="Direct link to What we are not shipping" translate="no">​</a></h2>
<ul>
<li class=""><strong>BTC subscriptions / auto-charge</strong>. No credible design on L1 today. The existing <a class="" href="https://docs.orcarail.com/docs/subscriptions/auto-charge/">Auto-charge docs</a> already exclude BTC; that stays correct.</li>
<li class=""><strong>On-chain atomic splits for BTC</strong>. Splits happen in the merchant-signed settlement PSBT. The split is still deterministic and visible in the broadcast transaction, but it is not enforced by script.</li>
<li class=""><strong>Fedimint or statechains</strong>. Interesting research; not in this phase.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="lightning-as-the-future-path">Lightning as the future path<a href="https://docs.orcarail.com/blog/phase-5-bitcoin-reduced-custody/#lightning-as-the-future-path" class="hash-link" aria-label="Direct link to Lightning as the future path" title="Direct link to Lightning as the future path" translate="no">​</a></h2>
<p>Recurring BTC payments have one realistic option: <strong>Lightning BOLT12 offers + <code>recurrence</code> extension</strong>. That would give us a BTC subscription story comparable to ERC-20 approve + pull. We track it as a future phase:</p>
<ul>
<li class="">Depends on mature BOLT12 recurrence implementations in LND and CLN.</li>
<li class="">Depends on Lightning wallet support (Phoenix, Zeus, Blink) for BOLT12 recurrence.</li>
<li class="">Requires an LN node fleet with sufficient liquidity; probably via a partner (Voltage, Greenlight).</li>
</ul>
<p>We will post a dedicated design doc when the upstream tooling is ready. Until then, BTC stays one-shot.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="deprecations">Deprecations<a href="https://docs.orcarail.com/blog/phase-5-bitcoin-reduced-custody/#deprecations" class="hash-link" aria-label="Direct link to Deprecations" title="Direct link to Deprecations" translate="no">​</a></h2>
<ul>
<li class=""><code>BitcoinHotWalletService</code> — keeps its interface, but the key provider moves to HSM/MPC. The unilateral p2wpkh deposit address stops being generated for new links.</li>
<li class="">Legacy BTC deposit addresses stay settleable until their expiry via the old sweep path.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="migration-plan">Migration plan<a href="https://docs.orcarail.com/blog/phase-5-bitcoin-reduced-custody/#migration-plan" class="hash-link" aria-label="Direct link to Migration plan" title="Direct link to Migration plan" translate="no">​</a></h2>
<ul>
<li class=""><strong>New BTC payment links</strong>: 2-of-2 multisig addresses. UI unchanged; address format updates to taproot.</li>
<li class=""><strong>Existing open BTC links</strong>: legacy unilateral addresses remain active until expiry; we do not force migration.</li>
<li class=""><strong>Merchants without a configured BTC signer</strong>: fall back to a platform-only multisig for now, with a mandatory onboarding step to attach a merchant key within 30 days. This preserves the refund path and avoids blocking existing BTC volume.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="risks-and-mitigations">Risks and mitigations<a href="https://docs.orcarail.com/blog/phase-5-bitcoin-reduced-custody/#risks-and-mitigations" class="hash-link" aria-label="Direct link to Risks and mitigations" title="Direct link to Risks and mitigations" translate="no">​</a></h2>
<ul>
<li class=""><strong>Merchant loses their key</strong>. Mitigation: merchant onboarding asks for <strong>two</strong> xpubs (primary + backup); the backup is optional but heavily encouraged.</li>
<li class=""><strong>Platform HSM outage</strong>. Mitigation: HSM is redundant across regions; emergency key recovery via multisig ceremony documented in the runbook.</li>
<li class=""><strong>Refund PSBT storage compromise</strong>. Mitigation: refund PSBTs encrypted at rest with a separate KMS key; they are still useless without the merchant's signature being re-signed for a different destination (the destination is fixed in the pre-signed PSBT).</li>
<li class=""><strong>MuSig2 maturity</strong>. Mitigation: v1 ships with explicit 2-of-2 <code>wsh(multi(...))</code>; MuSig2 comes later once tooling is widely audited.</li>
<li class=""><strong>Fee market spikes</strong>. Mitigation: settlement PSBTs include a CPFP hook the merchant can bump; keeper monitors mempool and warns merchants when settlement gas exceeds a threshold.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="status-checklist">Status checklist<a href="https://docs.orcarail.com/blog/phase-5-bitcoin-reduced-custody/#status-checklist" class="hash-link" aria-label="Direct link to Status checklist" title="Direct link to Status checklist" translate="no">​</a></h2>
<ul class="contains-task-list containsTaskList_mC6p">
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Taproot descriptor template finalized</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->HSM / MPC provider selected (Lit vs Turnkey vs in-house HSM)</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Merchant xpub onboarding flow in dashboard</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Per-link descriptor derivation and storage</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Pre-signed refund PSBT generation + encrypted storage</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Settlement co-sign UI (one-click merchant sign)</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Runbook for HSM failover and merchant key loss</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Canary cohort of merchants on BTC 2-of-2</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-is-next">What is next<a href="https://docs.orcarail.com/blog/phase-5-bitcoin-reduced-custody/#what-is-next" class="hash-link" aria-label="Direct link to What is next" title="Direct link to What is next" translate="no">​</a></h2>
<p>Optional decentralization of the keeper via EigenLayer: <strong><a class="" href="https://docs.orcarail.com/blog/phase-6-eigenlayer-keeper-avs/">Phase 6</a></strong>.</p>
<hr>
<p>Reference docs: <strong><a class="" href="https://docs.orcarail.com/docs/non-custodial/phases/phase-5-bitcoin/">Phase 5 status</a></strong> · <strong><a class="" href="https://docs.orcarail.com/docs/non-custodial/bitcoin-considerations/">Bitcoin considerations</a></strong> · <strong><a class="" href="https://docs.orcarail.com/docs/non-custodial/security-model/">Security model</a></strong></p>]]></content:encoded>
            <category>Payments</category>
            <category>Multi-Chain</category>
            <category>Web3</category>
        </item>
        <item>
            <title><![CDATA[Phase 6: Decentralized Scheduler and EigenLayer]]></title>
            <link>https://docs.orcarail.com/blog/phase-6-eigenlayer-keeper-avs/</link>
            <guid>https://docs.orcarail.com/blog/phase-6-eigenlayer-keeper-avs/</guid>
            <pubDate>Mon, 20 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Phase 6 of the OrcaRail non-custodial roadmap. What EigenLayer restaking actually buys you, where an AVS makes sense for a payment system, and why we are keeping it optional.]]></description>
            <content:encoded><![CDATA[<p><strong>April 20, 2026</strong> — Phase 6 is the phase where we explicitly do <strong>not</strong> build something, unless a real requirement forces it. EigenLayer restaking is powerful, but it is not a general-purpose home for "a payment system." This post explains what an AVS would give us, when it is worth building, and why Chainlink + NestJS is sufficient for most of what we need.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="tldr">TL;DR<a href="https://docs.orcarail.com/blog/phase-6-eigenlayer-keeper-avs/#tldr" class="hash-link" aria-label="Direct link to TL;DR" title="Direct link to TL;DR" translate="no">​</a></h2>
<ul>
<li class="">EigenLayer is <strong>restaking + slashable attestations from ETH operators</strong>. It is not a chain, not a contract platform, not a custody solution.</li>
<li class="">Two places it could help OrcaRail: a <strong>Keeper AVS</strong> for decentralized <code>charge()</code> and a <strong>Bridge Attestation AVS</strong> for cross-chain settlement.</li>
<li class="">We will <strong>defer the build</strong> unless a customer or compliance requirement demands decentralized liveness beyond what Chainlink Automation + NestJS gives us.</li>
<li class="">If we ever build one, we start with Othentic / Eigen Foundation templates, not from scratch.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-eigenlayer-actually-gives-you">What EigenLayer actually gives you<a href="https://docs.orcarail.com/blog/phase-6-eigenlayer-keeper-avs/#what-eigenlayer-actually-gives-you" class="hash-link" aria-label="Direct link to What EigenLayer actually gives you" title="Direct link to What EigenLayer actually gives you" translate="no">​</a></h2>
<p>An <strong>AVS</strong> (Actively Validated Service) is a network of operators running an off-chain computation whose attestations are posted on-chain with cryptoeconomic security from restaked ETH. Misbehavior is slashable.</p>
<p>What that gets you:</p>
<ul>
<li class=""><strong>Decentralized liveness</strong>: a task runs even if one party (OrcaRail) goes offline.</li>
<li class=""><strong>Slashable correctness</strong>: a bad attestation loses the operator stake.</li>
<li class=""><strong>ETH-economic security</strong>: you inherit a slice of Ethereum's validator stake instead of bootstrapping your own token.</li>
</ul>
<p>What it does <strong>not</strong> get you:</p>
<ul>
<li class="">A smart contract platform. Contracts still deploy on Ethereum / L2s.</li>
<li class="">Custody. EigenLayer does not hold USDC for you.</li>
<li class="">Solana or Bitcoin native support. Cross-chain bridges exist, and they add complexity and trust.</li>
<li class="">A general scheduler. You still define the off-chain task and on-chain verification yourself.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="where-an-avs-could-help-orcarail">Where an AVS could help OrcaRail<a href="https://docs.orcarail.com/blog/phase-6-eigenlayer-keeper-avs/#where-an-avs-could-help-orcarail" class="hash-link" aria-label="Direct link to Where an AVS could help OrcaRail" title="Direct link to Where an AVS could help OrcaRail" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-keeper-avs-decentralized-charge">1. Keeper AVS (decentralized <code>charge()</code>)<a href="https://docs.orcarail.com/blog/phase-6-eigenlayer-keeper-avs/#1-keeper-avs-decentralized-charge" class="hash-link" aria-label="Direct link to 1-keeper-avs-decentralized-charge" title="Direct link to 1-keeper-avs-decentralized-charge" translate="no">​</a></h3>
<p>Today and through <a class="" href="https://docs.orcarail.com/blog/phase-3-multi-evm-and-keeper-redundancy/">Phase 3</a>, the keeper picture is:</p>
<ul>
<li class="">NestJS scheduler (primary)</li>
<li class="">Chainlink Automation or Gelato (fallback)</li>
</ul>
<p>That gives us two-way redundancy. A Keeper AVS would give us <strong>N-way</strong> redundancy with slashable liveness: operators attest "these IDs were due and I called <code>charge</code>," and missing a due charge is a slashable offense.</p>
<p>When it is worth it:</p>
<ul>
<li class="">When we have a customer whose contract forbids any single-party reliance on our infrastructure.</li>
<li class="">When regulatory compliance explicitly asks for it (rare today).</li>
</ul>
<p>When it is not worth it:</p>
<ul>
<li class="">When the marginal reliability over Chainlink is small and the engineering cost is months.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-bridge-attestation-avs-relay-replacement">2. Bridge attestation AVS (Relay replacement)<a href="https://docs.orcarail.com/blog/phase-6-eigenlayer-keeper-avs/#2-bridge-attestation-avs-relay-replacement" class="hash-link" aria-label="Direct link to 2. Bridge attestation AVS (Relay replacement)" title="Direct link to 2. Bridge attestation AVS (Relay replacement)" translate="no">​</a></h3>
<p>Our cross-chain settlement today uses Relay (see <a href="https://github.com/orcarail/orcarail/tree/main/api/src/withdrawals/services/bridge" target="_blank" rel="noopener noreferrer" class="">api/src/withdrawals/services/bridge</a>). Relay is trusted. An AVS could attest "funds observed on chain X, release on chain Y" with slashable security — similar shape to Hyperlane ISM-with-EigenLayer or Omni.</p>
<p>When it is worth it:</p>
<ul>
<li class="">When Relay introduces terms or performance we cannot accept.</li>
<li class="">When the platform processes enough cross-chain volume that bridge risk is material.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-fraud--compliance-oracle">3. Fraud / compliance oracle<a href="https://docs.orcarail.com/blog/phase-6-eigenlayer-keeper-avs/#3-fraud--compliance-oracle" class="hash-link" aria-label="Direct link to 3. Fraud / compliance oracle" title="Direct link to 3. Fraud / compliance oracle" translate="no">​</a></h3>
<p>"Is this wallet sanctioned?" "Was the merchandise delivered?" — policy checks currently in the NestJS webhook path could become AVS attestations. Niche use; only useful if the platform takes on an explicit on-chain policy responsibility.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-we-defer-the-build">Why we defer the build<a href="https://docs.orcarail.com/blog/phase-6-eigenlayer-keeper-avs/#why-we-defer-the-build" class="hash-link" aria-label="Direct link to Why we defer the build" title="Direct link to Why we defer the build" translate="no">​</a></h2>
<ul>
<li class="">Chainlink Automation + NestJS is ~0 engineering cost. A Keeper AVS is months.</li>
<li class="">Building an AVS means running operators (or coordinating others to) and maintaining slashing conditions. That is an operational burden comparable to running our own blockchain node fleet.</li>
<li class="">The security improvement is only meaningful once we already have two-way redundancy. We do not yet (we get it in Phase 3). Compounded: only after Phase 3 is stable does a Keeper AVS become a candidate.</li>
<li class="">Even conservatively scoped, an AVS will have its own custody considerations (restaked ETH, operator compensation economics).</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="decision-log">Decision log<a href="https://docs.orcarail.com/blog/phase-6-eigenlayer-keeper-avs/#decision-log" class="hash-link" aria-label="Direct link to Decision log" title="Direct link to Decision log" translate="no">​</a></h2>
<p>We will keep a public decision log at <a class="" href="https://docs.orcarail.com/docs/non-custodial/eigenlayer-evaluation/">/docs/non-custodial/eigenlayer-evaluation</a> with the current recommendation and any triggers that would flip it. Today's recommendation: <strong>defer</strong>.</p>
<p>Triggers that would re-open the discussion:</p>
<ol>
<li class="">A sales conversation explicitly blocked by "single-party keeper" risk.</li>
<li class="">A regulatory framework that names AVS-backed liveness as an acceptable control.</li>
<li class="">Chainlink Automation pricing or availability degrading meaningfully on our most-used chains.</li>
<li class="">A partnership where we could reuse someone else's keeper AVS at near-zero ops cost.</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="if-we-do-build-it">If we do build it<a href="https://docs.orcarail.com/blog/phase-6-eigenlayer-keeper-avs/#if-we-do-build-it" class="hash-link" aria-label="Direct link to If we do build it" title="Direct link to If we do build it" translate="no">​</a></h2>
<ul>
<li class=""><strong>Start from a template</strong>. Othentic and Eigen Foundation publish templates for task-attestation AVSes. We will not hand-roll slashing.</li>
<li class=""><strong>Keep the on-chain entry point unchanged</strong>. <code>SubscriptionHub.charge(ids[])</code> stays public and permissionless. The AVS just becomes one more caller alongside NestJS and Chainlink.</li>
<li class=""><strong>Don't introduce new tokens or staking mechanics</strong> for our own volume. Operators are paid in ETH out of the platform gas budget; no OrcaRail token.</li>
<li class=""><strong>Audit it</strong>. Even a template-based AVS needs an audit.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="status-checklist">Status checklist<a href="https://docs.orcarail.com/blog/phase-6-eigenlayer-keeper-avs/#status-checklist" class="hash-link" aria-label="Direct link to Status checklist" title="Direct link to Status checklist" translate="no">​</a></h2>
<ul class="contains-task-list containsTaskList_mC6p">
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Decision log page live</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Quarterly review of triggers</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->POC sandbox (not production) if a trigger fires</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-is-next">What is next<a href="https://docs.orcarail.com/blog/phase-6-eigenlayer-keeper-avs/#what-is-next" class="hash-link" aria-label="Direct link to What is next" title="Direct link to What is next" translate="no">​</a></h2>
<p>The final phase deletes the custody code paths that Phases 1 to 5 replaced: <strong><a class="" href="https://docs.orcarail.com/blog/phase-7-retiring-custody/">Phase 7</a></strong>.</p>
<hr>
<p>Reference docs: <strong><a class="" href="https://docs.orcarail.com/docs/non-custodial/phases/phase-6-decentralized-keepers/">Phase 6 status</a></strong> · <strong><a class="" href="https://docs.orcarail.com/docs/non-custodial/eigenlayer-evaluation/">EigenLayer evaluation</a></strong> · <strong><a class="" href="https://docs.orcarail.com/docs/non-custodial/keeper-strategy/">Keeper strategy</a></strong></p>]]></content:encoded>
            <category>Payments</category>
            <category>Web3</category>
            <category>Multi-Chain</category>
        </item>
        <item>
            <title><![CDATA[Phase 7: Retiring the Custody Infrastructure]]></title>
            <link>https://docs.orcarail.com/blog/phase-7-retiring-custody/</link>
            <guid>https://docs.orcarail.com/blog/phase-7-retiring-custody/</guid>
            <pubDate>Mon, 20 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Phase 7 of the OrcaRail non-custodial roadmap. Deleting the hd_wallet_seed table, the WALLET_ENCRYPTION_KEY, and the EVM/Solana sweep paths, and updating TOS and compliance posture.]]></description>
            <content:encoded><![CDATA[<p><strong>April 20, 2026</strong> — Phase 7 is the cleanup. By the time we get here, EVM and Solana volumes are on contract receivers and <code>SubscriptionHub</code>, Bitcoin is on 2-of-2 multisig, and every new payment link avoids the legacy sweep path. This phase removes the legacy code and the legacy secrets.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="tldr">TL;DR<a href="https://docs.orcarail.com/blog/phase-7-retiring-custody/#tldr" class="hash-link" aria-label="Direct link to TL;DR" title="Direct link to TL;DR" translate="no">​</a></h2>
<ul>
<li class="">Drop <code>hd_wallet_seed</code>, the <code>WALLET_ENCRYPTION_KEY</code> config, and the derivation logic for flagged chains.</li>
<li class="">Delete EVM/SOL paths in <code>api/src/withdrawals/</code>: <code>SmartAccountWalletService.drainSmartAccountWallet</code>, <code>solana-withdrawal-transfer.service.ts</code>, related spec files.</li>
<li class="">Keep the BTC path (reduced to <a class="" href="https://docs.orcarail.com/blog/phase-5-bitcoin-reduced-custody/">Phase 5</a>'s 2-of-2 model).</li>
<li class="">Update TOS, privacy policy, and SOC2 controls to reflect a materially smaller custody surface.</li>
<li class="">Publish a postmortem summarizing what we learned.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-this-phase-changes">What this phase changes<a href="https://docs.orcarail.com/blog/phase-7-retiring-custody/#what-this-phase-changes" class="hash-link" aria-label="Direct link to What this phase changes" title="Direct link to What this phase changes" translate="no">​</a></h2>
<p>Before this phase lands, the codebase has two of everything — the old sweep path and the new contract path — behind feature flags. After this phase, the new path is the only path on EVM and Solana.</p>
<div class="wrapper_vprU"><button type="button" class="expandBtn_RmxB" aria-label="Show diagram fullscreen" title="Fullscreen"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7" stroke-linecap="round" stroke-linejoin="round"></path></svg></button></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-we-delete">What we delete<a href="https://docs.orcarail.com/blog/phase-7-retiring-custody/#what-we-delete" class="hash-link" aria-label="Direct link to What we delete" title="Direct link to What we delete" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="database">Database<a href="https://docs.orcarail.com/blog/phase-7-retiring-custody/#database" class="hash-link" aria-label="Direct link to Database" title="Direct link to Database" translate="no">​</a></h3>
<ul>
<li class=""><code>hd_wallet_seed</code> table and its TypeORM entity at <a href="https://github.com/orcarail/orcarail/tree/main/api/src/payments/infrastructure/persistence/relational/entities" target="_blank" rel="noopener noreferrer" class="">api/src/payments/infrastructure/persistence/relational/entities/hd-wallet-seed.entity.ts</a>.</li>
<li class=""><code>wallet_address.derivationPath</code> column is retained for historical lookups but becomes nullable; no new rows write it for EVM/SOL.</li>
<li class="">A migration archives the encrypted seed rows to cold storage for seven years (regulatory retention), then drops the table.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="code">Code<a href="https://docs.orcarail.com/blog/phase-7-retiring-custody/#code" class="hash-link" aria-label="Direct link to Code" title="Direct link to Code" translate="no">​</a></h3>
<p>In <a href="https://github.com/orcarail/orcarail/tree/main/api/src/payments/wallet.service.ts" target="_blank" rel="noopener noreferrer" class="">api/src/payments/wallet.service.ts</a>:</p>
<ul>
<li class="">Delete <code>encryptSeed</code>, <code>decryptSeed</code>, <code>getOrCreateHDWallet</code>, <code>generateAddressForNetwork</code> (EVM + SOL branches), <code>getNextAvailableIndex</code>, and the <code>@account-kit/wallet-client</code> dynamic import.</li>
<li class=""><code>getOrCreateAddressForPaymentLink</code> becomes a thin wrapper over <code>factory.computeAddress</code> for EVM and <code>findProgramAddressSync</code> for Solana.</li>
</ul>
<p>In <a href="https://github.com/orcarail/orcarail/tree/main/api/src/withdrawals/services/smart-account-wallet.service.ts" target="_blank" rel="noopener noreferrer" class="">api/src/withdrawals/services/smart-account-wallet.service.ts</a>:</p>
<ul>
<li class="">Delete <code>drainSmartAccountWallet</code>, <code>transferFromSmartAccount</code>, <code>batchTransferFromSmartAccount</code>, <code>getSmartAccountClientForDepositWallet</code>, and <code>derivePrivateKey</code>.</li>
<li class="">The module stays (it still has a small footprint for BTC-related helpers and for reading balances).</li>
</ul>
<p>Other deletions:</p>
<ul>
<li class=""><a href="https://github.com/orcarail/orcarail/tree/main/api/src/withdrawals/services/solana-withdrawal-transfer.service.ts" target="_blank" rel="noopener noreferrer" class="">api/src/withdrawals/services/solana-withdrawal-transfer.service.ts</a></li>
<li class="">Corresponding <code>.spec.ts</code> files and fixtures.</li>
<li class="">The <code>subscription-auto-charge.processor.ts</code> custodial branch (the <code>SubscriptionHub.charge</code> branch is what remains).</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="config">Config<a href="https://docs.orcarail.com/blog/phase-7-retiring-custody/#config" class="hash-link" aria-label="Direct link to Config" title="Direct link to Config" translate="no">​</a></h3>
<ul>
<li class=""><code>WALLET_ENCRYPTION_KEY</code> — dropped from <code>.env</code>, deployment secrets, and docs.</li>
<li class="">Any Alchemy Account Kit signer material in config (API keys for <code>@account-kit/*</code> remain if still used for paymaster).</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-stays">What stays<a href="https://docs.orcarail.com/blog/phase-7-retiring-custody/#what-stays" class="hash-link" aria-label="Direct link to What stays" title="Direct link to What stays" translate="no">​</a></h2>
<ul>
<li class=""><strong>BTC hot wallet</strong> — reduced to the 2-of-2 multisig model from <a class="" href="https://docs.orcarail.com/blog/phase-5-bitcoin-reduced-custody/">Phase 5</a>. No EVM/SOL HD seeds remain.</li>
<li class=""><strong>Alchemy paymaster policy</strong> — used by the keeper to sponsor <code>charge()</code> where applicable.</li>
<li class=""><strong>Relay bridge executors</strong> — still orchestrate cross-chain settlement; callers are keeper EOAs, not custodial signers.</li>
<li class=""><strong>All webhooks, emails, invoicing, dashboard, analytics</strong> — unchanged.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="legal-and-compliance-updates">Legal and compliance updates<a href="https://docs.orcarail.com/blog/phase-7-retiring-custody/#legal-and-compliance-updates" class="hash-link" aria-label="Direct link to Legal and compliance updates" title="Direct link to Legal and compliance updates" translate="no">​</a></h2>
<ul>
<li class=""><strong>Terms of Service</strong>: "OrcaRail does not custody EVM or Solana funds during payment settlement" becomes a factual statement, not aspirational copy.</li>
<li class=""><strong>Privacy policy</strong>: remove references to stored seed material.</li>
<li class=""><strong>SOC2 scope</strong>: custody controls shrink; audit findings map to the new smaller surface.</li>
<li class=""><strong>Money transmitter posture</strong>: re-review with counsel. Fewer custody touchpoints simplify the analysis in several jurisdictions.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="postmortem">Postmortem<a href="https://docs.orcarail.com/blog/phase-7-retiring-custody/#postmortem" class="hash-link" aria-label="Direct link to Postmortem" title="Direct link to Postmortem" translate="no">​</a></h2>
<p>A companion post will summarize what we learned across Phases 0 to 7 — what took longer than expected, what went smoother, what the real engineering cost of non-custody was, and how merchants reacted. Expected cadence: one post within 30 days of Phase 7 shipping.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="deprecations-none-new">Deprecations (none new)<a href="https://docs.orcarail.com/blog/phase-7-retiring-custody/#deprecations-none-new" class="hash-link" aria-label="Direct link to Deprecations (none new)" title="Direct link to Deprecations (none new)" translate="no">​</a></h2>
<p>This phase is itself the deprecation. Every <code>useOnChainReceiver</code>-flagged path becomes default-on; the flag is deleted.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="migration-plan">Migration plan<a href="https://docs.orcarail.com/blog/phase-7-retiring-custody/#migration-plan" class="hash-link" aria-label="Direct link to Migration plan" title="Direct link to Migration plan" translate="no">​</a></h2>
<p>By the time Phase 7 runs, every new payment and subscription for 12+ months has been non-custodial. The migration is about long-tail legacy links:</p>
<ul>
<li class=""><strong>Legacy open payment links</strong> past expiry → settle any residual dust via a one-time script, then stop.</li>
<li class=""><strong>Legacy subscriptions</strong> that never migrated → email notice 30 days before shutdown, offer one-click migration in dashboard, suspend auto-charge if no migration.</li>
<li class=""><strong>Residual balances on legacy deposit addresses</strong> → sweep with the old drain path one last time, to merchant withdrawal addresses, then retire the keys.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="risks-and-mitigations">Risks and mitigations<a href="https://docs.orcarail.com/blog/phase-7-retiring-custody/#risks-and-mitigations" class="hash-link" aria-label="Direct link to Risks and mitigations" title="Direct link to Risks and mitigations" translate="no">​</a></h2>
<ul>
<li class=""><strong>Residual dust on old addresses</strong>. Mitigation: final-sweep script run before decommission; any unrecoverable dust published in a public report.</li>
<li class=""><strong>Legal risk from deleting too early</strong>. Mitigation: 7-year archival of encrypted seed rows (never decryptable without the encryption key, which is destroyed in ceremony); auditors can still verify historical state.</li>
<li class=""><strong>Someone depends on an undocumented API shape</strong>. Mitigation: 90-day public deprecation notice; API changelog entry; targeted outreach to top merchants.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="status-checklist">Status checklist<a href="https://docs.orcarail.com/blog/phase-7-retiring-custody/#status-checklist" class="hash-link" aria-label="Direct link to Status checklist" title="Direct link to Status checklist" translate="no">​</a></h2>
<ul class="contains-task-list containsTaskList_mC6p">
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->All EVM + SOL merchants on non-custodial flow for at least 90 days</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Residual legacy subscriptions zeroed</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Final-sweep script completed</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Migration completed for <code>hd_wallet_seed</code> to cold archive</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Code deletions merged</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->TOS + privacy policy updated and shipped</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Postmortem post published</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-end-of-the-roadmap">The end of the roadmap<a href="https://docs.orcarail.com/blog/phase-7-retiring-custody/#the-end-of-the-roadmap" class="hash-link" aria-label="Direct link to The end of the roadmap" title="Direct link to The end of the roadmap" translate="no">​</a></h2>
<p>After Phase 7, the custody posture is:</p>
<ul>
<li class=""><strong>EVM, Solana</strong>: non-custodial. OrcaRail holds zero seed material.</li>
<li class=""><strong>Bitcoin</strong>: reduced custody via 2-of-2 multisig with merchant signer.</li>
<li class=""><strong>In-flight moment</strong>: eliminated on EVM/SOL; reduced to a multisig refund path on BTC.</li>
</ul>
<p>That is what we set out to do in the <a class="" href="https://docs.orcarail.com/blog/non-custodial-roadmap/">Non-Custodial Roadmap</a>.</p>
<hr>
<p>Reference docs: <strong><a class="" href="https://docs.orcarail.com/docs/non-custodial/phases/phase-7-retire-custody/">Phase 7 status</a></strong> · <strong><a class="" href="https://docs.orcarail.com/docs/non-custodial/security-model/">Security model</a></strong> · <strong><a class="" href="https://docs.orcarail.com/docs/non-custodial/roadmap/">Roadmap</a></strong></p>]]></content:encoded>
            <category>Payments</category>
            <category>Web3</category>
            <category>Multi-Chain</category>
            <category>Announcement</category>
        </item>
        <item>
            <title><![CDATA[The Protocol Debate: Five Visions for a Fully Non-Custodial OrcaRail]]></title>
            <link>https://docs.orcarail.com/blog/protocol-debate-non-custodial-futures/</link>
            <guid>https://docs.orcarail.com/blog/protocol-debate-non-custodial-futures/</guid>
            <pubDate>Mon, 20 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[A moderated debate between five designs for turning OrcaRail into a fully non-custodial protocol — smart contracts plus API, pure on-chain Uniswap-style, an L3 appchain, an intents-and-solvers network, and a standards-first reference implementation.]]></description>
            <content:encoded><![CDATA[<p><strong>April 20, 2026</strong> — The <a class="" href="https://docs.orcarail.com/blog/non-custodial-roadmap/">non-custodial roadmap</a> we published last week describes one path: smart contracts on each chain, an OrcaRail-run keeper, an OrcaRail-run indexer, and an OrcaRail-run API. It removes custody but keeps us in the middle of almost everything else.</p>
<p>Several readers — rightly — asked: if the goal is to become a <strong>protocol</strong>, why stop at removing custody? What would the rail look like if OrcaRail could go dark tomorrow and payments kept flowing?</p>
<p>This post is a debate. Five positions argue for five different architectures. A moderator pokes at each. Nobody wins outright, but by the end we are clearer about which trade-offs we are actually making.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-fully-non-custodial-protocol-means-precisely">What "fully non-custodial protocol" means, precisely<a href="https://docs.orcarail.com/blog/protocol-debate-non-custodial-futures/#what-fully-non-custodial-protocol-means-precisely" class="hash-link" aria-label="Direct link to What &quot;fully non-custodial protocol&quot; means, precisely" title="Direct link to What &quot;fully non-custodial protocol&quot; means, precisely" translate="no">​</a></h2>
<p>Before the debate starts, we need a shared definition. A system is a <strong>fully non-custodial protocol</strong> if <strong>all</strong> of these hold:</p>
<ol>
<li class=""><strong>Custody</strong>: no party holds user funds in transit, not even for a block.</li>
<li class=""><strong>Liveness</strong>: no single party is required for a legitimate payment or subscription charge to happen.</li>
<li class=""><strong>Censorship-resistance</strong>: no single party can deny a well-formed, paid transaction.</li>
<li class=""><strong>Upgrade / change control</strong>: upgrades require multi-party consent, not a single company's deploy.</li>
<li class=""><strong>Transparency</strong>: the rules a user is trusting are fully readable on-chain or under verifiable hash.</li>
</ol>
<p>The current plan clears (1). It partially clears (3), (4), (5). It does <strong>not</strong> clear (2) — OrcaRail's keeper and API are still required for the happy path to fire reliably. The debate below is about whether to push the remaining four bars all the way, and at what cost.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-positions">The positions<a href="https://docs.orcarail.com/blog/protocol-debate-non-custodial-futures/#the-positions" class="hash-link" aria-label="Direct link to The positions" title="Direct link to The positions" translate="no">​</a></h2>
<p>Five architects walk in. Let's hear them.</p>
<ul>
<li class=""><strong>Pragmatist</strong> — Smart contracts + OrcaRail API (current roadmap).</li>
<li class=""><strong>Maximalist</strong> — Pure on-chain protocol + decentralized frontend (the "Uniswap model").</li>
<li class=""><strong>Sovereign</strong> — OrcaRail as an L3 / appchain with payment-specific precompiles.</li>
<li class=""><strong>Intents Believer</strong> — Payers express intents; a permissionless solver network settles them.</li>
<li class=""><strong>Standards Advocate</strong> — An open EIP for payment links and subscriptions; anyone implements.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="round-1--the-opening-statements">Round 1 — The opening statements<a href="https://docs.orcarail.com/blog/protocol-debate-non-custodial-futures/#round-1--the-opening-statements" class="hash-link" aria-label="Direct link to Round 1 — The opening statements" title="Direct link to Round 1 — The opening statements" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="pragmatist-ship-something-real-then-decentralize-the-painful-parts">Pragmatist: "Ship something real, then decentralize the painful parts."<a href="https://docs.orcarail.com/blog/protocol-debate-non-custodial-futures/#pragmatist-ship-something-real-then-decentralize-the-painful-parts" class="hash-link" aria-label="Direct link to Pragmatist: &quot;Ship something real, then decentralize the painful parts.&quot;" title="Direct link to Pragmatist: &quot;Ship something real, then decentralize the painful parts.&quot;" translate="no">​</a></h3>
<p>The roadmap already removes the hard problem (custody). Keepers can be anyone — our NestJS scheduler is one caller among several; Chainlink and Gelato can be registered tomorrow. The indexer is public: anyone can subscribe to the same <code>Paid</code> and <code>Charged</code> events and rebuild state. The "OrcaRail API" is <strong>not the settlement layer</strong>, it is a convenience layer on top of public contracts. Merchants who want the fully-protocol path can already skip us and call the factory directly.</p>
<p><strong>Claim</strong>: we are 80% protocol. The remaining 20% is tooling (wallets, dashboards, email), not trust. Tooling should stay iterable.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="maximalist-no-api-events-contracts-subgraph-thats-it">Maximalist: "No API. Events, contracts, subgraph. That's it."<a href="https://docs.orcarail.com/blog/protocol-debate-non-custodial-futures/#maximalist-no-api-events-contracts-subgraph-thats-it" class="hash-link" aria-label="Direct link to Maximalist: &quot;No API. Events, contracts, subgraph. That's it.&quot;" title="Direct link to Maximalist: &quot;No API. Events, contracts, subgraph. That's it.&quot;" translate="no">​</a></h3>
<p>Uniswap exists. 1inch exists. They are accessed via the frontends their companies host, but any of those frontends could go dark and the protocol would keep working. That is what "protocol" means.</p>
<p>For OrcaRail, that looks like:</p>
<ul>
<li class="">Factories, hubs, splitters on every EVM/Solana chain.</li>
<li class="">A <strong>canonical subgraph</strong> (or Solana indexer) anyone can query.</li>
<li class="">A <strong>decentralized frontend</strong> pinned to IPFS/Arweave, resolved via ENS (<code>orcarail.eth</code>). The merchant dashboard and pay app are static bundles; every release is content-addressed.</li>
<li class=""><strong>No OrcaRail REST API in the critical path.</strong> The SDK calls the subgraph. Webhooks are derived from on-chain events by indexer-as-a-service (Alchemy, QuickNode, self-hosted).</li>
</ul>
<p><strong>Claim</strong>: anything that requires an <code>api.orcarail.com</code> for a payment to work is a partial protocol.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="sovereign-make-payments-a-precompile-on-our-own-chain">Sovereign: "Make payments a precompile on our own chain."<a href="https://docs.orcarail.com/blog/protocol-debate-non-custodial-futures/#sovereign-make-payments-a-precompile-on-our-own-chain" class="hash-link" aria-label="Direct link to Sovereign: &quot;Make payments a precompile on our own chain.&quot;" title="Direct link to Sovereign: &quot;Make payments a precompile on our own chain.&quot;" translate="no">​</a></h3>
<p>Payments are latency-sensitive and repetitive. We pay the same gas for the same split every time. Why are we renting L1/L2 security for a use case that can be specialized?</p>
<p>Launch <strong>OrcaRail Chain</strong> as an OP Stack rollup (or a Cosmos appchain, or an Arbitrum Orbit chain). Then:</p>
<ul>
<li class="">Payment-link semantics are a <strong>precompile</strong>, not an 80-line Solidity contract. Fees go from cents to ~zero.</li>
<li class="">Keeper logic is baked into block production: the sequencer fires <code>charge()</code> calls as part of the block, slashable by the chain's own security.</li>
<li class="">Bridging to "real" chains (Ethereum, Arbitrum, Solana) uses the existing canonical bridge + Relay; OrcaRail Chain is the coordination layer, not the value layer.</li>
<li class="">Subscriptions become first-class — "subscription" is a transaction type, like "transfer" on Bitcoin.</li>
</ul>
<p><strong>Claim</strong>: the cheapest way to make a protocol work reliably at scale is to not share a block space with random NFT mints.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="intents-believer-payers-express-intent-solvers-compete-to-settle">Intents Believer: "Payers express intent. Solvers compete to settle."<a href="https://docs.orcarail.com/blog/protocol-debate-non-custodial-futures/#intents-believer-payers-express-intent-solvers-compete-to-settle" class="hash-link" aria-label="Direct link to Intents Believer: &quot;Payers express intent. Solvers compete to settle.&quot;" title="Direct link to Intents Believer: &quot;Payers express intent. Solvers compete to settle.&quot;" translate="no">​</a></h3>
<p>The payer says: "I want to pay merchant X $50 in USDC from any of my wallets, within the next hour, optimizing for fees." That's an <strong>intent</strong>, signed but not yet a transaction.</p>
<p>A permissionless <strong>solver network</strong> (CoW-style, SUAVE, Anoma, Across-style relayers) sees the intent, finds the cheapest route — including bridging, cross-chain, from whatever token the payer holds — and settles it. Solvers are paid a bounty embedded in the intent.</p>
<p>For subscriptions: the payer signs a recurring intent ("pull $20/month of USDC from my wallet to this merchant PDA, for 12 months, cancellable anytime"). Solvers compete to call <code>charge()</code> when due, earning a micro-fee. This is what Phase 6's "keeper AVS" becomes if you squint, but with a real market instead of a slashing scheme.</p>
<p><strong>Claim</strong>: keepers aren't really a reliability problem — they're a market-design problem. Build the market.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="standards-advocate-write-an-eip-everyone-wins-including-us">Standards Advocate: "Write an EIP. Everyone wins, including us."<a href="https://docs.orcarail.com/blog/protocol-debate-non-custodial-futures/#standards-advocate-write-an-eip-everyone-wins-including-us" class="hash-link" aria-label="Direct link to Standards Advocate: &quot;Write an EIP. Everyone wins, including us.&quot;" title="Direct link to Standards Advocate: &quot;Write an EIP. Everyone wins, including us.&quot;" translate="no">​</a></h3>
<p>OrcaRail's payment links and subscriptions are a generic primitive. Shopify, Coinbase Commerce, other hosted crypto checkout stacks, and two dozen startups are building the same thing. We should write an <strong>EIP for non-custodial payment links</strong> and a companion <strong>EIP for allowance-pull subscriptions</strong>, with a reference implementation.</p>
<p>Then:</p>
<ul>
<li class="">Any wallet can render a payment-link URL with a standard UI ("you are paying merchant X, $50, USDC, non-custodial").</li>
<li class="">Any indexer (The Graph, Goldsky, Envio) supports the standard events out of the box.</li>
<li class="">Any processor — including a future OrcaRail competitor — can host the same protocol.</li>
<li class="">OrcaRail's product becomes <strong>the best implementation</strong> of an open standard, not a locked-in stack.</li>
</ul>
<p><strong>Claim</strong>: the biggest moat in payments is trust in the <em>primitive</em>, not in one company's stack. Make the primitive public.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="round-2--the-moderator-cross-examines">Round 2 — The moderator cross-examines<a href="https://docs.orcarail.com/blog/protocol-debate-non-custodial-futures/#round-2--the-moderator-cross-examines" class="hash-link" aria-label="Direct link to Round 2 — The moderator cross-examines" title="Direct link to Round 2 — The moderator cross-examines" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="to-pragmatist-be-honest--if-orcarail-stops-paying-the-paymaster-bill-does-alices-subscription-still-charge">To Pragmatist: "Be honest — if OrcaRail stops paying the paymaster bill, does Alice's subscription still charge?"<a href="https://docs.orcarail.com/blog/protocol-debate-non-custodial-futures/#to-pragmatist-be-honest--if-orcarail-stops-paying-the-paymaster-bill-does-alices-subscription-still-charge" class="hash-link" aria-label="Direct link to To Pragmatist: &quot;Be honest — if OrcaRail stops paying the paymaster bill, does Alice's subscription still charge?&quot;" title="Direct link to To Pragmatist: &quot;Be honest — if OrcaRail stops paying the paymaster bill, does Alice's subscription still charge?&quot;" translate="no">​</a></h3>
<p><strong>Pragmatist</strong>: In the current roadmap, after Phase 3, yes — Chainlink Automation keeps firing <code>charge()</code>. The paymaster bill is for keeper gas; Chainlink uses LINK for the same job. But <strong>merchants who need OrcaRail's dashboard to reconcile</strong> would degrade: emails, retries, human-readable failure codes all live in our API. The contracts keep running; the <strong>product</strong> doesn't.</p>
<p><strong>Moderator</strong>: Is "contracts keep running but humans can't tell" really liveness?</p>
<p><strong>Pragmatist</strong>: It's <em>settlement</em> liveness without <em>UX</em> liveness. That's a real distinction — we should own it, not hide it. It's also cheap to fix over time: publish our email templates, open-source the indexer, let someone else host the dashboard. We don't have to do all of that in Phase 1.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="to-maximalist-ens-pinned-ipfs-dashboards-are-great-until-a-regulator-sends-us-a-letter-about-a-merchant">To Maximalist: "ENS-pinned IPFS dashboards are great until a regulator sends us a letter about a merchant."<a href="https://docs.orcarail.com/blog/protocol-debate-non-custodial-futures/#to-maximalist-ens-pinned-ipfs-dashboards-are-great-until-a-regulator-sends-us-a-letter-about-a-merchant" class="hash-link" aria-label="Direct link to To Maximalist: &quot;ENS-pinned IPFS dashboards are great until a regulator sends us a letter about a merchant.&quot;" title="Direct link to To Maximalist: &quot;ENS-pinned IPFS dashboards are great until a regulator sends us a letter about a merchant.&quot;" translate="no">​</a></h3>
<p><strong>Maximalist</strong>: Then OrcaRail stops hosting that merchant on our dashboard. The protocol keeps serving them via another frontend, or their own. That is feature, not bug — compare TradFi, where "the processor froze my account" is a recurring drama that has no protocol-level remedy.</p>
<p><strong>Moderator</strong>: Merchants who get off-boarded from a card processor usually also get off-boarded from Visa's network. In payments, the rails and the processor are often the same censor.</p>
<p><strong>Maximalist</strong>: Correct, and that is exactly the problem a protocol solves. Visa cannot censor Ethereum. OrcaRail, on a protocol architecture, cannot censor merchants at the rail level — only at the frontend. Frontends are swappable; rails are not.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="to-sovereign-how-do-merchants-withdraw-to-usdc-on-ethereum-if-settlement-lives-on-orcarail-chain">To Sovereign: "How do merchants withdraw to USDC on Ethereum if settlement lives on OrcaRail Chain?"<a href="https://docs.orcarail.com/blog/protocol-debate-non-custodial-futures/#to-sovereign-how-do-merchants-withdraw-to-usdc-on-ethereum-if-settlement-lives-on-orcarail-chain" class="hash-link" aria-label="Direct link to To Sovereign: &quot;How do merchants withdraw to USDC on Ethereum if settlement lives on OrcaRail Chain?&quot;" title="Direct link to To Sovereign: &quot;How do merchants withdraw to USDC on Ethereum if settlement lives on OrcaRail Chain?&quot;" translate="no">​</a></h3>
<p><strong>Sovereign</strong>: Same way anyone leaves any L2: the canonical bridge. We'd integrate Relay natively so the exit is immediate for stables. The daily withdrawal throughput is tiny compared to the in-chain volume.</p>
<p><strong>Moderator</strong>: You're asking us to run a chain. Every chain that matters has failure modes — sequencer halts, state-root posting lag, bridge exits. Those fail <em>publicly</em> and <em>visibly</em>. "OrcaRail sequencer offline for 3 hours, payments halted globally" is a worse headline than "OrcaRail API had a 3-hour outage."</p>
<p><strong>Sovereign</strong>: It's a worse headline only until you decentralize the sequencer. OP Stack's fault-proofs and shared sequencing (Espresso, Astria) make this progressively less of a single-party risk. You're right that we're not starting there. But you're also right that we shouldn't run a chain alone; we'd launch via a partner rollup-as-a-service with a credible path to shared sequencing.</p>
<p><strong>Moderator</strong>: That is a lot of dependencies.</p>
<p><strong>Sovereign</strong>: It is. The trade is: we stop paying gas forever, we stop fighting for mainnet blockspace, and we get to ship custom primitives. If payment volume is large enough to justify any of this, it's justified. If it's not, I'm wrong.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="to-intents-believer-solver-markets-have-an-mev-problem-who-protects-the-payer-from-a-solver-that-skims">To Intents Believer: "Solver markets have an MEV problem. Who protects the payer from a solver that skims?"<a href="https://docs.orcarail.com/blog/protocol-debate-non-custodial-futures/#to-intents-believer-solver-markets-have-an-mev-problem-who-protects-the-payer-from-a-solver-that-skims" class="hash-link" aria-label="Direct link to To Intents Believer: &quot;Solver markets have an MEV problem. Who protects the payer from a solver that skims?&quot;" title="Direct link to To Intents Believer: &quot;Solver markets have an MEV problem. Who protects the payer from a solver that skims?&quot;" translate="no">​</a></h3>
<p><strong>Intents Believer</strong>: The intent is signed with strict constraints. Amount paid cannot exceed what the payer authorized. What can vary is the <strong>route</strong> (which bridge, which DEX if a swap is needed) and the <strong>timing</strong>. A malicious solver cannot redirect funds; at worst, they can be slow. Competition drives that out.</p>
<p><strong>Moderator</strong>: Competition drives fees <em>low</em> on high-volume routes. What about the $5 USDC → USDC cross-chain micropayment nobody is paid enough to solve?</p>
<p><strong>Intents Believer</strong>: That's a real gap. The answer is <strong>fallback solvers</strong> — OrcaRail runs one at cost. The market handles the top 95%; we handle the long tail. Over time, cheaper chains and better bridges close the gap.</p>
<p><strong>Moderator</strong>: So you're also running a keeper, just calling it a solver.</p>
<p><strong>Intents Believer</strong>: A keeper that is <em>one of several</em>, competing on a public intent, with a fallback — yes. That is the difference between "OrcaRail's backend is the keeper" and "OrcaRail is a participant in an open market."</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="to-standards-advocate-eips-take-years-what-do-we-do-until-then">To Standards Advocate: "EIPs take years. What do we do until then?"<a href="https://docs.orcarail.com/blog/protocol-debate-non-custodial-futures/#to-standards-advocate-eips-take-years-what-do-we-do-until-then" class="hash-link" aria-label="Direct link to To Standards Advocate: &quot;EIPs take years. What do we do until then?&quot;" title="Direct link to To Standards Advocate: &quot;EIPs take years. What do we do until then?&quot;" translate="no">​</a></h3>
<p><strong>Standards Advocate</strong>: You ship the <strong>reference implementation</strong> first, using your current plan. Then you draft the EIP around what you shipped, not in advance. That's how ERC-4337, ERC-721, and ERC-20 got written. The current roadmap is compatible with this — the <code>SubscriptionHub</code> surface could be the ERC surface, with small naming adjustments.</p>
<p><strong>Moderator</strong>: Any risk in publishing your "moat" as a standard?</p>
<p><strong>Standards Advocate</strong>: The moat isn't the contract. The moat is <strong>integrations, SLAs, compliance work, dashboards, email deliverability, merchant trust</strong>. All things a competitor can't copy by reading an EIP. Open-sourcing the contract surface moves competition to the places where we are strong.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="round-3--where-each-position-actually-wins">Round 3 — Where each position actually wins<a href="https://docs.orcarail.com/blog/protocol-debate-non-custodial-futures/#round-3--where-each-position-actually-wins" class="hash-link" aria-label="Direct link to Round 3 — Where each position actually wins" title="Direct link to Round 3 — Where each position actually wins" translate="no">​</a></h2>
<p>After the cross-examination, each position is stronger in <em>specific</em> dimensions. Honest scorecard:</p>
<table><thead><tr><th>Dimension</th><th>Pragmatist</th><th>Maximalist</th><th>Sovereign</th><th>Intents</th><th>Standards</th></tr></thead><tbody><tr><td>Time to ship Phase 1</td><td>Fast</td><td>Slow</td><td>Very slow</td><td>Slow</td><td>Fast</td></tr><tr><td>Custody elimination</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr><tr><td>Liveness without OrcaRail</td><td>Partial</td><td>Strong</td><td>Medium</td><td>Strong</td><td>Strong</td></tr><tr><td>Censorship-resistance</td><td>Partial</td><td>Strong</td><td>Medium</td><td>Strong</td><td>Strong</td></tr><tr><td>Cross-chain UX</td><td>Good</td><td>Good</td><td>Weak</td><td>Best</td><td>Good</td></tr><tr><td>Regulatory clarity</td><td>Medium</td><td>Medium</td><td>Weak</td><td>Weak</td><td>High</td></tr><tr><td>Dependency on OrcaRail infra</td><td>High</td><td>Low</td><td>Very high (chain)</td><td>Low</td><td>Low</td></tr><tr><td>OrcaRail's differentiation</td><td>High</td><td>Low</td><td>High</td><td>Medium</td><td>High</td></tr><tr><td>Onboarding for non-crypto-native merchants</td><td>Best</td><td>Hardest</td><td>Medium</td><td>Medium</td><td>Medium</td></tr><tr><td>Engineering cost</td><td>Low</td><td>Medium</td><td>Very high</td><td>High</td><td>Medium</td></tr><tr><td>Existing user-visible breakage</td><td>None</td><td>Significant</td><td>Major</td><td>Medium</td><td>Small</td></tr></tbody></table>
<p>No row is dominant. Which is why this is a debate and not a rollout plan.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="round-4--moderators-synthesis">Round 4 — Moderator's synthesis<a href="https://docs.orcarail.com/blog/protocol-debate-non-custodial-futures/#round-4--moderators-synthesis" class="hash-link" aria-label="Direct link to Round 4 — Moderator's synthesis" title="Direct link to Round 4 — Moderator's synthesis" translate="no">​</a></h2>
<p>Here is how I would actually read the debate, as the person who has to pick.</p>
<p><strong>Pragmatist wins today</strong> because the product has to keep shipping and we do not have the luxury of pausing for an 18-month architecture rewrite. The current roadmap is a strictly-better-than-custodial version of what we run today, with compatible incremental improvements.</p>
<p><strong>Maximalist wins on principle</strong> and captures a real constraint: the day our API is the reason a merchant cannot get paid is the day we stop being a protocol. That is the pressure that should guide every Phase 1-7 engineering decision: publish the indexer, publish the subgraph, pin the dashboard to IPFS under ENS, document how to self-host. The Pragmatist roadmap <strong>makes this possible</strong>, it does not <strong>force it</strong>. We should force it.</p>
<p><strong>Sovereign wins if scale justifies it.</strong> Below some volume threshold, running a chain is overhead. Above it, renting Ethereum block space to split $3 six ways every time is absurd. We will know we've crossed that threshold when a dominant fraction of our volume is same-chain merchant-to-payer routes and gas optimization is measurable line-item savings. Not yet.</p>
<p><strong>Intents Believer wins on cross-chain.</strong> Payments are inherently multi-asset, multi-chain. An intent-based payer flow ("pay merchant X, I don't care how") is the best UX possible for a crypto payer. We should adopt intents <strong>at the payer-SDK layer</strong> before we adopt them at the settlement layer. That makes existing solvers (Across, deBridge, Relay) a natural fit without requiring us to build a new market.</p>
<p><strong>Standards Advocate wins everywhere Maximalist does, with less risk.</strong> Writing an EIP around what we ship in Phases 1 and 2 is <strong>free</strong>, helpful for the ecosystem, and does not slow us down. It also gives us a credible "we are building a rail, not a trap" story for merchants evaluating crypto rails for the first time.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-blended-answer">The blended answer<a href="https://docs.orcarail.com/blog/protocol-debate-non-custodial-futures/#the-blended-answer" class="hash-link" aria-label="Direct link to The blended answer" title="Direct link to The blended answer" translate="no">​</a></h2>
<p>The boring-but-correct synthesis: <strong>ship Pragmatist, enforce Maximalist, adopt Intents for payer UX, write an EIP along the way, keep Sovereign as a Phase 8+ option conditional on scale.</strong></p>
<p>Concretely, what that means as incremental commitments on top of the existing <a class="" href="https://docs.orcarail.com/docs/non-custodial/roadmap/">roadmap</a>:</p>
<ul>
<li class=""><strong>M1: Public subgraph from Phase 1</strong>. Every <code>Paid</code> and <code>Charged</code> event in a canonical subgraph anyone can query. Non-blocking for the API.</li>
<li class=""><strong>M2: IPFS-pinned pay app from Phase 2</strong>. Every release is content-addressed, <code>pay.orcarail.eth</code> resolvable via ENS.</li>
<li class=""><strong>M3: Self-host kit from Phase 3</strong>. Docker-compose + docs that let anyone run an OrcaRail-compatible dashboard from the same contracts.</li>
<li class=""><strong>M4: Intent SDK from Phase 3</strong>. <code>orcarail.pay(intent)</code> on the client routes through existing solver networks (Across/Relay) for cross-chain payments. OrcaRail-run solver fallback for the long tail.</li>
<li class=""><strong>M5: EIP draft from Phase 2</strong>. Co-author the payment-link EIP with another processor or a wallet team, using our <code>SubscriptionHub</code> as the basis.</li>
<li class=""><strong>M6: Sovereign evaluation quarterly</strong> alongside <a class="" href="https://docs.orcarail.com/docs/non-custodial/eigenlayer-evaluation/">EigenLayer evaluation</a>. Triggers: payments volume by chain, gas cost per payment as % of payment value, demand from merchants for sub-cent settlement.</li>
</ul>
<p>These five additions take the existing roadmap from "non-custodial" to "non-custodial, protocol-shaped, credibly neutral." They do not slow down Phases 1-7. They are tracked as separate living workstreams.</p>
<p>They are formalized as <strong>Track P</strong> in the <a class="" href="https://docs.orcarail.com/blog/orcarail-protocol-whitepaper/">protocol whitepaper</a>, which turns M1-M5 into phases P1-P5 and keeps M6 (own-chain) as an optional P6.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-we-are-explicitly-not-doing-yet">What we are explicitly not doing yet<a href="https://docs.orcarail.com/blog/protocol-debate-non-custodial-futures/#what-we-are-explicitly-not-doing-yet" class="hash-link" aria-label="Direct link to What we are explicitly not doing yet" title="Direct link to What we are explicitly not doing yet" translate="no">​</a></h2>
<ul>
<li class=""><strong>Own chain</strong>. Not in the next 18 months. Re-evaluate quarterly.</li>
<li class=""><strong>OrcaRail token at launch</strong>. No token now. A future governance token is <strong>reserved as an option</strong> for post-decentralization (see the <a class="" href="https://docs.orcarail.com/blog/orcarail-protocol-whitepaper/">protocol whitepaper</a> for the full stance). No presale, no allocation, no points.</li>
<li class=""><strong>Pure on-chain Maximalist path with no API at all</strong>. The product needs human-readable surfaces, and merchants need someone to call when things go wrong. We will <em>enable</em> API-free usage, not <em>require</em> it.</li>
<li class=""><strong>Our own solver network</strong>. Use existing ones. We may run a <strong>fallback solver at cost</strong> for the long-tail routes existing solvers ignore, but we will not bootstrap a new competing network.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="where-this-lands">Where this lands<a href="https://docs.orcarail.com/blog/protocol-debate-non-custodial-futures/#where-this-lands" class="hash-link" aria-label="Direct link to Where this lands" title="Direct link to Where this lands" translate="no">​</a></h2>
<p>This post is a <strong>companion</strong> to the <a class="" href="https://docs.orcarail.com/blog/non-custodial-roadmap/">non-custodial roadmap</a>, not a replacement. The roadmap still tracks Phases 0-7. This debate adds a sixth axis — <em>protocol-shape</em> — that every phase should be evaluated against.</p>
<p>If you were in the debate, send us your position. We will publish strong counter-arguments.</p>
<hr>
<p><strong>Related reading</strong></p>
<ul>
<li class=""><a class="" href="https://docs.orcarail.com/blog/non-custodial-roadmap/">The OrcaRail Non-Custodial Roadmap</a> — the canonical roadmap</li>
<li class=""><a class="" href="https://docs.orcarail.com/blog/why-allowance-pull-subscriptions/">Why allowance-pull beats escrow and session keys</a> — the subscription-model debate, in the same format</li>
<li class=""><a class="" href="https://docs.orcarail.com/docs/non-custodial/eigenlayer-evaluation/">EigenLayer evaluation</a> — companion decision log for decentralized keepers</li>
<li class=""><a class="" href="https://docs.orcarail.com/docs/non-custodial/architecture/">Architecture</a> — what the Pragmatist path actually builds</li>
</ul>]]></content:encoded>
            <category>Payments</category>
            <category>Web3</category>
            <category>Multi-Chain</category>
            <category>Stablecoins</category>
            <category>Subscriptions</category>
        </item>
        <item>
            <title><![CDATA[Why Allowance-Pull Beats Escrow and Session Keys]]></title>
            <link>https://docs.orcarail.com/blog/why-allowance-pull-subscriptions/</link>
            <guid>https://docs.orcarail.com/blog/why-allowance-pull-subscriptions/</guid>
            <pubDate>Mon, 20 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[The design conversation behind OrcaRail's non-custodial subscription model. Why ERC-20 approve + pull (and SPL delegate on Solana) wins over escrow deposits and session-key smart wallets for crypto subscriptions.]]></description>
            <content:encoded><![CDATA[<p><strong>April 20, 2026</strong> — Every crypto subscription product has to solve the same problem: how does a payer authorize future payments without giving up custody? There are three realistic answers. We picked <strong>allowance-pull</strong>, and this post explains why.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-three-models">The three models<a href="https://docs.orcarail.com/blog/why-allowance-pull-subscriptions/#the-three-models" class="hash-link" aria-label="Direct link to The three models" title="Direct link to The three models" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-allowance-pull-erc-20-approve--spl-delegate">1. Allowance-pull (ERC-20 approve + SPL delegate)<a href="https://docs.orcarail.com/blog/why-allowance-pull-subscriptions/#1-allowance-pull-erc-20-approve--spl-delegate" class="hash-link" aria-label="Direct link to 1. Allowance-pull (ERC-20 approve + SPL delegate)" title="Direct link to 1. Allowance-pull (ERC-20 approve + SPL delegate)" translate="no">​</a></h3>
<p>The payer signs <code>approve(spender, cap)</code> — once — on the token contract. Later, the spender (our <code>SubscriptionHub</code> or Solana program) calls <code>transferFrom</code> (EVM) or transfers with delegate authority (SOL) when a period is due. The payer keeps custody; the spender can pull up to <code>cap</code> over the subscription's life.</p>
<p>Cancellation: payer signs <code>approve(spender, 0)</code> or <code>Revoke</code>. From that point, no pull can succeed.</p>
<p>This is what <a class="" href="https://docs.orcarail.com/docs/subscriptions/auto-charge/">Auto-charge</a> already uses today. <a class="" href="https://docs.orcarail.com/blog/phase-2-allowance-pull-subscriptions/">Phase 2</a> moves the spender from a platform-controlled hot wallet to an on-chain contract, but the payer side does not change.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-escrow-deposit">2. Escrow deposit<a href="https://docs.orcarail.com/blog/why-allowance-pull-subscriptions/#2-escrow-deposit" class="hash-link" aria-label="Direct link to 2. Escrow deposit" title="Direct link to 2. Escrow deposit" translate="no">​</a></h3>
<p>The payer deposits N periods of funds into a per-subscription escrow contract. The contract releases to the merchant on schedule. Payer can withdraw the unused balance at any time (minus paid periods).</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-smart-wallet-with-session-keys">3. Smart-wallet with session keys<a href="https://docs.orcarail.com/blog/why-allowance-pull-subscriptions/#3-smart-wallet-with-session-keys" class="hash-link" aria-label="Direct link to 3. Smart-wallet with session keys" title="Direct link to 3. Smart-wallet with session keys" translate="no">​</a></h3>
<p>The payer uses an ERC-4337 smart wallet and grants a scoped session key to the subscription contract. The session key can only do things the scope allows (e.g. "transfer USDC up to X per 30 days to this address"). Payer revokes by removing the session key.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-scoring">The scoring<a href="https://docs.orcarail.com/blog/why-allowance-pull-subscriptions/#the-scoring" class="hash-link" aria-label="Direct link to The scoring" title="Direct link to The scoring" translate="no">​</a></h2>
<p>We evaluated all three on five axes:</p>
<table><thead><tr><th>Axis</th><th>Allowance-pull</th><th>Escrow</th><th>Session keys</th></tr></thead><tbody><tr><td>Custody during active sub</td><td>Payer</td><td>Escrow contract</td><td>Payer (via smart wallet)</td></tr><tr><td>Steps for payer to set up</td><td>1 signature</td><td>1 deposit (any gas)</td><td>1 onboarding to 4337 wallet</td></tr><tr><td>Payer wallet compatibility</td><td>All wallets</td><td>All wallets</td><td>4337 wallets only</td></tr><tr><td>Funds locked / working capital</td><td>None</td><td>N months locked</td><td>None</td></tr><tr><td>Cancel UX</td><td>Revoke approve</td><td>Withdraw + cancel</td><td>Remove session key</td></tr><tr><td>Keeper risk</td><td>Any caller</td><td>Any caller</td><td>Any caller</td></tr><tr><td>Merchant-side complexity</td><td>Minimal</td><td>Release accounting</td><td>4337 bundler setup</td></tr><tr><td>Works with MetaMask / Phantom</td><td>Yes</td><td>Yes</td><td>Not natively</td></tr><tr><td>Works with Ledger / hardware</td><td>Yes</td><td>Yes</td><td>Partial</td></tr><tr><td>Regulatory clarity</td><td>High</td><td>Lower (smells escrow)</td><td>High</td></tr></tbody></table>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-not-escrow">Why not escrow<a href="https://docs.orcarail.com/blog/why-allowance-pull-subscriptions/#why-not-escrow" class="hash-link" aria-label="Direct link to Why not escrow" title="Direct link to Why not escrow" translate="no">​</a></h3>
<p>Escrow has the best-sounding pitch ("payer funds are locked in a contract, not a company") but worst real-world UX:</p>
<ul>
<li class="">Payers do not like locking N months of funds. A $20/month subscription with a 12-month escrow means $240 locked. Ceiling on conversion rate.</li>
<li class="">Withdrawals become complicated: the contract must track paid vs unpaid periods, handle partial refunds, and prevent the merchant from reading future funds.</li>
<li class="">"Escrow that holds customer funds" has a regulatory smell in several jurisdictions that "allowance to a smart contract" does not.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-not-session-keys">Why not session keys<a href="https://docs.orcarail.com/blog/why-allowance-pull-subscriptions/#why-not-session-keys" class="hash-link" aria-label="Direct link to Why not session keys" title="Direct link to Why not session keys" translate="no">​</a></h3>
<p>Session keys on 4337 smart wallets are elegant. But they require the payer's wallet to be a smart wallet. Most payers in 2026 still use EOAs (MetaMask, Rabby, hardware wallets, Safe signers) and Solana payers use Phantom-style keypair wallets. Forcing 4337 onboarding for a subscription is a conversion killer.</p>
<p>There is a path where 4337 becomes the default payer wallet and session keys become trivial. We are not there yet.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-allowance-pull-wins-today">Why allowance-pull wins today<a href="https://docs.orcarail.com/blog/why-allowance-pull-subscriptions/#why-allowance-pull-wins-today" class="hash-link" aria-label="Direct link to Why allowance-pull wins today" title="Direct link to Why allowance-pull wins today" translate="no">​</a></h3>
<ul>
<li class=""><strong>Zero change to payer wallet</strong>. Every wallet that can sign an ERC-20 <code>approve</code> works, which is all of them.</li>
<li class=""><strong>Zero funds locked</strong>. Payer keeps custody; pull happens just-in-time.</li>
<li class=""><strong>Revoke is universal</strong>. <code>approve(0)</code> or <code>Revoke</code> is a primitive every wallet UI already surfaces.</li>
<li class=""><strong>Keeper is commodity</strong>. <code>SubscriptionHub.charge(id)</code> is public and permissionless. NestJS, Chainlink, Gelato, or an EigenLayer AVS (see <a class="" href="https://docs.orcarail.com/blog/phase-6-eigenlayer-keeper-avs/">Phase 6</a>) can all call it.</li>
<li class=""><strong>Regulatory story is simpler</strong>. The platform never holds funds in transit.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="known-limitations-and-how-we-mitigate-them">Known limitations and how we mitigate them<a href="https://docs.orcarail.com/blog/why-allowance-pull-subscriptions/#known-limitations-and-how-we-mitigate-them" class="hash-link" aria-label="Direct link to Known limitations and how we mitigate them" title="Direct link to Known limitations and how we mitigate them" translate="no">​</a></h2>
<p>Allowance-pull is not perfect. The honest drawbacks:</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-infinite-approvals">1. Infinite approvals<a href="https://docs.orcarail.com/blog/why-allowance-pull-subscriptions/#1-infinite-approvals" class="hash-link" aria-label="Direct link to 1. Infinite approvals" title="Direct link to 1. Infinite approvals" translate="no">​</a></h3>
<p>Wallets often default to infinite <code>approve</code> values. Malicious contracts with infinite allowances drain wallets. Our mitigation: UI explicitly asks for a <em>capped</em> approval (e.g. <code>12 × monthly_amount</code> for an annual sub), shows the dollar number, and offers "cancel anytime" copy. The contract enforces <code>cap</code> separately from the ERC-20 allowance.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-revoke-between-cycles">2. Revoke-between-cycles<a href="https://docs.orcarail.com/blog/why-allowance-pull-subscriptions/#2-revoke-between-cycles" class="hash-link" aria-label="Direct link to 2. Revoke-between-cycles" title="Direct link to 2. Revoke-between-cycles" translate="no">​</a></h3>
<p>A payer can revoke mid-subscription and the next charge will fail. Same failure mode as a saved card being canceled. Handled via existing webhook + email: <code>subscription-insufficient-allowance.hbs</code> and <code>subscription-past-due.hbs</code>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-stale-allowance-after-price-change">3. Stale allowance after price change<a href="https://docs.orcarail.com/blog/why-allowance-pull-subscriptions/#3-stale-allowance-after-price-change" class="hash-link" aria-label="Direct link to 3. Stale allowance after price change" title="Direct link to 3. Stale allowance after price change" translate="no">​</a></h3>
<p>If the merchant raises the price mid-subscription, the old <code>cap</code> may be too small. Handled by the <code>cap</code> invariant reverting the <code>charge()</code> and the merchant UI prompting for a re-approve.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-reorg-induced-double-charge">4. Reorg-induced double-charge<a href="https://docs.orcarail.com/blog/why-allowance-pull-subscriptions/#4-reorg-induced-double-charge" class="hash-link" aria-label="Direct link to 4. Reorg-induced double-charge" title="Direct link to 4. Reorg-induced double-charge" translate="no">​</a></h3>
<p>Bot-scraping a block reorg can replay <code>charge()</code>. Handled by monotonic <code>lastChargedAt</code> in <code>SubscriptionHub</code>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-changes-for-payers-today">What changes for payers today<a href="https://docs.orcarail.com/blog/why-allowance-pull-subscriptions/#what-changes-for-payers-today" class="hash-link" aria-label="Direct link to What changes for payers today" title="Direct link to What changes for payers today" translate="no">​</a></h2>
<p>Nothing. Today's <a class="" href="https://docs.orcarail.com/docs/subscriptions/auto-charge/">Auto-charge</a> flow already asks for <code>approve(spender, amount)</code> and <code>SPL Approve</code> — the same steps. <a class="" href="https://docs.orcarail.com/blog/phase-2-allowance-pull-subscriptions/">Phase 2</a> moves the spender to a non-custodial contract address. Your wallet sees the same permission screen.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-changes-for-merchants">What changes for merchants<a href="https://docs.orcarail.com/blog/why-allowance-pull-subscriptions/#what-changes-for-merchants" class="hash-link" aria-label="Direct link to What changes for merchants" title="Direct link to What changes for merchants" translate="no">​</a></h2>
<p>Nothing in the API response shape. The <code>approval_spender_address</code> field in the subscription's <code>auto_charge</code> object just points at the <code>SubscriptionHub</code> contract instead of an OrcaRail hot wallet. The webhooks fire at the same moments.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="summary">Summary<a href="https://docs.orcarail.com/blog/why-allowance-pull-subscriptions/#summary" class="hash-link" aria-label="Direct link to Summary" title="Direct link to Summary" translate="no">​</a></h2>
<table><thead><tr><th>Consideration</th><th>Winner</th></tr></thead><tbody><tr><td>Payer onboarding UX</td><td>Allowance-pull</td></tr><tr><td>Working capital</td><td>Allowance-pull / session keys</td></tr><tr><td>Wallet compatibility</td><td>Allowance-pull</td></tr><tr><td>Regulatory clarity</td><td>Allowance-pull / session keys</td></tr><tr><td>Keeper flexibility</td><td>All three</td></tr><tr><td>Contract simplicity</td><td>Allowance-pull</td></tr></tbody></table>
<p>Allowance-pull wins outright on wallet compatibility and working capital; it ties or wins on every other axis. That is why OrcaRail subscriptions are built on it.</p>
<hr>
<p>Related: <strong><a class="" href="https://docs.orcarail.com/blog/phase-2-allowance-pull-subscriptions/">Phase 2: Allowance-pull subscriptions</a></strong> · <strong><a class="" href="https://docs.orcarail.com/docs/subscriptions/auto-charge/">Auto-charge docs</a></strong> · <strong><a class="" href="https://docs.orcarail.com/docs/non-custodial/security-model/">Security model</a></strong></p>]]></content:encoded>
            <category>Subscriptions</category>
            <category>Payments</category>
            <category>Web3</category>
            <category>Stablecoins</category>
        </item>
        <item>
            <title><![CDATA[Subscriptions on OrcaRail: Auto-Charge and Multichain]]></title>
            <link>https://docs.orcarail.com/blog/subscriptions-autocharge-multichain/</link>
            <guid>https://docs.orcarail.com/blog/subscriptions-autocharge-multichain/</guid>
            <pubDate>Wed, 25 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[How OrcaRail handles recurring crypto subscriptions—payment links vs auto-charge, on-chain approvals and billing, and how multichain fits merchant networks, payer context, and withdrawals.]]></description>
            <content:encoded><![CDATA[<p><strong>March 25, 2026</strong> — OrcaRail supports <strong>recurring subscriptions</strong> in the same API-first model as one-off payments: you create a subscription, we track billing periods, and payers complete each cycle—either by <strong>opening a payment link</strong> or by <strong>auto-charge</strong>, where they authorize us to pull stablecoins each period after a one-time on-chain approval.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-subscriptions-on-orcarail">Why subscriptions on OrcaRail<a href="https://docs.orcarail.com/blog/subscriptions-autocharge-multichain/#why-subscriptions-on-orcarail" class="hash-link" aria-label="Direct link to Why subscriptions on OrcaRail" title="Direct link to Why subscriptions on OrcaRail" translate="no">​</a></h2>
<p>Subscriptions are for SaaS, memberships, retainers, and any product billed on a <strong>fixed interval</strong> (day, week, month, year) with optional trials, cycle limits, and cancellation rules. You use the same <a class="" href="https://docs.orcarail.com/docs/authentication/overview/">Payments Auth</a> as the rest of the platform, and you can react to lifecycle events with <a class="" href="https://docs.orcarail.com/docs/subscriptions/webhooks/">subscription webhooks</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="two-ways-to-collect-payment-links-vs-auto-charge">Two ways to collect: payment links vs auto-charge<a href="https://docs.orcarail.com/blog/subscriptions-autocharge-multichain/#two-ways-to-collect-payment-links-vs-auto-charge" class="hash-link" aria-label="Direct link to Two ways to collect: payment links vs auto-charge" title="Direct link to Two ways to collect: payment links vs auto-charge" translate="no">​</a></h2>
<ul>
<li class=""><strong><code>send_payment_link</code></strong> (default): Each billing cycle, the payer gets a <strong>payment link</strong> (email and/or hosted flow). They pay when they open the link—familiar for crypto checkout and easy to combine with Relay routes and wallet choice.</li>
<li class=""><strong><code>auto_charge</code></strong>: The payer <strong>pre-authorizes</strong> OrcaRail’s <strong>hot wallet</strong> to pull the period amount on each renewal. After setup, renewals do not require the payer to click a new link each time—as long as balance and authorization remain valid.</li>
</ul>
<p>Create and configure collection with <a class="" href="https://docs.orcarail.com/docs/subscriptions/create-subscription/"><code>POST /api/v1/subscriptions</code></a>; list, update, pause, and cancel with <a class="" href="https://docs.orcarail.com/docs/subscriptions/manage-subscriptions/">manage subscriptions</a>. Full request fields and examples live in those guides.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="auto-charge-how-we-handle-it">Auto-charge: how we handle it<a href="https://docs.orcarail.com/blog/subscriptions-autocharge-multichain/#auto-charge-how-we-handle-it" class="hash-link" aria-label="Direct link to Auto-charge: how we handle it" title="Direct link to Auto-charge: how we handle it" translate="no">​</a></h2>
<ol>
<li class=""><strong>Merchant</strong> creates a subscription with <code>collection_method: "auto_charge"</code> and the usual <code>amount</code>, <code>interval</code>, <code>token_id</code>, <code>network_id</code>, and payer contact fields.</li>
<li class=""><strong>Payer</strong> opens the subscription or first-cycle payment experience. They see the <strong>total approval scope</strong> (for example, the sum of upcoming charges you ask them to cover) and signs an on-chain authorization:<!-- -->
<ul>
<li class="">On <strong>EVM</strong> chains, that is a standard ERC-20 <strong><code>approve(spender, amount)</code></strong> to our hot wallet as spender.</li>
<li class="">On <strong>Solana</strong>, the analogous step is <strong>SPL token delegation</strong> of at least one period’s amount to our Solana hot wallet.</li>
</ul>
</li>
<li class=""><strong>Payer</strong> calls the public <strong><code>POST /api/v1/subscriptions/:id/approve-auto-charge</code></strong> endpoint with the allowance (or delegation) <strong>transaction hash</strong>, <strong><code>payer_wallet_address</code></strong>, <strong><code>payer_network_id</code></strong>, and <strong><code>payer_token_id</code></strong>. No merchant API key is required—the payer proves intent by having signed the chain transaction.</li>
<li class=""><strong>OrcaRail verifies on-chain</strong> that the allowance or delegation is <strong>at least one billing cycle</strong> for the expected hot wallet before marking auto-charge <strong>approved</strong>. Before each pull, we can re-check authorization so transient RPC issues are not confused with a revoked allowance.</li>
<li class=""><strong>Each billing cycle</strong>, the billing pipeline attempts the <strong>pull</strong> (EVM <code>transferFrom</code>-style flow from the payer to settlement; Solana uses the delegated balance). On success, the period advances; on repeated failure (e.g. insufficient balance or revoked approval), the subscription can move to <strong><code>past_due</code></strong> and the payer is notified—you can listen for webhooks such as <code>subscription.payment_link.payment_failed</code> or <code>subscription.past_due</code> as described in <a class="" href="https://docs.orcarail.com/docs/subscriptions/auto-charge/">Auto-charge</a> and <a class="" href="https://docs.orcarail.com/docs/subscriptions/webhooks/">webhooks</a>.</li>
</ol>
<p><strong>Revoke and fallback:</strong> If the payer revokes on-chain, later pulls fail. They can also complete <strong><code>POST .../revoke-auto-charge</code></strong> after revoking so we record the state and can switch collection to <strong><code>send_payment_link</code></strong>, with email guidance to manage the subscription and pay via links again. Details are in <a class="" href="https://docs.orcarail.com/docs/subscriptions/auto-charge/">Auto-charge</a> and <a class="" href="https://docs.orcarail.com/docs/subscriptions/manage-subscriptions/">Manage subscriptions</a>.</p>
<p><strong>Security and clarity:</strong> Only the wallet that completed approval is used for pulls; we align UX with clear totals and cycle counts so payers know what they authorized. For very long or open-ended plans, consider capping approved amounts and refreshing approval periodically, or staying on payment links—see <a class="" href="https://docs.orcarail.com/docs/subscriptions/auto-charge/">Auto-charge</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="multichain-how-it-fits-subscriptions">Multichain: how it fits subscriptions<a href="https://docs.orcarail.com/blog/subscriptions-autocharge-multichain/#multichain-how-it-fits-subscriptions" class="hash-link" aria-label="Direct link to Multichain: how it fits subscriptions" title="Direct link to Multichain: how it fits subscriptions" translate="no">​</a></h2>
<ul>
<li class=""><strong>Merchant anchor:</strong> Every subscription is created with a <strong><code>network_id</code></strong> and <strong><code>token_id</code></strong> that define how the subscription is priced and settled in API terms—the “home” network and asset for that plan.</li>
<li class=""><strong>Payer context for auto-charge:</strong> Auto-charge stores <strong><code>payer_network_id</code></strong> and <strong><code>payer_token_id</code></strong>—the network and token where the payer actually set allowance or delegation. That can differ from the subscription’s primary fields when payers fund from another supported chain or asset, consistent with how quotes and checkout resolve payer-side routes.</li>
<li class=""><strong>Relay-aligned coverage:</strong> Supported networks and currencies stay aligned with <strong><a href="https://relay.link/" target="_blank" rel="noopener noreferrer" class="">Relay</a></strong>; when Relay expands chains and tokens, our inventory follows. We summarized that model in <a class="" href="https://docs.orcarail.com/blog/supported-networks-currencies-relay/">Supported networks and currencies: powered by Relay</a>.</li>
<li class=""><strong>Where proceeds land:</strong> Merchants still configure <strong>withdrawal addresses per chain type</strong> (and can override per payment where supported). For the full picture of multichain withdrawals and multiple addresses per chain, see <a class="" href="https://docs.orcarail.com/blog/orcarail-multichain-withdrawals-relay/">OrcaRail is multichain: withdrawals and Relay alignment</a>.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="summary">Summary<a href="https://docs.orcarail.com/blog/subscriptions-autocharge-multichain/#summary" class="hash-link" aria-label="Direct link to Summary" title="Direct link to Summary" translate="no">​</a></h2>
<table><thead><tr><th>Topic</th><th>OrcaRail behavior</th></tr></thead><tbody><tr><td><strong>Collection</strong></td><td><code>send_payment_link</code> per cycle, or <code>auto_charge</code> with on-chain approval</td></tr><tr><td><strong>Auto-charge</strong></td><td>EVM ERC-20 approve or Solana SPL delegate → public approve API → on-chain verification → per-cycle pull, with <code>past_due</code> and webhooks on failure</td></tr><tr><td><strong>Revoke</strong></td><td>On-chain revoke + optional <code>revoke-auto-charge</code>; can fall back to payment links</td></tr><tr><td><strong>Multichain</strong></td><td>Subscription <code>network_id</code> / <code>token_id</code>; payer approval stores <code>payer_network_id</code> / <code>payer_token_id</code>; Relay-aligned networks; per-chain-type withdrawals</td></tr></tbody></table>
<p>Subscriptions on OrcaRail combine <strong>RESTful subscription resources</strong> with <strong>non-custodial payer authorization</strong> for auto-charge and <strong>multichain</strong> payouts—without giving up the hosted pay experience and APIs you already use for one-off payments.</p>
<hr>
<p><strong><a href="https://app.orcarail.com/" target="_blank" rel="noopener noreferrer" class="">OrcaRail App</a></strong> · <strong><a href="https://docs.orcarail.com/" target="_blank" rel="noopener noreferrer" class="">Docs</a></strong> · <strong><a href="https://relay.link/" target="_blank" rel="noopener noreferrer" class="">Relay</a></strong></p>]]></content:encoded>
            <category>Announcement</category>
            <category>Payments</category>
            <category>Multi-Chain</category>
            <category>Web3</category>
            <category>Stablecoins</category>
            <category>Subscriptions</category>
        </item>
        <item>
            <title><![CDATA[Supported Networks and Currencies: Powered by Relay, Updated Automatically]]></title>
            <link>https://docs.orcarail.com/blog/supported-networks-currencies-relay/</link>
            <guid>https://docs.orcarail.com/blog/supported-networks-currencies-relay/</guid>
            <pubDate>Sun, 15 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[OrcaRail's supported networks and currencies come from Relay Link and stay in sync automatically—when Relay adds chains or tokens, we get them too.]]></description>
            <content:encoded><![CDATA[<p><strong>March 15, 2026</strong> — OrcaRail uses <strong><a href="https://relay.link/" target="_blank" rel="noopener noreferrer" class="">Relay Link</a></strong> for payments and cross-chain bridging. As a result, we support the same <strong>networks and currencies</strong> that Relay supports—and they’re <strong>integrated automatically</strong>. No hardcoded list to maintain; when Relay adds or updates chains and tokens, our system picks them up.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="where-the-list-comes-from">Where the List Comes From<a href="https://docs.orcarail.com/blog/supported-networks-currencies-relay/#where-the-list-comes-from" class="hash-link" aria-label="Direct link to Where the List Comes From" title="Direct link to Where the List Comes From" translate="no">​</a></h2>
<p>We don’t maintain a separate, hand-curated list of supported networks and tokens. Instead:</p>
<ul>
<li class=""><strong>Networks</strong> are synced from Relay’s <strong>Chains API</strong> (<a href="https://api.relay.link/chains" target="_blank" rel="noopener noreferrer" class="">api.relay.link/chains</a> for mainnet, plus testnets). Our seed process builds network records from Relay’s chain data—including EVM, Bitcoin, and Solana chain types where Relay supports them.</li>
<li class=""><strong>Currencies and tokens</strong> are synced from Relay’s <strong>Currencies v2 API</strong> (<a href="https://docs.relay.link/references/api/get-currencies-v2" target="_blank" rel="noopener noreferrer" class="">get-currencies-v2</a>). Tokens are upserted per network, so each chain gets the right set of payables and bridgeable assets.</li>
</ul>
<p>When Relay adds a new chain or currency, our seed/update process brings it in. You get <strong>automatic alignment</strong> with Relay’s coverage without extra integration work on your side.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-support-means">What “Support” Means<a href="https://docs.orcarail.com/blog/supported-networks-currencies-relay/#what-support-means" class="hash-link" aria-label="Direct link to What “Support” Means" title="Direct link to What “Support” Means" translate="no">​</a></h2>
<p>Payments and (where applicable) bridging follow <strong>Relay’s supported routes</strong>. Relay currently supports <strong>69+ blockchain networks</strong> across:</p>
<ul>
<li class=""><strong>EVM</strong> chains (Ethereum, Base, Polygon, Arbitrum, Optimism, and many more)</li>
<li class=""><strong>Bitcoin</strong></li>
<li class=""><strong>Solana</strong> (SVM)</li>
<li class=""><strong>Tron</strong></li>
</ul>
<p>Per chain, token support can be <strong>"All"</strong> (tokens where Solver or DEX liquidity exists) or <strong>"Limited"</strong> (only tokens listed with <code>supportsBridging: true</code>). For the canonical picture of routes and token support, see Relay’s docs:</p>
<ul>
<li class=""><a href="https://docs.relay.link/references/api/api_resources/supported-routes" target="_blank" rel="noopener noreferrer" class="">Supported Tokens &amp; Routes</a> — how to check if a route is supported</li>
<li class=""><a href="https://docs.relay.link/references/api/api_resources/contract-addresses" target="_blank" rel="noopener noreferrer" class="">Contract Addresses</a> — solver and contract addresses per chain</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-to-see-what-orcarail-supports">How to See What OrcaRail Supports<a href="https://docs.orcarail.com/blog/supported-networks-currencies-relay/#how-to-see-what-orcarail-supports" class="hash-link" aria-label="Direct link to How to See What OrcaRail Supports" title="Direct link to How to See What OrcaRail Supports" translate="no">​</a></h2>
<p>Use our API to get the current set of networks and tokens available in OrcaRail:</p>
<ul>
<li class=""><strong>Networks:</strong> <code>GET /payments/networks</code> — list all supported networks (optionally filter with <code>?active=true</code>).</li>
<li class=""><strong>Tokens per network:</strong> <code>GET /payments/networks/:id/tokens</code> — list tokens for a given network (use the network <code>id</code> from the list above).</li>
<li class=""><strong>Fiat/display currencies:</strong> <code>GET /price/currencies</code> — list supported fiat currencies for pricing and quotes.</li>
</ul>
<p>Full details are in the <a class="" href="https://docs.orcarail.com/docs/api-reference/payments/#list-networks">Payments API – List Networks / List Tokens</a> and <a class="" href="https://docs.orcarail.com/docs/api-reference/price/#list-currencies">Price API – List Currencies</a> docs.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="summary">Summary<a href="https://docs.orcarail.com/blog/supported-networks-currencies-relay/#summary" class="hash-link" aria-label="Direct link to Summary" title="Direct link to Summary" translate="no">​</a></h2>
<table><thead><tr><th>Source</th><th>What we sync</th><th>How it’s updated</th></tr></thead><tbody><tr><td><strong>Networks</strong></td><td>From Relay Chains API</td><td>Via our network seed; new chains appear</td></tr><tr><td><strong>Currencies/tokens</strong></td><td>From Relay Currencies v2, per network</td><td>Via our token seed; new tokens appear</td></tr><tr><td><strong>Relay coverage</strong></td><td>69+ chains, EVM + Bitcoin + Solana + Tron</td><td>Relay is the source of truth; we follow</td></tr></tbody></table>
<p>Supported networks and currencies at OrcaRail are <strong>powered by Relay and updated automatically</strong>—one integration, many chains.</p>
<hr>
<p><strong><a href="https://app.orcarail.com/" target="_blank" rel="noopener noreferrer" class="">OrcaRail App</a></strong> · <strong><a href="https://docs.orcarail.com/" target="_blank" rel="noopener noreferrer" class="">Docs</a></strong> · <strong><a href="https://relay.link/" target="_blank" rel="noopener noreferrer" class="">Relay</a></strong></p>]]></content:encoded>
            <category>Announcement</category>
            <category>Multi-Chain</category>
            <category>Payments</category>
            <category>Crypto</category>
            <category>Web3</category>
        </item>
        <item>
            <title><![CDATA[OrcaRail is Multichain: Multiple Withdrawals per Chain and Relay Alignment]]></title>
            <link>https://docs.orcarail.com/blog/orcarail-multichain-withdrawals-relay/</link>
            <guid>https://docs.orcarail.com/blog/orcarail-multichain-withdrawals-relay/</guid>
            <pubDate>Thu, 05 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[OrcaRail is multichain with multiple withdrawal addresses per chain. We do not support Bitcoin or Solana yet; Relay supports Bitcoin and Solana, and so do we—through alignment and roadmap.]]></description>
            <content:encoded><![CDATA[<p><strong>March 5, 2026</strong> — OrcaRail is <strong>multichain by design</strong>. Here’s a clear picture of what we support today, how withdrawals work per chain, and how we line up with Relay on Bitcoin and Solana.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="multichain-not-every-chain-yet">Multichain, Not Every Chain (Yet)<a href="https://docs.orcarail.com/blog/orcarail-multichain-withdrawals-relay/#multichain-not-every-chain-yet" class="hash-link" aria-label="Direct link to Multichain, Not Every Chain (Yet)" title="Direct link to Multichain, Not Every Chain (Yet)" translate="no">​</a></h2>
<p>OrcaRail today is built for <strong>EVM-compatible chains</strong>. We do <strong>not</strong> support <strong>Bitcoin</strong> or <strong>Solana</strong> (or Solana-native tokens) as first-class chains in our payment and withdrawal flows. That keeps our integration surface focused and our APIs consistent while we scale.</p>
<p>If your stack is Ethereum, Base, Polygon, Arbitrum, Optimism, or other EVM L1s/L2s, you get one integration and one set of docs. No separate Bitcoin or Solana-specific flows—for now.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="multiple-withdrawal-addresses-per-chain-type">Multiple Withdrawal Addresses per Chain Type<a href="https://docs.orcarail.com/blog/orcarail-multichain-withdrawals-relay/#multiple-withdrawal-addresses-per-chain-type" class="hash-link" aria-label="Direct link to Multiple Withdrawal Addresses per Chain Type" title="Direct link to Multiple Withdrawal Addresses per Chain Type" translate="no">​</a></h2>
<p>Withdrawals are where “multichain” really pays off. You can configure <strong>multiple withdrawal addresses per chain type</strong> in OrcaRail.</p>
<ul>
<li class=""><strong>Per-chain control:</strong> Set a different default (or set of addresses) for Ethereum, Base, Polygon, etc., so funds land where you want on each network.</li>
<li class=""><strong>Per-payment override:</strong> When creating a payment intent, you can still pass a <code>withdrawal_address</code> to route that specific payment to a vendor or treasury on the right chain.</li>
<li class=""><strong>No single bottleneck:</strong> Run marketplaces, SaaS, or multi-entity setups without forcing everything through one chain or one address.</li>
</ul>
<p>So: multichain means multiple networks and <strong>multiple withdrawal destinations per chain</strong>, all configurable in the dashboard and via API.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="relay-supports-bitcoin-and-solanaand-so-do-we-on-the-roadmap">Relay Supports Bitcoin and Solana—And So Do We (On the Roadmap)<a href="https://docs.orcarail.com/blog/orcarail-multichain-withdrawals-relay/#relay-supports-bitcoin-and-solanaand-so-do-we-on-the-roadmap" class="hash-link" aria-label="Direct link to Relay Supports Bitcoin and Solana—And So Do We (On the Roadmap)" title="Direct link to Relay Supports Bitcoin and Solana—And So Do We (On the Roadmap)" translate="no">​</a></h2>
<p><strong><a href="https://relay.link/" target="_blank" rel="noopener noreferrer" class="">Relay</a></strong> supports <strong>Bitcoin</strong> and <strong>Solana</strong> (and their tokens) as part of its multichain coverage. OrcaRail is built to align with Relay’s model: one link, many chains.</p>
<p>We don’t support Bitcoin or Solana <em>today</em>, but our architecture and roadmap are built so that <strong>when we add them, it’s the same product</strong>: same APIs, same withdrawal model (multiple addresses per chain), same dashboard. “So we do” here means: we’re committed to the same multichain vision Relay embodies—Bitcoin and Solana included—and we’re expanding in that direction.</p>
<p>Until then, you get a stable, EVM-first multichain experience with full control over where funds go on each supported chain.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="summary">Summary<a href="https://docs.orcarail.com/blog/orcarail-multichain-withdrawals-relay/#summary" class="hash-link" aria-label="Direct link to Summary" title="Direct link to Summary" translate="no">​</a></h2>
<table><thead><tr><th>Area</th><th>OrcaRail today</th></tr></thead><tbody><tr><td><strong>Chains</strong></td><td>EVM-compatible (Ethereum, Base, Polygon, Arbitrum, Optimism, etc.)</td></tr><tr><td><strong>Bitcoin / Solana</strong></td><td>Not supported yet; aligned with Relay’s support on the roadmap</td></tr><tr><td><strong>Withdrawals</strong></td><td>Multiple withdrawal addresses per chain type; per-payment overrides supported</td></tr><tr><td><strong>Relay</strong></td><td>Same multichain philosophy; we expand chain support in line with Relay (Bitcoin, Solana, and beyond)</td></tr></tbody></table>
<p>Multichain at OrcaRail means: <strong>many EVM chains now, multiple withdrawal addresses per chain, and a path to Bitcoin and Solana in step with Relay.</strong></p>
<hr>
<p><strong><a href="https://app.orcarail.com/" target="_blank" rel="noopener noreferrer" class="">OrcaRail App</a></strong> · <strong><a href="https://docs.orcarail.com/" target="_blank" rel="noopener noreferrer" class="">Docs</a></strong> · <strong><a href="https://relay.link/" target="_blank" rel="noopener noreferrer" class="">Relay</a></strong></p>]]></content:encoded>
            <category>Announcement</category>
            <category>Multi-Chain</category>
            <category>Payments</category>
            <category>Crypto</category>
            <category>Web3</category>
        </item>
        <item>
            <title><![CDATA[OrcaRail is Born: Open, Multi-Chain Crypto Payment Rails]]></title>
            <link>https://docs.orcarail.com/blog/orcarail-born/</link>
            <guid>https://docs.orcarail.com/blog/orcarail-born/</guid>
            <pubDate>Thu, 01 Jan 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[OrcaRail is stablecoin-first and multichain, with transparent hosted pricing and a free self-hosted option (Open source soon). Accept crypto with predictable developer APIs and webhooks.]]></description>
            <content:encoded><![CDATA[<p><strong>January 1, 2026</strong> — Today, we are thrilled to announce the launch of <strong>OrcaRail</strong>.</p>
<p>Built with the assistance of AI and driven by a singular conviction: <strong>crypto payments must be open, transparent, and accessible across all chains.</strong> For too long, merchants and developers have been forced to choose between complex, unmaintained open-source tools or expensive, closed-ecosystem payment gateways that lock you in and charge high fees.</p>
<p>We built OrcaRail to break that paradigm. OrcaRail is a <strong>multichain payment platform</strong> that bridges Web2 business logic and Web3 settlement — <strong>hosted</strong> with simple per-transaction pricing and a generous free tier, or <strong>self-hosted</strong> <span class="or-badge">Open source soon</span> for full sovereignty.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-philosophy-a-transparent-public-good">The Philosophy: A Transparent Public Good<a href="https://docs.orcarail.com/blog/orcarail-born/#the-philosophy-a-transparent-public-good" class="hash-link" aria-label="Direct link to The Philosophy: A Transparent Public Good" title="Direct link to The Philosophy: A Transparent Public Good" translate="no">​</a></h2>
<p>We believe the financial rails of the internet should be a <strong>public good</strong>. <strong>Hosted OrcaRail</strong> is <strong>$0.10 per completed transaction</strong>, with <strong>your first 1,000 transactions free</strong>, so we can run reliable infrastructure while staying approachable for builders. <strong>Self-hosted OrcaRail</strong> <span class="or-badge">Open source soon</span> is <strong>free</strong>: deploy the open-source stack on your own hardware and pay only what your infrastructure costs.</p>
<p>Individual payment quotes can still include <strong>optional line items</strong> you control — for example a configurable <strong>support fee</strong> (percentage) and <strong>commission</strong> on API keys — plus <strong>bridge fees</strong> when routing across tokens or networks. Those are documented in our <a class="" href="https://docs.orcarail.com/docs/fees-and-limits/overview/">Fees &amp; limits</a> guides; they are separate from the hosted platform per-transaction price.</p>
<p>By staying <strong>open source</strong> and letting the community improve the product, we aim for <strong>non-custodial</strong>, high-performance rails with less counterparty risk than closed gateways — <strong>transparent by design</strong>.</p>
<p>If builders use hosted OrcaRail, self-host <span class="or-badge">Open source soon</span>, or mix both, together we can push back on opaque, high-fee payment silos. The future of commerce should be <strong>open and inspectable</strong>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-developer-experience-familiar-payment-primitives">The Developer Experience: Familiar payment primitives<a href="https://docs.orcarail.com/blog/orcarail-born/#the-developer-experience-familiar-payment-primitives" class="hash-link" aria-label="Direct link to The Developer Experience: Familiar payment primitives" title="Direct link to The Developer Experience: Familiar payment primitives" translate="no">​</a></h2>
<p>If you know how to integrate traditional Web2 payment processors, you already know how to use OrcaRail. We designed our architecture to give you predictable states, auditable flows, and retry-safe webhooks.</p>
<ul>
<li class=""><strong>Stablecoin-First:</strong> Price your goods in fiat (USD/EUR) and settle instantly in USDC or USDT. Eliminate volatility risk for your business while offering customers a seamless checkout experience.</li>
<li class=""><strong>Drop-In Checkout:</strong> Use our hosted payment links, embeddable widgets, and WalletConnect-ready interfaces to provide a clean UX.</li>
<li class=""><strong>Webhooks &amp; Idempotency:</strong> Keep your database perfectly synced with on-chain reality. Our system provides reliable events for <code>succeeded</code>, <code>processing</code>, and <code>canceled</code> states, complete with automated retries.</li>
<li class=""><strong>Node.js SDK &amp; REST API:</strong> Build once, connect everywhere.<!-- -->
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">npm install @orcarail/node</span><br></div></code></pre></div></div>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="multi-chain-and-multi-token-native">Multi-Chain and Multi-Token Native<a href="https://docs.orcarail.com/blog/orcarail-born/#multi-chain-and-multi-token-native" class="hash-link" aria-label="Direct link to Multi-Chain and Multi-Token Native" title="Direct link to Multi-Chain and Multi-Token Native" translate="no">​</a></h2>
<p>Web3 is fragmented, but your payment gateway shouldn't be. You get one integration that works seamlessly across networks.</p>
<p>Currently, OrcaRail supports <strong>EVM-compatible chains</strong> out of the box. But we are not stopping there—<strong>all Relay-supported chains are actively on the way.</strong> Our smart routing technology automatically helps select the fastest or lowest-fee network for each specific payment, ensuring your customers never abandon a cart due to exorbitant gas fees.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="dynamic-withdrawals-built-for-saas--marketplaces">Dynamic Withdrawals: Built for SaaS &amp; Marketplaces<a href="https://docs.orcarail.com/blog/orcarail-born/#dynamic-withdrawals-built-for-saas--marketplaces" class="hash-link" aria-label="Direct link to Dynamic Withdrawals: Built for SaaS &amp; Marketplaces" title="Direct link to Dynamic Withdrawals: Built for SaaS &amp; Marketplaces" translate="no">​</a></h2>
<p>Modern internet businesses are complex. Whether you are running a SaaS platform, a multi-vendor marketplace, or a creator economy app, routing funds manually is a nightmare. OrcaRail solves this natively:</p>
<ul>
<li class=""><strong>Per-Payment Routing:</strong> Pass a <code>withdrawal_address</code> when creating a payment intent. When the customer pays, funds are automatically routed directly to that specific vendor's wallet.</li>
<li class=""><strong>Default Fallbacks:</strong> For simpler setups, omit the address and let funds settle into your global account default.</li>
<li class=""><strong>Split Commissions:</strong> Running a platform? Set a commission percentage on your API keys. You earn your platform cut on every transaction, visibly calculated at checkout, and automatically sent to your own withdrawal address.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="whats-next-on-the-roadmap">What's Next on the Roadmap?<a href="https://docs.orcarail.com/blog/orcarail-born/#whats-next-on-the-roadmap" class="hash-link" aria-label="Direct link to What's Next on the Roadmap?" title="Direct link to What's Next on the Roadmap?" translate="no">​</a></h2>
<p>This is just day one. As we scale, our commitment to an open ecosystem only deepens:</p>
<ol>
<li class=""><strong>Expanding Chain Support:</strong> Rapidly rolling out support for non-EVM chains via Relay integration.</li>
<li class=""><strong>Self-Hosted</strong> <span class="or-badge">Open source soon</span>: Deploy the open-source stack on your own infrastructure for sovereignty and privacy — no per-transaction software fee from us.</li>
<li class=""><strong>Advanced Compliance Tools:</strong> Optional metadata fields and integrations for seamless KYT/KYC workflows.</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="try-it-feel-the-difference">Try It: Feel the Difference<a href="https://docs.orcarail.com/blog/orcarail-born/#try-it-feel-the-difference" class="hash-link" aria-label="Direct link to Try It: Feel the Difference" title="Direct link to Try It: Feel the Difference" translate="no">​</a></h2>
<p>We invite you to experience how easy crypto payments can be.</p>
<ul>
<li class="">🚀 <strong><a href="https://app.orcarail.com/" target="_blank" rel="noopener noreferrer" class="">Start Building</a></strong> — Create an account, generate an API key, and make your first payment link in under two minutes.</li>
<li class="">🎮 <strong><a href="https://demo.orcarail.com/" target="_blank" rel="noopener noreferrer" class="">Try the Live Demo</a></strong> — Test the complete end-to-end flow from intent creation to webhook confirmation.</li>
<li class="">📖 <strong><a href="https://docs.orcarail.com/" target="_blank" rel="noopener noreferrer" class="">Read the Documentation</a></strong> — Explore our API reference, SDK guides, and architectural overviews.</li>
</ul>
<p><em>The future should be open and transparent. Let's build it together.</em></p>
<hr>
<p><strong><a href="https://app.orcarail.com/" target="_blank" rel="noopener noreferrer" class="">OrcaRail App</a></strong> · <strong><a href="https://github.com/orcarail/orcarail" target="_blank" rel="noopener noreferrer" class="">GitHub</a></strong> · <strong><a href="https://docs.orcarail.com/blog/orcarail-born/#" class="">X/Twitter</a></strong></p>]]></content:encoded>
            <category>Announcement</category>
            <category>Crypto</category>
            <category>Payments</category>
            <category>Open Source</category>
            <category>Multi-Chain</category>
            <category>Stablecoins</category>
            <category>Web3</category>
        </item>
    </channel>
</rss>