Swap Fee Module
Last updated
Last updated
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:
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:
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:
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:
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.