Skip to content

Commit ff7116c

Browse files
committed
fix: optimize swap amounts by accounting flashloan fees
1 parent f2e3618 commit ff7116c

File tree

2 files changed

+47
-8
lines changed

2 files changed

+47
-8
lines changed

src/components/transactions/Swap/hooks/useSwapOrderAmounts.ts

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import { normalize, normalizeBN, valueToBigNumber } from '@aave/math-utils';
22
import { OrderKind } from '@cowprotocol/cow-sdk';
33
import { Dispatch, useEffect } from 'react';
44

5-
import { COW_PARTNER_FEE } from '../constants/cow.constants';
5+
import { COW_PARTNER_FEE, FLASH_LOAN_FEE_BPS } from '../constants/cow.constants';
6+
import { PARASWAP_FLASH_LOAN_FEE_BPS } from '../constants/paraswap.constants';
67
import {
78
isCowProtocolRates,
89
OrderType,
@@ -21,6 +22,14 @@ const marketOrderKindPerSwapType: Record<SwapType, OrderKind> = {
2122
[SwapType.WithdrawAndSwap]: OrderKind.SELL,
2223
};
2324

25+
const isPositionSwap = (swapType: SwapType, usingFlashloan: boolean) => {
26+
return swapType != SwapType.Swap && usingFlashloan;
27+
};
28+
29+
const getFlashLoanFeeBps = (provider: SwapProvider) => {
30+
return provider === SwapProvider.COW_PROTOCOL ? FLASH_LOAN_FEE_BPS : PARASWAP_FLASH_LOAN_FEE_BPS;
31+
};
32+
2433
/**
2534
* Computes normalized sell/buy amounts used to build transactions.
2635
*
@@ -78,6 +87,17 @@ export const useSwapOrderAmounts = ({
7887
: valueToBigNumber(state.inputAmount).multipliedBy(partnetFeeBps).dividedBy(10000);
7988
// const partnerFeeToken = state.side === 'sell' ? state.destinationToken : state.sourceToken;
8089

90+
const flashLoanFeeBps = isPositionSwap(state.swapType, state.useFlashloan ?? false)
91+
? getFlashLoanFeeBps(state.provider)
92+
: 0;
93+
const flashLoanFeeAmount =
94+
state.processedSide == 'sell'
95+
? valueToBigNumber(state.outputAmount).multipliedBy(flashLoanFeeBps).dividedBy(10000)
96+
: valueToBigNumber(state.inputAmount).multipliedBy(flashLoanFeeBps).dividedBy(10000);
97+
98+
console.info('partnerFeeAmount', partnerFeeAmount.toString());
99+
console.info('flashLoanFeeAmount', flashLoanFeeAmount.toString());
100+
81101
if (!isInvertedSwap) {
82102
// on classic swaps, minimum is calculated from the output token and sent amount is from the input token
83103
sellAmountToken = state.sourceToken;
@@ -130,8 +150,11 @@ export const useSwapOrderAmounts = ({
130150
const outputAmountAfterPartnerFees = valueToBigNumber(outputAmountAfterNetworkFees).minus(
131151
partnerFeeAmount
132152
);
133-
const outputAmountAfterSlippage = valueToBigNumber(
153+
const outputAmountAfterFlashLoanFees = valueToBigNumber(
134154
outputAmountAfterPartnerFees
155+
).minus(flashLoanFeeAmount);
156+
const outputAmountAfterSlippage = valueToBigNumber(
157+
outputAmountAfterFlashLoanFees
135158
).multipliedBy(1 - Number(state.slippage) / 100);
136159
buyAmountFormatted = outputAmountAfterSlippage.toFixed();
137160
} else {
@@ -144,9 +167,12 @@ export const useSwapOrderAmounts = ({
144167
const sellAmountAfterPartnerFees = valueToBigNumber(sellAmountAfterNetworkFees).plus(
145168
partnerFeeAmount
146169
);
147-
const sellAmountAfterSlippage = valueToBigNumber(sellAmountAfterPartnerFees).multipliedBy(
148-
1 + Number(state.slippage) / 100
170+
const sellAmountAfterFlashLoanFees = valueToBigNumber(sellAmountAfterPartnerFees).plus(
171+
flashLoanFeeAmount
149172
);
173+
const sellAmountAfterSlippage = valueToBigNumber(
174+
sellAmountAfterFlashLoanFees
175+
).multipliedBy(1 + Number(state.slippage) / 100);
150176
sellAmountFormatted = sellAmountAfterSlippage.toFixed();
151177
}
152178
} else if (state.orderType === OrderType.LIMIT) {
@@ -157,12 +183,14 @@ export const useSwapOrderAmounts = ({
157183
// Do not apply network costs on limit orders
158184
buyAmountFormatted = valueToBigNumber(state.outputAmount)
159185
.minus(partnerFeeAmount)
186+
.minus(flashLoanFeeAmount)
160187
.toFixed();
161188
} else {
162189
// on a buy limit order, we receive exactly the output amount and send the input amount after partner fees (no slippage applied)
163190
// Do not apply network costs on limit orders
164191
sellAmountFormatted = valueToBigNumber(state.inputAmount)
165192
.plus(partnerFeeAmount)
193+
.plus(flashLoanFeeAmount)
166194
.toFixed();
167195

168196
buyAmountFormatted = state.outputAmount;
@@ -226,7 +254,10 @@ export const useSwapOrderAmounts = ({
226254
const inputAmountAfterPartnerFees = valueToBigNumber(inputAmountAfterNetworkFees)
227255
.minus(partnerFeeAmount)
228256
.toFixed();
229-
const inputAmountAfterSlippage = valueToBigNumber(inputAmountAfterPartnerFees)
257+
const inputAmountAfterFlashLoanFees = valueToBigNumber(inputAmountAfterPartnerFees).minus(
258+
flashLoanFeeAmount
259+
);
260+
const inputAmountAfterSlippage = valueToBigNumber(inputAmountAfterFlashLoanFees)
230261
.multipliedBy(1 + Number(state.slippage) / 100)
231262
.toFixed();
232263
buyAmountFormatted = inputAmountAfterSlippage;
@@ -239,9 +270,12 @@ export const useSwapOrderAmounts = ({
239270
const sellAmountAfterPartnerFees = valueToBigNumber(sellAmountAfterNetworkFees).plus(
240271
partnerFeeAmount
241272
);
242-
const sellAmountAfterSlippage = valueToBigNumber(sellAmountAfterPartnerFees).multipliedBy(
243-
1 + Number(state.slippage) / 100
273+
const sellAmountAfterFlashLoanFees = valueToBigNumber(sellAmountAfterPartnerFees).plus(
274+
flashLoanFeeAmount
244275
);
276+
const sellAmountAfterSlippage = valueToBigNumber(
277+
sellAmountAfterFlashLoanFees
278+
).multipliedBy(1 + Number(state.slippage) / 100);
245279
sellAmountFormatted = sellAmountAfterSlippage.toFixed();
246280
}
247281
} else {
@@ -252,6 +286,7 @@ export const useSwapOrderAmounts = ({
252286
// Do not apply network costs on limit orders
253287
sellAmountFormatted = valueToBigNumber(state.outputAmount)
254288
.plus(partnerFeeAmount)
289+
.plus(flashLoanFeeAmount)
255290
.toFixed();
256291
} else {
257292
// on an inverted sell limit order, we sell the output amount and buy the input amount after partner fees (no slippage applied)
@@ -260,6 +295,7 @@ export const useSwapOrderAmounts = ({
260295
// Do not apply network costs on limit orders
261296
buyAmountFormatted = valueToBigNumber(state.inputAmount)
262297
.minus(partnerFeeAmount)
298+
.minus(flashLoanFeeAmount)
263299
.toFixed();
264300
}
265301
}
@@ -312,6 +348,7 @@ export const useSwapOrderAmounts = ({
312348
networkFeeAmountInSellFormatted,
313349
networkFeeAmountInBuyFormatted,
314350
partnerFeeAmountFormatted: partnerFeeAmount.toFixed(),
351+
flashLoanFeeAmountFormatted: flashLoanFeeAmount.toFixed(),
315352
partnerFeeBps: partnetFeeBps,
316353
});
317354
}, [

src/components/transactions/Swap/types/state.types.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ export type TokensSwapState = {
9494
networkFeeAmountInBuyFormatted?: string;
9595
/** Partner fee amount applied to this order, normalized to the fee token units (depends on side). */
9696
partnerFeeAmountFormatted?: string;
97+
/** Flash loan fee amount applied to this order, normalized to the fee token units (depends on side). */
98+
flashLoanFeeAmountFormatted?: string;
9799
/** Partner fee in basis points used to compute partnerFeeAmountFormatted. */
98100
partnerFeeBps?: number;
99101

@@ -279,8 +281,8 @@ export const swapDefaultState: SwapState = {
279281
networkFeeAmountInSellFormatted: '0',
280282
networkFeeAmountInBuyFormatted: '0',
281283
partnerFeeAmountFormatted: '0',
284+
flashLoanFeeAmountFormatted: '0',
282285
partnerFeeBps: 0,
283-
284286
limitsOrderButtonBlocked: false,
285287
showSlippageWarning: false,
286288
showChangeNetworkWarning: false,

0 commit comments

Comments
 (0)