Dexter
Dexter
Docs

BNB Smart Chain (BSC)

Dual-scheme EVM
BNB Chain
BNB Smart Chain

BSC stablecoins lack EIP-3009, so Dexter supports two payment paths: standard Permit2 for compatibility and a hardened custom contract for on-chain security guarantees. Both are live, same facilitator.

Gas sponsoredPermit2EVMProduction

Network ID

NetworkCAIP-2 identifierStatus
BNB Smart Chaineip155:56Production

Why BSC Has Two Paths

BSC stablecoins lack EIP-3009

USDT and USDC on BSC are Binance-Peg bridge wrappers — standard ERC-20. They don't implement transferWithAuthorization (EIP-3009), the function that powers x402 on every other EVM chain. Permit2 and exact-approval are two different solutions to this gap.

Permit2 (standard)exact-approval (hardened)
Schemeexactexact-approval
How it worksUniswap Permit2 + x402ExactPermit2ProxyDexterBSCFacilitator custom contract
First paymentFully gasless (facilitator sponsors the Permit2 approval via erc20ApprovalGasSponsoring)One contract approval (~$0.02 BNB, paid by user)
After thatGasless signatureGasless signature
User needs BNB?NoYes (first payment only, ~$0.02)
SDKStandard @x402/evm or @dexterai/x402@dexterai/x402 or custom handler
On-chain fee capsNoYes (5% MAX_FEE_BPS)
Token allowlistNo (any ERC-20)Yes (USDT + USDC)
Pause mechanismNoYes

Token Details

TokenContractSymbolDecimals
Binance-Peg USDT0x55d398326f99059fF775485246999027B3197955USDT18
Binance-Peg USDC0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580dUSDC18

18 decimals, not 6

Both BSC stablecoins use 18 decimals. 1 USDT = 1000000000000000000 (1e18), not 1000000 (1e6). The facilitator returns extra.decimals: 18 in the /supported response. The SDK handles this automatically.

Path 1: Permit2 (Standard)

The simplest integration path. Works with the unmodified @x402/evm package or @dexterai/x402 SDK. No BSC-specific code needed.

The facilitator returns scheme: "exact" with extra.assetTransferMethod: "permit2" for BSC. The upstream ExactEvmScheme routes Permit2 payloads automatically.

Contracts on BSC:

Integration:

import { wrapFetch } from '@dexterai/x402/client';
 
const x402Fetch = wrapFetch(fetch, {
  evmPrivateKey: process.env.EVM_PRIVATE_KEY,
  preferredNetwork: 'eip155:56',
});
 
// BSC payment handled automatically via Permit2
const response = await x402Fetch('https://api.example.com/protected');

Path 2: exact-approval (Hardened)

Uses a custom smart contract with on-chain security guarantees that Permit2 does not provide at the settlement layer.

When to use this path

Use exact-approval when you want on-chain fee enforcement, token restrictions, emergency pause capability, or facilitator-only access control on settlement. For most integrations, Permit2 is simpler and sufficient.

How it works:

  1. One-time: User approves the DexterBSCFacilitator contract (~$0.02 BNB)
  2. Per payment: User signs an EIP-712 Payment message with: from, to, token, amount, fee, nonce, deadline, paymentId
  3. Settlement: Facilitator calls executePayment() on the contract. Contract re-verifies signature, checks nonce, enforces allowlist and fee caps, moves tokens via safeTransferFrom

Security model:

FeatureDetail
ReentrancyGuardnonReentrant on executePayment
PausableOwner-callable pause() and unpause()
Token allowlistallowedTokens mapping, owner setTokenAllowed()
Fee capsminFee floor + MAX_FEE_BPS hard cap (5%)
Fee separationFees go to feeRecipient, not the executor wallet
Nonce trackingusedNonces[user][nonce] mapping, random 128-bit nonces
Access controlFacilitator-only on executePayment
SafeERC20All transfers — required because BSC USDT doesn't return bool
ProxyTransparentUpgradeableProxy — upgradeable without re-approval

Contract:

Integration:

// Check allowance
const allowance = await publicClient.readContract({
  address: tokenAddress,
  abi: erc20Abi,
  functionName: "allowance",
  args: [userAddress, "0x3D56A1A196aC81c959A1be21ABC28c173fB063B8"],
});
 
// Approve if needed (~$0.02 BNB, one time)
if (allowance < totalPaymentAmount) {
  await walletClient.writeContract({
    address: tokenAddress,
    abi: erc20Abi,
    functionName: "approve",
    args: ["0x3D56A1A196aC81c959A1be21ABC28c173fB063B8", approvalAmount],
  });
}
 
// Sign the EIP-712 payment (gasless)
const signature = await walletClient.signTypedData({
  domain: { name: "DexterBSCFacilitator", version: "1", chainId: 56n,
    verifyingContract: "0x3D56A1A196aC81c959A1be21ABC28c173fB063B8" },
  types: {
    Payment: [
      { name: "from", type: "address" }, { name: "to", type: "address" },
      { name: "token", type: "address" }, { name: "amount", type: "uint256" },
      { name: "fee", type: "uint256" }, { name: "nonce", type: "uint256" },
      { name: "deadline", type: "uint256" }, { name: "paymentId", type: "bytes32" },
    ],
  },
  primaryType: "Payment",
  message: { from: userAddress, to: merchantAddress, token: tokenAddress,
    amount: paymentAmount, fee: feeAmount, nonce: randomNonce,
    deadline: BigInt(deadlineUnix), paymentId: randomBytes32 },
});
 
// Submit to facilitator (same /verify + /settle as every other chain)

Best Fit

  • merchants accepting payment from BSC-native users holding USDT or USDC
  • agents operating on BSC that need programmatic gasless payments
  • teams that want the standard Permit2 path with zero BSC-specific code
  • high-value or regulated use cases that benefit from on-chain fee caps and token restrictions (exact-approval)

Quick Support Check

# Returns two kinds: exact (permit2) and exact-approval
curl -s https://x402.dexter.cash/supported | jq '.kinds[] | select(.network == "eip155:56")'

Validate Before Shipping

  1. Confirm BSC appears twice in /supported — one exact kind with assetTransferMethod: "permit2" and one exact-approval kind.
  2. Confirm you are using eip155:56 as the network identifier.
  3. Confirm amounts use 18 decimals (not 6).
  4. Test POST /verify and POST /settle with a real BSC-targeted payment.
  5. If using exact-approval, confirm the user has approved the DexterBSCFacilitator contract.

Proof of Operation

First two exact-approval settlements on BSC mainnet:

On this page