Docs/How-To Guides/Fund with USDC

>_ DOCS / HOW-TO GUIDES

FUND WITH
USDC.

Add USDC on Base to your P402 account. Settlement is gasless for you — P402 pays the gas via EIP-3009 transferWithAuthorization.

Two Ways to Fund

Dashboard (Recommended)

EASY
  1. 1.Go to Dashboard → Settings → Billing
  2. 2.Click "Add Funds"
  3. 3.Connect wallet (MetaMask, Coinbase, WalletConnect)
  4. 4.Enter USDC amount and sign one transaction
  5. 5.Balance appears in under 30 seconds

Programmatic (EIP-3009)

ADVANCED
  1. 1.Sign an EIP-3009 TransferWithAuthorization off-chain
  2. 2.POST the signed payload to /api/v1/facilitator/settle
  3. 3.P402 submits the transaction and pays gas
  4. 4.No ETH required in your wallet

Chain & Token Details

Network
Base Mainnet (Chain ID: 8453)
Token
USDC (USD Coin)
USDC Contract
0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
P402 Treasury
0xFa772434DCe6ED78831EbC9eeAcbDF42E2A031a6
Decimals
6 (1 USDC = 1,000,000 atomic units)
Minimum deposit
$1.00 USDC
Settlement time
< 30 seconds on Base
Gas paid by
P402 (gasless for user via EIP-3009)

Get USDC on Base

If you don't have USDC on Base, bridge it from Ethereum or buy directly.

Bridge from Ethereum

Use the official Base Bridge to move USDC from Ethereum mainnet to Base.

bridge.base.org
Buy directly on Coinbase

Purchase USDC and withdraw directly to your Base wallet — no bridge needed.

coinbase.com
Swap on Base DEXs

Swap any Base token for USDC via Uniswap, Aerodrome, or BaseSwap.

What is EIP-3009?

EIP-3009 is an Ethereum standard implemented by USDC. It defines a function called transferWithAuthorization that lets a token holder pre-authorize a transfer off-chain by signing a typed message (EIP-712). A third party (the facilitator) can then submit that authorization to the USDC contract on-chain, triggering the transfer and paying the gas themselves.

The result: you sign once in your browser (free), and P402 pays the gas to execute the transfer. You never need ETH in your wallet to move USDC.

Authorization FieldWhat it means
fromYour wallet address — the sender of the USDC
toRecipient address — P402's treasury (0xFa772...)
valueAmount in atomic units. USDC has 6 decimals: 10 USDC = 10,000,000
validAfterUnix timestamp: authorization is not valid before this time (use now - 60s to allow clock skew)
validBeforeUnix timestamp: authorization expires at this time (set to now + 3600s for 1 hour)
nonce32-byte random hex string. Used once — P402 rejects any replay of the same nonce

Programmatic Funding (EIP-3009)

For autonomous agents or server-side funding, sign an EIP-3009 authorization and submit it directly. Your wallet never pays gas.

Step 1 — Sign the authorization
typescript
import { createWalletClient, http, parseUnits } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { base } from 'viem/chains';

const USDC_ADDRESS  = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913';
const P402_TREASURY = '0xFa772434DCe6ED78831EbC9eeAcbDF42E2A031a6';

const account = privateKeyToAccount(process.env.WALLET_PRIVATE_KEY as `0x${string}`);
const client  = createWalletClient({ account, chain: base, transport: http() });

// Nonce must be a 32-byte (64 hex char) random value, unique per wallet, never reused.
const nonce       = '0x' + crypto.getRandomValues(new Uint8Array(32))
                      .reduce((hex, b) => hex + b.toString(16).padStart(2, '0'), '');
const value       = parseUnits('10', 6);    // 10 USDC (6 decimals)
const validAfter  = BigInt(Math.floor(Date.now() / 1000) - 60);
const validBefore = BigInt(Math.floor(Date.now() / 1000) + 3600);  // 1 hour

const signature = await client.signTypedData({
  account,
  domain: {
    name: 'USD Coin',
    version: '2',
    chainId: base.id,
    verifyingContract: USDC_ADDRESS,
  },
  types: {
    TransferWithAuthorization: [
      { name: 'from',        type: 'address' },
      { name: 'to',          type: 'address' },
      { name: 'value',       type: 'uint256' },
      { name: 'validAfter',  type: 'uint256' },
      { name: 'validBefore', type: 'uint256' },
      { name: 'nonce',       type: 'bytes32' },
    ],
  },
  primaryType: 'TransferWithAuthorization',
  message: {
    from:        account.address,
    to:          P402_TREASURY,
    value,
    validAfter,
    validBefore,
    nonce:       nonce as `0x${string}`,
  },
});
Step 2 — Submit to P402
typescript
const response = await fetch('https://p402.io/api/v1/facilitator/settle', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.P402_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    paymentPayload: {
      x402Version: 2,
      scheme: 'exact',
      network: 'eip155:8453',
      payload: {
        signature,
        authorization: {
          from:        account.address,
          to:          P402_TREASURY,
          value:       value.toString(),
          validAfter:  validAfter.toString(),
          validBefore: validBefore.toString(),
          nonce,
        },
      },
    },
    paymentRequirements: {
      scheme: 'exact',
      network: 'eip155:8453',
      maxAmountRequired: value.toString(),
      resource: 'https://p402.io/api/v2/sessions/fund',
      description: 'P402 account funding',
      payTo: P402_TREASURY,
      asset: USDC_ADDRESS,
    },
  }),
});

const result = await response.json();
console.log('Settled:', result.transaction);  // Base tx hash

Autonomous agents — use CDP wallets

For agents that fund themselves without human interaction, provision a CDP Server Wallet. P402 will automatically use the TEE-secured wallet to sign and submit the EIP-3009 authorization.

Connect your agent →