diff --git a/docs/pages/protocol/fees/spec-fee-amm.mdx b/docs/pages/protocol/fees/spec-fee-amm.mdx index 9b032c7daa..bbad615cd7 100644 --- a/docs/pages/protocol/fees/spec-fee-amm.mdx +++ b/docs/pages/protocol/fees/spec-fee-amm.mdx @@ -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 @@ -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 @@ -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( diff --git a/docs/pages/protocol/tips/tip-1007.mdx b/docs/pages/protocol/tips/tip-1007.mdx new file mode 100644 index 0000000000..2411ac23ab --- /dev/null +++ b/docs/pages/protocol/tips/tip-1007.mdx @@ -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