Skip to main content
This is the long version. If you only want to integrate, How it works is enough. Read this when you need to explain the model to a CTO, an auditor, or a nervous finance lead.

The problem being solved

A crypto payment processor has to answer one question: where does the customer’s money go first? Almost every processor answers “into our wallet.” That single choice creates everything merchants dislike about them — withdrawal delays, account freezes, minimum payout thresholds, and the risk that the processor’s insolvency becomes your insolvency. We answer “into a contract that can only pay the merchant.” Everything else follows from that.

The pool

Each merchant gets a pool — a small, immutable contract, one per chain. There are two outflows, not three. Our fee and the partner fee — 0.75% and 0.25%, 1% together — come off the gross, and what’s left inside the pool is entirely yours: nothing is carved out of it for settlement. On a connect-rail order you net 99% — a €100 order pays you €99.00. A deposit-rail order nets the same 99% of what actually reaches the pool, but a small amount was already held back earlier, at the one-time address, to cover the network cost of getting it there — see the deposit rail below. The contract enforces one ceiling that can never be raised on an existing pool: 2.5% of gross for our fee plus the partner fee, combined. Today’s live setting is 1%; worst case, ever, is 2.5%. Fees. Three properties matter:

Immutable

No admin function, no upgrade path, no pause switch. The code that exists at deployment is the code that runs forever.

Ownerless

Nobody holds a privileged key. There is no owner to compromise, subpoena, or socially engineer.

Address-bound

Payout addresses are part of the contract’s creation code, so the contract’s address is derived from them. Different recipients means a different address.
That last one is subtle and it’s the foundation of everything. Because the address is computed from the payout configuration, anyone can independently check that a given address pays a given merchant — by recomputing it. There is no database to trust.

Counterfactual addresses

Addresses are computed before the contract exists, using CREATE2 — a deterministic function of the creation code and a salt. Two consequences you’ll notice:
  • Your pool has the same address on all seven EVM chains, because the creation code is byte-identical across them. One address to whitelist, one to reconcile against.
  • We can show a customer a deposit-rail payment address before the forwarder contract behind it exists. That one is deployed lazily, at the moment it’s needed — our keeper’s gas. Your pool itself is different: you deploy it yourself, one signature and one wallet-paid transaction per chain, the first time you activate that chain.

Two rails

Customers arrive in two different states, so there are two paths in.
The customer has a browser wallet. They sign up to two transactions: an ERC-20 approval for exactly the payment amount, then the deposit() call on your pool. Because the deposit consumes the whole allowance, the approval comes up on essentially every payment. If their wallet is on a different network, the checkout asks them to switch first.
  • Funds move straight into the pool
  • The customer pays their own network fee, for both transactions
  • Attribution is exact — the payment ID is in the transaction
  • Requires your pool to be deployed on that chain
Simple, cheap, and the best experience when it’s available.
The forwarder deserves a note: it is sweep-only in practice, and it is worth being precise about why. The contract does define a refund() function, but every forwarder is created with a refund window of zero length — the window is already closed in the block the deposit lands in, so refund() reverts from the first block and the sweep is the only path that can execute. That zero is not a per-invoice choice: it is fixed for every pool and constrained to zero in our database, so no configuration change and no tampered row can reopen it. Where the funds can go is fixed harder still — the destination pool is part of the forwarder’s creation code, and therefore part of its address, so no caller can redirect them anywhere else. It also stays callable after its first sweep, so a customer who pays the same address twice — which happens, when exchange withdrawals are slow or an address is re-pasted — can only ever send those funds to your pool. Detection is not automatic in every case. A second payment that lands while the order is still open is picked up and swept normally, including a late arrival on an expired order. One that lands after the order has already settled is not detected today: the money is safe at an address that can only pay you, but recovering it means contacting us for a manual sweep. Coming Automatic pickup of post-settlement arrivals is on the Roadmap.

Distribution

Funds accumulate. Nothing is split per payment, because splitting per payment means three transfers per order and network fees that dwarf small orders. distribute() reads the pool’s undistributed balance and credits each recipient; claim() then moves a credited share out. Neither needs you to act. Our keeper checks every pool every few minutes and, when a pool is due under your cadence, calls distribute() and then claim() to send your share to your payout address — signing and paying for both transactions itself. claim() always pays the credited recipient, never the caller, so whoever submits it, the money can only go to you.
distribute() is callable by anyone. Not just you, not just us. This is the property that makes the whole arrangement non-custodial — there is no party who can decline to release your funds, because releasing them doesn’t require anyone’s permission.
“Due” means one of two things: the balance has reached a threshold you set, or the maximum wait has elapsed — 24 hours by default. Both are yours to change per pool, in Pool → Settlement schedule: release on a timer, or release once the pool reaches an amount you name, with a maximum wait either way, entered in hours. So a pool nobody thinks about still settles at least daily. Shortening the wait is the lever that does something today, because the keeper signs and pays for settlement whichever way you set it. Coming A longer, monthly backstop — the setting that turns cadence into a real economic choice, once you pay for the settlement transaction yourself — is on the Roadmap. Claiming covers the schedule in full. One floor applies underneath all of it: distribute() reverts below 1.00 of the settlement token. Sub-floor dust isn’t distributed by us or by anyone else — it stays in the pool and rolls forward until later payments push the balance over the line.

Where the trust actually sits

The honest map: The database is display-only for money. If it were entirely rewritten by an attacker, the checkout would still refuse to send funds anywhere except your real address — because the browser checks the chain, not the database. How that check works.

What this costs you

Non-custody isn’t free. The honest trade-offs:
Deploying your pool is a wallet signature and a wallet-paid transaction from you — one per chain, once, when you activate it. Everything after that is different: our keeper signs and pays for your automatic settlement (distribute + claim) on its own gas, and that cost is not carved out of your share — you keep the full 99%. The one place gas genuinely comes off the top is the deposit rail, where the forwarder holds back a small, capped network fee before the funds ever reach your pool. A custodial processor absorbs comparable costs too — and charges you for them elsewhere, usually less visibly.
Nothing requires you to hold ETH, POL, BNB, AVAX, or TRX: the keeper settles and pays you on every chain without you touching a wallet. If you’d rather not wait for the next cycle, the Pool tab lets you release or withdraw yourself on EVM chains — that transaction you sign and pay for, in that chain’s native token. It’s an option, not a requirement.
We can’t refund on your behalf, because we never hold the money. Refunds.
A wrong payout address cannot be undone by support. This is why the payout attestation is signed from your own wallet and shown back to you for confirmation.

Next: the two ways to pay, in detail

When each is offered, and how to think about them.