> Feedback: If these docs are stale, missing, or confusing, post sanitized feedback to `https://docs.tempo.xyz/api/feedback` with `source: "mcp"`, a short `message`, and any relevant `toolName`, `relatedResource`, or `client`.
# Use Your Stablecoin for Fees

Enable users to pay transaction fees using your stablecoin. Tempo supports flexible fee payment options, allowing users to pay fees in any stablecoin they hold.

## Demo

<Demo.Container name="Use Your Stablecoin for Fees" footerVariant="source" src="tempoxyz/examples/tree/main/examples/issuance">
  <Connect stepNumber={1} />

  <AddFunds stepNumber={2} />

  <CreateOrLoadToken stepNumber={3} />

  <GrantTokenRoles stepNumber={4} roles={['issuer']} />

  <MintToken stepNumber={5} />

  <MintFeeAmmLiquidity stepNumber={6} />

  <PayWithIssuedToken stepNumber={7} last />
</Demo.Container>

## Steps

::::steps

### Create your stablecoin

First, create and mint your stablecoin by following the [Create a Stablecoin](/docs/guide/issuance/create-a-stablecoin) guide.

### Add fee pool liquidity

Before users can pay fees with your token, you need to provide liquidity in the Fee AMM between your token and a liquid quote token, or directly against validator payout tokens where you want explicit direct-route coverage.

To determine which validator tokens are needed, sample recent blocks and check the miner's preferred fee token using `getValidatorToken` on the FeeManager contract. For example, on Moderato testnet, validators accept fees in pathUSD and AlphaUSD. On mainnet, this token mix is different and subject to change.

Add liquidity to your token's fee pool:

:::code-group

```tsx twoslash [TypeScript]
// @noErrors
import { Hooks } from 'wagmi/tempo'
import { parseUnits } from 'viem'
import { useConnection } from 'wagmi'

const { address } = useConnection()
const yourToken = '0x...' // Your issued token address
const validatorToken = '0x20c0000000000000000000000000000000000001' // AlphaUSD on testnet

const mintFeeLiquidity = Hooks.amm.useMintSync() // [!code hl]

// Add 100 AlphaUSD of liquidity to the fee pool // [!code hl]
mintFeeLiquidity.mutate({ // [!code hl]
  feeToken: validatorToken,
  to: address,
  userTokenAddress: yourToken,
  validatorTokenAddress: validatorToken,
  validatorTokenAmount: parseUnits('100', 6),
}) // [!code hl]
```

```solidity [Solidity]
IFeeAMM feeAmm = IFeeAMM(TIP_FEE_AMM_ADDRESS);
address yourToken = 0x20c0000000000000000000000000000000000004; // Your issued token
address validatorToken = 0x20c0000000000000000000000000000000000001; // AlphaUSD

// Add 100 AlphaUSD of liquidity to the fee pool
feeAmm.mint(
  yourToken,
  validatorToken,
  100_000_000, // 100 tokens (6 decimals)
  address(this)
);
```

:::

You can also check your token's fee pool liquidity at any time:

:::code-group

```tsx twoslash [TypeScript]
// @noErrors
import { Hooks } from 'wagmi/tempo'

const { data: pool } = Hooks.amm.usePool({
  userToken: yourToken,
  validatorToken: '0x20c0000000000000000000000000000000000001', // AlphaUSD on testnet
})

const hasLiquidity = pool && pool.reserveValidatorToken > 0n
```

```solidity [Solidity]
IFeeAMM feeAmm = IFeeAMM(TIP_FEE_AMM_ADDRESS);
address yourToken = 0x20c0000000000000000000000000000000000004; // Your issued token
address validatorToken = 0x20c0000000000000000000000000000000000001; // AlphaUSD

// Get pool reserves
(uint256 reserveValidator, uint256 reserveUser) = feeAmm.getReserves(yourToken, validatorToken);

// Check if there's sufficient liquidity
require(reserveValidator > 0, "No liquidity available for fee conversion");
```

:::

If the pool has no liquidity (`reserveValidatorToken == 0`), you'll need to add liquidity to the fee pool before users can pay fees with your token. See the [Create a Stablecoin](/docs/guide/issuance/create-a-stablecoin) guide for instructions on minting fee AMM liquidity.

### Send payment with your token as fee

Your users can send payments using your issued stablecoin as the fee token:

:::code-group

```tsx twoslash [PayWithIssuedToken.tsx]
import React from 'react'
import { Hooks } from 'wagmi/tempo'
import { useConnection } from 'wagmi'
import { parseUnits, pad, stringToHex, isAddress } from 'viem'

// @noErrors
export function PayWithIssuedToken() {
  const { address } = useConnection()
  const [recipient, setRecipient] = React.useState<string>('')
  const [memo, setMemo] = React.useState<string>('')

  const feeToken = '0x...' // Your issued token address
  const paymentToken = '0x20c0000000000000000000000000000000000001' // AlphaUSD

  const { data: paymentBalance, refetch: paymentBalanceRefetch } = // [!code hl]
    Hooks.token.useGetBalance({ // [!code hl]
      account: address, // [!code hl]
      token: paymentToken, // [!code hl]
    }) // [!code hl]

  const { data: feeTokenBalance, refetch: feeTokenBalanceRefetch } = // [!code hl]
    Hooks.token.useGetBalance({ // [!code hl]
      account: address, // [!code hl]
      token: feeToken, // [!code hl]
    }) // [!code hl]

  const sendPayment = Hooks.token.useTransferSync({ // [!code hl]
    mutation: { // [!code hl]
      onSettled() { // [!code hl]
        paymentBalanceRefetch() // [!code hl]
        feeTokenBalanceRefetch() // [!code hl]
      }, // [!code hl]
    }, // [!code hl]
  }) // [!code hl]

  const isValidRecipient = recipient && isAddress(recipient)

  const handleTransfer = () => { // [!code hl]
    if (!isValidRecipient) return // [!code hl]
    sendPayment.mutate({ // [!code hl]
      amount: parseUnits('100', 6), // [!code hl]
      to: recipient as `0x${string}`, // [!code hl]
      token: paymentToken, // [!code hl]
      memo: memo ? pad(stringToHex(memo), { size: 32 }) : undefined, // [!code hl]
      feeToken, // Pay fees with your issued token // [!code hl]
    }) // [!code hl]
  } // [!code hl]

  return (
    <>
      <div>
        <label>Recipient address</label>
        <input
          type="text"
          value={recipient}
          onChange={(e) => setRecipient(e.target.value)}
          placeholder="0x..."
        />
      </div>
      <div>
        <label>Memo (optional)</label>
        <input
          type="text"
          value={memo}
          onChange={(e) => setMemo(e.target.value)}
          placeholder="INV-12345"
        />
      </div>
      <button // [!code hl]
        disabled={!address || !isValidRecipient || sendPayment.isPending} // [!code hl]
        onClick={handleTransfer} // [!code hl]
        type="button" // [!code hl]
      > {/* [!code hl] */}
      {sendPayment.isPending ? 'Sending...' : 'Send'} {/* [!code hl] */}
      </button> {/* [!code hl] */}
    </>
  )
}
```

```tsx twoslash [config.ts] filename="config.ts"
// @noErrors
import { createConfig, http } from 'wagmi'
import { tempo } from 'viem/chains'
import { tempoWallet } from 'wagmi/connectors'

export const config = createConfig({
  chains: [tempo],
  connectors: [tempoWallet()],
  transports: {
    [tempo.id]: http(),
  },
})
```

```solidity [Solidity]
ITIP20 token = ITIP20(0x20c0000000000000000000000000000000000001); // AlphaUSD
address yourToken = 0x20c0000000000000000000000000000000000004; // Your issued stablecoin
address recipient = 0xbeefcafe54750903ac1c8909323af7beb21ea2cb;

// Send payment using your token for fees
IFeeManager feeManager = IFeeManager(TIP_FEE_MANAGER_ADDRESS);
feeManager.setTransactionFeeToken(yourToken);
token.transfer(recipient, 100_000_000);
```

```rust [Rust]
use alloy::{
    primitives::{address, U256},
    providers::ProviderBuilder,
};
use tempo_alloy::{
    TempoNetwork,
    contracts::precompiles::{ITIPFeeAMM, TIP_FEE_MANAGER_ADDRESS},
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let provider = ProviderBuilder::new_with_network::<TempoNetwork>()
        .connect(&std::env::var("RPC_URL").expect("No RPC URL set"))
        .await?;

    // Your issued token
    let your_token = address!("0x20c0000000000000000000000000000000000004"); // [!code focus]
    // AlphaUSD
    let validator_token = address!("0x20c0000000000000000000000000000000000001"); // [!code focus]

    let fee_amm = ITIPFeeAMM::new( // [!code focus]
        TIP_FEE_MANAGER_ADDRESS, // [!code focus]
        &provider, // [!code focus]
    ); // [!code focus]

    let recipient = address!("0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"); // [!code focus]

    // Add 100 AlphaUSD of liquidity to the fee pool
    fee_amm // [!code focus]
        .mint( // [!code focus]
            your_token, // [!code focus]
            validator_token, // [!code focus]
            U256::from(100_000_000), // [!code focus]
            recipient, // [!code focus]
        ) // [!code focus]
        .send() // [!code focus]
        .await? // [!code focus]
        .get_receipt() // [!code focus]
        .await?; // [!code focus]

    println!("Fee liquidity added successfully"); // [!code focus]

    Ok(())
}
```

:::

Users can set your stablecoin as their default fee token at the account level, or specify it for individual transactions. Learn more about [how users pay fees in different stablecoins](/docs/guide/payments/pay-fees-in-any-stablecoin).

::::

## How It Works

When users pay transaction fees with your stablecoin, Tempo's fee system automatically handles the conversion if validators prefer a different token. The [Fee AMM](/docs/protocol/fees/spec-fee-amm) ensures seamless fee payments across all supported stablecoins.

Users can select your stablecoin as their fee token through:

* **Account-level preference**: Set as default for all transactions
* **Transaction-level preference**: Specify for individual transactions
* **Automatic selection**: When directly interacting with your token contract

Learn more about [how users pay fees in different stablecoins](/docs/guide/payments/pay-fees-in-any-stablecoin) and the complete [fee token preference hierarchy](/docs/protocol/fees/spec-fee#fee-token-preferences).

## Benefits

* **User convenience**: Users can pay fees with the same token they're using
* **Liquidity**: Encourages users to hold your stablecoin
* **Flexibility**: Works seamlessly with Tempo's fee system

## Best Practices

### Monitor pool liquidity

Regularly check your token's fee pool reserves to ensure users can consistently pay fees with your stablecoin. Low liquidity can prevent transactions from being processed.

### Maintain adequate reserves

Keep sufficient validator token reserves in your fee pool to handle expected transaction volume. Consider your user base size and typical transaction frequency when determining reserve levels.

As fees accrue in your token, the pool will run low on validator tokens and need to be rebalanced. Use [`rebalanceSwap`](/docs/guide/stablecoin-dex/managing-fee-liquidity#rebalance-liquidity) to replenish validator token reserves when they become depleted.

### Test before launch

Before promoting fee payments with your token, thoroughly test the flow on testnet:

1. Add liquidity to the fee pool
2. Verify users can set your token as their fee preference
3. Execute test transactions with various gas costs
4. Monitor that fee conversions work correctly

## Next Steps

<Cards>
  <Card description="Manage roles, supply caps, and transfer policies" to="/docs/guide/issuance/manage-stablecoin" icon="lucide:settings" title="Manage Your Stablecoin" />

  <Card description="Add and remove liquidity to enable fee conversions" to="/docs/guide/stablecoin-dex/managing-fee-liquidity" icon="lucide:droplet" title="Managing Fee Liquidity" />

  <Card description="Complete fee token specification" to="/docs/protocol/fees/spec-fee" icon="lucide:file-text" title="Fee Tokens" />
</Cards>
