---
id: TIP-1007
title: Fee Token Introspection
description: Addition of fee token introspection functionality to the FeeManager precompile, enabling smart contracts to query the fee token being used for the current transaction.
authors: Georgios Konstantopoulos
status: In Review
related: N/A
protocolVersion: TBD
---

# TIP-1007: Fee Token Introspection

## Abstract

TIP-1007 adds a `getFeeToken()` view function to the FeeManager precompile that returns the fee token address being used for the current transaction. This enables smart contracts to introspect which TIP-20 token is paying for gas fees during execution, allowing for dynamic logic based on the fee token choice.

## Motivation

Tempo transactions support paying gas fees in any USD-denominated TIP-20 token via the fee token preference system. However, prior to this TIP, there was no way for a smart contract to determine which fee token is being used for the current transaction during execution.

This capability was requested by a partner. It could be useful for contracts that want to:

- Adjust their internal logic based on which fee token is being used
- Provide fee token-aware pricing or routing decisions
- Emit events or logs that include the fee token for off-chain indexing
- Implement fee token-specific behavior in cross-chain messaging

---

# Specification

## New Function

The following function is added to the `IFeeManager` interface:

```solidity
interface IFeeManager {
    // ... existing functions ...

    /// @notice Returns the fee token being used for the current transaction
    /// @return The address of the TIP-20 token paying for gas fees
    /// @dev This value is set by the protocol before transaction execution begins.
    ///      Returns address(0) if no fee token has been set (e.g., in eth_call
    ///      simulations where the transaction handler does not run).
    function getFeeToken() external view returns (address);
}
```

## Behavior

### Fee Token Resolution

The fee token returned by `getFeeToken()` is the same token that was resolved by the protocol during transaction validation, following the [fee token preference rules](/protocol/fees/spec-fee#fee-token-resolution).

### Storage

The fee token is stored in **transient storage** (EIP-1153) within the FeeManager precompile. This means:

- The value is automatically cleared at the end of each transaction
- No persistent storage writes occur, minimizing gas costs
- The value is consistent across all calls within a transaction (including internal calls and subcalls)

### Timing

The fee token is set by the protocol in the `validate_against_state_and_deduct_caller` handler phase, before any user code executes. This ensures the value is available throughout the entire transaction execution.

### Gas Cost

Reading the fee token costs the standard warm transient storage read cost (100 gas for TLOAD). This is the cost of calling `getFeeToken()` itself; callers should account for additional gas used by the CALL opcode to invoke the precompile.

### Edge Cases

| Scenario | Return Value |
|----------|--------------|
| Normal transaction | The resolved fee token address |
| Free transaction (zero gas price) | The resolved fee token (may still be set) |
| `eth_call` simulation | `address(0)` (no transaction context) |

The only case where `address(0)` is returned is in simulation contexts (e.g., `eth_call`) where the protocol handler does not execute.

## Example Usage

```solidity
import { IFeeManager } from "./interfaces/IFeeManager.sol";

contract FeeTokenAware {
    IFeeManager constant FEE_MANAGER = IFeeManager(0xfeeC000000000000000000000000000000000000);
    address constant PATH_USD = 0x20C0000000000000000000000000000000000000;

    function doSomething() external {
        address feeToken = FEE_MANAGER.getFeeToken();

        if (feeToken == PATH_USD) {
            // User is paying fees in pathUSD
        } else if (feeToken != address(0)) {
            // User is paying fees in a different USD stablecoin
        } else {
            // No fee token context (e.g., eth_call simulation)
        }
    }
}
```

## Interface Addition

The following function is added to `IFeeManager`:

```solidity
/// @notice Returns the fee token being used for the current transaction
/// @return The address of the TIP-20 token paying for gas fees
function getFeeToken() external view returns (address);
```

---

# Invariants

- `getFeeToken()` must return a consistent value across all calls within the same transaction
- `getFeeToken()` must return `address(0)` in simulation contexts (e.g., `eth_call`) where no transaction handler runs
- `getFeeToken()` must be callable from `staticcall` contexts without reverting
- The fee token returned must match the token used for actual fee deduction in `collectFeePreTx` and `collectFeePostTx`
- Reading the fee token must not modify any state (view function)

## Test Cases

The test suite must cover:

1. **Basic functionality**: `getFeeToken()` returns the correct fee token address
2. **Zero when unset**: Returns `address(0)` when no fee token is set
3. **Consistency**: Same value returned from nested calls within a transaction
4. **Static call safety**: Works correctly when called via `staticcall`
5. **Transient storage**: Value is cleared between transactions
6. **Different fee tokens**: Works with various TIP-20 fee tokens (pathUSD, USDC, etc.)
7. **Dispatch coverage**: Function selector is correctly dispatched by the precompile
