·Transfa Team

How to Sponsor Transaction Fees on Tempo

Implement fee sponsorship on Tempo so your users never need to hold tokens for gas. Covers co-signature mechanics, SDK integration, and custom fee payer servers.

tempofee-sponsorshipgaslesstransactions

On most blockchains, users need to acquire a volatile token (ETH, SOL) before they can do anything. Tempo eliminates the volatile token (fees are paid in stablecoins) but users still need a stablecoin balance to cover gas. Fee sponsorship lets a third party pay the transaction fee on behalf of the user, so end users can interact with your application without holding any tokens at all.

This is different from how gasless transactions work on Ethereum. There's no Paymaster contract to deploy, no bundler infrastructure, no EIP-4337 stack. Tempo uses domain-separated co-signatures at the protocol level.

Prerequisites

How fee sponsorship works on Tempo

A standard Tempo transaction is signed by the sender, who also pays the fee. With fee sponsorship, two signatures are included:

  1. Sender signature: signed with domain prefix 0x76. The sender omits fee_token from their signing hash.
  2. Fee payer signature: signed with domain prefix 0x78. The fee payer commits to the sender's address, the fee token, and the full transaction.

The protocol validates both signatures and charges the fee payer's balance instead of the sender's. The domain separation (different prefix bytes) prevents either signature from being replayed in the other's context.

This design has a few consequences:

  • Fee sponsorship is built in, without a Paymaster, EntryPoint, or staking contract.
  • A sponsored transaction is one transaction with two signatures.
  • The fee payer's signature specifies which stablecoin to pay fees in. The sender doesn't need to know or care.

Use the public testnet sponsor

Moderato provides a public fee sponsorship service for testing. Instead of running your own fee payer, point your transport at the sponsor endpoint:

import { createWalletClient, http } from "viem";
import { tempoTestnet } from "viem/chains";
import { withFeePayer } from "viem/tempo";
 
const client = createWalletClient({
  chain: tempoTestnet,
  transport: withFeePayer(
    http(),
    http("https://sponsor.moderato.tempo.xyz")
  ),
});

Now any transaction sent through this client will be automatically sponsored. The user signs the transaction, the client forwards it to the sponsor service for the fee payer co-signature, and the combined transaction is submitted to the network.

With Wagmi

If you're building a React app with Wagmi:

import { createConfig, http } from "wagmi";
import { tempoTestnet } from "wagmi/chains";
import { withFeePayer } from "wagmi/tempo";
 
const config = createConfig({
  chains: [tempoTestnet],
  transports: {
    [tempoTestnet.id]: withFeePayer(
      http(),
      http("https://sponsor.moderato.tempo.xyz")
    ),
  },
});

Then send a sponsored transfer:

import { Hooks } from "wagmi/tempo";
import { parseUnits } from "viem";
 
function SendPayment() {
  const sendPayment = Hooks.tip20.useTransferSync();
 
  const handleSend = () => {
    sendPayment.mutate({
      amount: parseUnits("100", 6),
      to: "0xRECIPIENT_ADDRESS",
      token: "0x20c0000000000000000000000000000000000001",
      feePayer: true,
    });
  };
 
  return <button onClick={handleSend}>Send 100 AlphaUSD</button>;
}

Setting feePayer: true routes the transaction through the fee payer transport. The sender never needs a balance for gas.

Build a custom fee payer server

For production, you'll run your own fee payer service. This gives you control over which transactions to sponsor, spending limits, and which stablecoin to pay fees in.

The Tempo SDK provides a Handler.feePayer utility that handles the co-signature logic:

import { Handler } from "viem/tempo";
import { createServer } from "http";
import { privateKeyToAccount } from "viem/accounts";
 
const feePayerAccount = privateKeyToAccount("0xFEE_PAYER_PRIVATE_KEY");
 
const handler = Handler.feePayer({
  account: feePayerAccount,
  chain: tempoTestnet,
  transport: http("https://rpc.moderato.tempo.xyz"),
  // Optional: add custom validation logic
  async onRequest(request) {
    // Reject transactions you don't want to sponsor
    // Return true to sponsor, false to reject
    return true;
  },
});
 
const server = createServer(async (req, res) => {
  const body = await getBody(req);
  const result = await handler(JSON.parse(body));
  res.writeHead(200, { "Content-Type": "application/json" });
  res.end(JSON.stringify(result));
});
 
server.listen(3001);

Then point your client transport at your server:

const client = createWalletClient({
  chain: tempoTestnet,
  transport: withFeePayer(
    http("https://rpc.moderato.tempo.xyz"),
    http("http://localhost:3001")
  ),
});

How fee token selection works

When the protocol processes a transaction, it selects which stablecoin to charge for fees using this priority:

  1. Transaction-level fee_token: explicitly set in the transaction
  2. Account-level preference: set via setUserToken() on the Fee Manager precompile (0xfeec000000000000000000000000000000000000)
  3. Context-based: if the transaction calls transfer() or transferWithMemo() on a USD TIP-20 token, that token is used
  4. Fallback: pathUSD

At each level, the protocol checks three things: (a) the token is a USD-denominated TIP-20, (b) the payer has enough balance to cover gasLimit * gasPrice, and (c) the Fee AMM has liquidity for that token.

For fee sponsorship, the fee payer's co-signature specifies the fee token. If your fee payer holds AlphaUSD, sponsored transactions will be paid in AlphaUSD.

Fee costs

Tempo fees are denominated in USD. A standard TIP-20 transfer costs approximately 0.1 cent at base fee (20 gwei). The fee formula:

fee = ceil(base_fee * gas_used / 10^12)

The Fee AMM applies a 0.3% swap rate when converting between stablecoins (0.9970 ratio). This only applies when the fee token differs from what validators expect. On Moderato, validators expect AlphaUSD.

In practice, sponsoring transactions is cheap. At 0.1 cents per transfer, 10,000 sponsored transfers cost about $10.

Monitor sponsored transactions

Use the Transfa Data API to track transactions from your fee payer address:

curl -X GET "https://api.transfa.com/v1/wallets/0xFEE_PAYER_ADDRESS/transactions?chain=moderato" \
  -H "x-api-key: YOUR_API_KEY"

This shows all transaction activity associated with your fee payer, including the decoded token transfer events and balance changes. You can use this to monitor spending and set alerts when the fee payer's balance drops below a threshold.

Comparison with EIP-4337 paymasters

Tempo fee sponsorshipEIP-4337 paymasters
InfrastructureNone (protocol-native)EntryPoint contract, bundler, paymaster contract
Transaction typeSingle transaction, two signaturesUserOperation bundled into separate transaction
LatencySame as normal transactionExtra hop through bundler
Fee payer costGas for one transactionGas + bundler fees + paymaster verification
Account typeStandard EOASmart contract wallet required
DeploymentNo contractsDeploy paymaster, stake ETH

Tempo's approach is simpler but less flexible. EIP-4337 paymasters can implement arbitrary sponsorship logic on-chain (e.g., sponsor only if user holds an NFT). Tempo's validation happens off-chain in the fee payer server. The protocol just verifies the co-signature.

What to read next