Skip to content

Commit f16a583

Browse files
authored
fix: optimize swap amounts by accounting flashloan fees (#2826)
1 parent f2e3618 commit f16a583

File tree

2 files changed

+44
-8
lines changed

2 files changed

+44
-8
lines changed

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

Lines changed: 41 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,14 @@ 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+
8198
if (!isInvertedSwap) {
8299
// on classic swaps, minimum is calculated from the output token and sent amount is from the input token
83100
sellAmountToken = state.sourceToken;
@@ -130,8 +147,11 @@ export const useSwapOrderAmounts = ({
130147
const outputAmountAfterPartnerFees = valueToBigNumber(outputAmountAfterNetworkFees).minus(
131148
partnerFeeAmount
132149
);
133-
const outputAmountAfterSlippage = valueToBigNumber(
150+
const outputAmountAfterFlashLoanFees = valueToBigNumber(
134151
outputAmountAfterPartnerFees
152+
).minus(flashLoanFeeAmount);
153+
const outputAmountAfterSlippage = valueToBigNumber(
154+
outputAmountAfterFlashLoanFees
135155
).multipliedBy(1 - Number(state.slippage) / 100);
136156
buyAmountFormatted = outputAmountAfterSlippage.toFixed();
137157
} else {
@@ -144,9 +164,12 @@ export const useSwapOrderAmounts = ({
144164
const sellAmountAfterPartnerFees = valueToBigNumber(sellAmountAfterNetworkFees).plus(
145165
partnerFeeAmount
146166
);
147-
const sellAmountAfterSlippage = valueToBigNumber(sellAmountAfterPartnerFees).multipliedBy(
148-
1 + Number(state.slippage) / 100
167+
const sellAmountAfterFlashLoanFees = valueToBigNumber(sellAmountAfterPartnerFees).plus(
168+
flashLoanFeeAmount
149169
);
170+
const sellAmountAfterSlippage = valueToBigNumber(
171+
sellAmountAfterFlashLoanFees
172+
).multipliedBy(1 + Number(state.slippage) / 100);
150173
sellAmountFormatted = sellAmountAfterSlippage.toFixed();
151174
}
152175
} else if (state.orderType === OrderType.LIMIT) {
@@ -157,12 +180,14 @@ export const useSwapOrderAmounts = ({
157180
// Do not apply network costs on limit orders
158181
buyAmountFormatted = valueToBigNumber(state.outputAmount)
159182
.minus(partnerFeeAmount)
183+
.minus(flashLoanFeeAmount)
160184
.toFixed();
161185
} else {
162186
// on a buy limit order, we receive exactly the output amount and send the input amount after partner fees (no slippage applied)
163187
// Do not apply network costs on limit orders
164188
sellAmountFormatted = valueToBigNumber(state.inputAmount)
165189
.plus(partnerFeeAmount)
190+
.plus(flashLoanFeeAmount)
166191
.toFixed();
167192

168193
buyAmountFormatted = state.outputAmount;
@@ -226,7 +251,10 @@ export const useSwapOrderAmounts = ({
226251
const inputAmountAfterPartnerFees = valueToBigNumber(inputAmountAfterNetworkFees)
227252
.minus(partnerFeeAmount)
228253
.toFixed();
229-
const inputAmountAfterSlippage = valueToBigNumber(inputAmountAfterPartnerFees)
254+
const inputAmountAfterFlashLoanFees = valueToBigNumber(inputAmountAfterPartnerFees).minus(
255+
flashLoanFeeAmount
256+
);
257+
const inputAmountAfterSlippage = valueToBigNumber(inputAmountAfterFlashLoanFees)
230258
.multipliedBy(1 + Number(state.slippage) / 100)
231259
.toFixed();
232260
buyAmountFormatted = inputAmountAfterSlippage;
@@ -239,9 +267,12 @@ export const useSwapOrderAmounts = ({
239267
const sellAmountAfterPartnerFees = valueToBigNumber(sellAmountAfterNetworkFees).plus(
240268
partnerFeeAmount
241269
);
242-
const sellAmountAfterSlippage = valueToBigNumber(sellAmountAfterPartnerFees).multipliedBy(
243-
1 + Number(state.slippage) / 100
270+
const sellAmountAfterFlashLoanFees = valueToBigNumber(sellAmountAfterPartnerFees).plus(
271+
flashLoanFeeAmount
244272
);
273+
const sellAmountAfterSlippage = valueToBigNumber(
274+
sellAmountAfterFlashLoanFees
275+
).multipliedBy(1 + Number(state.slippage) / 100);
245276
sellAmountFormatted = sellAmountAfterSlippage.toFixed();
246277
}
247278
} else {
@@ -252,6 +283,7 @@ export const useSwapOrderAmounts = ({
252283
// Do not apply network costs on limit orders
253284
sellAmountFormatted = valueToBigNumber(state.outputAmount)
254285
.plus(partnerFeeAmount)
286+
.plus(flashLoanFeeAmount)
255287
.toFixed();
256288
} else {
257289
// on an inverted sell limit order, we sell the output amount and buy the input amount after partner fees (no slippage applied)
@@ -260,6 +292,7 @@ export const useSwapOrderAmounts = ({
260292
// Do not apply network costs on limit orders
261293
buyAmountFormatted = valueToBigNumber(state.inputAmount)
262294
.minus(partnerFeeAmount)
295+
.minus(flashLoanFeeAmount)
263296
.toFixed();
264297
}
265298
}
@@ -312,6 +345,7 @@ export const useSwapOrderAmounts = ({
312345
networkFeeAmountInSellFormatted,
313346
networkFeeAmountInBuyFormatted,
314347
partnerFeeAmountFormatted: partnerFeeAmount.toFixed(),
348+
flashLoanFeeAmountFormatted: flashLoanFeeAmount.toFixed(),
315349
partnerFeeBps: partnetFeeBps,
316350
});
317351
}, [

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)