Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions docs/pages/protocol/fees/spec-fee-amm.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Callout } from 'vocs/components'

## Abstract

This specification defines a system of one-way Automated Market Makers (AMMs) designed to facilitate gas fee payments from a user using one stablecoin (the `userToken`) to a validator who prefers a different stablecoin (the `validatorToken`). Each AMM handles fee swaps from a `userToken` to a `validatorToken` at one price (0.9970 `validatorToken` per `userToken`), and allows rebalancing in the other direction at another fixed price (0.9985 `validatorToken` per `userToken`).
This specification defines a system of one-way Automated Market Makers (AMMs) designed to facilitate gas fee payments from a user using one stablecoin (the `userToken`) to a validator who prefers a different stablecoin (the `validatorToken`). Each AMM handles fee swaps from a `userToken` to a `validatorToken` at one price (0.9970 `validatorToken` per `userToken`), and allows rebalancing in the other direction at another fixed price (1.0015 `userToken` per `validatorToken`).

## Motivation

Expand All @@ -30,7 +30,7 @@ The system is designed to minimize several forms of MEV:
The Fee AMM implements two distinct swap mechanisms:

1. **Fee Swaps**: Fixed-rate swaps at a price of `0.9970` (validator token per user token) from `userToken` to `validatorToken`
2. **Rebalancing Swaps**: Fixed-rate swaps at a price of `0.9985` (validator token per user token) from `validatorToken` to `userToken`
2. **Rebalancing Swaps**: Fixed-rate swaps at a price of `1.0015` (user token per validator token) from `validatorToken` to `userToken`

### Core Components

Expand Down Expand Up @@ -85,7 +85,7 @@ function rebalanceSwap(
) external returns (uint256 amountIn)
```

Executes rebalancing swaps from `validatorToken` to `userToken` at fixed rate of 0.9985 (validator token per user token). Can be executed by anyone. Calculates `amountIn = (amountOut * N) / SCALE + 1` (rounds up). Updates reserves immediately. Emits `RebalanceSwap` event.
Executes rebalancing swaps from `validatorToken` to `userToken` at fixed rate of 1.0015 (user token per validator token). Can be executed by anyone. Calculates `amountIn = (amountOut * N) / SCALE + 1` (rounds up). Updates reserves immediately. Emits `RebalanceSwap` event.

```solidity
function mint(
Expand Down
136 changes: 136 additions & 0 deletions docs/pages/protocol/tips/tip-1007.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
# Fee Token Introspection

This document specifies the addition of fee token introspection functionality to the FeeManager precompile, enabling smart contracts to query the fee token being used for the current transaction.

- **TIP ID**: TIP-1007
- **Authors/Owners**: Georgios Konstantopoulos
- **Status**: Draft
- **Related Specs/TIPs**: [Fee Manager](/protocol/fees/spec-fee), [TIP-20](/protocol/tip20/spec)
- **Protocol Version**: TBD

---

# Overview

## 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
Loading