It's worth knowing that Curve, the AMM system that Increment uses as its trading engine, charges a trading fee on every trade.
The Curve trading fee is being collected in the "out" token. This means that if a trader exchanges some quote tokens for some base tokens, the fee will be taken out in the base token. That's an issue because that'd imply that
positionSizeof LP positions changes with every trade, hence forcing us to re-calculate the funding payments after every trade.
Since it is much easier for internal accounting to charge a trading fee in quote tokens, 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
CurveMathcontract to derive how many tokens every trader would receive without paying any trading fees on Curve. We then calculate the fees payed as
outAmountExclFeesis the amount of tokens the trader would receive without paying any trading fees on Curve. and
outAmountis the amount of tokens the trader would receive when paying the trading fees on Curve.
and derive the percentage fees as:
outAmountExclFeetowards the trader. Imagine a trader who wants to swap 100 vUSD for some vETH, we'll begin by getting the number of vETH the trader would receive without paying a trading fee (by calling
CurveCryptoSwapViewer) and then we call Curve's
exchangefunction to perform the swap in the pool. Let's say the Viewer returns 72 vEUR while the
exchangereturns 71.8 vEUR. In this case we will account 72 vEUR towards the user.
For 2), we charge the trading fee by using the
percentageFeePayedcalculated 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
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
totalBaseFeesGrowthcounter 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.03 vUSD. So this trade increased the
totalTradingFeesGrowthcounter 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
tradingFeeon 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.
Last modified 4mo ago