diff --git a/src/liquidator.rs b/src/liquidator.rs index 093a79e..f03794a 100644 --- a/src/liquidator.rs +++ b/src/liquidator.rs @@ -116,6 +116,9 @@ impl Liquidator { let rpc_client = Arc::new(RpcClient::new(self.general_config.rpc_url.clone())); self.load_marginfi_accounts(rpc_client.clone()).await?; self.load_oracles_and_banks(rpc_client.clone()).await?; + self.liquidator_account + .load_initial_data(rpc_client.as_ref(), self.get_all_mints()) + .await?; Ok(()) } @@ -665,4 +668,11 @@ impl Liquidator { values } + + fn get_all_mints(&self) -> Vec { + self.banks + .values() + .map(|bank| bank.bank.mint) + .collect::>() + } } diff --git a/src/marginfi_ixs.rs b/src/marginfi_ixs.rs index 62aae77..2d63357 100644 --- a/src/marginfi_ixs.rs +++ b/src/marginfi_ixs.rs @@ -1,5 +1,6 @@ use anchor_lang::{system_program, InstructionData, Key, ToAccountMetas}; +use anchor_spl::token_2022; use log::trace; use solana_sdk::instruction::AccountMeta; use solana_sdk::{ @@ -38,20 +39,25 @@ pub fn make_deposit_ix( signer_token_account: Pubkey, bank_liquidity_vault: Pubkey, token_program: Pubkey, + mint: Pubkey, amount: u64, ) -> Instruction { + let mut accounts = marginfi::accounts::LendingAccountDeposit { + marginfi_group, + marginfi_account, + signer, + bank, + signer_token_account, + bank_liquidity_vault, + token_program, + } + .to_account_metas(Some(true)); + + maybe_add_bank_mint(&mut accounts, mint, &token_program); + Instruction { program_id: marginfi_program_id, - accounts: marginfi::accounts::LendingAccountDeposit { - marginfi_group, - marginfi_account, - signer, - bank, - signer_token_account, - bank_liquidity_vault, - token_program, - } - .to_account_metas(Some(true)), + accounts, data: marginfi::instruction::LendingAccountDeposit { amount }.data(), } } @@ -65,21 +71,26 @@ pub fn make_repay_ix( signer_token_account: Pubkey, bank_liquidity_vault: Pubkey, token_program: Pubkey, + mint: Pubkey, amount: u64, repay_all: Option, ) -> Instruction { + let mut accounts = marginfi::accounts::LendingAccountRepay { + marginfi_group, + marginfi_account, + signer, + bank, + signer_token_account, + bank_liquidity_vault, + token_program, + } + .to_account_metas(Some(true)); + + maybe_add_bank_mint(&mut accounts, mint, &token_program); + Instruction { program_id: marginfi_program_id, - accounts: marginfi::accounts::LendingAccountRepay { - marginfi_group, - marginfi_account, - signer, - bank, - signer_token_account, - bank_liquidity_vault, - token_program, - } - .to_account_metas(Some(true)), + accounts, data: marginfi::instruction::LendingAccountRepay { amount, repay_all }.data(), } } @@ -95,6 +106,7 @@ pub fn make_withdraw_ix( bank_liquidity_vault: Pubkey, token_program: Pubkey, observation_accounts: Vec, + mint: Pubkey, amount: u64, withdraw_all: Option, ) -> Instruction { @@ -110,6 +122,8 @@ pub fn make_withdraw_ix( } .to_account_metas(Some(true)); + maybe_add_bank_mint(&mut accounts, mint, &token_program); + trace!( "make_withdraw_ix: observation_accounts: {:?}", observation_accounts @@ -148,6 +162,7 @@ pub fn make_liquidate_ix( liquidatee_observation_accounts: Vec, asset_bank_oracle: Pubkey, liab_bank_oracle: Pubkey, + liab_mint: Pubkey, asset_amount: u64, ) -> Instruction { let mut accounts = marginfi::accounts::LendingAccountLiquidate { @@ -164,6 +179,8 @@ pub fn make_liquidate_ix( } .to_account_metas(Some(true)); + maybe_add_bank_mint(&mut accounts, liab_mint, &token_program); + accounts.extend([ AccountMeta::new_readonly(asset_bank_oracle, false), AccountMeta::new_readonly(liab_bank_oracle, false), @@ -187,3 +204,9 @@ pub fn make_liquidate_ix( data: marginfi::instruction::LendingAccountLiquidate { asset_amount }.data(), } } + +fn maybe_add_bank_mint(accounts: &mut Vec, mint: Pubkey, token_program: &Pubkey) { + if token_program == &token_2022::ID { + accounts.push(AccountMeta::new_readonly(mint, false)); + } +} diff --git a/src/wrappers/liquidator_account.rs b/src/wrappers/liquidator_account.rs index 3c780fd..e6f4f0d 100644 --- a/src/wrappers/liquidator_account.rs +++ b/src/wrappers/liquidator_account.rs @@ -19,7 +19,7 @@ pub struct LiquidatorAccount { pub account_wrapper: MarginfiAccountWrapper, pub signer_keypair: Arc, program_id: Pubkey, - token_program: Pubkey, + token_program_per_mint: HashMap, group: Pubkey, transaction_tx: Sender, } @@ -34,24 +34,40 @@ impl LiquidatorAccount { let signer_keypair = Arc::new(read_keypair_file(&config.keypair_path).unwrap()); let account = rpc_client.get_account(&liquidator_pubkey)?; - let marginfi_account = bytemuck::from_bytes::(&account.data[8..]); - let account_wrapper = MarginfiAccountWrapper::new(liquidator_pubkey, *marginfi_account); let program_id = marginfi::id(); - let token_program = spl_token::id(); let group = account_wrapper.account.group; + Ok(Self { account_wrapper, signer_keypair, program_id, - token_program, group, transaction_tx, + token_program_per_mint: HashMap::new(), }) } + pub async fn load_initial_data( + &mut self, + rpc_client: &RpcClient, + mints: Vec, + ) -> anyhow::Result<()> { + let token_program_per_mint = rpc_client + .get_multiple_accounts(&mints) + .unwrap() + .iter() + .zip(mints) + .map(|(account, mint)| (mint, account.as_ref().unwrap().owner)) + .collect(); + + self.token_program_per_mint = token_program_per_mint; + + Ok(()) + } + pub async fn liquidate( &mut self, liquidate_account: &MarginfiAccountWrapper, @@ -63,6 +79,7 @@ impl LiquidatorAccount { let liquidator_account_address = self.account_wrapper.address; let liquidatee_account_address = liquidate_account.address; let signer_pk = self.signer_keypair.pubkey(); + let liab_mint = liab_bank.bank.mint; let (bank_liquidaity_vault_authority, _) = crate::utils::find_bank_vault_authority_pda( &liab_bank.address, @@ -93,11 +110,12 @@ impl LiquidatorAccount { bank_liquidaity_vault_authority, bank_liquidaity_vault, bank_insurante_vault, - self.token_program, + self.token_program_per_mint.get(&liab_mint).unwrap().clone(), liquidator_observation_accounts, liquidatee_observation_accounts, asset_bank.bank.config.oracle_keys[0], liab_bank.bank.config.oracle_keys[0], + liab_mint, asset_amount, ); @@ -129,6 +147,9 @@ impl LiquidatorAccount { self.account_wrapper .get_observation_accounts(&[], &banks_to_exclude, banks); + let mint = bank.bank.mint; + let token_program = self.token_program_per_mint.get(&mint).unwrap().clone(); + let withdraw_ix = make_withdraw_ix( self.program_id, self.group, @@ -143,8 +164,9 @@ impl LiquidatorAccount { ) .0, bank.bank.liquidity_vault, - self.token_program, + token_program, observation_accounts, + mint, amount, withdraw_all, ); @@ -166,6 +188,9 @@ impl LiquidatorAccount { let signer_pk = self.signer_keypair.pubkey(); + let mint = bank.bank.mint; + let token_program = self.token_program_per_mint.get(&mint).unwrap().clone(); + let repay_ix = make_repay_ix( self.program_id, self.group, @@ -174,7 +199,8 @@ impl LiquidatorAccount { bank.address, *token_account, bank.bank.liquidity_vault, - self.token_program, + token_program, + mint, amount, repay_all, ); @@ -195,6 +221,9 @@ impl LiquidatorAccount { let signer_pk = self.signer_keypair.pubkey(); + let mint = bank.bank.mint; + let token_program = self.token_program_per_mint.get(&mint).unwrap().clone(); + let deposit_ix = make_deposit_ix( self.program_id, self.group, @@ -203,7 +232,8 @@ impl LiquidatorAccount { bank.address, token_account, bank.bank.liquidity_vault, - self.token_program, + token_program, + mint, amount, );