Skip to main content
Gasless trades let users swap and bridge without holding native gas tokens like ETH or MATIC. DZap executes the transaction on your behalf and deducts the gas cost from your output in the source token.

Why it matters

  • No gas tokens needed. Users can trade USDC on Arbitrum even if their ETH balance is zero.
  • Trade full balances. Users can swap their entire token holdings without leaving dust for gas.
  • Better UX. Removes the friction of acquiring native tokens before trading.
  • Multi-chain ready. Same flow works across all supported chains.

How it works

  1. You approve tokens for DZap to spend (EIP-2612 permit, Permit2, or standard approval)
  2. You request a gasless quote
  3. DZap executes the transaction, paying the gas fee
  4. DZap deducts an equivalent amount in the source token from your output
For trades with multiple source tokens, fees are split proportionally based on USD value.

Gasless swap

import { DZapClient, ApprovalModes } from '@dzapio/sdk';
import { createWalletClient, http } from 'viem';
import { arbitrum } from 'viem/chains';

const dzap = DZapClient.getInstance();

const walletClient = createWalletClient({
  account: '0xYourAddress',
  chain: arbitrum,
  transport: http(),
});

// 1. Check if token supports EIP-2612 permit (preferred for gasless)
const { data } = await dzap.getAllowance({
  chainId: 42161,
  sender: '0xYourAddress',
  tokens: [{ address: '0xaf88...', amount: 1_000_000n }],
  service: 'swap',
  mode: ApprovalModes.EIP2612Permit,  // Default: EIP-2612 reduces security risk vs unlimited approval
});

// 2. Sign permit if supported (no gas required)
if (data['0xaf88...'].type === 'eip2612') {
  const { data: permits } = await dzap.sign({
    chainId: 42161,
    sender: '0xYourAddress',
    tokens: [{ address: '0xaf88...', amount: '1000000' }],
    service: 'swap',
    signer: walletClient,
  });
  // Use permits['0xaf88...'].permitData in tradeGasless
}

// 3. Get gasless quote
const quotes = await dzap.getTradeQuotes({
  gasless: true,
  fromChain: 42161,
  account: '0xYourAddress',
  data: [{
    amount: '1000000',
    srcToken: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831',
    destToken: '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1',
    slippage: 1,
  }],
});

// 4. Execute gasless trade
const result = await dzap.tradeGasless({
  request: {
    integratorId: 'dzap',
    fromChain: 42161,
    sender: '0xYourAddress',
    refundee: '0xYourAddress',
    gasless: true,
    data: [{
      amount: '1000000',
      srcToken: '0xaf88...',
      destToken: '0x82aF...',
      srcDecimals: 6,
      destDecimals: 18,
      selectedRoute: quotes[0].protocol,
      recipient: '0xYourAddress',
      slippage: 1,
    }],
  },
  signer: walletClient,
});

Standard approval (alternative)

If the token does not support EIP-2612, use standard approval. Note: This requires an on-chain approval transaction and grants potentially unlimited allowance.
// Check with Default mode for standard approval
const { data } = await dzap.getAllowance({
  chainId: 42161,
  sender: '0xYourAddress',
  tokens: [{ address: '0xaf88...', amount: 1_000_000n }],
  service: 'swap',
  mode: ApprovalModes.Default,
});

// Approve if needed
if (data['0xaf88...'].allowance < 1_000_000n) {
  await dzap.approve({
    chainId: 42161,
    signer: walletClient,
    sender: '0xYourAddress',
    tokens: [{ address: '0xaf88...', amount: 1_000_000n }],
    service: 'swap',
    mode: ApprovalModes.Default,
  });
}

Gasless bridge

Same flow as gasless swap, just add toChain:
const quotes = await dzap.getTradeQuotes({
  gasless: true,
  fromChain: 42161,
  account: '0xYourAddress',
  data: [{
    amount: '1000000',
    srcToken: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831',
    destToken: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
    toChain: 8453,
    slippage: 1,
  }],
});

const result = await dzap.tradeGasless({
  request: {
    integratorId: 'dzap',
    fromChain: 42161,
    sender: '0xYourAddress',
    refundee: '0xYourAddress',
    gasless: true,
    data: [{
      amount: '1000000',
      srcToken: '0xaf88...',
      destToken: '0x8335...',
      toChain: 8453,
      srcDecimals: 6,
      destDecimals: 6,
      selectedRoute: quotes[0].protocol,
      recipient: '0xYourAddress',
      slippage: 1,
    }],
  },
  signer: walletClient,
});

Permit2 with gasless

If you have already approved tokens to Permit2, set hasPermit2ApprovalForAllTokens: true:
const result = await dzap.tradeGasless({
  request: {
    fromChain: 42161,
    sender: '0xYourAddress',
    refundee: '0xYourAddress',
    gasless: true,
    hasPermit2ApprovalForAllTokens: true,  // Skip approval check
    data: [{
      amount: '1000000',
      srcToken: '0xaf88...',
      destToken: '0x82aF...',
      srcDecimals: 6,
      destDecimals: 18,
      selectedRoute: 'uniswap',
      recipient: '0xYourAddress',
      slippage: 1,
    }],
  },
  signer: walletClient,
});

Fee calculation

Gasless fees are calculated at quote time and included in the response:
  • Single source token: Fee deducted entirely from that token
  • Multiple source tokens: Fee split proportionally based on USD value of each token
The quote response includes the effective rate after fees.

When to use gasless

ScenarioRecommendation
User has no native gas tokensUse gasless
User wants to trade entire token balanceUse gasless
High-frequency tradingRegular trade (lower total fees)
Single token swapsUse gasless
Complex multi-hop tradesCheck quote for fee impact
Last modified on May 4, 2026