Back to blog
Mar 22, 2026EngineeringArchitecture

Automating stablecoin payouts without taking custody

Most automated payment products take custody of user funds in order to schedule transfers. We didn't want to — and the contract design that makes that possible turned out to be the most interesting engineering problem we solved.

The ERC-20 allowance trick

Veltro's VeltroBatchPayout contract calls USDC.transferFrom(yourWallet, recipient, amount) for every recipient in a batch. The user pre-approves a generous USDC allowance to the contract once; every subsequent payout is a single transaction the user signs themselves. The contract never holds a balance.

OFAC screening must be synchronous

Our first architecture ran OFAC screening asynchronously after the batch was prepared. That was wrong. Screening must block the entire preparation step — no payout should be presentable for signature if any recipient hasn't been cleared. We moved screening into the preparation flow itself.

Zero custody simplifies the UX

Because Veltro never holds funds, the UX is: prepare → show summary → user signs → done. There's no "pending" state where funds are in transit through us. The only state that matters is "signed" or "not signed."

Single-transaction follow-ups

After the initial allowance, every subsequent batch payout is a single executeBatch call. The dashboard checks allowance() live and shows the user "Send payout (1 transaction)" — no extra signatures, no re-approval flow.