Skip to content

Commit

Permalink
Refactor fee calculation methods to use ResolvedFee type and improve …
Browse files Browse the repository at this point in the history
…clarity in swap fee handling
  • Loading branch information
piotrwitek committed Nov 6, 2024
1 parent 8213aac commit f790c1a
Show file tree
Hide file tree
Showing 10 changed files with 71 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 },
Expand All @@ -36,6 +37,7 @@ export async function buildOperation(
isIncreasingRisk,
isEarnPosition: dependencies.positionType === 'Earn',
positionData: getPositionDataAaveLike(dependencies),
isOpeningPosition,
})

const positionType = dependencies.positionType
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
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'

type GenerateTransitionArgs = {
swapData: SwapData
operation: IOperation
collectFeeFrom: 'sourceToken' | 'targetToken'
fee: BigNumber
fee: ResolvedFee
simulatedPositionTransition: IBaseSimulatedTransition
args: AaveLikeOpenArgs
dependencies: AaveLikeOpenDependencies
Expand All @@ -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: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.')
Expand All @@ -83,7 +84,7 @@ export const open: AaveLikeOpen = async (args, dependencies) => {
operation,
args,
collectFeeFrom,
fee: fee.feeToCharge,
fee: fee,
dependencies,
simulatedPositionTransition,
quoteSwapData,
Expand Down
17 changes: 12 additions & 5 deletions packages/dma-library/src/strategies/ajna/multiply/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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(
Expand All @@ -153,6 +153,7 @@ export async function getSwapData(
network: dependencies.network,
proxy: args.dpmProxyAddress,
}),
isOpeningPosition,
},
)
const fee = __feeOverride || feeResult.feeToCharge
Expand Down Expand Up @@ -187,6 +188,7 @@ export async function prepareAjnaMultiplyDMAPayload(
collectFeeFrom: CollectFeeFrom,
preSwapFee: BigNumber,
riskIsIncreasing: boolean,
isOpeningPosition = false,
) {
const collateralAmount = amountFromWei(
simulatedAdjustment.position.collateral.amount,
Expand Down Expand Up @@ -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
Expand Down
9 changes: 9 additions & 0 deletions packages/dma-library/src/strategies/ajna/multiply/open.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,16 @@ export const openMultiply: AjnaOpenMultiplyStrategy = async (args, dependencies)
position,
riskIsIncreasing,
oraclePrice,
true,
)
const { swapData, collectFeeFrom, preSwapFee } = await getSwapData(
{ ...mappedArgs, position },
dependencies,
simulatedAdjustment,
riskIsIncreasing,
positionType,
undefined,
true,
)
const operation = await buildOperation(
mappedArgs,
Expand All @@ -63,6 +66,7 @@ export const openMultiply: AjnaOpenMultiplyStrategy = async (args, dependencies)
simulatedAdjustment,
swapData,
riskIsIncreasing,
true,
)

return await prepareAjnaMultiplyDMAPayload(
Expand All @@ -74,6 +78,7 @@ export const openMultiply: AjnaOpenMultiplyStrategy = async (args, dependencies)
collectFeeFrom,
preSwapFee,
riskIsIncreasing,
true,
)
}

Expand Down Expand Up @@ -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)
Expand All @@ -132,6 +138,7 @@ async function simulateAdjustment(
network: dependencies.network,
proxy: args.dpmProxyAddress,
}),
isOpeningPosition,
})
const { swapData: preFlightSwapData } = await SwapUtils.getSwapDataHelper<
typeof dependencies.addresses,
Expand Down Expand Up @@ -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
Expand All @@ -225,6 +233,7 @@ async function buildOperation(
network: dependencies.network,
proxy: args.dpmProxyAddress,
}),
isOpeningPosition,
})
const swapAmountBeforeFees = simulatedAdjust.swap.fromTokenAmount
const collectFeeFrom = SwapUtils.acceptedFeeTokenBySymbol({
Expand Down
16 changes: 16 additions & 0 deletions packages/dma-library/src/utils/swap/calculate-swap-fee-amount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand Down
10 changes: 6 additions & 4 deletions packages/dma-library/src/utils/swap/fee-resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 <T extends string = string>(
fromToken: T,
toToken: T,
Expand All @@ -22,10 +27,7 @@ export const feeResolver = async <T extends string = string>(
proxyAddress: string
}
},
): Promise<{
feeType: SwapFeeType
feeToCharge: BigNumber
}> => {
): Promise<ResolvedFee> => {
if (isCorrelatedPosition(fromToken, toToken) || options?.isEarnPosition) {
return fixedFeeResolver(options?.positionData, options?.isOpeningPosition)
} else {
Expand Down
6 changes: 2 additions & 4 deletions packages/dma-library/src/utils/swap/fixed-fee-resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -15,10 +16,7 @@ export const fixedFeeResolver = async (
}
| undefined,
isOpeningPosition?: boolean,
): Promise<{
feeType: SwapFeeType
feeToCharge: BigNumber
}> => {
): Promise<ResolvedFee> => {
if (isOpeningPosition) {
return {
feeType: SwapFeeType.Fixed,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 = <T extends string = string>(
Expand All @@ -14,10 +15,7 @@ export const percentageFeeResolver = <T extends string = string>(
/** 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'
Expand Down

0 comments on commit f790c1a

Please sign in to comment.