diff --git a/packages/dma-library/src/strategies/aave-like/multiply/adjust/generate.ts b/packages/dma-library/src/strategies/aave-like/multiply/adjust/generate.ts index 1194b9b20..e93193acb 100644 --- a/packages/dma-library/src/strategies/aave-like/multiply/adjust/generate.ts +++ b/packages/dma-library/src/strategies/aave-like/multiply/adjust/generate.ts @@ -41,7 +41,6 @@ export async function generate({ // And do not mislead the user const sourceTokenAmount = isIncreasingRisk ? simulation.delta.debt : simulation.delta.collateral - // TODO: extract this to a helper function like on the left side const preSwapFee = calculatePreSwapFeeAmount(collectFeeFrom, sourceTokenAmount, fee, feeType) const postSwapFee = calculatePostSwapFeeAmount( diff --git a/packages/dma-library/src/strategies/aave-like/multiply/open/build-operation.ts b/packages/dma-library/src/strategies/aave-like/multiply/open/build-operation.ts index a9b1d9a9b..1d3737c9e 100644 --- a/packages/dma-library/src/strategies/aave-like/multiply/open/build-operation.ts +++ b/packages/dma-library/src/strategies/aave-like/multiply/open/build-operation.ts @@ -22,6 +22,7 @@ export async function buildOperation( reserveEModeCategory: number | undefined, args: BuildOperationArgs, dependencies: AaveLikeOpenDependencies, + isOpeningPosition = false, ) { const { collateralTokenAddress, debtTokenAddress } = getAaveTokenAddresses( { debtToken: args.debtToken, collateralToken: args.collateralToken }, @@ -36,6 +37,7 @@ export async function buildOperation( isIncreasingRisk, isEarnPosition: dependencies.positionType === 'Earn', positionData: getPositionDataAaveLike(dependencies), + isOpeningPosition, }) const positionType = dependencies.positionType diff --git a/packages/dma-library/src/strategies/aave-like/multiply/open/generate.ts b/packages/dma-library/src/strategies/aave-like/multiply/open/generate.ts index abaa6e264..b3bc20608 100644 --- a/packages/dma-library/src/strategies/aave-like/multiply/open/generate.ts +++ b/packages/dma-library/src/strategies/aave-like/multiply/open/generate.ts @@ -1,9 +1,11 @@ -import { ZERO } from '@dma-common/constants' -import { calculatePercentageFee } from '@dma-common/utils/swap' import { IOperation, SwapData } from '@dma-library/types' -import { calculateInflatedTokenFee } from '@dma-library/utils/swap' +import { + calculateInflatedTokenFee, + calculatePostSwapFeeAmount, + calculatePreSwapFeeAmount, +} from '@dma-library/utils/swap' +import type { ResolvedFee } from '@dma-library/utils/swap/fee-resolver' import { IBaseSimulatedTransition } from '@domain' -import BigNumber from 'bignumber.js' import { AaveLikeOpenArgs, AaveLikeOpenDependencies, IOpenStrategy } from './types' @@ -11,7 +13,7 @@ type GenerateTransitionArgs = { swapData: SwapData operation: IOperation collectFeeFrom: 'sourceToken' | 'targetToken' - fee: BigNumber + fee: ResolvedFee simulatedPositionTransition: IBaseSimulatedTransition args: AaveLikeOpenArgs dependencies: AaveLikeOpenDependencies @@ -30,14 +32,20 @@ export async function generate({ // When collecting fees from the target token (collateral here), we want to calculate the fee // Based on the toTokenAmount NOT minToTokenAmount so that we over estimate the fee where possible // And do not mislead the user - const shouldCollectFeeFromSourceToken = collectFeeFrom === 'sourceToken' - const preSwapFee = shouldCollectFeeFromSourceToken - ? calculatePercentageFee(simulatedPositionTransition.delta.debt, fee.toNumber()) - : ZERO - const postSwapFee = shouldCollectFeeFromSourceToken - ? ZERO - : calculatePercentageFee(swapData.toTokenAmount, fee.toNumber()) + const preSwapFee = calculatePreSwapFeeAmount( + collectFeeFrom, + simulatedPositionTransition.delta.debt, + fee.feeToCharge, + fee.feeType, + ) + + const postSwapFee = calculatePostSwapFeeAmount( + collectFeeFrom, + swapData.toTokenAmount, + fee.feeToCharge, + fee.feeType, + ) return { transaction: { diff --git a/packages/dma-library/src/strategies/aave-like/multiply/open/open.ts b/packages/dma-library/src/strategies/aave-like/multiply/open/open.ts index 742ae7e9c..76fdd118a 100644 --- a/packages/dma-library/src/strategies/aave-like/multiply/open/open.ts +++ b/packages/dma-library/src/strategies/aave-like/multiply/open/open.ts @@ -74,6 +74,7 @@ export const open: AaveLikeOpen = async (args, dependencies) => { reserveEModeCategory, { ...args, flashloanToken: flashloanTokenAddress }, dependencies, + true, ) if (operation === undefined) throw new Error('No operation built. Check your arguments.') @@ -83,7 +84,7 @@ export const open: AaveLikeOpen = async (args, dependencies) => { operation, args, collectFeeFrom, - fee: fee.feeToCharge, + fee: fee, dependencies, simulatedPositionTransition, quoteSwapData, diff --git a/packages/dma-library/src/strategies/ajna/multiply/common.ts b/packages/dma-library/src/strategies/ajna/multiply/common.ts index 876246f5b..9604dd740 100644 --- a/packages/dma-library/src/strategies/ajna/multiply/common.ts +++ b/packages/dma-library/src/strategies/ajna/multiply/common.ts @@ -2,7 +2,6 @@ import { ONE, TYPICAL_PRECISION, ZERO } from '@dma-common/constants' import { CollectFeeFrom } from '@dma-common/types' import { areAddressesEqual } from '@dma-common/utils/addresses/index' import { amountFromWei, amountToWei } from '@dma-common/utils/common' -import { calculatePercentageFee } from '@dma-common/utils/swap' import { BALANCER_FEE } from '@dma-library/config/flashloan-fees' import { getNeutralPrice, prepareAjnaDMAPayload, resolveTxValue } from '@dma-library/protocols/ajna' import { @@ -140,6 +139,7 @@ export async function getSwapData( riskIsIncreasing: boolean, positionType: PositionType, __feeOverride?: BigNumber, + isOpeningPosition = false, ) { const swapAmountBeforeFees = simulatedAdjust.swap.fromTokenAmount const feeResult = await SwapUtils.feeResolver( @@ -153,6 +153,7 @@ export async function getSwapData( network: dependencies.network, proxy: args.dpmProxyAddress, }), + isOpeningPosition, }, ) const fee = __feeOverride || feeResult.feeToCharge @@ -187,6 +188,7 @@ export async function prepareAjnaMultiplyDMAPayload( collectFeeFrom: CollectFeeFrom, preSwapFee: BigNumber, riskIsIncreasing: boolean, + isOpeningPosition = false, ) { const collateralAmount = amountFromWei( simulatedAdjustment.position.collateral.amount, @@ -229,11 +231,16 @@ export async function prepareAjnaMultiplyDMAPayload( network: dependencies.network, proxy: args.dpmProxyAddress, }), + isOpeningPosition, }) - const postSwapFee = - collectFeeFrom === 'sourceToken' - ? ZERO - : calculatePercentageFee(swapData.toTokenAmount, fee.feeToCharge.toNumber()) + + const postSwapFee = SwapUtils.calculatePostSwapFeeAmount( + collectFeeFrom, + swapData.toTokenAmount, + fee.feeToCharge, + fee.feeType, + ) + const tokenFee = preSwapFee.plus(postSwapFee) // Validation diff --git a/packages/dma-library/src/strategies/ajna/multiply/open.ts b/packages/dma-library/src/strategies/ajna/multiply/open.ts index a6a7bb211..37bf61278 100644 --- a/packages/dma-library/src/strategies/ajna/multiply/open.ts +++ b/packages/dma-library/src/strategies/ajna/multiply/open.ts @@ -48,6 +48,7 @@ export const openMultiply: AjnaOpenMultiplyStrategy = async (args, dependencies) position, riskIsIncreasing, oraclePrice, + true, ) const { swapData, collectFeeFrom, preSwapFee } = await getSwapData( { ...mappedArgs, position }, @@ -55,6 +56,8 @@ export const openMultiply: AjnaOpenMultiplyStrategy = async (args, dependencies) simulatedAdjustment, riskIsIncreasing, positionType, + undefined, + true, ) const operation = await buildOperation( mappedArgs, @@ -63,6 +66,7 @@ export const openMultiply: AjnaOpenMultiplyStrategy = async (args, dependencies) simulatedAdjustment, swapData, riskIsIncreasing, + true, ) return await prepareAjnaMultiplyDMAPayload( @@ -74,6 +78,7 @@ export const openMultiply: AjnaOpenMultiplyStrategy = async (args, dependencies) collectFeeFrom, preSwapFee, riskIsIncreasing, + true, ) } @@ -121,6 +126,7 @@ async function simulateAdjustment( position: AjnaPosition, riskIsIncreasing: true, oraclePrice: BigNumber, + isOpeningPosition = false, ) { const preFlightSwapAmount = amountToWei(ONE, args.quoteTokenPrecision) const fromToken = buildFromToken({ ...args, position }, riskIsIncreasing) @@ -132,6 +138,7 @@ async function simulateAdjustment( network: dependencies.network, proxy: args.dpmProxyAddress, }), + isOpeningPosition, }) const { swapData: preFlightSwapData } = await SwapUtils.getSwapDataHelper< typeof dependencies.addresses, @@ -212,6 +219,7 @@ async function buildOperation( simulatedAdjust: Domain.ISimulationV2 & Domain.WithSwap, swapData: SwapData, riskIsIncreasing: true, + isOpeningPosition = false, ) { /** Not relevant for Ajna */ const debtTokensDeposited = ZERO @@ -225,6 +233,7 @@ async function buildOperation( network: dependencies.network, proxy: args.dpmProxyAddress, }), + isOpeningPosition, }) const swapAmountBeforeFees = simulatedAdjust.swap.fromTokenAmount const collectFeeFrom = SwapUtils.acceptedFeeTokenBySymbol({ diff --git a/packages/dma-library/src/utils/swap/calculate-swap-fee-amount.ts b/packages/dma-library/src/utils/swap/calculate-swap-fee-amount.ts index bd2ea845b..75cc8e47f 100644 --- a/packages/dma-library/src/utils/swap/calculate-swap-fee-amount.ts +++ b/packages/dma-library/src/utils/swap/calculate-swap-fee-amount.ts @@ -61,6 +61,22 @@ export function calculateSwapFeeAmount( return preSwapFee.plus(postSwapFee) } +/** + * Calculate fee amount for the swap, based on the fee type + * and pre or post swap fees + */ +export function calculateSwapFeeAmountInflated( + collectFeeFrom: 'sourceToken' | 'targetToken' | undefined, + swapAmountBeforeFees: BigNumber, + toTokenAmount: BigNumber, + fee: BigNumber = new BigNumber(DEFAULT_FEE), + feeType: SwapFeeType, +) { + const preSwapFee = calculatePreSwapFeeAmount(collectFeeFrom, swapAmountBeforeFees, fee, feeType) + const postSwapFee = calculatePostSwapFeeAmount(collectFeeFrom, toTokenAmount, fee, feeType) + return calculateInflatedTokenFee({ preSwapFee, postSwapFee }) +} + /** * Calculate the inflated token fee amount */ diff --git a/packages/dma-library/src/utils/swap/fee-resolver.ts b/packages/dma-library/src/utils/swap/fee-resolver.ts index a87a1bb52..c773bf9c5 100644 --- a/packages/dma-library/src/utils/swap/fee-resolver.ts +++ b/packages/dma-library/src/utils/swap/fee-resolver.ts @@ -7,6 +7,11 @@ import { fixedFeeResolver } from './fixed-fee-resolver' import { isCorrelatedPosition } from './isCorrelatedPosition' import { percentageFeeResolver } from './percentage-fee-resolver' +export type ResolvedFee = { + feeType: SwapFeeType + feeToCharge: BigNumber +} + export const feeResolver = async ( fromToken: T, toToken: T, @@ -22,10 +27,7 @@ export const feeResolver = async ( proxyAddress: string } }, -): Promise<{ - feeType: SwapFeeType - feeToCharge: BigNumber -}> => { +): Promise => { if (isCorrelatedPosition(fromToken, toToken) || options?.isEarnPosition) { return fixedFeeResolver(options?.positionData, options?.isOpeningPosition) } else { diff --git a/packages/dma-library/src/utils/swap/fixed-fee-resolver.ts b/packages/dma-library/src/utils/swap/fixed-fee-resolver.ts index da26b5381..442890aa1 100644 --- a/packages/dma-library/src/utils/swap/fixed-fee-resolver.ts +++ b/packages/dma-library/src/utils/swap/fixed-fee-resolver.ts @@ -5,6 +5,7 @@ import BigNumber from 'bignumber.js' import { getEarnMultiplyFee } from '../fee-service/getEarnMultiplyFee' import type { ProtocolId } from '../fee-service/ProtocolId' +import type { ResolvedFee } from './fee-resolver' export const fixedFeeResolver = async ( positionData: @@ -15,10 +16,7 @@ export const fixedFeeResolver = async ( } | undefined, isOpeningPosition?: boolean, -): Promise<{ - feeType: SwapFeeType - feeToCharge: BigNumber -}> => { +): Promise => { if (isOpeningPosition) { return { feeType: SwapFeeType.Fixed, diff --git a/packages/dma-library/src/utils/swap/percentage-fee-resolver.ts b/packages/dma-library/src/utils/swap/percentage-fee-resolver.ts index e5333f3c9..fd71f53fc 100644 --- a/packages/dma-library/src/utils/swap/percentage-fee-resolver.ts +++ b/packages/dma-library/src/utils/swap/percentage-fee-resolver.ts @@ -2,6 +2,7 @@ import { DEFAULT_FEE, LOW_CORRELATED_ASSET_FEE } from '@dma-common/constants' import { SwapFeeType } from '@dma-library/types' import BigNumber from 'bignumber.js' +import type { ResolvedFee } from './fee-resolver' import { isCorrelatedPosition } from './isCorrelatedPosition' export const percentageFeeResolver = ( @@ -14,10 +15,7 @@ export const percentageFeeResolver = ( /** if the swap is an entry swap */ isEntrySwap?: boolean }, -): { - feeType: SwapFeeType - feeToCharge: BigNumber -} => { +): ResolvedFee => { let type = 'defaultMultiply' if (isCorrelatedPosition(fromToken, toToken) || options?.isEarnPosition) { type = 'earnMultiply'