Sponsor Gas on Solana
With ZeroDev, you can sponsor transaction fees for your users on Solana, so they don't need to hold SOL to interact with your DApp.
How Solana fee sponsorship works
Unlike EVM chains, Solana doesn't need ERC-4337 or paymasters for fee sponsorship. Every Solana transaction has a fee payer field that can be set to any account — it doesn't have to be the same account that initiates the transaction. ZeroDev takes advantage of this by setting the fee payer to a ZeroDev-managed wallet that covers two types of costs:
- Transaction fees — the cost of including and executing the transaction on the network.
- Rent — the minimum SOL deposit required to create new accounts or token accounts on-chain (e.g. when calling
createAccountorcreateAssociatedTokenAccount).
Your users sign the transaction normally, and ZeroDev's sponsorship server co-signs as the fee payer and broadcasts the transaction — all in a single step.
Paying for sponsored gas
When you sponsor gas through ZeroDev, there are two ways to pay for the gas:
-
Put down your credit card. We front the gas for your users, and then at the end of the billing cycle (once a month) we charge your credit card.
-
Buy gas credits from us.
Setting up gas sponsoring policies
To avoid over-spending on sponsoring, you must set up gas-sponsoring policies. Sign up on the ZeroDev dashboard if you haven't already, then set up gas policies.
Note that you MUST set up a gas policy to begin sponsoring. Without setting up a gas policy, there won't be any gas sponsored.
Installation
Install the ZeroDev Solana sponsorship SDK along with its peer dependencies:
npm i @zerodev/solana-sponsorship-sdk @solana/kit @solana-program/systemQuick Start
1. Get your RPC endpoint
Go to the ZeroDev dashboard and create a Solana project. Copy the RPC endpoint for the correct Solana network (mainnet or devnet), e.g. https://rpc.zerodev.app/api/v3/svm/YOUR_PROJECT_ID/chain/9034109930.
2. Create the sponsorship and Solana RPC clients
Get a Solana RPC URL from a provider like Alchemy or Helius, or use the public endpoint https://api.mainnet-beta.solana.com (restrictively rate-limited and not advisable for production).
import { createSolanaRpc, mainnet } from "@solana/kit";
import { createSponsorshipRpc } from "@zerodev/solana-sponsorship-sdk";
const sponsorshipRpc = createSponsorshipRpc({
endpoint: "https://rpc.zerodev.app/api/v3/svm/YOUR_PROJECT_ID/chain/9034109930",
});
const solanaRpc = createSolanaRpc(mainnet("YOUR_SOLANA_RPC_URL"));3. Get a recent blockhash
const { value: { blockhash: recentBlockhash, lastValidBlockHeight } } =
await solanaRpc.getLatestBlockhash({ commitment: "finalized" }).send();4. Create your transaction instruction(s)
This can be any Solana instruction. Here we use a simple SOL transfer as an example:
import { lamports } from "@solana/kit";
import { getTransferSolInstruction } from "@solana-program/system";
const transferInstruction = getTransferSolInstruction({
source: userKeypair, // your user's keypair signer
destination: toAddress, // destination address
amount: lamports(1_000_000n), // 0.001 SOL
});5. Get the sponsor fee payer and build the transaction
Fetch ZeroDev's fee payer address and set it as the transaction's fee payer. We use a NoopSigner as a placeholder because the fee payer's private key lives on ZeroDev's server, not the client. The real fee payer signature is added server-side when you call sponsorTransaction in the next step.
import {
createTransactionMessage,
pipe,
setTransactionMessageLifetimeUsingBlockhash,
address,
blockhash,
appendTransactionMessageInstructions,
setTransactionMessageFeePayerSigner,
createNoopSigner,
} from "@solana/kit";
const feePayer = await sponsorshipRpc.getFeePayer().send();
const message = pipe(
createTransactionMessage({ version: "legacy" }),
(msg) => setTransactionMessageFeePayerSigner(createNoopSigner(address(feePayer)), msg),
(msg) => appendTransactionMessageInstructions([transferInstruction], msg),
(msg) => setTransactionMessageLifetimeUsingBlockhash(
{ blockhash: blockhash(recentBlockhash), lastValidBlockHeight },
msg
),
);6. Sign and sponsor the transaction
The user signs the transaction, then ZeroDev co-signs as the fee payer and broadcasts it to the network:
import { partiallySignTransactionMessageWithSigners } from "@solana/kit";
import { sponsorTransaction } from "@zerodev/solana-sponsorship-sdk";
const signedMessage = await partiallySignTransactionMessageWithSigners(message);
const response = await sponsorTransaction(sponsorshipRpc, signedMessage);
console.log(`Transaction sponsored: https://explorer.solana.com/tx/${response.signature}`);Error Handling
If sponsorship fails (e.g., you've hit a policy limit), the SDK throws a SponsorshipError:
import { sponsorTransaction, SponsorshipError } from "@zerodev/solana-sponsorship-sdk";
try {
const response = await sponsorTransaction(sponsorshipRpc, signedMessage);
} catch (error) {
if (error instanceof SponsorshipError) {
console.error(`Sponsorship failed (code ${error.code}): ${error.message}`);
}
}