Skip to main content

Overview

SVM Gas Sponsorship is Dynamic’s built-in feature that automatically sponsors Solana (SVM) transaction fees for your users. When enabled, Dynamic handles all the complexity of fee sponsorship behind the scenes, allowing your users to transact without needing SOL for gas fees. When enabled, Dynamic automatically replaces the fee payer in Solana transactions with a sponsored account, so your users don’t need SOL for gas.
SVM Gas Sponsorship is available exclusively for V3 MPC embedded wallets. It works automatically once enabled - no code changes required.

Prerequisites

Enabling SVM Gas Sponsorship

  1. Go to the Dynamic Dashboard
  2. Navigate to Settings > Embedded Wallets
  3. Ensure Solana (SOL) is enabled in your chain configurations
  4. Toggle on SVM Gas Sponsorship
The SVM Gas Sponsorship toggle only appears when Solana is enabled in your chain configurations and you’re using V3 MPC wallets.

How It Works

Once enabled, gas sponsorship is applied automatically to all transactions from your users’ embedded wallets. Your code remains unchanged:
import DynamicSDKSwift
import SolanaWeb3

let sdk = DynamicSDK.instance()

func sendSOLGasless(
    wallet: BaseWallet,
    recipient: String,
    amountInSOL: Double
) async throws -> String {
    // Create connection and signer
    let connection = try sdk.solana.createConnection()
    let signer = sdk.solana.createSigner(wallet: wallet)

    // Get latest blockhash
    let blockhash = try await connection.getLatestBlockhash()

    // Convert SOL to lamports
    let lamports = UInt64(amountInSOL * 1_000_000_000)

    // Create transaction - sponsorship is handled automatically
    let transaction = try SolanaWeb3.SolanaTransactionBuilder.createVersionedTransferTransaction(
        from: wallet.address,
        to: recipient,
        lamports: lamports,
        recentBlockhash: blockhash.blockhash
    )

    // Sign and send - gas fees are sponsored automatically
    return try await signer.signAndSendEncodedTransaction(
        base64Transaction: transaction.serializeToBase64()
    )
}

Transaction Flow

When your application sends a transaction:
  1. Transaction Creation: Your app creates a standard Solana transaction
  2. Automatic Sponsorship: The SDK intercepts the transaction before signing
  3. Backend Processing: The transaction is sent to Dynamic’s backend
  4. Sponsorship Processing: Dynamic sponsors the transaction
  5. Fee Payer Replacement: The transaction’s fee payer is replaced with Dynamic’s sponsored account
  6. User Signing: The sponsored transaction is returned for the user to sign
  7. Broadcast: The fully signed transaction is sent to the Solana network

Limitations

Wallet Requirements

  • Embedded wallets only: Sponsorship only works with Dynamic’s MPC embedded wallets
  • V3 wallets required: Must be using V3 MPC wallet configuration
  • Not for external wallets: External wallets (Phantom, Solflare, etc.) are not supported

Transaction Constraints

  • Transaction size: Maximum 2KB for the base64-encoded transaction
  • Already-signed transactions: Transactions that are already signed will not be sponsored
  • Single transaction: Each transaction is sponsored individually (no batching)

Fallback Behavior

If sponsorship fails, the SDK will fall back to using the original transaction, which requires the user to have SOL for gas fees.
When sponsorship fails, the transaction will proceed without sponsorship. Ensure your UX handles cases where users may need SOL for gas fees as a fallback.

Checking Sponsorship Status

You can check if gas sponsorship is enabled in your project settings:
let sdk = DynamicSDK.instance()

func checkSponsorshipEnabled() -> Bool {
    guard let settings = sdk.projectSettings else { return false }
    return settings.sdk?.embeddedWallets?.svmGasSponsorshipEnabled ?? false
}

Error Handling

func sendTransactionWithFallback(
    wallet: BaseWallet,
    recipient: String,
    amountInSOL: Double
) async throws -> String {
    do {
        // Attempt transaction - sponsorship applied automatically if enabled
        return try await sendSOLGasless(
            wallet: wallet,
            recipient: recipient,
            amountInSOL: amountInSOL
        )
    } catch {
        let errorDesc = error.localizedDescription.lowercased()

        if errorDesc.contains("insufficient") {
            // Even with sponsorship, user needs SOL for the transfer amount (not fees)
            throw SolanaError.insufficientBalance
        } else if errorDesc.contains("sponsor") {
            // Sponsorship failed, user may need SOL for gas
            throw SolanaError.sponsorshipFailed
        } else {
            throw error
        }
    }
}

Best Practices

  1. Don’t assume sponsorship: Build your UI to handle cases where sponsorship might not be available
  2. Show transaction status: Provide feedback during the sponsorship and signing process
  3. Test in Sandbox first: Verify sponsorship works in your Sandbox environment before going live
  4. Monitor usage: Keep an eye on sponsorship usage in your dashboard

Next Steps