← Back to Home

Example 02: Gasless USDC Transfer

This example demonstrates how to send USDC on Solana without requiring the user to hold SOL for gas fees, using Lazorkit smart wallets and a paymaster.

What You’ll Learn

  • Sending USDC using the SPL Token Program
  • Executing transactions from a smart wallet
  • Sponsoring gas fees using Lazorkit paymaster
  • Signing transactions securely with passkeys

How It Works

1. Smart Wallet as Sender

The USDC transfer is initiated from the Lazorkit smart wallet created during passkey login.

2. Gasless Transaction

Instead of the user paying SOL for gas, Lazorkit’s paymaster sponsors the transaction fee.

3. Passkey Signing

The user authorizes the transaction using Face ID / Touch ID through WebAuthn.

Code Example

Minimal gasless USDC transfer implementation using Lazorkit. This snippet shows how a smart wallet signs and sends an SPL token transaction with fees sponsored by a paymaster.

import { useWallet } from "@lazorkit/wallet";
import {
  getAssociatedTokenAddress,
  createAssociatedTokenAccountInstruction,
  createTransferInstruction,
} from "@solana/spl-token";
import { PublicKey, Connection } from "@solana/web3.js";

const USDC_MINT = new PublicKey(
  "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU" // Devnet USDC
);

const RECIPIENT = new PublicKey("");

export function GaslessUSDCTransfer() {
  const { smartWalletPubkey, signAndSendTransaction } = useWallet();

  async function sendUSDC() {
    if (!smartWalletPubkey) return;

    const amount = 1_000_000; // 1 USDC (6 decimals)
    const instructions = [];

    // Smart wallets are off-curve → pass true
    const fromATA = await getAssociatedTokenAddress(
      USDC_MINT,
      smartWalletPubkey,
      true
    );

    const toATA = await getAssociatedTokenAddress(
      USDC_MINT,
      RECIPIENT
    );

    // Create recipient ATA if missing
    const connection = new Connection("https://api.devnet.solana.com");
    const toInfo = await connection.getAccountInfo(toATA);

    if (!toInfo) {
      instructions.push(
        createAssociatedTokenAccountInstruction(
          smartWalletPubkey,
          toATA,
          RECIPIENT,
          USDC_MINT
        )
      );
    }

    instructions.push(
      createTransferInstruction(
        fromATA,
        toATA,
        smartWalletPubkey,
        amount
      )
    );

    await signAndSendTransaction({
      instructions,
      transactionOptions: { feeToken: "USDC" },
    });
  }

  return <button onClick={sendUSDC}>Send 1 USDC (Gasless)</button>;
}