Skip to main content

percli_program/instructions/
liquidate.rs

1use anchor_lang::prelude::*;
2use percli_core::LiquidationPolicy;
3
4use crate::error::{from_risk_error, PercolatorError};
5use crate::state::{engine_from_account_data, MARKET_ACCOUNT_SIZE};
6
7#[derive(Accounts)]
8pub struct Liquidate<'info> {
9    /// Permissionless — anyone can liquidate.
10    pub liquidator: Signer<'info>,
11
12    /// CHECK: Validated via owner, discriminator, and size.
13    #[account(
14        mut,
15        owner = crate::ID @ PercolatorError::AccountNotFound,
16        constraint = market.data_len() == MARKET_ACCOUNT_SIZE @ PercolatorError::AccountNotFound,
17    )]
18    pub market: UncheckedAccount<'info>,
19}
20
21pub fn handler(ctx: Context<Liquidate>, account_idx: u16, funding_rate: i64) -> Result<bool> {
22    let market = &ctx.accounts.market;
23    let mut data = market.try_borrow_mut_data()?;
24
25    require!(&data[0..8] == b"percmrkt", PercolatorError::AccountNotFound);
26
27    let engine = engine_from_account_data(&mut data);
28    let oracle_price = engine.last_oracle_price;
29    let clock = Clock::get()?;
30
31    let liquidated = engine
32        .liquidate_at_oracle_not_atomic(
33            account_idx,
34            clock.slot,
35            oracle_price,
36            LiquidationPolicy::FullClose,
37            funding_rate,
38        )
39        .map_err(from_risk_error)?;
40
41    Ok(liquidated)
42}