use crate::*;
use anchor_spl::token::{Mint, TokenAccount};
use vipers::prelude::*;
#[derive(Accounts)]
pub struct CreateYiToken<'info> {
pub mint: Account<'info, Mint>,
#[account(
init,
seeds = [
b"YiToken".as_ref(),
mint.key().as_ref()
],
bump,
space = 8 + YiToken::SIZE,
payer = payer
)]
pub yi_token: AccountLoader<'info, YiToken>,
pub underlying_token_mint: Account<'info, Mint>,
pub underlying_tokens: Account<'info, TokenAccount>,
#[account(mut)]
pub payer: Signer<'info>,
pub system_program: Program<'info, System>,
}
impl<'info> CreateYiToken<'info> {
fn create_yi_token(
&mut self,
bump: u8,
stake_fee_millibps: u32,
unstake_fee_millibps: u32,
) -> Result<()> {
let yi_token = &mut self.yi_token.load_init()?;
yi_token.mint = self.mint.key();
yi_token.bump = bump;
yi_token.underlying_token_mint = self.underlying_token_mint.key();
yi_token.underlying_tokens = self.underlying_tokens.key();
invariant!(stake_fee_millibps <= MILLIBPS_PER_WHOLE, InvalidStakeFee);
invariant!(
unstake_fee_millibps <= MILLIBPS_PER_WHOLE,
InvalidUnstakeFee
);
yi_token.stake_fee_millibps = stake_fee_millibps;
yi_token.unstake_fee_millibps = unstake_fee_millibps;
Ok(())
}
}
pub fn handler(
ctx: Context<CreateYiToken>,
stake_fee_millibps: u32,
unstake_fee_millibps: u32,
) -> Result<()> {
ctx.accounts.create_yi_token(
*unwrap_int!(ctx.bumps.get("yi_token")),
stake_fee_millibps,
unstake_fee_millibps,
)
}
impl<'info> Validate<'info> for CreateYiToken<'info> {
fn validate(&self) -> Result<()> {
assert_keys_eq!(self.mint.mint_authority.unwrap(), self.yi_token);
assert_keys_eq!(self.mint.freeze_authority.unwrap(), self.yi_token);
invariant!(self.mint.supply == 0);
invariant!(
self.underlying_token_mint.decimals == self.mint.decimals,
DecimalMismatch
);
assert_is_zero_token_account!(self.underlying_tokens);
assert_keys_eq!(self.underlying_tokens.owner, self.yi_token);
assert_keys_eq!(self.underlying_tokens.mint, self.underlying_token_mint);
Ok(())
}
}