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

feat: lending pool add bank lite #138

Merged
merged 4 commits into from
Nov 24, 2023
Merged
Show file tree
Hide file tree
Changes from 2 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
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
use anchor_lang::prelude::*;
use solana_program::sysvar::Sysvar;

pub fn initialize(ctx: Context<MarginfiAccountInitialize>) -> MarginfiResult {
pub fn initialize_account(ctx: Context<MarginfiAccountInitialize>) -> MarginfiResult {
let MarginfiAccountInitialize {
authority,
marginfi_group,
Expand Down
61 changes: 60 additions & 1 deletion programs/marginfi/src/instructions/marginfi_group/add_pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ use crate::{
INSURANCE_VAULT_SEED, LIQUIDITY_VAULT_AUTHORITY_SEED, LIQUIDITY_VAULT_SEED,
},
events::{GroupEventHeader, LendingPoolBankCreateEvent},
state::marginfi_group::{Bank, BankConfig, MarginfiGroup},
state::{
marginfi_group::{Bank, BankConfig, MarginfiGroup},
price::OracleSetup,
},
MarginfiResult,
};
use anchor_lang::prelude::*;
Expand Down Expand Up @@ -162,3 +165,59 @@ 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(())
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::events::{GroupEventHeader, MarginfiGroupCreateEvent};
use crate::{state::marginfi_group::MarginfiGroup, MarginfiResult};
use anchor_lang::prelude::*;

pub fn initialize(ctx: Context<MarginfiGroupInitialize>) -> MarginfiResult {
pub fn initialize_group(ctx: Context<MarginfiGroupInitialize>) -> MarginfiResult {
let marginfi_group = &mut ctx.accounts.marginfi_group.load_init()?;

marginfi_group.set_initial_configuration(ctx.accounts.admin.key());
Expand Down
14 changes: 12 additions & 2 deletions programs/marginfi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub mod prelude;
pub mod state;
pub mod utils;

use crate::state::price::OracleSetup;
use anchor_lang::prelude::*;
use instructions::*;
use prelude::*;
Expand All @@ -24,10 +25,11 @@ cfg_if::cfg_if! {

#[program]
pub mod marginfi {

use super::*;

pub fn marginfi_group_initialize(ctx: Context<MarginfiGroupInitialize>) -> MarginfiResult {
marginfi_group::initialize(ctx)
marginfi_group::initialize_group(ctx)
}

pub fn marginfi_group_configure(
Expand All @@ -44,6 +46,14 @@ pub mod marginfi {
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>,
) -> MarginfiResult {
marginfi_group::lending_pool_add_bank_lite(ctx, oracle_setup, oracle_keys)
}

pub fn lending_pool_configure_bank(
ctx: Context<LendingPoolConfigureBank>,
bank_config_opt: BankConfigOpt,
Expand Down Expand Up @@ -85,7 +95,7 @@ pub mod marginfi {

/// Initialize a marginfi account for a given group
pub fn marginfi_account_initialize(ctx: Context<MarginfiAccountInitialize>) -> MarginfiResult {
marginfi_account::initialize(ctx)
marginfi_account::initialize_account(ctx)
}

pub fn lending_account_deposit(
Expand Down
16 changes: 16 additions & 0 deletions programs/marginfi/src/state/marginfi_group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -866,6 +866,22 @@ impl BankConfig {
Ok(())
}

pub fn new_with_oracle_config(oracle_setup: OracleSetup, oracle_keys: Vec<Pubkey>) -> Self {
assert!(oracle_keys.len() <= MAX_ORACLE_KEYS);

let mut oracle_keys = [Pubkey::default(); 5];

for (i, key) in oracle_keys.into_iter().enumerate() {
oracle_keys[i] = key;
}

Self {
oracle_setup,
oracle_keys,
..Default::default()
}
}

#[inline]
pub fn is_deposit_limit_active(&self) -> bool {
self.deposit_limit != u64::MAX
Expand Down
21 changes: 21 additions & 0 deletions programs/marginfi/tests/marginfi_group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,27 @@ 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
55 changes: 55 additions & 0 deletions test-utils/src/marginfi_group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,61 @@ impl MarginfiGroupFixture {
Ok(bank_fixture)
}

pub async fn try_lending_pool_add_bank_lite(
&self,
bank_asset_mint_fixture: &MintFixture,
bank_config: BankConfig,
) -> Result<BankFixture, BanksClientError> {
let bank_key = Keypair::new();
let bank_mint = bank_asset_mint_fixture.key;
let bank_fixture =
BankFixture::new(self.ctx.clone(), bank_key.pubkey(), bank_asset_mint_fixture);

let mut accounts = marginfi::accounts::LendingPoolAddBank {
marginfi_group: self.key,
admin: self.ctx.borrow().payer.pubkey(),
bank_mint,
bank: bank_key.pubkey(),
liquidity_vault_authority: bank_fixture.get_vault_authority(BankVaultType::Liquidity).0,
liquidity_vault: bank_fixture.get_vault(BankVaultType::Liquidity).0,
insurance_vault_authority: bank_fixture.get_vault_authority(BankVaultType::Insurance).0,
insurance_vault: bank_fixture.get_vault(BankVaultType::Insurance).0,
fee_vault_authority: bank_fixture.get_vault_authority(BankVaultType::Fee).0,
fee_vault: bank_fixture.get_vault(BankVaultType::Fee).0,
rent: sysvar::rent::id(),
token_program: token::ID,
system_program: system_program::id(),
}
.to_account_metas(Some(true));

accounts.push(AccountMeta::new_readonly(bank_config.oracle_keys[0], false));

let ix = Instruction {
program_id: marginfi::id(),
accounts,
data: marginfi::instruction::LendingPoolAddBankLite {
oracle_setup: bank_config.oracle_setup,
oracle_keys: vec![bank_config.oracle_keys[0]],
}
.data(),
};

let tx = Transaction::new_signed_with_payer(
&[ix],
Some(&self.ctx.borrow().payer.pubkey().clone()),
&[&self.ctx.borrow().payer, &bank_key],
self.ctx.borrow().last_blockhash,
);

self.ctx
.borrow_mut()
.banks_client
.process_transaction(tx)
.await?;

Ok(bank_fixture)
}

pub fn make_lending_pool_configure_bank_ix(
&self,
bank: &BankFixture,
Expand Down
Loading