NoHoldPay
Blockchains

Ethereum and EVM Chains

Accept ETH, USDC, USDT, PYUSD, and EURC on Ethereum, Base, Polygon, and BNB Chain. Paste one EVM address and every invoice gets its own forwarder address that sweeps to your treasury.

All EVM chains share the same wallet type and address format. One wallet works across every EVM chain - and across mainnet and testnet.

Networks

NetworkChain keyEVM IDBlock timeMin invoice
EthereumETH1~12s$5.00
BaseBASE8453~2s$1.00
PolygonMATIC137~2s$1.00
BNB Smart ChainBSC56~0.45s$1.00
Ethereum Sepolia (testnet)ETH_SEPOLIA11155111~12s$0.10

Finality uses each chain's finalized block tag - roughly 13-15 minutes on Ethereum and Base, a few minutes on Polygon, and a few seconds on BNB Smart Chain.


Supported coins

ChainCoins
ETHETH (native), USDC, USDT, PYUSD
BASEETH (native), USDC, EURC
MATICPOL (native), USDC, USDT
BSCBNB (native), USDC, USDT
ETH_SEPOLIAETH (native), USDC

The dashboard shows live contract addresses for each coin when you start a payment, so you can verify the token before paying.


Wallet setup

Paste an EVM address - 0x + 40 hex, with valid EIP-55 checksum. The dashboard validates the checksum before saving.

Do not paste a custodial exchange deposit address. Exchange deposits are shared across many users - you can't prove which payment belongs to which invoice.

Compatible wallets:

Smart-contract wallets (Safe, Argent, Ambire) are supported. A preflight check rejects treasuries that can't receive ETH inline.

The same 0x address is valid on every EVM chain, and on their testnets, so you can reuse one address across the EVM chains you enable instead of a separate wallet per chain. See Choosing your wallets for how to keep your total wallet count low.

Open your wallet and copy the receive address.

In NoHoldPay, go to Wallets -> Add wallet and pick the chain.
Paste the address. The dashboard validates the EIP-55 checksum.

EVM wallets use the CREATE2 forwarder. Optionally tick Also accept gasless stablecoin payments.

Save, then complete the on-screen CREATE2 onboarding: you sign one typed-data message in your wallet, with no gas to pay, and the platform broadcasts the transactions.


CREATE2 forwarder (unique address per payment)

Every invoice gets a unique on-chain address, so there is nothing to disambiguate and the customer pays the quoted amount exactly. The platform sweeps to your registered treasury within minutes after confirmation.

The forwarder's destination is welded into its bytecode via Solady CWIA immutable args - the platform cannot redirect funds.

The wallet becomes payable only once the onboarding below is finished. Until then the chain stays out of the customer's picker.

One-time onboarding (per wallet, per chain):

Attest - the platform broadcasts the attest transaction. No cost to you.

Register Treasury - Prepare - the dashboard fetches the EIP-712 typed-data envelope.

Register Treasury - Submit - your wallet (MetaMask, Rabby, Ledger, or any injected EVM wallet) signs the typed-data with your control key. Default expiry 24 hours.

Finalise - after on-chain confirmation, the wallet is ready. The dashboard polls automatically and resumes after a page reload.

Treasury rotation: call Register Treasury again with a new address. The new version applies to new payments. Old versions stay readable so historical addresses always remain sweepable.

See Payment modes for how the forwarder compares with the other chain families.

Sweep state

StateMeaning
auto_pendingConfirmed. Awaiting sweep (~5 min).
sweptFunds delivered to treasury.
auto_failedSweep failed. The platform retries.
stuck_needs_manualRepeated failures - use Sweep manually on the payment detail page.
manual_in_flightYou signed a manual sweep. Awaiting confirmation.

When a payment hits stuck_needs_manual, the dashboard shows a Sweep manually button. Click it, sign the returned calldata with your own wallet, and the funds sweep to your treasury.

Native gas tokens (ETH/POL/BNB) auto-sweep inline during forwarder deployment - they cannot reach stuck_needs_manual under normal operation.


Gasless stablecoins (EIP-3009)

Customers pay supported stablecoins without holding gas. They sign a typed-data message in their wallet, and the platform relay broadcasts transferWithAuthorization on-chain. The signed message names your address as the destination - the relay cannot redirect funds.

ChainGasless-eligible tokens
ETHCircle USDC, PYUSD (PayPal USD)
ETH_SEPOLIACircle USDC
BASECircle USDC, EURC (Euro Coin)
MATICCircle USDC
BSCNone - Binance-Peg USDC is bridged and does not implement EIP-3009

The signing deadline is the invoice expiry itself. On Ethereum-family chains the payment window defaults to 20 minutes from chain selection (your operator can tune it per chain). After the invoice expires, the signed authorization is no longer accepted and the customer creates a new payment.

Stackable on the CREATE2 forwarder. Enable per wallet via Also accept gasless stablecoin payments. Where your operator enables direct settlement, a gasless payment lands straight in your treasury with no sweep. See Gasless USDC.


Gas economics (CREATE2 + Gasless)

For CREATE2 and gasless stablecoin payments, the platform pays operator gas first and charges the actual cost to your Prepaid Credit. Where customer-facing pass-through is supported, each wallet has these settings:

SettingDefaultWhat it does
gas_handling_modesmartsmart, always_absorb, or always_pass
auto_markup_above_pct2.00%In smart mode, markup customer above this percentage of payment

always_absorb and always_pass skip the smart-mode percentage logic. Customer-facing pass-through is based on quote-time estimates. The actual operator gas cost is charged through Prepaid Credit after settlement.


Testnet (ETH_SEPOLIA)

Use a separate test wallet. Sepolia ETH and Sepolia USDC have no value.

Faucets (verified working):


Common errors

CodeWhen
PAYMENT_MODE_CONFLICTA legacy shared-address wallet already exists on this chain - retire it first
INFLIGHT_CAP_EXCEEDEDPer-merchant CREATE2 in-flight USD cap exceeded - contact support
REGISTER_TREASURY_SIG_INVALID / _HIGH_S / _MISMATCHSignature wasn't signed by the control key, or non-canonical
REGISTER_TREASURY_NONCE_DRIFTOn-chain nonce moved between Prepare and Submit - re-run Prepare
TREASURY_IS_FORWARDERTreasury cannot be a NoHoldPay forwarder address
X402_AUTHORIZATION_EXPIREDCustomer waited too long to sign
X402_NONCE_ALREADY_USEDCustomer's authorisation was already consumed

See also

On this page