Skip to main content
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 to configure your project.
  • Visit the Sponsor Gas section of the dashboard, 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:
npm install @dynamic-labs-sdk/zerodev @dynamic-labs-sdk/evm
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 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:
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:
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 for details.

When sponsorship is used

ScenarioSponsored?
sendUserOperation with walletAccount (default)Yes (withSponsorship: true)
sendUserOperation with withSponsorship: falseNo — user pays gas
sendUserOperation with kernelClient onlyDepends on how the kernel client was created

More