Skip to content

Commit

Permalink
fix: compact add bank ix
Browse files Browse the repository at this point in the history
  • Loading branch information
jkbpvsc committed Nov 23, 2023
1 parent 25615a2 commit dc64339
Show file tree
Hide file tree
Showing 7 changed files with 149 additions and 158 deletions.
12 changes: 6 additions & 6 deletions clients/rust/marginfi-cli/src/entrypoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,9 @@ pub enum GroupCommand {
#[clap(long)]
liability_weight_maint: f64,
#[clap(long)]
deposit_limit: u64,
deposit_limit_ui: u64,
#[clap(long)]
borrow_limit: u64,
borrow_limit_ui: u64,
#[clap(long)]
pyth_oracle: Pubkey,
#[clap(long)]
Expand Down Expand Up @@ -473,8 +473,8 @@ fn group(subcmd: GroupCommand, global_options: &GlobalOptions) -> Result<()> {
insurance_ir_fee,
protocol_fixed_fee_apr,
protocol_ir_fee,
deposit_limit,
borrow_limit,
deposit_limit_ui,
borrow_limit_ui,
risk_tier,
oracle_type,
} => processor::group_add_bank(
Expand All @@ -487,8 +487,8 @@ fn group(subcmd: GroupCommand, global_options: &GlobalOptions) -> Result<()> {
asset_weight_maint,
liability_weight_init,
liability_weight_maint,
deposit_limit,
borrow_limit,
deposit_limit_ui,
borrow_limit_ui,
optimal_utilization_rate,
plateau_interest_rate,
max_interest_rate,
Expand Down
13 changes: 10 additions & 3 deletions clients/rust/marginfi-cli/src/processor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -312,8 +312,8 @@ pub fn group_add_bank(
asset_weight_maint: f64,
liability_weight_init: f64,
liability_weight_maint: f64,
deposit_limit: u64,
borrow_limit: u64,
deposit_limit_ui: u64,
borrow_limit_ui: u64,
optimal_utilization_rate: f64,
plateau_interest_rate: f64,
max_interest_rate: f64,
Expand Down Expand Up @@ -342,6 +342,12 @@ pub fn group_add_bank(
let protocol_fixed_fee_apr: WrappedI80F48 = I80F48::from_num(protocol_fixed_fee_apr).into();
let protocol_ir_fee: WrappedI80F48 = I80F48::from_num(protocol_ir_fee).into();

let mint_account = rpc_client.get_account(&bank_mint)?;
let mint = spl_token::state::Mint::unpack(&mint_account.data)?;

let deposit_limit = deposit_limit_ui * 10_u64.pow(mint.decimals as u32);
let borrow_limit = borrow_limit_ui * 10_u64.pow(mint.decimals as u32);

let interest_rate_config = InterestRateConfig {
optimal_utilization_rate,
plateau_interest_rate,
Expand Down Expand Up @@ -425,7 +431,8 @@ pub fn group_add_bank(
oracle_keys: create_oracle_key_array(oracle_key),
risk_tier: risk_tier.into(),
..BankConfig::default()
},
}
.into(),
})
.instructions()?;

Expand Down
63 changes: 2 additions & 61 deletions programs/marginfi/src/instructions/marginfi_group/add_pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@ use crate::{
INSURANCE_VAULT_SEED, LIQUIDITY_VAULT_AUTHORITY_SEED, LIQUIDITY_VAULT_SEED,
},
events::{GroupEventHeader, LendingPoolBankCreateEvent},
state::{
marginfi_group::{Bank, BankConfig, MarginfiGroup},
price::OracleSetup,
},
state::marginfi_group::{Bank, BankConfig, BankConfigCompact, MarginfiGroup},
MarginfiResult,
};
use anchor_lang::prelude::*;
Expand Down Expand Up @@ -73,7 +70,7 @@ pub fn lending_pool_add_bank(
}

#[derive(Accounts)]
#[instruction(bank_config: BankConfig)]
#[instruction(bank_config: BankConfigCompact)]
pub struct LendingPoolAddBank<'info> {
pub marginfi_group: AccountLoader<'info, MarginfiGroup>,

Expand Down Expand Up @@ -165,59 +162,3 @@ pub struct LendingPoolAddBank<'info> {
pub token_program: Program<'info, Token>,
pub system_program: Program<'info, System>,
}

/// Adds a bank with a default bank config providing just the oracle setup
pub fn lending_pool_add_bank_lite(
ctx: Context<LendingPoolAddBank>,
oracle_setup: OracleSetup,
oracle_keys: Vec<Pubkey>,
) -> MarginfiResult {
let LendingPoolAddBank {
bank_mint,
liquidity_vault,
insurance_vault,
fee_vault,
bank: bank_loader,
..
} = ctx.accounts;

let mut bank = bank_loader.load_init()?;

let liquidity_vault_bump = *ctx.bumps.get("liquidity_vault").unwrap();
let liquidity_vault_authority_bump = *ctx.bumps.get("liquidity_vault_authority").unwrap();
let insurance_vault_bump = *ctx.bumps.get("insurance_vault").unwrap();
let insurance_vault_authority_bump = *ctx.bumps.get("insurance_vault_authority").unwrap();
let fee_vault_bump = *ctx.bumps.get("fee_vault").unwrap();
let fee_vault_authority_bump = *ctx.bumps.get("fee_vault_authority").unwrap();

*bank = Bank::new(
ctx.accounts.marginfi_group.key(),
BankConfig::new_with_oracle_config(oracle_setup, oracle_keys),
bank_mint.key(),
bank_mint.decimals,
liquidity_vault.key(),
insurance_vault.key(),
fee_vault.key(),
Clock::get().unwrap().unix_timestamp,
liquidity_vault_bump,
liquidity_vault_authority_bump,
insurance_vault_bump,
insurance_vault_authority_bump,
fee_vault_bump,
fee_vault_authority_bump,
);

bank.config.validate()?;
bank.config.validate_oracle_setup(ctx.remaining_accounts)?;

emit!(LendingPoolBankCreateEvent {
header: GroupEventHeader {
marginfi_group: ctx.accounts.marginfi_group.key(),
signer: Some(*ctx.accounts.admin.key)
},
bank: bank_loader.key(),
mint: bank_mint.key(),
});

Ok(())
}
16 changes: 3 additions & 13 deletions programs/marginfi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@ pub mod prelude;
pub mod state;
pub mod utils;

use crate::state::price::OracleSetup;
use anchor_lang::prelude::*;
use instructions::*;
use prelude::*;
use state::marginfi_group::{BankConfig, BankConfigOpt};
use state::marginfi_group::{BankConfigCompact, BankConfigOpt};

cfg_if::cfg_if! {
if #[cfg(feature = "mainnet-beta")] {
Expand All @@ -25,7 +24,6 @@ cfg_if::cfg_if! {

#[program]
pub mod marginfi {

use super::*;

pub fn marginfi_group_initialize(ctx: Context<MarginfiGroupInitialize>) -> MarginfiResult {
Expand All @@ -41,17 +39,9 @@ pub mod marginfi {

pub fn lending_pool_add_bank(
ctx: Context<LendingPoolAddBank>,
bank_config: BankConfig,
) -> MarginfiResult {
marginfi_group::lending_pool_add_bank(ctx, bank_config)
}

pub fn lending_pool_add_bank_lite(
ctx: Context<LendingPoolAddBank>,
oracle_setup: OracleSetup,
oracle_keys: Vec<Pubkey>,
bank_config: BankConfigCompact,
) -> MarginfiResult {
marginfi_group::lending_pool_add_bank_lite(ctx, oracle_setup, oracle_keys)
marginfi_group::lending_pool_add_bank(ctx, bank_config.into())
}

pub fn lending_pool_configure_bank(
Expand Down
126 changes: 126 additions & 0 deletions programs/marginfi/src/state/marginfi_group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,55 @@ pub fn load_pyth_price_feed(ai: &AccountInfo) -> MarginfiResult<PriceFeed> {
Ok(price_feed)
}

#[zero_copy]
#[repr(C)]
#[cfg_attr(
any(feature = "test", feature = "client"),
derive(PartialEq, Eq, TypeLayout)
)]
#[derive(Default, Debug, AnchorDeserialize, AnchorSerialize)]
pub struct InterestRateConfigCompact {
// Curve Params
pub optimal_utilization_rate: WrappedI80F48,
pub plateau_interest_rate: WrappedI80F48,
pub max_interest_rate: WrappedI80F48,

// Fees
pub insurance_fee_fixed_apr: WrappedI80F48,
pub insurance_ir_fee: WrappedI80F48,
pub protocol_fixed_fee_apr: WrappedI80F48,
pub protocol_ir_fee: WrappedI80F48,
}

impl From<InterestRateConfigCompact> for InterestRateConfig {
fn from(ir_config: InterestRateConfigCompact) -> Self {
InterestRateConfig {
optimal_utilization_rate: ir_config.optimal_utilization_rate,
plateau_interest_rate: ir_config.plateau_interest_rate,
max_interest_rate: ir_config.max_interest_rate,
insurance_fee_fixed_apr: ir_config.insurance_fee_fixed_apr,
insurance_ir_fee: ir_config.insurance_ir_fee,
protocol_fixed_fee_apr: ir_config.protocol_fixed_fee_apr,
protocol_ir_fee: ir_config.protocol_ir_fee,
_padding: [0; 8],
}
}
}

impl From<InterestRateConfig> for InterestRateConfigCompact {
fn from(ir_config: InterestRateConfig) -> Self {
InterestRateConfigCompact {
optimal_utilization_rate: ir_config.optimal_utilization_rate,
plateau_interest_rate: ir_config.plateau_interest_rate,
max_interest_rate: ir_config.max_interest_rate,
insurance_fee_fixed_apr: ir_config.insurance_fee_fixed_apr,
insurance_ir_fee: ir_config.insurance_ir_fee,
protocol_fixed_fee_apr: ir_config.protocol_fixed_fee_apr,
protocol_ir_fee: ir_config.protocol_ir_fee,
}
}
}

#[zero_copy]
#[repr(C)]
#[cfg_attr(
Expand Down Expand Up @@ -760,6 +809,83 @@ pub enum RiskTier {
Isolated,
}

#[zero_copy]
#[repr(C)]
#[cfg_attr(
any(feature = "test", feature = "client"),
derive(PartialEq, Eq, TypeLayout)
)]
#[derive(AnchorDeserialize, AnchorSerialize, Debug)]
/// TODO: Convert weights to (u64, u64) to avoid precision loss (maybe?)
pub struct BankConfigCompact {
pub asset_weight_init: WrappedI80F48,
pub asset_weight_maint: WrappedI80F48,

pub liability_weight_init: WrappedI80F48,
pub liability_weight_maint: WrappedI80F48,

pub deposit_limit: u64,

pub interest_rate_config: InterestRateConfigCompact,
pub operational_state: BankOperationalState,

pub oracle_setup: OracleSetup,
pub oracle_keys: [Pubkey; MAX_ORACLE_KEYS],

pub borrow_limit: u64,

pub risk_tier: RiskTier,

/// USD denominated limit for calculating asset value for initialization margin requirements.
/// Example, if total SOL deposits are equal to $1M and the limit it set to $500K,
/// then SOL assets will be discounted by 50%.
///
/// In other words the max value of liabilities that can be backed by the asset is $500K.
/// This is useful for limiting the damage of orcale attacks.
///
/// Value is UI USD value, for example value 100 -> $100
pub total_asset_value_init_limit: u64,
}

impl From<BankConfigCompact> for BankConfig {
fn from(config: BankConfigCompact) -> Self {
Self {
asset_weight_init: config.asset_weight_init,
asset_weight_maint: config.asset_weight_maint,
liability_weight_init: config.liability_weight_init,
liability_weight_maint: config.liability_weight_maint,
deposit_limit: config.deposit_limit,
interest_rate_config: config.interest_rate_config.into(),
operational_state: config.operational_state,
oracle_setup: config.oracle_setup,
oracle_keys: config.oracle_keys,
borrow_limit: config.borrow_limit,
risk_tier: config.risk_tier,
total_asset_value_init_limit: config.total_asset_value_init_limit,
_padding: [0; 5],
}
}
}

impl From<BankConfig> for BankConfigCompact {
fn from(config: BankConfig) -> Self {
Self {
asset_weight_init: config.asset_weight_init,
asset_weight_maint: config.asset_weight_maint,
liability_weight_init: config.liability_weight_init,
liability_weight_maint: config.liability_weight_maint,
deposit_limit: config.deposit_limit,
interest_rate_config: config.interest_rate_config.into(),
operational_state: config.operational_state,
oracle_setup: config.oracle_setup,
oracle_keys: config.oracle_keys,
borrow_limit: config.borrow_limit,
risk_tier: config.risk_tier,
total_asset_value_init_limit: config.total_asset_value_init_limit,
}
}
}

assert_struct_size!(BankConfig, 544);
#[zero_copy]
#[repr(C)]
Expand Down
21 changes: 0 additions & 21 deletions programs/marginfi/tests/marginfi_group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,27 +181,6 @@ async fn marginfi_group_add_bank_success() -> anyhow::Result<()> {
Ok(())
}

#[tokio::test]
async fn marginfi_group_add_bank_lite_success() -> anyhow::Result<()> {
// Setup test executor with non-admin payer
let test_f = TestFixture::new(None).await;

let bank_asset_mint_fixture = MintFixture::new(test_f.context.clone(), None, None).await;

let res = test_f
.marginfi_group
.try_lending_pool_add_bank_lite(&bank_asset_mint_fixture, *DEFAULT_USDC_TEST_BANK_CONFIG)
.await;
assert!(res.is_ok());

// Check bank is active
let bank = res.unwrap();
let bank = test_f.try_load(&bank.key).await?;
assert!(bank.is_some());

Ok(())
}

#[tokio::test]
async fn marginfi_group_add_bank_failure_fake_pyth_feed() -> anyhow::Result<()> {
// Setup test executor with non-admin payer
Expand Down
Loading

0 comments on commit dc64339

Please sign in to comment.