From 9340ac6b63ad7cf264fcac98626447f754f42148 Mon Sep 17 00:00:00 2001 From: 0xripleys <105607696+0xripleys@users.noreply.github.com> Date: Mon, 20 Mar 2023 14:33:33 -0400 Subject: [PATCH] cli changes for v2.0.1 (#133) --- token-lending/cli/src/main.rs | 198 +++++++++++++++++++++++++++++++++- 1 file changed, 195 insertions(+), 3 deletions(-) diff --git a/token-lending/cli/src/main.rs b/token-lending/cli/src/main.rs index 9324a1687ae..efd3b899473 100644 --- a/token-lending/cli/src/main.rs +++ b/token-lending/cli/src/main.rs @@ -1,7 +1,7 @@ use lending_state::SolendState; use solana_client::rpc_config::RpcSendTransactionConfig; use solana_sdk::{commitment_config::CommitmentLevel, compute_budget::ComputeBudgetInstruction}; -use solend_program::state::{RateLimiterConfig, SLOTS_PER_YEAR}; +use solend_program::{instruction::set_lending_market_owner_and_config, state::RateLimiterConfig}; use solend_sdk::{ instruction::{ liquidate_obligation_and_redeem_reserve_collateral, redeem_reserve_collateral, @@ -89,6 +89,12 @@ struct PartialReserveConfig { pub protocol_liquidation_fee: Option, /// Protocol take rate is the amount borrowed interest protocol recieves, as a percentage pub protocol_take_rate: Option, + /// Rate Limiter's max window size + pub rate_limiter_window_duration: Option, + /// Rate Limiter's max outflow per window + pub rate_limiter_max_outflow: Option, + /// Added borrow weight in basis points + pub added_borrow_weight_bps: Option, } /// Reserve Fees with optional fields @@ -524,6 +530,55 @@ fn main() { .help("Borrow limit"), ) ) + .subcommand( + SubCommand::with_name("set-lending-market-owner-and-config") + .about("Set lending market owner and config") + .arg( + Arg::with_name("lending_market_owner") + .long("market-owner") + .validator(is_keypair) + .value_name("KEYPAIR") + .takes_value(true) + .required(true) + .help("Owner of the lending market"), + ) + .arg( + Arg::with_name("lending_market") + .long("market") + .validator(is_pubkey) + .value_name("PUBKEY") + .takes_value(true) + .required(true) + .help("Lending market address"), + ) + .arg( + Arg::with_name("new_lending_market_owner") + .long("new-lending-market-owner") + .validator(is_keypair) + .value_name("KEYPAIR") + .takes_value(true) + .required(false) + .help("Owner of the lending market"), + ) + .arg( + Arg::with_name("rate_limiter_window_duration") + .long("rate-limiter-window-duration") + .validator(is_parsable::) + .value_name("INTEGER") + .takes_value(true) + .required(false) + .help("Rate Limiter Window Duration in Slots"), + ) + .arg( + Arg::with_name("rate_limiter_max_outflow") + .long("rate-limiter-max-outflow") + .validator(is_parsable::) + .value_name("INTEGER") + .takes_value(true) + .required(false) + .help("Rate Limiter max outflow denominated in dollars within 1 window"), + ) + ) .subcommand( SubCommand::with_name("update-reserve") .about("Update a reserve config") @@ -717,6 +772,33 @@ fn main() { .required(false) .help("Switchboard price feed account: https://switchboard.xyz/#/explorer"), ) + .arg( + Arg::with_name("rate_limiter_window_duration") + .long("rate-limiter-window-duration") + .validator(is_parsable::) + .value_name("INTEGER") + .takes_value(true) + .required(false) + .help("Rate Limiter Window Duration in Slots"), + ) + .arg( + Arg::with_name("rate_limiter_max_outflow") + .long("rate-limiter-max-outflow") + .validator(is_parsable::) + .value_name("INTEGER") + .takes_value(true) + .required(false) + .help("Rate Limiter max outflow of token amounts within 1 window"), + ) + .arg( + Arg::with_name("added_borrow_weight_bps") + .long("added-borrow-weight-bps") + .validator(is_parsable::) + .value_name("INTEGER") + .takes_value(true) + .required(false) + .help("Added borrow weight in basis points"), + ) ) .get_matches(); @@ -885,6 +967,24 @@ fn main() { source_liquidity, ) } + ("set-lending-market-owner-and-config", Some(arg_matches)) => { + let lending_market_owner_keypair = + keypair_of(arg_matches, "lending_market_owner").unwrap(); + let lending_market_pubkey = pubkey_of(arg_matches, "lending_market").unwrap(); + let new_lending_market_owner_keypair = + keypair_of(arg_matches, "new_lending_market_owner"); + let rate_limiter_window_duration = + value_of(arg_matches, "rate_limiter_window_duration"); + let rate_limiter_max_outflow = value_of(arg_matches, "rate_limiter_max_outflow"); + command_set_lending_market_owner_and_config( + &mut config, + lending_market_pubkey, + lending_market_owner_keypair, + new_lending_market_owner_keypair, + rate_limiter_window_duration, + rate_limiter_max_outflow, + ) + } ("update-reserve", Some(arg_matches)) => { let reserve_pubkey = pubkey_of(arg_matches, "reserve").unwrap(); let lending_market_owner_keypair = @@ -908,6 +1008,10 @@ fn main() { let pyth_product_pubkey = pubkey_of(arg_matches, "pyth_product"); let pyth_price_pubkey = pubkey_of(arg_matches, "pyth_price"); let switchboard_feed_pubkey = pubkey_of(arg_matches, "switchboard_feed"); + let rate_limiter_window_duration = + value_of(arg_matches, "rate_limiter_window_duration"); + let rate_limiter_max_outflow = value_of(arg_matches, "rate_limiter_max_outflow"); + let added_borrow_weight_bps = value_of(arg_matches, "added_borrow_weight_bps"); let borrow_fee_wad = borrow_fee.map(|fee| (fee * WAD as f64) as u64); let flash_loan_fee_wad = flash_loan_fee.map(|fee| (fee * WAD as f64) as u64); @@ -932,6 +1036,9 @@ fn main() { fee_receiver, protocol_liquidation_fee, protocol_take_rate, + rate_limiter_window_duration, + rate_limiter_max_outflow, + added_borrow_weight_bps, }, pyth_product_pubkey, pyth_price_pubkey, @@ -1439,6 +1546,50 @@ fn command_add_reserve( Ok(()) } +fn command_set_lending_market_owner_and_config( + config: &mut Config, + lending_market_pubkey: Pubkey, + lending_market_owner_keypair: Keypair, + new_lending_market_owner_keypair: Option, + rate_limiter_window_duration: Option, + rate_limiter_max_outflow: Option, +) -> CommandResult { + let lending_market_info = config.rpc_client.get_account(&lending_market_pubkey)?; + let lending_market = LendingMarket::unpack_from_slice(lending_market_info.data.borrow())?; + println!("{:#?}", lending_market); + + let recent_blockhash = config.rpc_client.get_latest_blockhash()?; + let message = Message::new_with_blockhash( + &[set_lending_market_owner_and_config( + config.lending_program_id, + lending_market_pubkey, + lending_market_owner_keypair.pubkey(), + if let Some(owner) = new_lending_market_owner_keypair { + owner.pubkey() + } else { + lending_market.owner + }, + RateLimiterConfig { + window_duration: rate_limiter_window_duration + .unwrap_or(lending_market.rate_limiter.config.window_duration), + max_outflow: rate_limiter_max_outflow + .unwrap_or(lending_market.rate_limiter.config.max_outflow), + }, + )], + Some(&config.fee_payer.pubkey()), + &recent_blockhash, + ); + + let transaction = Transaction::new( + &vec![config.fee_payer.as_ref(), &lending_market_owner_keypair], + message, + recent_blockhash, + ); + + send_transaction(config, transaction)?; + Ok(()) +} + #[allow(clippy::too_many_arguments, clippy::unnecessary_unwrap)] fn command_update_reserve( config: &mut Config, @@ -1452,6 +1603,7 @@ fn command_update_reserve( ) -> CommandResult { let reserve_info = config.rpc_client.get_account(&reserve_pubkey)?; let mut reserve = Reserve::unpack_from_slice(reserve_info.data.borrow())?; + println!("Reserve: {:#?}", reserve); let mut no_change = true; if reserve_config.optimal_utilization_rate.is_some() && reserve.config.optimal_utilization_rate @@ -1666,6 +1818,46 @@ fn command_update_reserve( ); reserve.liquidity.switchboard_oracle_pubkey = switchboard_feed_pubkey.unwrap(); } + + if reserve_config.rate_limiter_window_duration.is_some() + && reserve.rate_limiter.config.window_duration + != reserve_config.rate_limiter_window_duration.unwrap() + { + no_change = false; + println!( + "Updating rate_limiter_window_duration from {} to {}", + reserve.rate_limiter.config.window_duration, + reserve_config.rate_limiter_window_duration.unwrap(), + ); + reserve.rate_limiter.config.window_duration = + reserve_config.rate_limiter_window_duration.unwrap(); + } + + if reserve_config.rate_limiter_max_outflow.is_some() + && reserve.rate_limiter.config.max_outflow + != reserve_config.rate_limiter_max_outflow.unwrap() + { + no_change = false; + println!( + "Updating rate_limiter_max_outflow from {} to {}", + reserve.rate_limiter.config.max_outflow, + reserve_config.rate_limiter_max_outflow.unwrap(), + ); + reserve.rate_limiter.config.max_outflow = reserve_config.rate_limiter_max_outflow.unwrap(); + } + + if reserve_config.added_borrow_weight_bps.is_some() + && reserve.config.added_borrow_weight_bps != reserve_config.added_borrow_weight_bps.unwrap() + { + no_change = false; + println!( + "Updating added_borrow_weight_bps from {} to {}", + reserve.config.added_borrow_weight_bps, + reserve_config.added_borrow_weight_bps.unwrap(), + ); + reserve.config.added_borrow_weight_bps = reserve_config.added_borrow_weight_bps.unwrap(); + } + if no_change { println!("No changes made for reserve {}", reserve_pubkey); return Ok(()); @@ -1678,8 +1870,8 @@ fn command_update_reserve( config.lending_program_id, reserve.config, RateLimiterConfig { - window_duration: SLOTS_PER_YEAR / 365, - max_outflow: u64::MAX, + window_duration: reserve.rate_limiter.config.window_duration, + max_outflow: reserve.rate_limiter.config.max_outflow, }, reserve_pubkey, lending_market_pubkey,