diff --git a/Cargo.lock b/Cargo.lock index f32663a..8d1c66f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2910,6 +2910,7 @@ dependencies = [ [[package]] name = "marginfi" version = "0.1.0" +source = "git+https://github.com/mrgnlabs/marginfi-v2?branch=main#24dfeb16d121034dda9a25056a0810c774714f64" dependencies = [ "anchor-lang 0.29.0", "anchor-lang 0.30.1", diff --git a/src/geyser.rs b/src/geyser.rs index 3b5dd74..b702cd5 100644 --- a/src/geyser.rs +++ b/src/geyser.rs @@ -3,7 +3,7 @@ use anchor_lang::AccountDeserialize; use crossbeam::channel::Sender; use futures::StreamExt; use log::{error, info}; -use marginfi::{instructions::marginfi_account, state::marginfi_account::MarginfiAccount}; +use marginfi::state::marginfi_account::MarginfiAccount; use solana_program::pubkey::Pubkey; use solana_sdk::account::Account; use std::{collections::HashMap, mem::size_of}; @@ -170,7 +170,6 @@ impl GeyserService { } } } - Ok(()) } /// Builds a geyser subscription request payload diff --git a/src/liquidator.rs b/src/liquidator.rs index eb1bfad..1fbf284 100644 --- a/src/liquidator.rs +++ b/src/liquidator.rs @@ -41,10 +41,8 @@ use solana_sdk::{ account::Account, account_info::IntoAccountInfo, bs58, clock::Clock, signature::Keypair, }; use std::{ - cell::RefCell, cmp::min, collections::HashMap, - rc::Rc, sync::{atomic::AtomicBool, Arc}, }; use switchboard_on_demand::PullFeedAccountData; @@ -155,28 +153,44 @@ impl Liquidator { match msg.account_type { AccountType::OracleAccount => { if let Some(bank_to_update_pk) = self.oracle_to_bank.get(&msg.address) { - let oracle_ai = (&msg.address, &mut msg.account).into_account_info(); let bank_to_update: &mut BankWrapper = self.banks.get_mut(bank_to_update_pk).unwrap(); - let oracle_price_adapter = - OraclePriceFeedAdapter::try_from_bank_config_with_max_age( - &bank_to_update.bank.config, - &[oracle_ai.clone()], - &Clock::default(), - i64::MAX as u64, - ) - .unwrap(); - - match oracle_price_adapter { - OraclePriceFeedAdapter::SwitchboardPull(_) => { - let full_swb = - crate::utils::load_swb_pull_account(&oracle_ai).unwrap(); - let feed_hash = hex::encode(full_swb.feed_hash); + let oracle_price_adapter = match bank_to_update.bank.config.oracle_setup + { + OracleSetup::SwitchboardPull => { + let mut offsets_data = + [0u8; std::mem::size_of::()]; + offsets_data.copy_from_slice( + &msg.account.data + [8..std::mem::size_of::() + 8], + ); + let swb_feed = crate::utils::load_swb_pull_account_from_bytes( + &offsets_data, + ) + .unwrap(); + + let feed_hash = hex::encode(swb_feed.feed_hash); bank_to_update.oracle_adapter.swb_feed_hash = Some(feed_hash); + + OraclePriceFeedAdapter::SwitchboardPull( + SwitchboardPullPriceFeed { + feed: Box::new((&swb_feed).into()), + }, + ) } - _ => {} - } + _ => { + let oracle_account_info = + (&msg.address, &mut msg.account).into_account_info(); + OraclePriceFeedAdapter::try_from_bank_config_with_max_age( + &bank_to_update.bank.config, + &[oracle_account_info], + &Clock::default(), + i64::MAX as u64, + ) + .unwrap() + } + }; bank_to_update.oracle_adapter.price_adapter = oracle_price_adapter; } @@ -689,28 +703,30 @@ impl Liquidator { (oracle_address.unwrap(), oracle_account.unwrap()) }; - let mut oracle_account_info = - (&oracle_address, &mut oracle_account).into_account_info(); - let price_adapter = match bank.config.oracle_setup { OracleSetup::SwitchboardPull => { - let swb_feed = crate::utils::load_swb_pull_account_from_bytes( - &oracle_account_info.data.borrow() - [0..std::mem::size_of::()], - ) - .unwrap(); + let mut offsets_data = [0u8; std::mem::size_of::()]; + offsets_data.copy_from_slice( + &oracle_account.data[8..std::mem::size_of::() + 8], + ); + let swb_feed = + crate::utils::load_swb_pull_account_from_bytes(&offsets_data).unwrap(); OraclePriceFeedAdapter::SwitchboardPull(SwitchboardPullPriceFeed { feed: Box::new((&swb_feed).into()), }) } - _ => OraclePriceFeedAdapter::try_from_bank_config_with_max_age( - &bank.config, - &[oracle_account_info], - &Clock::default(), - i64::MAX as u64, - ) - .unwrap(), + _ => { + let oracle_account_info = + (&oracle_address, &mut oracle_account).into_account_info(); + OraclePriceFeedAdapter::try_from_bank_config_with_max_age( + &bank.config, + &[oracle_account_info], + &Clock::default(), + i64::MAX as u64, + ) + .unwrap() + } }; self.banks.insert( diff --git a/src/rebalancer.rs b/src/rebalancer.rs index 4c321b0..7150fe0 100644 --- a/src/rebalancer.rs +++ b/src/rebalancer.rs @@ -29,7 +29,7 @@ use marginfi::{ constants::EXP_10_I80F48, state::{ marginfi_account::{BalanceSide, MarginfiAccount, RequirementType}, - price::{OraclePriceFeedAdapter, PriceAdapter, PriceBias}, + price::{OraclePriceFeedAdapter, OracleSetup, PriceBias, SwitchboardPullPriceFeed}, }, }; use solana_client::rpc_client::RpcClient; @@ -43,6 +43,7 @@ use std::{ collections::{HashMap, HashSet}, sync::{atomic::AtomicBool, Arc}, }; +use switchboard_on_demand::PullFeedAccountData; /// The rebalancer is responsible to keep the liquidator account /// "rebalanced" -> Document this better @@ -187,28 +188,44 @@ impl Rebalancer { match msg.account_type { AccountType::OracleAccount => { if let Some(bank_to_update_pk) = self.oracle_to_bank.get(&msg.address) { - let oracle_ai = (&msg.address, &mut msg.account).into_account_info(); let bank_to_update: &mut BankWrapper = self.banks.get_mut(bank_to_update_pk).unwrap(); - let oracle_price_adapter = - OraclePriceFeedAdapter::try_from_bank_config_with_max_age( - &bank_to_update.bank.config, - &[oracle_ai.clone()], - &Clock::default(), - i64::MAX as u64, - ) - .unwrap(); - - match oracle_price_adapter { - OraclePriceFeedAdapter::SwitchboardPull(_) => { - let full_swb = - crate::utils::load_swb_pull_account(&oracle_ai).unwrap(); - let feed_hash = hex::encode(full_swb.feed_hash); + let oracle_price_adapter = match bank_to_update.bank.config.oracle_setup + { + OracleSetup::SwitchboardPull => { + let mut offsets_data = + [0u8; std::mem::size_of::()]; + offsets_data.copy_from_slice( + &msg.account.data + [8..std::mem::size_of::() + 8], + ); + let swb_feed = crate::utils::load_swb_pull_account_from_bytes( + &offsets_data, + ) + .unwrap(); + + let feed_hash = hex::encode(swb_feed.feed_hash); bank_to_update.oracle_adapter.swb_feed_hash = Some(feed_hash); + + OraclePriceFeedAdapter::SwitchboardPull( + SwitchboardPullPriceFeed { + feed: Box::new((&swb_feed).into()), + }, + ) + } + _ => { + let oracle_account_info = + (&msg.address, &mut msg.account).into_account_info(); + OraclePriceFeedAdapter::try_from_bank_config_with_max_age( + &bank_to_update.bank.config, + &[oracle_account_info], + &Clock::default(), + i64::MAX as u64, + ) + .unwrap() } - _ => {} - } + }; bank_to_update.oracle_adapter.price_adapter = oracle_price_adapter; } @@ -262,7 +279,7 @@ impl Rebalancer { bank.oracle_adapter.simulated_price = Some(price); } - self.should_stop_liquidations().await; + self.should_stop_liquidations().await.unwrap(); self.has_tokens_in_token_accounts() || self.has_non_preferred_deposits() || self.has_liabilities() diff --git a/src/utils.rs b/src/utils.rs index dd37596..3b12e61 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -296,7 +296,7 @@ impl<'a> BankAccountWithPriceFeedEva<'a> { .map(move |balance| { let bank = banks .get(&balance.bank_pk) - .ok_or_else(|| anyhow::anyhow!("Bank not found"))? + .ok_or_else(|| anyhow::anyhow!("Bank {:?} not found", balance.bank_pk))? .clone(); Ok(BankAccountWithPriceFeedEva { bank, balance }) @@ -575,24 +575,12 @@ pub fn find_oracle_keys(bank_config: &BankConfig) -> Vec { } pub fn load_swb_pull_account(account_info: &AccountInfo) -> anyhow::Result { - let bytes = &account_info.data.borrow().to_vec(); + let bytes = &account_info.data.borrow().to_vec()[8..std::mem::size_of::()]; Ok(load_swb_pull_account_from_bytes(bytes)?) } pub fn load_swb_pull_account_from_bytes(bytes: &[u8]) -> anyhow::Result { - println!( - "struct alignment {}", - std::mem::align_of::() - ); - println!("bytes alignment {}", std::mem::align_of_val(bytes)); - println!( - "offset {}", - bytes - .as_ptr() - .align_offset(std::mem::align_of::()) - ); - if bytes .as_ptr() .align_offset(std::mem::align_of::())