yi/instructions/
create_yi_token.rs

1//! Processor for [yi::create_yi_token].
2
3use crate::*;
4use anchor_spl::token::{Mint, TokenAccount};
5use vipers::prelude::*;
6
7/// Accounts for [yi::create_yi_token].
8#[derive(Accounts)]
9pub struct CreateYiToken<'info> {
10    /// The [Mint] of the [YiToken].
11    pub mint: Account<'info, Mint>,
12
13    /// The [YiToken] to be created.
14    #[account(
15        init,
16        seeds = [
17            b"YiToken".as_ref(),
18            mint.key().as_ref()
19        ],
20        bump,
21        space = 8 + YiToken::SIZE,
22        payer = payer
23    )]
24    pub yi_token: AccountLoader<'info, YiToken>,
25
26    /// [YiToken::underlying_token_mint].
27    pub underlying_token_mint: Account<'info, Mint>,
28
29    /// [YiToken::underlying_tokens].
30    pub underlying_tokens: Account<'info, TokenAccount>,
31
32    /// Payer.
33    #[account(mut)]
34    pub payer: Signer<'info>,
35
36    /// [System] program.
37    pub system_program: Program<'info, System>,
38}
39
40impl<'info> CreateYiToken<'info> {
41    fn create_yi_token(
42        &mut self,
43        bump: u8,
44        stake_fee_millibps: u32,
45        unstake_fee_millibps: u32,
46    ) -> Result<()> {
47        let yi_token = &mut self.yi_token.load_init()?;
48        yi_token.mint = self.mint.key();
49        yi_token.bump = bump;
50        yi_token.underlying_token_mint = self.underlying_token_mint.key();
51        yi_token.underlying_tokens = self.underlying_tokens.key();
52
53        invariant!(stake_fee_millibps <= MILLIBPS_PER_WHOLE, InvalidStakeFee);
54        invariant!(
55            unstake_fee_millibps <= MILLIBPS_PER_WHOLE,
56            InvalidUnstakeFee
57        );
58
59        yi_token.stake_fee_millibps = stake_fee_millibps;
60        yi_token.unstake_fee_millibps = unstake_fee_millibps;
61        Ok(())
62    }
63}
64
65pub fn handler(
66    ctx: Context<CreateYiToken>,
67    stake_fee_millibps: u32,
68    unstake_fee_millibps: u32,
69) -> Result<()> {
70    ctx.accounts.create_yi_token(
71        *unwrap_int!(ctx.bumps.get("yi_token")),
72        stake_fee_millibps,
73        unstake_fee_millibps,
74    )
75}
76
77impl<'info> Validate<'info> for CreateYiToken<'info> {
78    fn validate(&self) -> Result<()> {
79        assert_keys_eq!(self.mint.mint_authority.unwrap(), self.yi_token);
80        assert_keys_eq!(self.mint.freeze_authority.unwrap(), self.yi_token);
81        invariant!(self.mint.supply == 0);
82
83        invariant!(
84            self.underlying_token_mint.decimals == self.mint.decimals,
85            DecimalMismatch
86        );
87
88        assert_is_zero_token_account!(self.underlying_tokens);
89        assert_keys_eq!(self.underlying_tokens.owner, self.yi_token);
90        assert_keys_eq!(self.underlying_tokens.mint, self.underlying_token_mint);
91        Ok(())
92    }
93}