Skip to content

Commit

Permalink
Merge pull request #23 from OasisDEX:jt/sc-14562/lib-create-strategie…
Browse files Browse the repository at this point in the history
…s-for-new-operations

✨ feat(with ops): create strategies for new withdraw-to-ltv operations for auto
  • Loading branch information
halaprix authored Mar 8, 2024
2 parents 185dc44 + 76c3080 commit 03c45aa
Show file tree
Hide file tree
Showing 13 changed files with 372 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export const OPERATION_NAMES = {
BORROW: 'AAVEV3Borrow',
PAYBACK_WITHDRAW: 'AAVEV3PaybackWithdraw',
WITHDRAW: 'AAVEV3Withdraw_3',
WITHDRAW_TO_DEBT: 'AAVEV3WithdrawToDebt_3',
WITHDRAW_TO_DEBT: 'AAVEV3WithdrawToDebt_4',
},
},
spark: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export function getAaveV3WithdrawToDebtOperationDefinition(network: Network) {
optional: false,
},
{
hash: getActionHash(SERVICE_REGISTRY_NAMES.common.SWAP),
hash: getActionHash(SERVICE_REGISTRY_NAMES.common.SWAP_ACTION),
optional: false,
},
{
Expand Down
2 changes: 1 addition & 1 deletion packages/dma-library/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@oasisdex/dma-library",
"version": "0.5.21-dma-v2-workers.19-test.10",
"version": "0.5.21-dma-v2-workers.28-auto-withdraw-to-ltv",
"typings": "lib/index.d.ts",
"types": "lib/index.d.ts",
"main": "lib/index.js",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import BigNumber from 'bignumber.js'

type WithdrawToDebtArgs = {
withdrawAmount: BigNumber
swapAmount: BigNumber
receiveAtLeast: BigNumber
swapData: string
collateralTokenAddress: string
Expand Down Expand Up @@ -40,7 +41,7 @@ export const withdrawToDebt: AaveV3WithdrawToDebtOperation = async args => {
const swapCollateralTokensForDebtTokens = actions.common.swap(network, {
fromAsset: args.collateralTokenAddress,
toAsset: args.debtTokenAddress,
amount: args.withdrawAmount,
amount: args.swapAmount,
receiveAtLeast: args.receiveAtLeast,
fee: ZERO.toNumber(),
withData: args.swapData,
Expand Down
23 changes: 14 additions & 9 deletions packages/dma-library/src/operations/aave/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,6 @@ import {
AaveV3PaybackWithdrawOperation,
paybackWithdraw as aaveV3PaybackWithdraw,
} from './borrow/v3/payback-withdraw'
import { type AaveV3WithdrawOperation, withdraw as aaveV3Withdraw } from './borrow/v3/withdraw'
import {
type AaveV3WithdrawToDebtOperation,
withdrawToDebt as aaveV3WithdrawToDebt,
} from './borrow/v3/withdraw-to-debt'
// Multiply
import {
AaveV2AdjustDownOperation,
Expand All @@ -53,6 +48,12 @@ import {
} from './multiply/v3/adjust-risk-up'
import { AaveV3CloseOperation, close as aaveV3Close } from './multiply/v3/close'
import { AaveV3OpenOperation, open as aaveV3Open } from './multiply/v3/open'
// Auto
import { type AaveV3WithdrawOperation, withdraw as aaveV3Withdraw } from './auto/withdraw'
import {
type AaveV3WithdrawToDebtOperation,
withdrawToDebt as aaveV3WithdrawToDebt,
} from './auto/withdraw-to-debt'

const borrow = {
v2: {
Expand All @@ -68,8 +69,6 @@ const borrow = {
depositBorrow: aaveV3DepositBorrow,
openDepositBorrow: aaveV3OpenDepositBorrow,
paybackWithdraw: aaveV3PaybackWithdraw,
withdraw: aaveV3Withdraw,
withdrawToDebt: aaveV3WithdrawToDebt,
},
}

Expand Down Expand Up @@ -102,8 +101,6 @@ export type AaveBorrowOperations = {
depositBorrow: AaveV3DepositBorrowOperation
openDepositBorrow: AaveV3OpenDepositBorrowOperation
paybackWithdraw: AaveV3PaybackWithdrawOperation
withdraw: AaveV3WithdrawOperation
withdrawToDebt: AaveV3WithdrawToDebtOperation
}
}

Expand All @@ -125,9 +122,17 @@ export type AaveMultiplyOperations = {
export type AaveOperations = {
borrow: AaveBorrowOperations
multiply: AaveMultiplyOperations
auto: {
withdraw: AaveV3WithdrawOperation
withdrawToDebt: AaveV3WithdrawToDebtOperation
}
}

export const aaveOperations: AaveOperations = {
borrow,
multiply,
auto: {
withdraw: aaveV3Withdraw,
withdrawToDebt: aaveV3WithdrawToDebt,
},
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import BigNumber from 'bignumber.js'

type WithdrawToDebtArgs = {
withdrawAmount: BigNumber
swapAmount: BigNumber
receiveAtLeast: BigNumber
swapData: string
collateralTokenAddress: string
Expand Down
30 changes: 22 additions & 8 deletions packages/dma-library/src/operations/spark/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
import { AaveV3WithdrawOperation, withdraw as aaveV3Withdraw } from "@dma-library/operations/aave/auto/withdraw";
import {
AaveV3WithdrawToDebtOperation,
withdrawToDebt as aaveV3WithdrawToDebt
} from "@dma-library/operations/aave/auto/withdraw-to-debt";
import { borrow as sparkBorrow, SparkBorrowOperation } from './borrow/borrow'
import { deposit as sparkDeposit, SparkDepositOperation } from './borrow/deposit'
import {
Expand All @@ -12,14 +17,6 @@ import {
paybackWithdraw as sparkPaybackWithdraw,
SparkPaybackWithdrawOperation,
} from './borrow/payback-withdraw'
import {
withdraw as sparkWithdraw,
SparkWithdrawOperation,
} from './borrow/withdraw'
import {
withdrawToDebt as sparkWithdrawToDebt,
SparkWithdrawToDebtOperation,
} from './borrow/withdraw-to-debt'
import {
adjustRiskDown as sparkAdjustRiskDown,
SparkAdjustDownOperation,
Expand All @@ -30,6 +27,15 @@ import {
} from './multiply/adjust-risk-up'
import { close as sparkClose, SparkCloseOperation } from './multiply/close'
import { open as sparkOpen, SparkOpenOperation } from './multiply/open'
// Auto
import {
withdraw as sparkWithdraw,
SparkWithdrawOperation,
} from './auto/withdraw'
import {
withdrawToDebt as sparkWithdrawToDebt,
SparkWithdrawToDebtOperation,
} from './auto/withdraw-to-debt'

const borrow = {
borrow: sparkBorrow,
Expand Down Expand Up @@ -67,9 +73,17 @@ export type SparkMultiplyOperations = {
export type SparkOperations = {
borrow: SparkBorrowOperations
multiply: SparkMultiplyOperations
auto: {
withdraw: SparkWithdrawOperation
withdrawToDebt: SparkWithdrawToDebtOperation
}
}

export const sparkOperations: SparkOperations = {
borrow,
multiply,
auto: {
withdraw: sparkWithdraw,
withdrawToDebt: sparkWithdrawToDebt,
},
}
159 changes: 159 additions & 0 deletions packages/dma-library/src/strategies/aave/auto/withdraw-to-ltv/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
import { ONE, ZERO } from "@dma-common/constants";
import { withdraw as withdrawOp } from '@dma-library/operations/aave/auto/withdraw'
import { withdrawToDebt } from '@dma-library/operations/aave/auto/withdraw-to-debt'
import { getAaveTokenAddress } from '@dma-library/strategies/aave/common'
import { AaveLikeTokens } from '@dma-library/types'
import { WithV3Protocol } from '@dma-library/types/aave/protocol'
import * as Strategies from '@dma-library/types/strategies'
import * as StrategyParams from '@dma-library/types/strategy-params'
import { getSwapDataHelper } from '@dma-library/utils/swap'
import { PositionBalance } from '@domain'
import BigNumber from 'bignumber.js'

export type AaveV3WithdrawArgs = {
oraclePrice: BigNumber
targetLTV: BigNumber
slippage: BigNumber
shouldWithdrawToDebt: boolean
}

export type AaveV3WithdrawDependencies = Omit<
StrategyParams.WithAaveLikeStrategyDependencies,
'protocolType'
> &
StrategyParams.WithGetSwap &
WithV3Protocol

export type WithdrawToLTVStrategy = Omit<Strategies.IStrategy, 'simulation'>

export type AaveV3WithdrawToLTV = (
args: AaveV3WithdrawArgs,
dependencies: Omit<AaveV3WithdrawDependencies, 'protocol'>,
) => Promise<WithdrawToLTVStrategy>

export const withdraw: AaveV3WithdrawToLTV = async (args, dependencies) => {
const currentPosition = dependencies.currentPosition

const amountToWithdraw = determineWithdrawalAmount(
currentPosition.debt,
currentPosition.collateral,
args.targetLTV,
args.oraclePrice,
)

const collateralTokenSymbol = currentPosition.collateral.symbol
const debtTokenSymbol = currentPosition.debt.symbol

if (args.shouldWithdrawToDebt) {
const FEE = new BigNumber(20)
const FEE_BASIS = new BigNumber(10000)
const feeAmount = amountToWithdraw.times(FEE.div(FEE_BASIS)).integerValue(BigNumber.ROUND_FLOOR);
const amountToSwap = amountToWithdraw.minus(feeAmount)
const { swapData } = await getSwapDataHelper<typeof dependencies.addresses, AaveLikeTokens>({
args: {
fromToken: { symbol: collateralTokenSymbol as AaveLikeTokens },
toToken: { symbol: debtTokenSymbol as AaveLikeTokens },
slippage: args.slippage,
fee: ZERO,
// Before fees here refers to fees collected by the Swap contract
// not by CollectFee.sol
swapAmountBeforeFees: amountToSwap,
},
addresses: dependencies.addresses,
services: {
getSwapData: dependencies.getSwapData,
getTokenAddress: getAaveTokenAddress,
},
})

const operation = await withdrawToDebt({
withdrawAmount: amountToWithdraw,
collateralTokenAddress: getTokenAddressFromDependencies(
dependencies,
currentPosition.collateral.symbol,
),
receiveAtLeast: swapData.minToTokenAmount,
swapAmount: amountToSwap,
swapData: `${swapData.exchangeCalldata}`,
debtTokenAddress: getTokenAddressFromDependencies(dependencies, debtTokenSymbol),
debtIsEth: debtTokenSymbol === 'WETH',
proxy: dependencies.proxy,
addresses: dependencies.addresses,
network: dependencies.network,
})

return {
transaction: {
calls: operation.calls,
operationName: operation.operationName,
},
}
}

if (!args.shouldWithdrawToDebt) {
const operation = await withdrawOp({
withdrawAmount: amountToWithdraw,
collateralTokenAddress: getTokenAddressFromDependencies(
dependencies,
currentPosition.collateral.symbol,
),
collateralIsEth: collateralTokenSymbol === 'WETH',
proxy: dependencies.proxy,
addresses: dependencies.addresses,
network: dependencies.network,
})

return {
transaction: {
calls: operation.calls,
operationName: operation.operationName,
},
}
}

throw new Error('Should not be reached')
}

function determineWithdrawalAmount(
existingDebt: PositionBalance,
existingCollateral: PositionBalance,
targetLTV: BigNumber,
oraclePrice: BigNumber,
) {
const COLLATERAL_PRECISION = existingCollateral.precision
const DEBT_PRECISION = existingDebt.precision

// We scale down because BigNumber can handle precision maths
// with large floating point numbers
const scaledDownDebt = existingDebt.amount.div(new BigNumber(10).pow(DEBT_PRECISION))

// nextCollateral = existingDebt / (targetLTV * oraclePrice)
const scaledDownNextCollateral = scaledDownDebt.div(targetLTV.times(oraclePrice))
const nextCollateral = scaledDownNextCollateral.multipliedBy(
new BigNumber(10).pow(COLLATERAL_PRECISION),
)
const amountToWithdraw = existingCollateral.amount.minus(nextCollateral)

if (amountToWithdraw.lte(ZERO)) {
console.debug('next-collateral', nextCollateral.toString())
console.debug('amount-to-withdraw', amountToWithdraw.toString())
throw new Error('Cannot withdraw zero or less')
}

return amountToWithdraw
}

function getTokenAddressFromDependencies(
deps: Omit<AaveV3WithdrawDependencies, 'protocol'>,
symbol: string,
) {
const address = deps.addresses.tokens[symbol]

if (!address) {
console.debug('symbol:', symbol)
console.debug('tokens:', deps.addresses.tokens)
throw new Error('Could not get address from position token symbol')
}

return address
}
7 changes: 7 additions & 0 deletions packages/dma-library/src/strategies/aave/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
import { AaveV2Adjust, AaveV3Adjust, adjust } from './multiply/adjust'
import { AaveV2Close, AaveV3Close, close } from './multiply/close'
import { AaveV2Open, AaveV3Open, open } from './multiply/open'
import { AaveV3WithdrawToLTV, withdraw } from './auto/withdraw-to-ltv'

export const aave: {
borrow: {
Expand Down Expand Up @@ -45,6 +46,9 @@ export const aave: {
adjust: AaveV3Adjust
}
}
auto: {
withdraw: AaveV3WithdrawToLTV
}
} = {
borrow: {
v2: {
Expand Down Expand Up @@ -73,6 +77,9 @@ export const aave: {
adjust: (args, dependencies) => withV3Protocol(adjust, args, dependencies),
},
},
auto: {
withdraw: (args, dependencies) => withV3Protocol(withdraw, args, dependencies),
},
}

type DepsWithV2Protocol<T> = T & WithV2Protocol
Expand Down
Loading

0 comments on commit 03c45aa

Please sign in to comment.