Products

ExchangeMove your own moneyPayoutsPay many at oncePaymentsGet paid by customersClaimsLet people take their share

Company

DevelopersPricing

Resources

BlogReleases and decisions, datedLearnExplainers and comparisons
Open app

31 Jul 2026·craft·Blog

Paying 500 wallets at once: what actually breaks

The failures that show up once a list gets long — and what a batch has to do about each one.

Paying one person on-chain is trivial. Paying five hundred is a different job, and the ways it goes wrong are rarely dramatic — no hacks, no exploits. It is a transaction that will not fit in a block, a spreadsheet with one bad address, or a batch that half-succeeded and left you reconciling by hand at midnight.

Here is what actually breaks, in the order you will meet it.

Your batch does not fit in a block

Every chain caps how much gas one block can hold, and a batch transfer is one transaction. Add recipients and you eventually cross the line: the transaction is valid, the payload is fine, and it simply cannot be mined.

recipients per one batch transaction Ethereum · Base Optimism · BNB Arbitrum Polygon HyperEVM 440 native 546 token 845 870 880 900 60 73 measured on real receipts — the block itself is the limit, not our policy
Recipients that fit into ONE batch transaction, by network and asset — measured on real receipts. Tokens fit more than the native coin.

The limit is not a round number, and it is different per chain and per asset. These are the ceilings we enforce, measured on real receipts rather than estimated:

NetworkNative coinToken (USDC, USDT…)
Ethereum, Base, Optimism, BNB440546
Arbitrum845870
Polygon880900
HyperEVM6073

Two things surprise people here. First, tokens are cheaper than the native coin — a token transfer inside a batch costs less gas than sending the chain's own currency, so the token ceiling is higher. Second, Arbitrum and Polygon are not "the same as Ethereum": their blocks hold far more, which is why a payroll run that has to be split into three transactions on Ethereum goes out as one there.

If a tool lets you paste 1,000 rows without saying a word about this, it is going to fail at signing time — after you have already done the work.

One bad address takes the whole batch with it

A batch is atomic by default: if any transfer inside it reverts, everything reverts. That is the right behaviour — you do not want 300 of 500 people paid and no record of which — but it means a single typo, a contract address that rejects transfers, or a recipient that is a contract without a payable fallback, kills the run.

The fix is not clever code, it is checking before you sign: validate every row, flag duplicates, and show the total in the same units the wallet will show. Anything you discover after signing costs gas.

The quiet one: partial cross-chain delivery

Same-chain batches are all-or-nothing. Cross-chain is not. When recipients sit on different chains, each destination is a separate leg with its own bridge, and legs finish at different times. A tool that reports "sent" the moment the source transaction confirms is telling you about the easy half.

What you want to see instead: per-leg status, and a guaranteed on-chain way to get the source amount back for any leg that cannot be filled. If you cannot answer "which three of my ninety recipients have not received anything yet" from the interface, you will answer it from a block explorer.

Fees you only notice next month

Two costs hide in batch payouts.

The first is gas you pay for other people's convenience: sending 500 separate transfers costs several times more gas than one batch, because every transaction pays a base cost of its own before it does any work.

The second is the exchange leg. If you hold USDC and pay in the chain's native coin — or the other way round — someone converts, and the spread on that conversion is often larger than every gas fee in the run. Ask what rate you are getting, not just what fee is charged.

Custody: the question nobody asks until it matters

Most "payout automation" quietly means one thing: you give a service the ability to move your money, and it does so on a schedule. That works right up until the day it doesn't — a compromised key, a frozen account, a company that changes its terms.

The alternative is not worse automation, it is a different split of duties: the tool prepares the batch, validates it, computes the totals, and then a human signs. You keep the keys; the machine does the boring part. Scheduling still works — the difference is that at the appointed hour you have a batch ready to sign, not a transfer that already happened without you.

We build Cherum this way on purpose. It is also why our own scheduler never signs anything: it prepares a draft and waits.

A short checklist before your next run

  • Know the recipient ceiling for your chain and asset, and split the list before you sign, not after.
  • Validate every address and flag duplicates; check the total against your own arithmetic.
  • For cross-chain runs, demand per-leg status and a guaranteed on-chain refund path for legs that fail.
  • Compare the conversion rate, not only the visible fee.
  • Decide consciously whether anyone other than you can move the money — and if the answer is yes, know what happens on their worst day.

None of this is exotic. It is the difference between a payout that is done when the interface says done, and one that you spend the evening reconciling.