Does x402 work on BNB Chain?
Short answer: the Permit2 path works on both BNB Smart Chain and its testnet — the contracts are deployed and verified. The default EIP-3009 path that most x402 clients implement works on exactly one token on mainnet and on no token on testnet. No public facilitator settles BNB Chain today, so nothing is payable end to end yet.
If you follow the standard x402 integration guide on BNB Chain with a Binance-Peg stablecoin, you will emit a challenge no client can satisfy: the payer signs a TransferWithAuthorization for a function that does not exist on the token, and the failure only surfaces at settlement with no error that says so.
What the chain actually says
Every verdict below was read from the chain, not from token documentation. A selector is classified by its revert data: an empty revert means no dispatcher branch matched, so the function is absent; a revert carrying an Error(string) means the function exists and rejected the arguments. Each token is also probed with a selector that certainly does not exist, so a contract that fabricates return data cannot produce a false positive.
BNB Smart Chain Testnet (advertised only) (eip155:97)
Payment asset: USDT (18 decimals), 0x337610d27c682E347C9cD60BD4b3b107C9d34dDd. Default transfer method: Permit2.
Testnet — settlement here spends only faucet value.
Payable today: no. Documented only: no facilitator settles this network, so the chain is not selectable and no endpoint here will issue a challenge for it.
EIP-3009 (transferWithAuthorization) — does not work. No EIP-3009 asset was found on eip155:97. USDT (0x3376…4dDd), BUSD (0xeD24…12Ee) and USDC (0x6454…8930) all revert with EMPTY return data for both transferWithAuthorization(...) and authorizationState(address,bytes32) — the signature of a missing function, not a failing one — while the control selector 0xdeadbeef reverts identically, confirming none of them fabricates return data. A client following the standard x402 EIP-3009 path on BNB testnet signs a message for a function that does not exist.
Permit2 — works. Canonical Permit2 (0x0000…78BA3, 9152 bytes) and the x402 exact proxy 0x4020…0001 (2913 bytes) are both deployed on eip155:97 at the same CREATE2 addresses and byte lengths as on Radius; the proxy's PERMIT2() returns canonical Permit2 and its WITNESS_TYPE_STRING() returns "…Witness(address to,uint256 validAfter)". So a PermitTransferFrom signed for it is redeemable — by any facilitator that will settle this network, of which there are currently none.
BNB Smart Chain (advertised only) (eip155:56)
Payment asset: FDUSD (18 decimals), 0xc5f0f7b66764F6ec8C8Dff7BA683102295E16409. Default transfer method: Permit2.
REAL FUNDS — this is a production network. Anything settled here moves value that cannot be re-minted from a faucet.
Payable today: no. Documented only: no facilitator settles this network, so the chain is not selectable and no endpoint here will issue a challenge for it.
EIP-3009 (transferWithAuthorization) — works. FDUSD (0xc5f0…6409) implements ERC-3009 on eip155:56. transferWithAuthorization(...) called with a garbage signature reverts Error("Invalid signature") — the function exists and rejected the arguments — and authorizationState(address,bytes32) returns false for an unused nonce, while the control selector 0xdeadbeef reverts with empty data, so the proxy is not fabricating returns. EIP-712 domain confirmed by separator reconstruction as { name: "First Digital USD", version: "1" }. It omits the TRANSFER_WITH_AUTHORIZATION_TYPEHASH() getter, which is a Circle convention rather than part of ERC-3009, so that getter's absence is not evidence against support. By contrast the Binance-Peg tokens — USDT (0x55d3…7955), USDC (0x8AC7…580d) and BUSD (0xe9e7…7D56) — all revert with empty data for both mandated members and have no EIP-3009.
Permit2 — works. Canonical Permit2 (0x0000…78BA3, 9152 bytes) and the x402 exact proxy 0x4020…0001 (2913 bytes) are both deployed on eip155:56 at the same CREATE2 addresses and byte lengths as on Radius; the proxy's PERMIT2() returns canonical Permit2. The upto proxy 0x4020…0002 (3142 bytes) is deployed too, and its WITNESS_TYPE_STRING() carries the `facilitator` member the upto scheme binds.
The stablecoin that breaks the pattern
The expectation going in was that BNB Chain's bridged Binance-Peg tokens lack EIP-3009 and that this breaks x402's default path. That holds for Binance-Peg USDT, USDC and BUSD — all three revert with empty data for both members ERC-3009 mandates. It does not hold universally: FDUSD implements ERC-3009 correctly, so EIP-3009 is available on BNB mainnet if you use that token. FDUSD omits the TRANSFER_WITH_AUTHORIZATION_TYPEHASH() getter, which is a Circle convention rather than part of ERC-3009 — probing for that getter alone would have reported a false negative. Scope: this is a survey of four mainnet tokens and three testnet tokens, all named in the evidence above. FDUSD was the only one of them with EIP-3009 and none of the three on testnet had it — but neither chain was searched exhaustively, so another token may well implement it.
Which facilitators settle BNB Chain
- https://x402.org/facilitator (Coinbase) — 9 networks registered, no BNB network of any kind.
- https://facilitator.payai.network — 32 networks registered, no BNB network of any kind.
- https://facilitator.x402.rs — advertises eip155:97 for both exact and upto with an empty signer list, but its /verify rejects that network under every label tried (eip155:97, bsc-testnet, bnb-testnet, bsc, binance-smart-chain-testnet), all returning unsupported_scheme. The same request body sent with network base-sepolia reaches signature recovery on the same endpoint, so the refusal is the network, not the request shape.
What a payer must do before their first payment
- Approve Permit2 once, per token. Call approve on the ERC-20 with canonical Permit2 (0x000000000022D473030F116dDEE9F6B43aC78BA3) as the spender. Without it, every signed permit is valid and still unredeemable. It is a one-time on-chain transaction and it costs BNB gas.
- Hold BNB for gas. Neither BNB chain is gasless, and the x402 facilitators that sponsor gas elsewhere do not cover BNB.
- Mind the decimals. The BNB stablecoins here are 18-decimal, unlike the 6-decimal USDC most x402 examples assume. An amount copied from a Base or Radius example is wrong by a factor of 10^12.
- Sign against Permit2's domain, not the token's. A Permit2 payment's EIP-712 domain is Permit2's own. The token's domain only matters on the EIP-3009 path — and on BNB mainnet's FDUSD that domain is { name: "First Digital USD", version: "1" }, confirmed by reconstructing the domain separator rather than by reading documentation.
What is still missing
grug402 runs its own Permit2-based facilitator, and the Permit2 contracts it depends on are deployed on both BNB chains, so the settlement shape fits. It does not serve BNB today, and two separate things are missing. First, capability: the facilitator's chain list covers only the Radius chains and it refuses any network without an enabled capability row, so BNB has to be added there — a code change, not a setting. Second, funding: the settlement signer holds no tBNB, and the official BNB testnet faucet requires holding BNB on mainnet, so a human has to fund it. Neither has been done, and no payment has been settled end to end on either BNB chain — deployed contracts and a well-formed signature rejection are evidence that the pieces exist, not proof that a payment completes. Both BNB entries therefore stay documented-only rather than appearing payable.