Swap Fees
More Details
For more detailed information on Swap Fees please see the Swap Fee Concepts section.
A swap fee is charged for each swap, as well as on the non-proportional amounts in add/remove liquidity operations. The swap fee is always charged on the amount in:
- EXACT_IN, on the given amount (see Vault.sol):
// Round up to avoid losses during precision loss.
locals.totalSwapFeeAmountScaled18 = poolSwapParams.amountGivenScaled18.mulUp(swapState.swapFeePercentage);
poolSwapParams.amountGivenScaled18 -= locals.totalSwapFeeAmountScaled18;
- EXACT_OUT, the calculated amount (see Vault.sol)):
// To ensure symmetry with EXACT_IN, the swap fee used by ExactOut is
// `amountCalculated * fee% / (100% - fee%)`. Add it to the calculated amountIn. Round up to avoid losing
// value due to precision loss. Note that if the `swapFeePercentage` were 100% here, this would revert with
// division by zero. We protect against this by ensuring in PoolConfigLib and HooksConfigLib that all swap
// fees (static, dynamic, pool creator, and aggregate) are less than 100%.
locals.totalSwapFeeAmountScaled18 = amountCalculatedScaled18.mulDivUp(
swapState.swapFeePercentage,
swapState.swapFeePercentage.complement()
);
Swap fees come in two different forms for V3 pools:
- Static Swap Fee:
- Initially set as part of the pool registration.
- Authorized addresses can then change the value by invoking the vault.setStaticSwapFeePercentage(address pool, uint256 swapFeePercentage) function.
- If the staticSwapFeePercentage is changed, it will emit an event:
SwapFeePercentageChanged(pool, swapFeePercentage);
- Note -
setStaticSwapFeePercentage
can also be called as part of a regular hook
- Dynamic Swap Fee Using Hooks:
- Using Hooks a pool can be set up to use dynamic swap fees.
- The Vault uses the
onComputeDynamicSwapFeePercentage()
hook to fetch the dynamic swap fee. This function can implement arbitrary logic. - Even when a pool is set to use dynamic swap fees, it still maintains a static swap fee. However, this static fee is not utilized.
The pseudo logic to determine how swap fee is calculated looks like:
swapFeePercentage =
Pool has DynamicSwapFee => call DynamicSwapFeeHook in the pool
else => load static Swap fee percentage from Vault