use crate::*;
use anchor_spl::token::{Mint, TokenAccount};
use vipers::{assert_is_zero_token_account, assert_keys_eq, invariant, AsKeyRef, Validate};
#[derive(Accounts)]
#[instruction(bump: u8)]
pub struct CreateVault<'info> {
#[account(
init,
seeds = [
b"raydium_stake_lp_compound_vault".as_ref(),
amm.to_account_info().key.as_ref(),
base.key.as_ref()
],
bump,
payer = payer
)]
pub vault: Box<Account<'info, Vault>>,
pub base: Signer<'info>,
pub manager: Signer<'info>,
#[account(mut)]
pub payer: Signer<'info>,
pub system_program: Program<'info, System>,
#[account(mut)]
pub vault_lp_token_mint: Box<Account<'info, Mint>>,
pub farm_lp_mint: Box<Account<'info, Mint>>,
pub farm_reward_token_a_mint: Box<Account<'info, Mint>>,
pub farm_reward_token_b_mint: Box<Account<'info, Mint>>,
pub pool_lp_custody_account: Box<Account<'info, TokenAccount>>,
pub pool_token_a_custody_account: Box<Account<'info, TokenAccount>>,
pub pool_token_b_custody_account: Box<Account<'info, TokenAccount>>,
pub amm: Box<Account<'info, AmmInfoV4>>,
}
pub fn handler(
ctx: Context<CreateVault>,
manager: Pubkey,
serum_program_id: Pubkey,
pool_program_id: Pubkey,
farm_program_id: Pubkey,
farm: Pubkey,
farm_authority: Pubkey,
serum_market: Pubkey,
serum_vault_signer: Pubkey,
amm_authority: Pubkey,
) -> Result<()> {
msg!("Starting vault creation.");
let vault = &mut ctx.accounts.vault;
vault.base = ctx.accounts.base.key();
vault.bump = *ctx.bumps.get("vault").unwrap();
vault.manager = manager;
vault.vault_lp_token_mint = ctx.accounts.vault_lp_token_mint.key();
vault.farm_lp_mint = ctx.accounts.farm_lp_mint.key();
vault.farm_reward_token_a_mint = ctx.accounts.farm_reward_token_a_mint.key();
vault.farm_reward_token_b_mint = ctx.accounts.farm_reward_token_b_mint.key();
vault.pool_token_a_mint = *ctx.accounts.amm.coin_mint.as_key_ref();
vault.pool_token_b_mint = *ctx.accounts.amm.pc_mint.as_key_ref();
vault.pool_lp_token_mint = *ctx.accounts.amm.lp_mint.as_key_ref();
assert_keys_eq!(
ctx.accounts.pool_lp_custody_account.mint,
ctx.accounts.amm.lp_mint
);
assert_keys_eq!(
ctx.accounts.pool_token_a_custody_account.mint,
ctx.accounts.amm.coin_mint
);
assert_keys_eq!(
ctx.accounts.pool_token_b_custody_account.mint,
ctx.accounts.amm.pc_mint
);
vault.pool_lp_custody_account = ctx.accounts.pool_lp_custody_account.key();
vault.pool_token_a_custody_account = ctx.accounts.pool_token_a_custody_account.key();
vault.pool_token_b_custody_account = ctx.accounts.pool_token_b_custody_account.key();
vault.amm = ctx.accounts.amm.key();
vault.pool_coin_token_account = *ctx.accounts.amm.token_coin.as_key_ref();
vault.pool_pc_token_account = *ctx.accounts.amm.token_pc.as_key_ref();
vault.pool_withdraw_queue = *ctx.accounts.amm.withdraw_queue.as_key_ref();
vault.pool_temp_lp_token_account = *ctx.accounts.amm.token_temp_lp.as_key_ref();
vault.amm_authority = amm_authority;
vault.amm_open_orders = *ctx.accounts.amm.open_orders.as_key_ref();
vault.amm_target = *ctx.accounts.amm.target_orders.as_key_ref();
vault.farm = farm;
vault.farm_authority = farm_authority;
vault.serum_market = serum_market;
vault.serum_program_id = serum_program_id;
vault.serum_vault_signer = serum_vault_signer;
vault.pool_program_id = pool_program_id;
vault.farm_program_id = farm_program_id;
vault.deposits_allowed = true;
vault.withdraws_allowed = true;
vault.fee_millibps = 0;
vault.external_fee_millibps = 0;
vault.crank_time = clock::get_time_as_u64()?;
vault.crank_step = 0;
vault.token_a_added = 0;
vault.token_b_added = 0;
vault.token_a_removed = 0;
vault.token_b_removed = 0;
vault.token_a_rewards = 0;
vault.token_b_rewards = 0;
msg!("Finished creating vaults.");
emit!(VaultCreateEvent {
vault: vault.key(),
manager,
});
Ok(())
}
impl<'info> Validate<'info> for CreateVault<'info> {
fn validate(&self) -> Result<()> {
assert_is_zero_token_account!(self.pool_lp_custody_account);
assert_is_zero_token_account!(self.pool_token_a_custody_account);
assert_is_zero_token_account!(self.pool_token_b_custody_account);
invariant!(self.vault_lp_token_mint.supply == 0);
assert_keys_eq!(self.vault_lp_token_mint.mint_authority.unwrap(), self.vault,);
assert_keys_eq!(self.pool_lp_custody_account.owner, self.vault);
assert_keys_eq!(self.pool_token_a_custody_account.owner, self.vault,);
assert_keys_eq!(self.pool_token_b_custody_account.owner, self.vault,);
assert_keys_eq!(self.pool_lp_custody_account.mint, self.amm.lp_mint);
assert_keys_eq!(self.pool_token_a_custody_account.mint, self.amm.coin_mint);
assert_keys_eq!(self.pool_token_b_custody_account.mint, self.amm.pc_mint);
Ok(())
}
}