Skip to content

Commit

Permalink
Refactor fee calculation logic to apply the fee limit - cannot be hig…
Browse files Browse the repository at this point in the history
…her than 1 year of the current debt
  • Loading branch information
piotrwitek committed Nov 21, 2024
1 parent 0852297 commit 664b63b
Show file tree
Hide file tree
Showing 9 changed files with 49 additions and 17 deletions.
32 changes: 22 additions & 10 deletions packages/dma-library/src/utils/fee-service/calculateFee.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export const calculateFee = (position: OasisPosition, toTimestampInSeconds?: num
.slice(startEventIndex) // slice events before the start event

const [totalFee] = eventsToCalculate.reduce(
([accumulatedFee, accumulatedSwapAmount], event, index, arr) => {
([accumulatedFee, accumulatedDebtSwapAmount], event, index, arr) => {
// calculations are in wei unit
const nextEvent = arr[index + 1]
const isThisLastEvent = nextEvent === undefined
Expand All @@ -57,21 +57,21 @@ export const calculateFee = (position: OasisPosition, toTimestampInSeconds?: num
: new BigNumber(nextEvent.timestamp.toString()).toNumber()

const eventSwapAmount = getEventDebtSwapAmount(event)
const newAccumulatedSwapAmount =
const newAccumulatedDebtSwapAmount =
isWithdrawEvent(event) || isDeriskEvent(event)
? accumulatedSwapAmount.minus(eventSwapAmount)
: accumulatedSwapAmount.plus(eventSwapAmount)
? accumulatedDebtSwapAmount.minus(eventSwapAmount)
: accumulatedDebtSwapAmount.plus(eventSwapAmount)

const eventFee = calculateFeeBetweenTimestamps(
newAccumulatedSwapAmount.toString(),
newAccumulatedDebtSwapAmount.toString(),
event.timestamp, // in seconds
nextTimestampOrEnd,
)
const fractions = 10 ** Number(event.debtToken?.decimals)
log(index, event.kind, {
periodDays: calculateDaysBetweenTimestamps(event.timestamp, nextTimestampOrEnd),
periodAssetsUnderManagement:
newAccumulatedSwapAmount.div(fractions).toString() + ' ' + event.debtToken?.symbol,
newAccumulatedDebtSwapAmount.div(fractions).toString() + ' ' + event.debtToken?.symbol,
periodFee:
new BigNumber(eventFee).div(fractions).toString() + ' ' + event.debtToken?.symbol,
})
Expand All @@ -80,16 +80,26 @@ export const calculateFee = (position: OasisPosition, toTimestampInSeconds?: num
// and start accumulating again from this point but keep the accumulated swap
// as we are calculating fee on assets that are accumulated in the position
if (isDeriskEvent(event)) {
return [new BigNumber(eventFee), newAccumulatedSwapAmount]
return [new BigNumber(eventFee), newAccumulatedDebtSwapAmount]
}

// accumulate fee and swap amount and go to next event
const newAccumulatedFee = accumulatedFee.plus(eventFee)
return [newAccumulatedFee, newAccumulatedSwapAmount]
return [newAccumulatedFee, newAccumulatedDebtSwapAmount]
},
[new BigNumber(0), new BigNumber(0)],
)

// apply the fee limit - cannot be higher than 1 year of the current debt
const totalFeeLimit = new BigNumber(position.debt).times(AUM_FEE_RATE).toFixed(0)
if (totalFee.isGreaterThan(totalFeeLimit)) {
log(
'Fee limit based on position debt reached (' + totalFeeLimit.toString() + ' / ',
totalFee.toString() + '). Applying the fee limit.',
)
return totalFeeLimit.toString()
}

return totalFee.toString()
}

Expand All @@ -110,15 +120,17 @@ const getEventDebtSwapAmount = (event: OasisEvent) => {
}

const calculateFeeBetweenTimestamps = (
amountInCollateral: string,
cumulativeDebtSwapAmount: string,
fromTimestamp: bigint,
toTimestamp: number,
) => {
const startTimestamp = fromTimestamp
const endTimestamp = toTimestamp
const daysPassed = calculateDaysBetweenTimestamps(startTimestamp, endTimestamp)

const feeValue = new BigNumber(AUM_FEE_RATE).times(daysPassed / 365).times(amountInCollateral)
const feeValue = new BigNumber(AUM_FEE_RATE)
.times(daysPassed / 365)
.times(cumulativeDebtSwapAmount)

return feeValue.toFixed(0)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ export const getAaveLikePosition = async (
client: GraphQLClient,
positionId: string,
): Promise<OasisPosition | undefined> => {
const events = (await getSdk(client).GetPosition({ id: positionId })).position?.events
return events ? { events } : undefined
const position = (await getSdk(client).GetPosition({ id: positionId })).position
if (!position?.events) {
return undefined
}

const events = position.events
const debt = position.debt.toString()
return { events, debt }
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ export const getMorphoPosition = async (
client: GraphQLClient,
positionId: string,
): Promise<OasisPosition | undefined> => {
const events = (await getSdk(client).GetPosition({ id: positionId })).borrowPosition?.oasisEvents
return events ? { events } : undefined
const position = (await getSdk(client).GetPosition({ id: positionId })).borrowPosition
if (!position?.oasisEvents) {
return undefined
}
const events = position.oasisEvents
const debt = position.debt.toString()
return { events, debt }
}
Original file line number Diff line number Diff line change
Expand Up @@ -4097,12 +4097,13 @@ export type GetPositionQueryVariables = Exact<{
}>;


export type GetPositionQuery = { __typename?: 'Query', position?: { __typename?: 'Position', events: Array<{ __typename?: 'PositionEvent', kind: string, blockNumber: bigint, timestamp: bigint, swapToToken?: string | null, swapToAmount?: string | null, swapFromToken?: string | null, swapFromAmount?: string | null, collateralBefore: string, collateralAfter: string, collateralDelta: string, debtBefore: string, debtAfter: string, debtDelta: string, collateralToken?: { __typename?: 'Token', address: string, symbol: string, decimals: bigint } | null, debtToken?: { __typename?: 'Token', address: string, symbol: string, decimals: bigint } | null }> } | null };
export type GetPositionQuery = { __typename?: 'Query', position?: { __typename?: 'Position', debt: string, events: Array<{ __typename?: 'PositionEvent', kind: string, blockNumber: bigint, timestamp: bigint, swapToToken?: string | null, swapToAmount?: string | null, swapFromToken?: string | null, swapFromAmount?: string | null, collateralBefore: string, collateralAfter: string, collateralDelta: string, debtBefore: string, debtAfter: string, debtDelta: string, collateralToken?: { __typename?: 'Token', address: string, symbol: string, decimals: bigint } | null, debtToken?: { __typename?: 'Token', address: string, symbol: string, decimals: bigint } | null }> } | null };


export const GetPositionDocument = gql`
query GetPosition($id: ID!) {
position(id: $id) {
debt
events(first: 10000, orderBy: blockNumber, orderDirection: asc) {
kind
blockNumber
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7453,12 +7453,13 @@ export type GetPositionQueryVariables = Exact<{
}>;


export type GetPositionQuery = { __typename?: 'Query', borrowPosition?: { __typename?: 'BorrowPosition', oasisEvents?: Array<{ __typename?: 'OasisEvent', kind: string, blockNumber: bigint, timestamp: bigint, swapToToken?: string | null, swapToAmount?: string | null, swapFromToken?: string | null, swapFromAmount?: string | null, collateralBefore: string, collateralAfter: string, collateralDelta: string, debtBefore: string, debtAfter: string, debtDelta: string, collateralToken?: { __typename?: 'Token', address: string, symbol: string, decimals: bigint } | null, debtToken?: { __typename?: 'Token', address: string, symbol: string, decimals: bigint } | null }> | null } | null };
export type GetPositionQuery = { __typename?: 'Query', borrowPosition?: { __typename?: 'BorrowPosition', debt: bigint, oasisEvents?: Array<{ __typename?: 'OasisEvent', kind: string, blockNumber: bigint, timestamp: bigint, swapToToken?: string | null, swapToAmount?: string | null, swapFromToken?: string | null, swapFromAmount?: string | null, collateralBefore: string, collateralAfter: string, collateralDelta: string, debtBefore: string, debtAfter: string, debtDelta: string, collateralToken?: { __typename?: 'Token', address: string, symbol: string, decimals: bigint } | null, debtToken?: { __typename?: 'Token', address: string, symbol: string, decimals: bigint } | null }> | null } | null };


export const GetPositionDocument = gql`
query GetPosition($id: ID!) {
borrowPosition(id: $id) {
debt
oasisEvents(first: 10000, orderBy: blockNumber, orderDirection: asc) {
kind
blockNumber
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
query GetPosition($id: ID!) {
position(id: $id) {
debt
events(first: 10000, orderBy: blockNumber, orderDirection: asc) {
kind
blockNumber
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
query GetPosition($id: ID!) {
borrowPosition(id: $id) {
debt
oasisEvents(first: 10000, orderBy: blockNumber, orderDirection: asc) {
kind
blockNumber
Expand Down
1 change: 1 addition & 0 deletions packages/dma-library/src/utils/fee-service/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export type OasisPosition = {
debt: string
events: OasisEvent[]
}

Expand Down
6 changes: 5 additions & 1 deletion packages/dma-library/src/utils/swap/fee-resolver.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { SwapFeeType } from '@dma-library/types'
import BigNumber from 'bignumber.js'

import { ProtocolId } from '../fee-service'
import type { FixedFeePositionData } from '../fee-service/getFixedFeeForPosition'
import { fixedFeeResolver } from './fixed-fee-resolver'
import { isCorrelatedPosition } from './isCorrelatedPosition'
Expand All @@ -23,7 +24,10 @@ export const feeResolver = async <T extends string = string>(
positionData?: FixedFeePositionData
},
): Promise<ResolvedFee> => {
if (isCorrelatedPosition(fromToken, toToken) || options?.isEarnPosition) {
// currently ajna is not supported for fixed fee
const isNotAjnaPosition = options?.positionData?.protocolId !== ProtocolId.AJNA

if (isCorrelatedPosition(fromToken, toToken) && isNotAjnaPosition) {
return fixedFeeResolver(
options?.positionData,
options?.isOpeningPosition,
Expand Down

0 comments on commit 664b63b

Please sign in to comment.