collateral fees: fixes after devnet test (#880)

This commit is contained in:
Christian Kamm 2024-02-14 11:32:57 +01:00 committed by GitHub
parent 7a1be5a188
commit 3993a3fa66
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 64 additions and 6 deletions

View File

@ -26,6 +26,7 @@ use prometheus::{register_histogram, Encoder, Histogram, IntCounter, Registry};
use solana_sdk::{ use solana_sdk::{
instruction::{AccountMeta, Instruction}, instruction::{AccountMeta, Instruction},
pubkey::Pubkey, pubkey::Pubkey,
signature::Signature,
}; };
use tokio::task::JoinHandle; use tokio::task::JoinHandle;
use tracing::*; use tracing::*;
@ -507,12 +508,13 @@ async fn charge_collateral_fees_inner(
ix_to_send.push(ixs); ix_to_send.push(ixs);
} }
send_batched_log_errors_no_confirm( let txsigs = send_batched_log_errors_no_confirm(
client.transaction_builder().await?, client.transaction_builder().await?,
&client.client, &client.client,
&ix_to_send, &ix_to_send,
) )
.await; .await;
info!("charge collateral fees: {:?}", txsigs);
Ok(()) Ok(())
} }
@ -522,7 +524,9 @@ async fn send_batched_log_errors_no_confirm(
mut tx_builder: TransactionBuilder, mut tx_builder: TransactionBuilder,
client: &mango_v4_client::Client, client: &mango_v4_client::Client,
ixs_list: &[PreparedInstructions], ixs_list: &[PreparedInstructions],
) { ) -> Vec<Signature> {
let mut txsigs = Vec::new();
let mut current_batch = PreparedInstructions::new(); let mut current_batch = PreparedInstructions::new();
for ixs in ixs_list { for ixs in ixs_list {
let previous_batch = current_batch.clone(); let previous_batch = current_batch.clone();
@ -533,7 +537,7 @@ async fn send_batched_log_errors_no_confirm(
tx_builder.instructions = previous_batch.to_instructions(); tx_builder.instructions = previous_batch.to_instructions();
match tx_builder.send(client).await { match tx_builder.send(client).await {
Err(err) => error!("could not send transaction: {err:?}"), Err(err) => error!("could not send transaction: {err:?}"),
_ => {} Ok(txsig) => txsigs.push(txsig),
} }
current_batch = ixs.clone(); current_batch = ixs.clone();
@ -544,7 +548,9 @@ async fn send_batched_log_errors_no_confirm(
tx_builder.instructions = current_batch.to_instructions(); tx_builder.instructions = current_batch.to_instructions();
match tx_builder.send(client).await { match tx_builder.send(client).await {
Err(err) => error!("could not send transaction: {err:?}"), Err(err) => error!("could not send transaction: {err:?}"),
_ => {} Ok(txsig) => txsigs.push(txsig),
} }
} }
txsigs
} }

View File

@ -67,6 +67,11 @@ pub fn token_charge_collateral_fees(ctx: Context<TokenChargeCollateralFees>) ->
} }
} }
// If there's no assets or no liabs, we can't charge fees
if total_asset_health.is_zero() || total_liab_health.is_zero() {
return Ok(());
}
// Users only pay for assets that are actively used to cover their liabilities. // Users only pay for assets that are actively used to cover their liabilities.
let asset_usage_scaling = (total_liab_health / total_asset_health) let asset_usage_scaling = (total_liab_health / total_asset_health)
.max(I80F48::ZERO) .max(I80F48::ZERO)
@ -77,7 +82,7 @@ pub fn token_charge_collateral_fees(ctx: Context<TokenChargeCollateralFees>) ->
let token_position_count = account.active_token_positions().count(); let token_position_count = account.active_token_positions().count();
for bank_ai in &ctx.remaining_accounts[0..token_position_count] { for bank_ai in &ctx.remaining_accounts[0..token_position_count] {
let mut bank = bank_ai.load_mut::<Bank>()?; let mut bank = bank_ai.load_mut::<Bank>()?;
if bank.collateral_fee_per_day <= 0.0 { if bank.collateral_fee_per_day <= 0.0 || bank.maint_asset_weight.is_zero() {
continue; continue;
} }

View File

@ -1,3 +1,4 @@
#![allow(unused_assignments)]
use super::*; use super::*;
#[tokio::test] #[tokio::test]
@ -44,6 +45,18 @@ async fn test_collateral_fees() -> Result<(), TransportError> {
) )
.await; .await;
let empty_account = create_funded_account(
&solana,
group,
owner,
2,
&context.users[1],
&mints[0..0],
0,
0,
)
.await;
let hour = 60 * 60; let hour = 60 * 60;
send_tx( send_tx(
@ -92,6 +105,32 @@ async fn test_collateral_fees() -> Result<(), TransportError> {
.await .await
.unwrap(); .unwrap();
//
// TEST: It works on empty accounts
//
send_tx(
solana,
TokenChargeCollateralFeesInstruction {
account: empty_account,
},
)
.await
.unwrap();
let mut last_time = solana.clock_timestamp().await;
solana.set_clock_timestamp(last_time + 9 * hour).await;
// send it twice, because the first time will never charge anything
send_tx(
solana,
TokenChargeCollateralFeesInstruction {
account: empty_account,
},
)
.await
.unwrap();
last_time = solana.clock_timestamp().await;
// //
// TEST: Without borrows, charging collateral fees has no effect // TEST: Without borrows, charging collateral fees has no effect
// //
@ -99,7 +138,15 @@ async fn test_collateral_fees() -> Result<(), TransportError> {
send_tx(solana, TokenChargeCollateralFeesInstruction { account }) send_tx(solana, TokenChargeCollateralFeesInstruction { account })
.await .await
.unwrap(); .unwrap();
let mut last_time = solana.clock_timestamp().await; last_time = solana.clock_timestamp().await;
solana.set_clock_timestamp(last_time + 9 * hour).await;
// send it twice, because the first time will never charge anything
send_tx(solana, TokenChargeCollateralFeesInstruction { account })
.await
.unwrap();
last_time = solana.clock_timestamp().await;
// no effect // no effect
assert_eq!( assert_eq!(
account_position(solana, account, tokens[0].bank).await, account_position(solana, account, tokens[0].bank).await,