Skip to content

Commit

Permalink
Add fee state to pool generation args, basic setup of text fixture, W…
Browse files Browse the repository at this point in the history
…IP updating tests to include the fee
  • Loading branch information
jgur-psyops committed Aug 27, 2024
1 parent 33eae0f commit 18b2b3a
Show file tree
Hide file tree
Showing 7 changed files with 429 additions and 163 deletions.
206 changes: 43 additions & 163 deletions programs/marginfi/src/instructions/marginfi_group/add_pool.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use crate::{
constants::{
FEE_VAULT_AUTHORITY_SEED, FEE_VAULT_SEED, INSURANCE_VAULT_AUTHORITY_SEED,
INSURANCE_VAULT_SEED, LIQUIDITY_VAULT_AUTHORITY_SEED, LIQUIDITY_VAULT_SEED,
FEE_STATE_SEED, FEE_VAULT_AUTHORITY_SEED, FEE_VAULT_SEED, INSURANCE_VAULT_AUTHORITY_SEED, INSURANCE_VAULT_SEED, LIQUIDITY_VAULT_AUTHORITY_SEED, LIQUIDITY_VAULT_SEED
},
events::{GroupEventHeader, LendingPoolBankCreateEvent},
state::marginfi_group::{Bank, BankConfig, BankConfigCompact, MarginfiGroup},
state::{fee_state::FeeState, marginfi_group::{Bank, BankConfig, BankConfigCompact, MarginfiGroup}},
MarginfiResult,
};
use anchor_lang::prelude::*;
Expand All @@ -19,6 +18,16 @@ pub fn lending_pool_add_bank(
ctx: Context<LendingPoolAddBank>,
bank_config: BankConfig,
) -> MarginfiResult {
// Transfer the flat sol init fee to the global fee wallet
let fee_state = ctx.accounts.fee_state.load()?;
let bank_init_flat_sol_fee = fee_state.bank_init_flat_sol_fee;
if bank_init_flat_sol_fee > 0 {
anchor_lang::system_program::transfer(
ctx.accounts.transfer_flat_fee(),
bank_init_flat_sol_fee as u64,
)?;
}

let LendingPoolAddBank {
bank_mint,
liquidity_vault,
Expand Down Expand Up @@ -69,6 +78,10 @@ pub fn lending_pool_add_bank(
Ok(())
}

/*
. Aligns line spacing for easier comparison against with_seed
.
*/
#[derive(Accounts)]
#[instruction(bank_config: BankConfigCompact)]
pub struct LendingPoolAddBank<'info> {
Expand All @@ -80,181 +93,34 @@ pub struct LendingPoolAddBank<'info> {
)]
pub admin: Signer<'info>,

/// Pays to init accounts and pays `fee_state.bank_init_flat_sol_fee` lamports to the protocol
#[account(mut)]
pub fee_payer: Signer<'info>,

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

// Note: there is just one FeeState per program, so no further check is required.
#[account(
init,
space = 8 + std::mem::size_of::<Bank>(),
payer = fee_payer,
)]
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 = [
LIQUIDITY_VAULT_SEED.as_bytes(),
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(),
],
seeds = [FEE_STATE_SEED.as_bytes()],
bump,
has_one = global_fee_wallet
)]
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(
ctx: Context<LendingPoolAddBankWithSeed>,
bank_config: BankConfig,
_bank_seed: u64,
) -> MarginfiResult {
let LendingPoolAddBankWithSeed {
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.liquidity_vault;
let liquidity_vault_authority_bump = ctx.bumps.liquidity_vault_authority;
let insurance_vault_bump = ctx.bumps.insurance_vault;
let insurance_vault_authority_bump = ctx.bumps.insurance_vault_authority;
let fee_vault_bump = ctx.bumps.fee_vault;
let fee_vault_authority_bump = ctx.bumps.fee_vault_authority;

*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_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(())
}

/// A copy of LendingPoolAddBank 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 LendingPoolAddBank is preserved for backwards-compatibility.
#[derive(Accounts)]
#[instruction(bank_config: BankConfigCompact, bank_seed: u64)]
pub struct LendingPoolAddBankWithSeed<'info> {
pub marginfi_group: AccountLoader<'info, MarginfiGroup>,

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

/// CHECK: The fee admin's native SOL wallet, validated against fee state
#[account(mut)]
pub fee_payer: Signer<'info>,
pub global_fee_wallet: AccountInfo<'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,
/*
In the "with seed" version of this ix, the seed is defined here
.
.
.
*/
)]
pub bank: AccountLoader<'info, Bank>,

Expand Down Expand Up @@ -331,3 +197,17 @@ pub struct LendingPoolAddBankWithSeed<'info> {
pub token_program: Interface<'info, TokenInterface>,
pub system_program: Program<'info, System>,
}

impl<'info> LendingPoolAddBank<'info> {
fn transfer_flat_fee(
&self,
) -> CpiContext<'_, '_, '_, 'info, anchor_lang::system_program::Transfer<'info>> {
CpiContext::new(
self.system_program.to_account_info(),
anchor_lang::system_program::Transfer {
from: self.fee_payer.to_account_info(),
to: self.global_fee_wallet.to_account_info(),
},
)
}
}
Loading

0 comments on commit 18b2b3a

Please sign in to comment.