Skip to main content
This recipe walks through the cleanest gasless funding path Eco supports today: a user signs an ERC-3009 transferWithAuthorization; Eco’s relayer broadcasts; USDC lands in the user’s Circle Gateway balance on Polygon.

When to use

  • Onboarding flows where users don’t yet hold the source chain’s gas token
  • Nanopayment / micro-deposit flows where gas would dominate the value transferred
  • Any flow where the UX win of “no gas” beats the marginal latency

1. Create the quoted deposit vault

curl -X POST https://api.eco.com/circle-gateway/v2/depositAddresses \
  -H "Content-Type: application/json" \
  -d '{
    "sourceChainId": 8453,
    "amount": "100000000",
    "recipient": "0xRecipientOnGateway",
    "depositor": "0xUserWallet"
  }'
Returns { vaultAddress, amount, deadline }. The vault is quoted for this specific amount; fund it before deadline (Unix seconds). Repeating the same request while the quote is pending returns the same vault.

2. Have the user sign an ERC-3009 authorization

Sign for the quoted amount, with to set to the vaultAddress. USDC’s EIP-712 domain name varies per chain: "USDC" on Base Sepolia, "USD Coin" elsewhere. Use the right one.
import { toHex } from 'viem';

const value = BigInt(amount); // quoted amount from step 1
const nonce = toHex(crypto.getRandomValues(new Uint8Array(32)));
const validBefore = String(Math.floor(Date.now() / 1000) + 3600);

const signature = await signTypedDataAsync({
  domain: { name: 'USD Coin', version: '2', chainId, 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: owner, to: vaultAddress, value, validAfter: 0n, validBefore: BigInt(validBefore), nonce },
});

3. Submit the signed authorization

curl -X POST https://api.eco.com/circle-gateway/v1/gasless/transferWithAuthorization \
  -H "Content-Type: application/json" \
  -d '{
    "chainId": 8453,
    "from": "0xSigner",
    "to": "0xVaultAddress",
    "value": "100000000",
    "validAfter": "0",
    "validBefore": "1717200000",
    "nonce": "0x...",
    "signature": "0x..."
  }'
Returns 202 Accepted with { id, status: "PENDING" }. The value must be at least the quoted amount and the vault’s quote must not be expired.

4. Poll for completion

Poll the relayer job:
curl https://api.eco.com/circle-gateway/v1/gasless/jobs/<id>
Status transitions: PENDINGCOMPLETED (or FAILED). Response includes transferTxHash once complete. Then poll the vault status until the deposit intent is published:
curl "https://api.eco.com/circle-gateway/v2/depositAddresses/0xVaultAddress?sourceChainId=8453"
state transitions PENDINGFUNDING_DETECTEDPUBLISHED, and the response carries the intentHash. See the state table for the full list. End-to-end (Base Sepolia → Polygon Amoy): typically 20–40 seconds.

What the user paid

Nothing onchain. Eco’s deposit-address service paid source-chain gas; Eco’s solver service paid Polygon-side gas. You’ve successfully completed a gasless deposit into Gateway.