Valantis Documentation
Valantis Website
  • Welcome to Valantis
  • Sovereign Pool
    • The Modules
      • Pool Manager
      • Liquidity Module
      • Swap Fee Module
      • Verifier Module
      • Oracle Module
      • Sovereign Vault
        • Rebase token support
      • Gauge
    • Interacting with Pools
      • Swap Parameters
      • Swap Steps
      • Multi Token Support
      • Deposit Liquidity
      • Withdraw Liquidity
      • Flash Loans
  • Hybrid Order Type (HOT)
    • Understanding HOT: A Graphical Overview
    • HOT API
      • HTTP request parameters
      • HTTP request response
      • Reasoning for Request structure
      • Solver Integration
      • Market Maker integration
    • HOT Smart Contracts
      • Interfaces
      • State variables and roles
      • AMM
      • HOT Swap
      • AMM Swap
      • Hybrid Order Type (HOT) struct parameters
      • Alternating Nonce Bitmap
      • Deposits
      • Withdrawals
      • Deployment Assumptions
    • Liquidity Manager Docs
      • Reference Oracle
      • Deposit
      • Withdraw
      • Signature
    • Swap
      • Swap Context
      • AMM Swap
      • HOT Swap
      • HOT Quote Parameters
        • Bitmap Nonce Instructions
    • Solver Docs
      • Solver Request
      • Simple HOT Swap Example
      • Partial Fill HOT Swap Example
    • Risks and Trust Assumptions
      • Roles
        • Sovereign Pool Manager
        • HOT Manager
        • HOT Signer
        • Liquidity Provider
      • Threats
        • Deposit Sandwich
        • Malicious Price Bound
        • Malicious Signer
        • Mispriced HOT Quote
  • Validly
    • Understanding Validly
    • Swap
    • Deposits and Withdrawals
    • Deployments
  • Stake Exchange (stHYPE AMM)
    • Swap
      • Instant Withdrawals (LST -> Native Token)
      • New Stake (Native Token -> LST)
    • LP Positions
      • LP Withdrawals Instant
      • LP Withdrawal Queued
    • Ratio Fee
    • Lending of Reserves
    • Smart contracts
      • STEXAMM.sol
      • StHYPEWithdrawalModule.sol
      • StexRatioSwapFeeModule.sol
      • DepositWrapper.sol
      • AaveLendingModule.sol
    • Risks and Trust Assumptions
    • Integration examples
  • Deploy and Build
  • Resources
    • Audits
    • Links
    • Get HYPE on HyperEVM
Powered by GitBook
On this page

Was this helpful?

  1. Sovereign Pool
  2. The Modules

Swap Fee Module

PreviousLiquidity ModuleNextVerifier Module

Last updated 1 year ago

Was this helpful?

The Swap Fee Module is responsible for calculating the fees applied at swap time. It is an optional module. When Swap Fee Module is not set, the pool will use the default constant swap fee set at construction.

At the beginning of each swap, the following function gets called:

struct SwapFeeModuleData {
    uint256 feeInBips;
    bytes internalContext;
}

function getSwapFeeInBips(
        address _tokenIn,
        address _tokenOut,
        uint256 _amountIn,
        address _user,
        bytes memory _swapFeeModuleContext
    ) external returns (SwapFeeModuleData memory swapFeeModuleData);

It takes the following inputs:

  • _tokenIn Input token for the swap.

  • _tokenOut Output token for the swap.

  • _amountIn Input token amount which _user wants to trade.

  • _user address of msg.sender in the pool’s swap function.

  • _swapFeeModuleContext Optional bytes encoded calldata for the case where the Swap Fee Module leverages off-chain or external data to function. For example, this can be used to provide signed price feeds or volatility estimates.

The module returns the fee amount to be charged in basis points (swapFeeModuleData.feeInBips) and arbitrary internal context as bytes for the case where the Swap Fee Module needs to be called once again at the end of the swap (swapFeeModuleData.internalContext). IMPORTANT: Since the Swap Fee Module gets queried before the Liquidity Module, there is no way to know in advance how much liquidity will be filled when quoting fees. Hence the swapFeeModuleData.feeInBips should be understood as follows:

First, we calculate amountInMinusFee as follows:

uint256 amountInMinusFee = Math.mulDiv(_amountIn, 1e4, 1e4 + swapFeeModuleData.feeInBips);

Note that swapFeeModuleData.feeInBips must not be greater than 1e4, meaning that the maximum possible swap fee is 50%.

Then, once the Liquidity Module gets queried and returns liquidityQuote.amountInFilled, the effectiveFee is calculated as follows:

uint256 effectiveFee = Math.mulDiv(liquidityQuote.amountInFilled, swapFeeModuleData.feeInBips, 1e4, Math.Rounding.Up);

We round up to ensure that fee calculation goes in favor of the pool.

So the total amount that the user gets changed in tokenIn will be liquidityQuote.amountInFilled + effectiveFee

swapFeeModuleData.feeInBips should be interpreted as the fee multiplier in basis points which gets applied to the tokenIn amount filled by the liquidity module, not the user’s initial _amountIn

If swapFeeModuleData.internalContext is a non-empty byte encoded payload, the following function gets called after execution of the swap:

function callbackOnSwapEnd(
        uint256 _effectiveFee,
        uint256 _amountInUsed,
        uint256 _amountOut,
        SwapFeeModuleData memory _swapFeeModuleData
    ) external;

This allows the Swap Fee Module to make any required internal state updates.

Swap Fee Modules can be reusable across both Universal and Sovereign pools without requiring developers to re-write nor replace Liquidity Modules. They can implement any kind of fee calculation logic, as long as they do not quote a fee above 50% of the input token amount on each swap.

Alternatively, in the case where a Swap Fee Module is not added to the pool (swapFeeModule = address(0)), the pool will use an immutable fee multiplier to calculate swap fees, lowering gas costs. Even after whitelisting a swap fee module, poolManager can always reset it to address(0), in which case a default constant swap fee would be applied.

Alternatively, both the Swap Fee Module and the immutable default fee can be ignored and the Liquidity Module can consider fee accounting logic when providing price quotes. Though this removes the ability for a Pool Manager to collect fees.

NOTE: The Swap Fee Module can only be changed by the Pool Manager once every 3 days. This prevents unexpected changes in Swap Fee logic.

Swap Fee Module in context