Skip to main content

The split

distribute() reads the pool’s current token balance and credits each committed recipient to a pull-claim ledger.
The percentages are configurable per merchant at pool creation. Only the basis-point caps are hardcoded. Production currently runs two configurations: four pools at 100/0 where treasury takes the full 1%, and two at 75/25.

Merchants keep 98.505%, not 99%

MerchantPool.distribute() carves a 50 bps distributor reward from the merchant share (MerchantPool.sol:203), and every live pool carries distribution_incentive_bps = 50. The all-in merchant cost is 1.495%, not 1%.
The site previously advertised “keep 99% / 1% flat, all-in”. That was corrected in the 2026-07-28 production-readiness audit, and src/lib/__tests__/feeDisclosure.test.ts now re-implements the split and asserts the published copy against it. The reward exists to incentivise anyone to call distribute(). Whether to keep, cut, or re-frame it is an open pricing decision. Note that zeroing it removes the only channel by which the keeper currently recovers deposit-rail gas — see Gas reimbursement.

Permissionless, and why that matters

distribute() can be called by anyone. The settlement spec names this the regulatory linchpin: because we cannot withhold a merchant’s funds, we are not a custodian of them in any meaningful sense.
Any design that gives the platform the ability to block, delay, or condition a merchant’s payout destroys this property. It is not tradeable for operational convenience, fee recovery, or debt collection. A claim-gating proposal was evaluated in full and rejected on exactly this ground.
The practical consequence: mechanisms that recover money from a merchant must be bounded fees inside the split, never gates on the payout.

Pull, not push

distribute() credits a ledger; claim() moves the funds. Separating them means a blacklisted or reverting recipient cannot block the whole distribution for everyone else.

Who calls it

The merchant path is being consolidated into a single Claim button backed by a DistributeAndClaim helper, so one signature does both and the second pool call hits a warm implementation.

The backstop

claimable[token][treasury] is populated only by distribute(). If a merchant never claims, the platform’s 0.75% is never credited and there is nothing to auto-claim — a churned merchant means permanently unrealised revenue and funds sitting in a pool looking like a bug. “Auto-claim without auto-distribute” is not a valid design; the claim would revert. The eager five-minute cron is being retired in favour of a monthly conditional job that distributes a dormant pool and claims only the treasury’s share, never the merchant’s.
On production today, 11 of 14 real distributions came from the backstop. This path is load-bearing right now, not theoretical.
Two things change its design once merchants bear deposit-rail gas:
  • The backstop becomes the platform’s gas-debt collection path, not just revenue insurance. Its trigger should be economic — distribute when treasuryBps × undistributed + gas_owed > distribute_cost — rather than a pure value threshold.
  • The monthly window is the gas float. Stretching the cadence from five minutes to 31 days stretches the platform’s native-gas exposure by the same factor. The cadence decision and the treasury exposure are one decision, and they were originally written as two independent issues.

Cost of distributing

Measured 150,516 gas for distribute plus claim on Base. That is roughly $0.10 per month for 50 merchants — negligible on EVM. On TRON it is not negligible. A merchant’s distribute-plus-claim costs about **4.59inTRX,becausetheysignfromtheirownwalletandthereforeburnenergyat100sunratherthanusingtheplatformsrentedenergy.Itamortisesoverthebatchabout4.59** in TRX, because they sign from their own wallet and therefore burn energy at 100 sun rather than using the platform's rented energy. It amortises over the batch — about 0.23 per order at 20 orders — which makes claim cadence a genuine merchant-facing economic decision rather than a preference.