Trading fees
Last updated
Last updated
It's worth knowing that Curve, the AMM system that Increment uses as its trading engine, charges a variable trading fee on every trade.
The Increment system harmonizes all trading fees in quote tokens and to do so, we 1) reimburse all trading fees paid to the curve pool and 2) charge our trading fee at the protocol level (in quote tokens only).
For 1), we use the CurveMath
contract to derive how many tokens every trader would receive without paying any trading fees on Curve. We then calculate the fees payed as
, where outAmountExclFees
is the amount of tokens the trader would receive without paying any trading fees on Curve. and outAmount
is the amount of tokens the trader would receive when paying the trading fees on Curve.
and derive the percentage fees as:
We account outAmountExclFee
towards the trader. Imagine a trader who wants to swap 100 vUSD for some vEUR, we'll begin by getting the number of vEUR the trader would receive without paying a trading fee (by calling get_dy_ex_fees
on the CurveCryptoSwapViewer
) and then we call Curve's exchange
function to perform the swap in the pool. Let's say the Viewer returns 72 vEUR while the exchange
returns 71.8 vEUR. In this case we will account 72 vEUR towards the user.
For 2), we charge the trading fee by using the percentageFeePayed
calculated before and the vQuote amount traded. If the trader exchanges vBase for vQuote, we charge the fee using the vQuote received. If the trader exchanges some vQuote for vBase, we charge the fee using the vQuote amount the trader passed in.
In our above example the percentage fee would be 0.2 (72-71.8) / 72 ~ 0.3%. When multiplying the quote amount (100 vUSD) with the percentage fee we get 100 * 0.3% = 0.3 vUSD trading fee. We deduct this trading fee from the UA balance of the trader.
The exact math and code can be found in Perpetual._baseForQuote
, Perpetual._quoteForBase
and Perpetual._chargeQuoteFees
.
When a LP removes liquidity we must consider the same steps as seen before. The Curve CryptoSwap generates fees in every trade. So we use two variables to keep track of the fee growth of base and quote tokens for each pool.
Let's continue the example above to show how this works. We now assume that we have a total of 1000 vUSD and 1000 vEUR in the pool. The trade in the example above incremented the totalBaseFeesGrowth
counter by 0.2 vUSD (feesPayed
) / 1000 vUSD = 0.02%. That means as the result of the trade additional 0.02% of the total base tokens in the Curve Pools are fees. Further that trade produced ("quote only") trading fees of 0.3 vUSD. So this trade increased the totalTradingFeesGrowth
counter by 0.3 vUSD / 1000 vUSD (totalQuoteProvided)= 0.03%.
When a LP provides liquidity for the first time we store the current growth in base and quote fees. When they now want to withdraw their liquidity we can compute the growth in base and quote supply which is due to fees as:
Let's imagine that a LP provided liquidity right before the trade (of 100 vUSD for 72 vEUR) happened and withdraws their liquidity after the trade has been executed. We know that their base balance increased by 0.02% in the meantime from fees alone. The growth in fees alone must be neutralized. We can do that by only accounting the amount after fees towards the LP.
Let's say the LP was able to withdraw 100 vBase from the Curve pool. In that case we would only account 100 / (1 + 0.2%) = 99.98 base tokens toward their balance. On the other hand the LP had earned tradingFee
on their supplied liquidity. Let's imagine they initially provided 100 vQuote as liquidity. They could now claim 100 * 0.03% = 0.03 vQuote tokens as ("quote only") trading fees. So our LP would end up with 99.98 + 0.03 = 100.01 vQuote, i.e a net gain of 0.01 because they earned trading fees from the trade we described above.
The amount of quote and base tokens provided as liquidity is not completely arbitrary, but must be inline with the current market prices. This prevents liquidity providers from receiving an unfair share of trading fees.