Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rust client: ix cu limits based on health compute cost #768

Merged
merged 2 commits into from
Nov 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 12 additions & 14 deletions bin/liquidator/src/liquidate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,6 @@ impl<'a> LiquidateHelper<'a> {
Ok(Some(txsig))
}

fn liq_compute_limit_instruction(&self) -> solana_sdk::instruction::Instruction {
solana_sdk::compute_budget::ComputeBudgetInstruction::set_compute_unit_limit(
self.config.compute_limit_for_liq_ix,
)
}

async fn perp_liq_base_or_positive_pnl(&self) -> anyhow::Result<Option<Signature>> {
let all_perp_base_positions: anyhow::Result<
Vec<Option<(PerpMarketIndex, i64, I80F48, I80F48)>>,
Expand Down Expand Up @@ -208,7 +202,7 @@ impl<'a> LiquidateHelper<'a> {
"computed transfer maximums"
);

let liq_ix = self
let mut liq_ixs = self
.client
.perp_liq_base_or_positive_pnl_instruction(
(self.pubkey, &self.liqee),
Expand All @@ -218,9 +212,10 @@ impl<'a> LiquidateHelper<'a> {
)
.await
.context("creating perp_liq_base_or_positive_pnl_instruction")?;
liq_ixs.cu = liq_ixs.cu.max(self.config.compute_limit_for_liq_ix);
let txsig = self
.client
.send_and_confirm_owner_tx(vec![self.liq_compute_limit_instruction(), liq_ix])
.send_and_confirm_owner_tx(liq_ixs.to_instructions())
.await
.context("sending perp_liq_base_or_positive_pnl_instruction")?;
info!(
Expand Down Expand Up @@ -253,7 +248,7 @@ impl<'a> LiquidateHelper<'a> {
}
let (perp_market_index, _) = perp_negative_pnl.first().unwrap();

let liq_ix = self
let mut liq_ixs = self
.client
.perp_liq_negative_pnl_or_bankruptcy_instruction(
(self.pubkey, &self.liqee),
Expand All @@ -263,9 +258,10 @@ impl<'a> LiquidateHelper<'a> {
)
.await
.context("creating perp_liq_negative_pnl_or_bankruptcy_instruction")?;
liq_ixs.cu = liq_ixs.cu.max(self.config.compute_limit_for_liq_ix);
let txsig = self
.client
.send_and_confirm_owner_tx(vec![self.liq_compute_limit_instruction(), liq_ix])
.send_and_confirm_owner_tx(liq_ixs.to_instructions())
.await
.context("sending perp_liq_negative_pnl_or_bankruptcy_instruction")?;
info!(
Expand Down Expand Up @@ -374,7 +370,7 @@ impl<'a> LiquidateHelper<'a> {
// TODO: log liqor's assets in UI form
// TODO: log liquee's liab_needed, need to refactor program code to be able to be accessed from client side
//
let liq_ix = self
let mut liq_ixs = self
.client
.token_liq_with_token_instruction(
(self.pubkey, &self.liqee),
Expand All @@ -384,9 +380,10 @@ impl<'a> LiquidateHelper<'a> {
)
.await
.context("creating liq_token_with_token ix")?;
liq_ixs.cu = liq_ixs.cu.max(self.config.compute_limit_for_liq_ix);
let txsig = self
.client
.send_and_confirm_owner_tx(vec![self.liq_compute_limit_instruction(), liq_ix])
.send_and_confirm_owner_tx(liq_ixs.to_instructions())
.await
.context("sending liq_token_with_token")?;
info!(
Expand Down Expand Up @@ -433,7 +430,7 @@ impl<'a> LiquidateHelper<'a> {
.max_token_liab_transfer(liab_token_index, quote_token_index)
.await?;

let liq_ix = self
let mut liq_ixs = self
.client
.token_liq_bankruptcy_instruction(
(self.pubkey, &self.liqee),
Expand All @@ -442,9 +439,10 @@ impl<'a> LiquidateHelper<'a> {
)
.await
.context("creating liq_token_bankruptcy")?;
liq_ixs.cu = liq_ixs.cu.max(self.config.compute_limit_for_liq_ix);
let txsig = self
.client
.send_and_confirm_owner_tx(vec![self.liq_compute_limit_instruction(), liq_ix])
.send_and_confirm_owner_tx(liq_ixs.to_instructions())
.await
.context("sending liq_token_with_token")?;
info!(
Expand Down
6 changes: 4 additions & 2 deletions bin/liquidator/src/trigger_tcs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1122,7 +1122,7 @@ impl Context {
};

let liqee = self.account_fetcher.fetch_mango_account(&pending.pubkey)?;
let trigger_ix = self
let mut trigger_ixs = self
.mango_client
.token_conditional_swap_trigger_instruction(
(&pending.pubkey, &liqee),
Expand All @@ -1134,7 +1134,9 @@ impl Context {
&allowed_tokens,
)
.await?;
tx_builder.instructions.push(trigger_ix);
tx_builder
.instructions
.append(&mut trigger_ixs.instructions);

let txsig = tx_builder
.send_and_confirm(&self.mango_client.client)
Expand Down
24 changes: 14 additions & 10 deletions bin/settler/src/settle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ use mango_v4::accounts_zerocopy::KeyedAccountSharedData;
use mango_v4::health::HealthType;
use mango_v4::state::{PerpMarket, PerpMarketIndex};
use mango_v4_client::{
chain_data, health_cache, prettify_solana_client_error, MangoClient, TransactionBuilder,
chain_data, health_cache, prettify_solana_client_error, MangoClient, PreparedInstructions,
TransactionBuilder,
};
use solana_sdk::address_lookup_table_account::AddressLookupTableAccount;
use solana_sdk::commitment_config::CommitmentConfig;
use solana_sdk::instruction::Instruction;
use solana_sdk::signature::Signature;

use solana_sdk::signer::Signer;
Expand Down Expand Up @@ -180,7 +180,7 @@ impl SettlementState {
mango_client,
account_fetcher,
perp_market_index,
instructions: Vec::new(),
instructions: PreparedInstructions::new(),
max_batch_size: 8, // the 1.4M max CU limit if we assume settle ix can be up to around 150k
blockhash: mango_client
.client
Expand Down Expand Up @@ -242,7 +242,7 @@ struct SettleBatchProcessor<'a> {
mango_client: &'a MangoClient,
account_fetcher: &'a chain_data::AccountFetcher,
perp_market_index: PerpMarketIndex,
instructions: Vec<Instruction>,
instructions: PreparedInstructions,
max_batch_size: usize,
blockhash: solana_sdk::hash::Hash,
address_lookup_tables: &'a Vec<AddressLookupTableAccount>,
Expand All @@ -254,7 +254,7 @@ impl<'a> SettleBatchProcessor<'a> {
let fee_payer = client.fee_payer.clone();

TransactionBuilder {
instructions: self.instructions.clone(),
instructions: self.instructions.clone().to_instructions(),
address_lookup_tables: self.address_lookup_tables.clone(),
payer: fee_payer.pubkey(),
signers: vec![fee_payer],
Expand Down Expand Up @@ -296,15 +296,19 @@ impl<'a> SettleBatchProcessor<'a> {
) -> anyhow::Result<Option<Signature>> {
let a_value = self.account_fetcher.fetch_mango_account(&account_a)?;
let b_value = self.account_fetcher.fetch_mango_account(&account_b)?;
let ix = self.mango_client.perp_settle_pnl_instruction(
let new_ixs = self.mango_client.perp_settle_pnl_instruction(
self.perp_market_index,
(&account_a, &a_value),
(&account_b, &b_value),
)?;
self.instructions.push(ix);
let previous = self.instructions.clone();
self.instructions.append(new_ixs.clone());

// if we exceed the batch limit or tx size limit, send a batch without the new ix
let needs_send = if self.instructions.len() > self.max_batch_size {
let max_cu_per_tx = 1_400_000;
let needs_send = if self.instructions.len() > self.max_batch_size
|| self.instructions.cu >= max_cu_per_tx
{
true
} else {
let tx = self.transaction()?;
Expand All @@ -321,9 +325,9 @@ impl<'a> SettleBatchProcessor<'a> {
too_big
};
if needs_send {
let ix = self.instructions.pop().unwrap();
self.instructions = previous;
let txsig = self.send().await?;
self.instructions.push(ix);
self.instructions.append(new_ixs);
return Ok(txsig);
}

Expand Down
21 changes: 14 additions & 7 deletions bin/settler/src/tcs_start.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
use itertools::Itertools;
use mango_v4::error::{IsAnchorErrorWithCode, MangoError};
use mango_v4::state::*;
use mango_v4_client::PreparedInstructions;
use mango_v4_client::{chain_data, error_tracking::ErrorTracking, MangoClient};
use solana_sdk::instruction::Instruction;

use tracing::*;
use {fixed::types::I80F48, solana_sdk::pubkey::Pubkey};
Expand Down Expand Up @@ -93,11 +93,11 @@ impl State {
}

for startable_chunk in startable.chunks(8) {
let mut instructions = vec![];
let mut instructions = PreparedInstructions::new();
let mut ix_targets = vec![];
let mut liqor_account = mango_client.mango_account().await?;
for (pubkey, tcs_id, incentive_token_index) in startable_chunk {
let ix = match self.make_start_ix(pubkey, *tcs_id).await {
let ixs = match self.make_start_ix(pubkey, *tcs_id).await {
Ok(v) => v,
Err(e) => {
self.errors.record_error(
Expand All @@ -108,23 +108,26 @@ impl State {
continue;
}
};
instructions.push(ix);
instructions.append(ixs);
ix_targets.push((*pubkey, *tcs_id));
liqor_account.ensure_token_position(*incentive_token_index)?;
}

// Clear newly created token positions, so the liqor account is mostly empty
for token_index in startable_chunk.iter().map(|(_, _, ti)| *ti).unique() {
let mint = mango_client.context.token(token_index).mint_info.mint;
instructions.append(&mut mango_client.token_withdraw_instructions(
instructions.append(mango_client.token_withdraw_instructions(
&liqor_account,
mint,
u64::MAX,
false,
)?);
}

let txsig = match mango_client.send_and_confirm_owner_tx(instructions).await {
let txsig = match mango_client
.send_and_confirm_owner_tx(instructions.to_instructions())
.await
{
Ok(v) => v,
Err(e) => {
warn!("error sending transaction: {e:?}");
Expand Down Expand Up @@ -154,7 +157,11 @@ impl State {
Ok(())
}

async fn make_start_ix(&self, pubkey: &Pubkey, tcs_id: u64) -> anyhow::Result<Instruction> {
async fn make_start_ix(
&self,
pubkey: &Pubkey,
tcs_id: u64,
) -> anyhow::Result<PreparedInstructions> {
let account = self.account_fetcher.fetch_mango_account(pubkey).unwrap();
self.mango_client
.token_conditional_swap_start_instruction((pubkey, &account), tcs_id)
Expand Down
Loading
Loading