> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dynamic.xyz/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# EVM Gas Sponsorship Quickstart

> Set up gasless EVM transactions so your app pays gas for users

With ZeroDev and Dynamic, you can **sponsor gas** so your users don't pay transaction fees. This page is the minimal path to get sponsorship working.

## Prerequisites

* Create a Zerodev account and projects for each network you want to support, as well as a gas policy for each one. Make sure you use [the V1 dashboard](https://dashboard.zerodev.app/create-legacy-project) to configure your project.
* Visit the [Sponsor Gas section of the dashboard](https://app.dynamic.xyz/dashboard/smart-wallets), toggle on Zerodev and add your project IDs.

## 1. Add the ZeroDev extension

Install the package and add the extension when creating your client. You need the EVM extension as well:

```bash theme={"system"}
npm install @dynamic-labs-sdk/zerodev @dynamic-labs-sdk/evm
```

```javascript theme={"system"}
import { createDynamicClient } from "@dynamic-labs-sdk/client";
import { addEvmExtension } from "@dynamic-labs-sdk/evm";
import { addZerodevExtension } from "@dynamic-labs-sdk/zerodev";

const dynamicClient = createDynamicClient({
  environmentId: "YOUR_ENVIRONMENT_ID",
});

addEvmExtension();
addZerodevExtension();
```

See [Adding ZeroDev Extension](/javascript/reference/zerodev/adding-zerodev-extension) for details.

## 2. Send a sponsored transaction

Use `sendUserOperation` with a wallet account. **Sponsorship is on by default** when you use a wallet account, so your users don't pay gas:

```javascript theme={"system"}
import { sendUserOperation } from "@dynamic-labs-sdk/zerodev";
import { isEvmWalletAccount } from "@dynamic-labs-sdk/evm";
import { getPrimaryWalletAccount } from "@dynamic-labs-sdk/client";
import { parseEther } from "viem";

const walletAccount = getPrimaryWalletAccount();

if (walletAccount && isEvmWalletAccount(walletAccount)) {
  const receipt = await sendUserOperation({
    walletAccount,
    calls: [
      {
        to: "0xRecipientAddress...",
        value: parseEther("0.01"),
        data: "0x",
      },
    ],
  });
  console.log("Sponsored tx sent:", receipt.userOpHash);
}
```

That's the basic flow: enable in dashboard → add extension → call `sendUserOperation` with a wallet account.

## Optional: check if an operation can be sponsored

To show different UI when sponsorship isn't available (e.g. unsupported network or paymaster limit), use `canSponsorUserOperation` before sending:

```javascript theme={"system"}
import { canSponsorUserOperation, sendUserOperation } from "@dynamic-labs-sdk/zerodev";
import { parseEther } from "viem";

const calls = [
  { to: "0xRecipientAddress...", value: parseEther("0.01"), data: "0x" },
];

const canSponsor = await canSponsorUserOperation({ walletAccount, calls });

if (canSponsor) {
  await sendUserOperation({ walletAccount, calls });
} else {
  // Fallback: let user pay gas, or show a message
}
```

See [canSponsorUserOperation](/javascript/reference/zerodev/can-sponsor-user-operation) for details.

## When sponsorship is used

| Scenario                                           | Sponsored?                                   |
| -------------------------------------------------- | -------------------------------------------- |
| `sendUserOperation` with `walletAccount` (default) | Yes (`withSponsorship: true`)                |
| `sendUserOperation` with `withSponsorship: false`  | No — user pays gas                           |
| `sendUserOperation` with `kernelClient` only       | Depends on how the kernel client was created |

## React

In React, set up the extensions at module level and call `sendUserOperation` inside a button handler:

```tsx theme={"system"}
// dynamicClient.ts — module-level setup
import { createDynamicClient } from '@dynamic-labs-sdk/client';
import { addEvmExtension } from '@dynamic-labs-sdk/evm';
import { addZerodevExtension } from '@dynamic-labs-sdk/zerodev';

export const dynamicClient = createDynamicClient({ environmentId: 'YOUR_ENVIRONMENT_ID' });
addEvmExtension();
addZerodevExtension();
```

```tsx theme={"system"}
// SponsoredSendButton.tsx
import { sendUserOperation, canSponsorUserOperation } from '@dynamic-labs-sdk/zerodev';
import { isEvmWalletAccount } from '@dynamic-labs-sdk/evm';
import { useGetWalletAccounts } from '@dynamic-labs-sdk/react-hooks';
import { useState } from 'react';
import { parseEther } from 'viem';

function SponsoredSendButton({ recipientAddress }) {
  const { data: walletAccounts = [] } = useGetWalletAccounts();
  const walletAccount = walletAccounts.find(isEvmWalletAccount);
  const [opHash, setOpHash] = useState('');

  const handleSend = async () => {
    if (!walletAccount) return;

    const calls = [{ to: recipientAddress, value: parseEther('0.01'), data: '0x' }];
    const canSponsor = await canSponsorUserOperation({ walletAccount, calls });

    if (canSponsor) {
      const receipt = await sendUserOperation({ walletAccount, calls });
      setOpHash(receipt.userOpHash);
    } else {
      console.warn('Sponsorship not available for this operation');
    }
  };

  return (
    <div>
      <button onClick={handleSend} disabled={!walletAccount}>Send (Gasless)</button>
      {opHash && <p>Op hash: {opHash}</p>}
    </div>
  );
}
```

## More

* [sendUserOperation](/javascript/reference/zerodev/send-user-operation) — Full API, batching, and options
* [Adding ZeroDev Extension](/javascript/reference/zerodev/adding-zerodev-extension) — Extension setup only
* [createKernelClientForWalletAccount](/javascript/reference/zerodev/create-kernel-client-for-wallet-account) — When you need a kernel client for advanced flows
* [isGasSponsorshipError](/javascript/reference/zerodev/is-gas-sponsorship-error) — Handling sponsorship errors
