Skip to main content

Overview

On Solana, fee sponsorship and rent sponsorship are separate. Fee sponsorship covers the network fee for a transaction. Rent sponsorship covers the rent-exempt lamports needed when instructions create new accounts. If an instruction creates a new account and the user signer is the payer, Turnkey pre-funds that signer for the rent-exempt amount. The amount is based on the size of the new account data and is intended to make the account rent exempt. When enabled, sponsored rent is added to your monthly gas bill and counts toward the same spend limits used for sponsored transaction fees. See Spend limits. Rent sponsorship is disabled by default and must be enabled separately in the Turnkey dashboard. For the broader transaction-construction model behind sponsored Solana flows, including payer behavior and account-creation caveats, see Solana transaction construction for sponsored flows.

Enable rent sponsorship

If your sponsored Solana transactions may create accounts, you must explicitly enable rent sponsorship in the Turnkey dashboard.
  1. Enable gas sponsorship.
  2. Turn on Sponsor Solana Rent.
  3. Click Save Configuration.
Turnkey dashboard showing Sponsor Solana Rent enabled
Refunded rent from later-closed accounts follows Solana account rules. It does not automatically return to the sponsor.

Rent extraction risk

On Solana, when an account is later closed, the rent previously deposited into that account is returned according to Solana account rules, usually to the configured destination for the close operation. That destination is usually the signer or account owner, not the sponsor that originally funded the rent. This creates a rent extraction risk for sponsored Solana transactions: the sponsor covers the rent needed to create the account, but the refunded rent can later flow back to the signer instead. This is not necessarily malicious. It can happen in ordinary product flows. A common example is a swap that temporarily wraps SOL into wSOL, uses that account during execution, and then closes the temporary account before the transaction completes. In a self-funded flow, the rent simply returns to the user. In a sponsored flow, that same rent may have been pre-funded by the sponsor and then refunded back to the signer.

Mitigations and guardrails

The best mitigation depends on how much transaction flexibility your product allows.
  • Reuse a constrained set of token accounts where possible instead of creating and closing them repeatedly.
  • Avoid or strip CloseAccount patterns from sponsored flows when that works for your product.
  • Prefer backend-generated or backend-validated transactions for higher-control flows.
  • Use spend caps, rate limits, monitoring, and alerts to bound and detect repeated leakage.
  • Treat account creation and account closure as first-class review criteria for sponsored Solana transactions.

Strip CloseAccount instructions before submission

One practical guardrail is to inspect the transaction payload before submission and remove SPL Token CloseAccount instructions. This is especially useful when you receive a prebuilt transaction from a routing service such as Jupiter and want to keep your sponsored flow from immediately refunding rent back to the signer. In the SPL Token program, CloseAccount is instruction discriminator 9. A simple filter can remove those instructions before you hand the transaction to Turnkey:
const SPL_TOKEN_PROGRAM_IDS = new Set([
  "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
  "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb",
]);

const CLOSE_ACCOUNT_INSTRUCTION_DISCRIMINATOR = 9;

function isCloseAccountInstruction(ix: TransactionInstruction): boolean {
  return (
    SPL_TOKEN_PROGRAM_IDS.has(ix.programId.toBase58()) &&
    ix.data[0] === CLOSE_ACCOUNT_INSTRUCTION_DISCRIMINATOR
  );
}

const filteredInstructions = txMessage.instructions.filter(
  (ix) => !isCloseAccountInstruction(ix),
);
This does not eliminate all rent-related risk, but it removes one of the most common leakage paths in sponsored swap flows.

Disable Jupiter auto wrap and unwrap for SOL flows

Another useful guardrail is to disable Jupiter’s automatic SOL wrapping and unwrapping behavior when you request the swap transaction. When wrapAndUnwrapSol is enabled, Jupiter may create a temporary wSOL account for the transaction and then close it before completion. In a sponsored flow, that pattern can create a rent refund path back to the signer. To prevent that, set wrapAndUnwrapSol to false in the Jupiter API request:
body: JSON.stringify({
  quoteResponse,
  userPublicKey: request.signWith,
  wrapAndUnwrapSol: false,
  dynamicComputeUnitLimit: true,
  prioritizationFeeLamports: "auto",
})
With this setting disabled, your application should manage wSOL explicitly instead of relying on Jupiter to create and close a temporary account on the user’s behalf. This higher-control approach is often a better fit for sponsored flows because it lets you:
  • reuse a persistent wSOL account instead of creating a fresh one per swap
  • avoid automatic close-account behavior in the routed transaction
  • review account lifecycle decisions on the backend before submission
For products with tighter controls, the strongest approach is usually to combine both mitigations: disable auto wrap and unwrap where possible, and still validate or sanitize the final instruction payload before sending it.

Key custody matters

These mitigations are weaker if end users can export or independently control the signer key. Even if your application removes account-close instructions from the original sponsored flow, a user who later controls the signer can submit a separate transaction to close previously created accounts and reclaim rent. If you need stronger protection, keep transaction submission behind your backend and avoid giving end users independent signer control.

Policy guidance

These example deny policies can help reduce common Solana rent-leakage patterns in sponsored flows.

Deny sponsored Solana CloseAccount

{
  "effect": "EFFECT_DENY",
  "condition": "solana.tx.instructions.any(i, (i.program_key == 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA' || i.program_key == 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb') && i.instruction_data_hex == '09')"
}

Deny sponsored Solana account lifecycle ops

{
  "effect": "EFFECT_DENY",
  "condition": "solana.tx.instructions.any(i, i.program_key == 'ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL') || solana.tx.instructions.any(i, (i.program_key == 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA' || i.program_key == 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb') && (i.instruction_data_hex == '09' || i.instruction_data_hex == '11'))"
}

Next steps