Skip to main content

klend_interface/helpers/
liquidate.rs

1use solana_instruction::Instruction;
2use solana_pubkey::Pubkey;
3
4use super::{
5    common::{
6        build_refresh_all_obligation_reserves, build_refresh_obligation,
7        build_refresh_obligation_remaining_accounts, build_refresh_reserve,
8    },
9    info::{FarmsAccounts, ObligationInfo, ReserveInfo},
10};
11use crate::{
12    instructions::liquidate::{
13        liquidate_obligation_and_redeem_reserve_collateral_v2,
14        LiquidateObligationAndRedeemReserveCollateralV2Accounts,
15    },
16    pda::{self, ReservePdas},
17    KLEND_PROGRAM_ID,
18};
19
20/// Build instructions to liquidate an undercollateralized obligation.
21///
22/// The liquidator repays debt on `repay_reserve` and receives collateral
23/// from `withdraw_reserve`. Both reserves and the obligation are refreshed
24/// automatically.
25///
26/// `obligation_reserves` should contain [`ReserveInfo`] for every deposit and
27/// borrow reserve on the obligation.
28///
29/// Returns: `[refresh_other_reserves..., refresh_repay_reserve, refresh_withdraw_reserve,
30///            refresh_obligation, liquidate_and_redeem_v2]`
31#[allow(clippy::too_many_arguments)]
32pub fn liquidate(
33    liquidator: Pubkey,
34    repay_reserve: &ReserveInfo,
35    withdraw_reserve: &ReserveInfo,
36    obligation: &ObligationInfo,
37    obligation_reserves: &[ReserveInfo],
38    user_source_liquidity: Pubkey,
39    user_destination_collateral: Pubkey,
40    user_destination_liquidity: Pubkey,
41    liquidity_amount: u64,
42    min_acceptable_received_liquidity_amount: u64,
43    max_allowed_ltv_override_percent: u64,
44    collateral_farms: Option<&FarmsAccounts>,
45    debt_farms: Option<&FarmsAccounts>,
46) -> Vec<Instruction> {
47    let (lma, _) = pda::lending_market_authority(&KLEND_PROGRAM_ID, &repay_reserve.lending_market);
48    let repay_pdas = ReservePdas::derive(&KLEND_PROGRAM_ID, &repay_reserve.address);
49    let withdraw_pdas = ReservePdas::derive(&KLEND_PROGRAM_ID, &withdraw_reserve.address);
50
51    let remaining = build_refresh_obligation_remaining_accounts(obligation);
52
53    let mut ixs = build_refresh_all_obligation_reserves(
54        obligation,
55        obligation_reserves,
56        &[repay_reserve.address, withdraw_reserve.address],
57    );
58    ixs.push(build_refresh_reserve(repay_reserve));
59    ixs.push(build_refresh_reserve(withdraw_reserve));
60    ixs.push(build_refresh_obligation(
61        &repay_reserve.lending_market,
62        obligation,
63    ));
64    ixs.push(liquidate_obligation_and_redeem_reserve_collateral_v2(
65        LiquidateObligationAndRedeemReserveCollateralV2Accounts {
66            liquidator,
67            obligation: obligation.address,
68            lending_market: repay_reserve.lending_market,
69            lending_market_authority: lma,
70            repay_reserve: repay_reserve.address,
71            repay_reserve_liquidity_mint: repay_reserve.liquidity_mint,
72            repay_reserve_liquidity_supply: repay_pdas.liquidity_supply_vault,
73            withdraw_reserve: withdraw_reserve.address,
74            withdraw_reserve_liquidity_mint: withdraw_reserve.liquidity_mint,
75            withdraw_reserve_collateral_mint: withdraw_pdas.collateral_mint,
76            withdraw_reserve_collateral_supply: withdraw_pdas.collateral_supply_vault,
77            withdraw_reserve_liquidity_supply: withdraw_pdas.liquidity_supply_vault,
78            withdraw_reserve_liquidity_fee_receiver: withdraw_pdas.fee_vault,
79            user_source_liquidity,
80            user_destination_collateral,
81            user_destination_liquidity,
82            repay_liquidity_token_program: repay_reserve.liquidity_token_program,
83            withdraw_liquidity_token_program: withdraw_reserve.liquidity_token_program,
84            collateral_obligation_farm_user_state: collateral_farms
85                .map(|f| f.obligation_farm_user_state),
86            collateral_reserve_farm_state: collateral_farms.map(|f| f.reserve_farm_state),
87            debt_obligation_farm_user_state: debt_farms.map(|f| f.obligation_farm_user_state),
88            debt_reserve_farm_state: debt_farms.map(|f| f.reserve_farm_state),
89        },
90        liquidity_amount,
91        min_acceptable_received_liquidity_amount,
92        max_allowed_ltv_override_percent,
93        remaining,
94    ));
95
96    ixs
97}