Skip to content

Commit

Permalink
Merge pull request #178 from balancer/swap-fee-updates
Browse files Browse the repository at this point in the history
Update swap fee sections to reflect final approach.
  • Loading branch information
johngrantuk authored Nov 25, 2024
2 parents 108ef4a + c29a350 commit 43eb127
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 14 deletions.
8 changes: 4 additions & 4 deletions docs/concepts/vault/swap-fee.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: Swap Fee
order: 8
---
# Swap fee
A swap fee is charged for each swap, as well as on the non-proportional amounts in add/remove liquidity operations. When a pool is registered, the initial swap fee is passed as a parameter and stored as part of [the pool's configuration](https://github.com/balancer/balancer-v3-monorepo/blob/main/pkg/interfaces/contracts/vault/VaultTypes.sol#L28-L39). The swap fee is always charged on the calculated amount (i.e., on `amountOut` for EXACT_IN, and `amountIn` for EXACT_OUT).
A swap fee is charged for each swap, as well as on the non-proportional amounts in add/remove liquidity operations. When a pool is registered, the initial swap fee is passed as a parameter and stored as part of [the pool's configuration](https://github.com/balancer/balancer-v3-monorepo/blob/main/pkg/interfaces/contracts/vault/VaultTypes.sol#L28-L39). The swap fee is always charged on the amount in (i.e., on the given amount for EXACT_IN, and the calculated amount for EXACT_OUT).

:::info
Let's imagine a liquidity pool that maintains an equal balance of DAI and USDC, known as a 50/50 pool. A user decides to add liquidity to this pool, but does so in an unbalanced manner: they contribute 15 DAI and 10 USDC.
Expand Down Expand Up @@ -33,10 +33,10 @@ Different types of pools can have varying minimum and maximum swap fees. These v

This means that all new pool types (assuming they implement `IBasePool`) will need to think about what the swap fee range should be, according to the pool type's math and other constraints, then override and set the values accordingly. (Note that invariant limits must also be defined for new pool types, by implementing `IUnbalancedLiquidityInvariantRatioBounds`.)

## Dynamic swap fee
Liquidity pools can be set up to use dynamic swap fees. When registering a pool with a dynamic swap fee, `shouldCallComputeDynamicSwapFee` should be true in the HooksConfig.
## Dynamic swap fee (using Hooks)
Using Hooks a pool can be set up to use dynamic swap fees. When registering a pool with a dynamic swap fee, `shouldCallComputeDynamicSwapFee` should be true in the HooksConfig.

Instead of getting the swap fee from the [pool's configuration](https://github.com/balancer/balancer-v3-monorepo/blob/main/pkg/interfaces/contracts/vault/VaultTypes.sol#L28-L39), the Vault uses the [`onComputeDynamicSwapFeePercentage()`](/developer-reference/contracts/hooks-api.html#oncomputedynamicswapfeepercentage) hook to fetch the dynamic swap fee from the pool. This function returns the swap fee percentage to be used for the current swap. It's important to note that even when a pool is set to use dynamic swap fees, it still maintains a static swap fee, which is not directly used (though it is sent to the dynamic fee hook for reference).
Instead of getting the swap fee from the [pool's configuration](https://github.com/balancer/balancer-v3-monorepo/blob/main/pkg/interfaces/contracts/vault/VaultTypes.sol#L28-L39), the Vault uses the [`onComputeDynamicSwapFeePercentage()`](/developer-reference/contracts/hooks-api.html#oncomputedynamicswapfeepercentage) hook to fetch the dynamic swap fee. This function returns the swap fee percentage to be used for the current swap. It's important to note that even when a pool is set to use dynamic swap fees, it still maintains a static swap fee, which is not directly used (though it is sent to the dynamic fee hook for reference).

:::info
The capability to compute dynamic swap fee percentages opens up new and creative ways to calculate fees. For example, the fees can be adjusted depending on the swap direction, or configured to maintain a token's pegged value.
Expand Down
4 changes: 2 additions & 2 deletions docs/integration-guides/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ features:
icon: /images/build.svg
iconDark: /images/build-dark.svg
details: How to add & remove tokens to a pool
link: /integration-guides/add-&-remove-liquidity/add-liquidity-to-pool.md
link: /integration-guides/add-and-remove-liquidity/add-liquidity-to-pool.md
- title: Swapping
icon: /images/build.svg
iconDark: /images/build-dark.svg
Expand All @@ -18,7 +18,7 @@ features:
icon: /images/build.svg
iconDark: /images/build-dark.svg
details: How to integrate with Balancer v3 liquidity
link: /integration-guides/aggregators/swaps-for-aggregators.md
link: /integration-guides/aggregators/introduction.md

---
# Integration Guides
Expand Down
36 changes: 28 additions & 8 deletions docs/integration-guides/aggregators/swap-fees.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,40 @@ title: Swap Fees

# Swap Fees

:::info Work in progress
Dynamic Swap Fees and Hooks are still WIP and not finalized
::: info More Details
For more detailed information on Swap Fees please see the [Swap Fee Concepts](/concepts/vault/swap-fee.md) section.
:::

[Swap fees](../../concepts/vault/swap-fee.md) come in two different forms for v3 pools:
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](https://github.com/balancer/balancer-v3-monorepo/blob/72ccd408936b8786fd4a9e5bd9c7bd6bc08fd991/pkg/vault/contracts/Vault.sol#L370)):
```solidity
// 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](https://github.com/balancer/balancer-v3-monorepo/blob/72ccd408936b8786fd4a9e5bd9c7bd6bc08fd991/pkg/vault/contracts/Vault.sol#L412))):
```solidity
// 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](../../concepts/vault/swap-fee.md#setting-a-static-swap-fee):
* [Static Swap Fee](/concepts/vault/swap-fee.md#setting-a-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);`
* `setStaticSwapFeePercentage` can also be called as part of a regular [hook](../../concepts/core-concepts/hooks.md)
* [Dynamic Swap Fee](../../concepts/vault/swap-fee.md#dynamic-swap-fee):
* At registration pools can be set up to use dynamic swap fees.
* The Vault uses the `_getSwapFeePercentage(PoolConfig memory config)` to fetch the swap fee from the pool. This function can implement arbitrary logic.
* Note - `setStaticSwapFeePercentage` can also be called as part of a regular [hook](../../concepts/core-concepts/hooks.md)
* [Dynamic Swap Fee Using Hooks](/concepts/vault/swap-fee.md#dynamic-swap-fee):
* Using Hooks a pool can be set up to use dynamic swap fees.
* The Vault uses the [`onComputeDynamicSwapFeePercentage()`](/developer-reference/contracts/hooks-api.html#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:
Expand Down

0 comments on commit 43eb127

Please sign in to comment.