Method: the x402 outside-payer filter
Version 2, as of 2026-10-13.
Licence: CC BY 4.0. Reuse it, adapt it, build on it, with attribution to Sato Hub (satohub.ai). The data this method produces, and the history behind it, are not covered by this licence.
This is the filter Sato Hub applies before it counts a payment to an x402 seller as a sign of demand from outside. It keeps a reading from counting as independent demand when the evidence shows too few payers other than us, or one payer carrying nearly all of the money. Its results are worded as measurements ("fewer than 3 outside payers"), never as a finding about anyone.
It answers one narrow question: of the USDC that arrived at this payout address through x402-style payments in the window, does the evidence of demand come from payers other than us, and from more than one of them? It does not answer whether a payment was needed, who stands behind a wallet, or whether the service was delivered.
1. Definitions
- Payout address (
payTo). The address a seller registers in an x402 discovery catalogue. One payout address on one chain is one merchant in this method. A host can front many merchants and one merchant can list on many hosts. - x402-style payment. A USDC
Transferto the payout address whose same transaction also carries a USDCAuthorizationUsed(authorizer, nonce)event where the authorizer equals the transfer'sfrom. That pair is what anexact-scheme x402 settlement looks like on chain (an EIP-3009transferWithAuthorizationsubmitted by a facilitator). Some gasless USDC sends that are not x402 use EIP-3009 as well, so the label is "x402-style payment", never "x402 revenue". - All USDC received. Every USDC
Transferto the payout address in the window. Context only. It is never used to rank. - Outside payer. A payer address that is not one of Sato Hub's own payer wallets. Our wallets are removed before any count is made, in both the all-USDC and the x402-style readings.
- Distinct outside payers. The number of different outside payer (authorizer) addresses among the x402-style payments.
- Top-payer share. The USDC from the single largest outside payer divided by all outside x402-style USDC, a number from 0 to 1. Null when there is nothing to divide.
- Machine-noise window. An x402-style window whose mean payment is below 0.02 USDC and whose distinct outside payers number 3 or fewer.
- Paid signal. The tier 1 condition, defined in section 2, step 6.
- Window. 7 days ending on the read date, every block of the window, on Base.
- Same-operator question. Whether two payer addresses are controlled by one party. This filter does not answer it. Section 3 lists what it can and cannot see.
2. Method
Reference code: the Sato Hub app (private). Names of the functions and constants that implement each step are given in backticks; the open description above and below is the method.
- Read every USDC transfer to the catalogued payout addresses on Base for the 7-day window, in full, no sampling (
readX402Settlement). The payout addresses come from the public discovery catalogues. A chain other than Base is not measured: every payment field there is unknown, not zero. - Join to the authorization. For each chunk of the window, read the USDC
AuthorizationUsedlogs for that chunk's payers and keep a transfer only when its transaction hash and payer match an authorization (authorizationKeys,applyX402Join). If any chunk's authorization read fails, the x402-style reading for the whole window is unknown. There are no partial counts. - Remove our own payers. Transfers, USDC and payer addresses belonging to Sato Hub's own wallets are subtracted before counting (
isOurPayer). A merchant that is ours is shown and labelled, and is held at the lowest tier whatever its numbers. - Count (
paymentsFor). From what is left: x402-style transfers, USDC, distinct outside payers, and the top-payer share (largest outside payer's USDC over total outside USDC, rounded to 4 places). - Classify the window. The machine-noise rule (
classifyNoise) and the second-source rule (classifyArtemis: at least 3 transfers from at least 2 distinct payers, mirroring a public filter of that name) are computed on the x402-style figures when they are known, on the all-USDC figures otherwise. The second is context; the first feeds step 6. - Decide the tier (
evidenceTier, which callshasPaidSignal):- Tier 1, paid signal: x402-style state is yes, at least 3 distinct outside payers (
MIN_PAYERS_FOR_PAID_SIGNAL), the window is not classed as machine noise, and the top payer carries at most 90% of the outside USDC (MAX_TOP_PAYER_SHARE). An unknown share does not pass. - Tier 2: at least one listed endpoint answered HTTP 402 with a parseable payment payload when we asked (
answersFor; see the method "Reading an x402 facilitator's matrix", step 8). - Tier 3: everything else; within it, unknown is listed before an explicit no.
- Tier 1, paid signal: x402-style state is yes, at least 3 distinct outside payers (
- Order inside a tier (
compareByEvidence): tier first; within tier 3, unknown before no; then the lower median listed price (a merchant with no price comes last); then the slug, for a stable order. Listing count, self-reported text and any payment to Sato Hub never enter the order.
evidenceTier and hasPaidSignal are the only functions in the app that decide a tier. The collector's dry run keeps a JavaScript copy of hasPaidSignal, used only to print a tier-1 figure; a test pins the copy to the original on every payments shape the collector emits.
Every published figure carries its window, the read date, the chain, and a sentence that says it is x402-style. Nothing is summed across chains or venues.
Holds on facilitator throughput
Daily facilitator transaction counts are a different measurement: transactions sent by known facilitator keys, an upper bound on settlements. Three kinds of hold can remove a reading from public pages. A hold names what it held and why; the stored count stays exact.
- Curated hold. A person checked the reading and recorded the reason and evidence. It holds every day on the named chains until the entry is removed.
- Unchecked surge hold (
unchecked_surge). The collector stamps a new or sudden reading of 50 or more transactions whose payee sample could not decide anything. It is held until a sample of at least 50 transactions is read, or a person has checked the day. - Payee-concentration hold (the automatic hold). On at least 50 sampled settlements, if the Wilson lower bound (z = 1.96,
wilsonLower) of the share paid to a single recipient is 0.9 or more, the operator-day is held. This is the only rule that uses the 50-settlement sample, the 0.9 bound and self-lifting: a later day whose sample is spread over recipients is shown again. It measures concentration, not intent.
A stored scan screen can also hold a reading in the same way as the automatic hold. None of these holds changes the outside-payer filter above, which applies to merchants, not to facilitator throughput.
3. Limits
- The filter checks the count and spread of payer addresses, not who controls them. Three addresses controlled by one party count as three. A seller paying itself from several wallets, or from wallets a third party funded, passes the count and share steps if the money is spread. Nothing in the current code traces where a payer's balance came from.
- The share of settlements funded by the operator is not measured. It would need a funding trace per payer. The facilitator scorecard shows it as unknown, with this reason.
- The 90% line came from one spot check; the other lines are conventions. The cap on a single payer's share was set after a check in which one wallet had sent 99.95% of a seller's USDC and four others $0.18 between them. A payer set just under the line passes. The 3-payer floor and the noise thresholds were not derived from data; they are fixed conventions.
- Our own-payer list is ours only. It removes our wallets. It does not remove anyone else's tests or loops.
- Base only, and only
exact-style EIP-3009 settlements. Solana carries most x402 transactions by count and is not read by this method. Schemes that do not emitAuthorizationUsedare invisible to it. - One window. 7 days is a snapshot. A seller can pass in one window and not the next.
- A failed read is unknown, not no. A tier-3 merchant with unknown payments has not been shown to have no demand.
- Payments are keyed by payout address, not by facilitator. The settlement transaction's sender is not in the log; naming the facilitator needs one extra lookup per settlement, which this method does not do. So outside-payer counts and top-payer shares cannot be assigned to a facilitator from this data.
- Not a statement about anyone. A merchant at tier 3 has not been shown to be anything; a merchant at tier 1 has shown a pattern of payments with these properties in this window. Neither is a grade of the service, its safety or its delivery. Delivery is a separate paid check, run apart from this method.
Cite as
Sato Hub, "Method: the x402 outside-payer filter", version 2, 2026-10-13, CC BY 4.0, satohub.ai.