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

Upstream add bank with bump #242

Closed
wants to merge 4 commits into from
Closed
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
185 changes: 185 additions & 0 deletions programs/marginfi/src/instructions/marginfi_group/add_pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,3 +331,188 @@ pub struct LendingPoolAddBankWithSeed<'info> {
pub token_program: Interface<'info, TokenInterface>,
pub system_program: Program<'info, System>,
}


/// A copy of LendingPoolAddBankWithSeed but with explicit bumps provided.
/// These bumps are used by multiple marginfi functions to efficiently generate the correct address to be used.
#[derive(Accounts)]
#[instruction(
bank_config: BankConfigCompact,
bank_seed: u64,
liquidity_vault_bump: u8,
liquidity_vault_auth_bump: u8,
insurance_vault_bump: u8,
insurance_vault_auth_bump: u8,
fee_vault_bump: u8,
fee_vault_auth_bump: u8
)]
pub struct LendingPoolAddBankWithSeedAndBump<'info> {
pub marginfi_group: AccountLoader<'info, MarginfiGroup>,

#[account(
mut,
address = marginfi_group.load()?.admin,
)]
pub admin: Signer<'info>,

#[account(mut)]
pub fee_payer: Signer<'info>,

pub bank_mint: Box<InterfaceAccount<'info, Mint>>,

#[account(
init,
space = 8 + std::mem::size_of::<Bank>(),
payer = fee_payer,
seeds = [
marginfi_group.key().as_ref(),
bank_mint.key().as_ref(),
&bank_seed.to_le_bytes(),
],
bump,
)]
pub bank: AccountLoader<'info, Bank>,

/// CHECK: ⋐ ͡⋄ ω ͡⋄ ⋑
#[account(
seeds = [
LIQUIDITY_VAULT_AUTHORITY_SEED.as_bytes(),
bank.key().as_ref(),
],
bump
)]
pub liquidity_vault_authority: AccountInfo<'info>,

#[account(
init,
payer = fee_payer,
token::mint = bank_mint,
token::authority = liquidity_vault_authority,

seeds = [
b"liquidity_vault",
bank.key().as_ref(),
],
bump,
)]
pub liquidity_vault: Box<InterfaceAccount<'info, TokenAccount>>,

/// CHECK: ⋐ ͡⋄ ω ͡⋄ ⋑
#[account(
seeds = [
INSURANCE_VAULT_AUTHORITY_SEED.as_bytes(),
bank.key().as_ref(),
],
bump
)]
pub insurance_vault_authority: AccountInfo<'info>,

#[account(
init,
payer = fee_payer,
token::mint = bank_mint,
token::authority = insurance_vault_authority,

seeds = [
INSURANCE_VAULT_SEED.as_bytes(),
bank.key().as_ref(),
],
bump,
)]
pub insurance_vault: Box<InterfaceAccount<'info, TokenAccount>>,

/// CHECK: ⋐ ͡⋄ ω ͡⋄ ⋑
#[account(
seeds = [
FEE_VAULT_AUTHORITY_SEED.as_bytes(),
bank.key().as_ref(),
],
bump
)]
pub fee_vault_authority: AccountInfo<'info>,

#[account(
init,
payer = fee_payer,
token::mint = bank_mint,
token::authority = fee_vault_authority,

seeds = [
FEE_VAULT_SEED.as_bytes(),
bank.key().as_ref(),
],
bump,
)]
pub fee_vault: Box<InterfaceAccount<'info, TokenAccount>>,

pub rent: Sysvar<'info, Rent>,
pub token_program: Interface<'info, TokenInterface>,
pub system_program: Program<'info, System>,
}





/// A copy of lending_pool_add_bank but with an additional bank seed provided.
/// This seed is used by the LendingPoolAddBankWithSeed.bank to generate a
/// PDA account to sign for newly added bank transactions securely.
/// The previous lending_pool_add_bank is preserved for backwards-compatibility.
pub fn lending_pool_add_bank_with_seed_and_bump(
ctx: Context<LendingPoolAddBankWithSeedAndBump>,
bank_config: BankConfig,
_bank_seed: u64,
liquidity_vault_bump: u8,
liquidity_vault_auth_bump: u8,
insurance_vault_bump: u8,
insurance_vault_auth_bump: u8,
fee_vault_bump: u8,
fee_vault_auth_bump: u8

) -> MarginfiResult {
let LendingPoolAddBankWithSeedAndBump {
bank_mint,
liquidity_vault,
insurance_vault,
fee_vault,
bank: bank_loader,
..
} = ctx.accounts;

let mut bank = bank_loader.load_init()?;


*bank = Bank::new(
ctx.accounts.marginfi_group.key(),
bank_config,
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_auth_bump,
// liquidity_vault_authority_bump,
insurance_vault_bump,
insurance_vault_auth_bump,
// insurance_vault_authority_bump,
fee_vault_bump,
fee_vault_auth_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(())
}
26 changes: 26 additions & 0 deletions programs/marginfi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,32 @@ pub mod marginfi {
marginfi_group::lending_pool_add_bank_with_seed(ctx, bank_config.into(), bank_seed)
}

/// A copy of lending_pool_add_bank_with_seed with explicit bumps
/// to circumvent a CPI issue with bumps not being relayed correctly?
pub fn lending_pool_add_bank_with_seed_and_bump(
ctx: Context<LendingPoolAddBankWithSeedAndBump>,
bank_config: BankConfigCompact,
bank_seed: u64,
liquidity_vault_bump: u8,
liquidity_vault_auth_bump: u8,
insurance_vault_bump: u8,
insurance_vault_auth_bump: u8,
fee_vault_bump: u8,
fee_vault_auth_bump: u8
) -> MarginfiResult {
marginfi_group::lending_pool_add_bank_with_seed_and_bump(
ctx,
bank_config.into(),
bank_seed,
liquidity_vault_bump,
liquidity_vault_auth_bump,
insurance_vault_bump,
insurance_vault_auth_bump,
fee_vault_bump,
fee_vault_auth_bump
)
}

pub fn lending_pool_configure_bank(
ctx: Context<LendingPoolConfigureBank>,
bank_config_opt: BankConfigOpt,
Expand Down
86 changes: 86 additions & 0 deletions test-utils/src/marginfi_group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,92 @@ impl MarginfiGroupFixture {
Ok(bank_fixture)
}


pub async fn try_lending_pool_add_bank_with_seed_and_bump(
&self,
bank_asset_mint_fixture: &MintFixture,
bank_config: BankConfig,
bank_seed: u64,
) -> Result<BankFixture, BanksClientError> {
let bank_mint = bank_asset_mint_fixture.key;

// Create PDA account from seeds
let (pda, _bump) = Pubkey::find_program_address(
[
self.key.as_ref(),
bank_mint.as_ref(),
&bank_seed.to_le_bytes(),
]
.as_slice(),
&marginfi::id(),
);

let bank_mint = bank_asset_mint_fixture.key;
let bank_fixture = BankFixture::new(self.ctx.clone(), pda, bank_asset_mint_fixture);

let liquidity_vault = bank_fixture.get_vault(BankVaultType::Liquidity);
let liquidity_vault_authority = bank_fixture.get_vault_authority(BankVaultType::Liquidity);

let insurance_vault = bank_fixture.get_vault(BankVaultType::Insurance);
let insurance_vault_authority = bank_fixture.get_vault_authority(BankVaultType::Insurance);

let fee_vault = bank_fixture.get_vault(BankVaultType::Fee);
let fee_vault_authority = bank_fixture.get_vault_authority(BankVaultType::Fee);

let mut accounts = marginfi::accounts::LendingPoolAddBankWithSeed {
marginfi_group: self.key,
admin: self.ctx.borrow().payer.pubkey(),
fee_payer: self.ctx.borrow().payer.pubkey(),
bank_mint,
bank: pda,
liquidity_vault_authority: liquidity_vault_authority.0,
liquidity_vault: liquidity_vault.0,
insurance_vault_authority: insurance_vault_authority.0,
insurance_vault: insurance_vault.0,
fee_vault_authority: fee_vault_authority.0,
fee_vault: fee_vault.0,
rent: sysvar::rent::id(),
token_program: bank_fixture.get_token_program(),
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::LendingPoolAddBankWithSeedAndBump {
bank_config: bank_config.into(),
bank_seed,
liquidity_vault_bump: liquidity_vault.1,
liquidity_vault_auth_bump: liquidity_vault_authority.1,

fee_vault_bump: fee_vault.1,
fee_vault_auth_bump: fee_vault_authority.1,

insurance_vault_bump: insurance_vault.1,
insurance_vault_auth_bump: insurance_vault_authority.1,
}
.data(),
};

let tx = Transaction::new_signed_with_payer(
&[ix],
Some(&self.ctx.borrow().payer.pubkey().clone()),
&[&self.ctx.borrow().payer],
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