Skip to content

Instantly share code, notes, and snippets.

@leanazulyoro
Created June 13, 2025 15:53
Show Gist options
  • Save leanazulyoro/88d28d69136d3b7891360bf954340acc to your computer and use it in GitHub Desktop.
Save leanazulyoro/88d28d69136d3b7891360bf954340acc to your computer and use it in GitHub Desktop.
import { buildSwapParams } from 'swapper/src'
import {
Address,
Chain,
getContract,
PublicClient,
Transport
} from 'viem'
import { borrowStrategyABI } from '../../metadata/abis'
import { StrategyIds } from '../../metadata/strategyIds'
import { TAddresses } from '../../metadata/types'
import { FlashLoanExecutorEncoder } from '../encoders/flashLoanExecutorEncoder'
import {
IPosition,
IBorrowStrategyEncoder,
Execution
} from '../types'
import { getContracts } from '../contracts'
import { ONE_ETHER } from '../constants'
export type BorrowWithLeverageParams = {
borrowAmount: bigint
}
export type BorrowWithLeverageOptions = {
flashBorrowToken?: Address
maxSlippage?: bigint
}
async function borrowStrategy<chain extends Chain>(
client: PublicClient<Transport, chain>,
addresses: TAddresses,
strategies: StrategyIds,
position: IPosition<IBorrowStrategyEncoder>,
params: BorrowWithLeverageParams,
options?: BorrowWithLeverageOptions
) {
const positionContract =
position.contract ||
getContract({
abi: borrowStrategyABI,
address: position.address,
client: client as PublicClient
})
const depositToken = await positionContract.read.asset()
const borrowToken = await positionContract.read.borrowToken()
const { oracleContract, flashLoanExecutorContract } = getContracts(addresses)
const oracle = getContract({
...oracleContract,
client: client as PublicClient
})
const flashLoanExecutor = getContract({
...flashLoanExecutorContract,
client: client as PublicClient
})
const { borrowAmount } = params
const maxSlippage = options?.maxSlippage || BigInt(0.005e18)
const flashBorrowToken = options?.flashBorrowToken || depositToken
const flashLoanAmount = await oracle.read.quote([
borrowToken,
flashBorrowToken,
(borrowAmount * ONE_ETHER) / (ONE_ETHER + maxSlippage)
]) as bigint
const flashLoanRepayAmount = await flashLoanExecutor.read.getRepayAmount([
flashBorrowToken,
flashLoanAmount
])
const flashLoanRepayAmountInBorrowToken = (await oracle.read.quote([
depositToken,
borrowToken,
flashLoanRepayAmount
])) as bigint
const flashLoanRepayAmountInBorrowTokenWithSlippage =
(flashLoanRepayAmountInBorrowToken * (ONE_ETHER + maxSlippage)) / ONE_ETHER
const zapOutParams = await buildSwapParams(client, {
amountIn: flashLoanRepayAmountInBorrowTokenWithSlippage,
from: position.address,
to: flashLoanExecutor.address,
tokenIn: borrowToken,
tokenOut: flashBorrowToken
})
const featureCallData = position.encoder.encodeBorrowCallData({
borrowAmount
})
const executions: Execution[] = [
// deposit the flashBorrowAmount into the position
{
callData: position.encoder.encodeDepositCallData({
depositAmount: flashLoanAmount
}),
target: position.address,
value: 0n
},
// borrow
{
callData: featureCallData,
target: position.address,
value: 0n
},
// transfer to FlashLoanExecutor
{
callData: position.encoder.encodeTransferOutCallData({
amountOut: flashLoanRepayAmountInBorrowTokenWithSlippage,
to: flashLoanExecutor.address,
token: borrowToken,
zapOutParams
}),
target: position.address,
value: 0n
}
]
const zapInParams = await buildSwapParams(client, {
amountIn: flashLoanAmount,
from: flashLoanExecutor.address,
to: position.address,
tokenIn: flashBorrowToken,
tokenOut: depositToken
})
const callData = FlashLoanExecutorEncoder.encodeStartCallData({
executions,
flashBorrowAmount: flashLoanAmount,
flashBorrowToken,
position: position.address,
zapInParams
})
return { callData, target: flashLoanExecutor.address, value: 0n }
}
/*
type SynthBorrowWithLeverageParams = BorrowWithLeverageParams & {
tokenIn?: Address
depositToken: Address
}
async function synthStrategy<chain extends Chain>(
client: PublicClient<Transport, chain>,
addresses: TAddresses,
strategies: StrategyIds,
position: IPosition<ISynthStrategyEncoder>,
params: SynthBorrowWithLeverageParams,
options?: BorrowWithLeverageOptions
) {
// TODO: implement borrow for synth strategy
}
*/
export async function borrowWithLeverage<chain extends Chain>(
client: PublicClient<Transport, chain>,
addresses: TAddresses,
strategies: StrategyIds,
position: IPosition,
params: BorrowWithLeverageParams,
options?: BorrowWithLeverageOptions
) {
/*const { SYNTH_STRATEGY_ID } = strategies
if (position.strategyId === SYNTH_STRATEGY_ID) {
return synthStrategy(
client,
addresses,
strategies,
<IPosition<ISynthStrategyEncoder>>position,
params as SynthBorrowWithLeverageParams,
options
)
}*/
return borrowStrategy(
client,
addresses,
strategies,
<IPosition<IBorrowStrategyEncoder>>position,
params,
options
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment