dloom_flow/amm/instructions/
create_pool.rs

1// FILE: programs/dloom_flow/src/instructions/amm_create_pool.rs
2
3use crate::{amm::state::AmmPool, constants::*, errors::DloomError, events::AmmPoolCreated};
4use anchor_lang::prelude::*;
5use anchor_spl::token_interface::{Mint, TokenAccount, TokenInterface};
6
7/// The handler for the `create_amm_pool` instruction.
8pub fn handle_create_amm_pool(
9    ctx: Context<CreateAmmPool>,
10    fee_rate: u16,
11    protocol_fee_share: u16,
12    referrer_fee_share: u16,
13) -> Result<()> {
14    require!(
15        fee_rate as u128 <= BASIS_POINT_MAX,
16        DloomError::InvalidFeeRates
17    );
18    require!(
19        protocol_fee_share as u128 <= BASIS_POINT_MAX,
20        DloomError::InvalidFeeRates
21    );
22    require!(
23        referrer_fee_share as u128 <= BASIS_POINT_MAX,
24        DloomError::InvalidFeeRates
25    );
26
27    let total_fee_share = (protocol_fee_share as u128)
28        .checked_add(referrer_fee_share as u128)
29        .ok_or(DloomError::MathOverflow)?;
30    require!(
31        total_fee_share <= BASIS_POINT_MAX,
32        DloomError::FeeShareExceedsTotal
33    );
34
35    let amm_pool = &mut ctx.accounts.amm_pool;
36    amm_pool.bump = ctx.bumps.amm_pool;
37    amm_pool.authority = ctx.accounts.authority.key();
38    amm_pool.token_a_mint = ctx.accounts.token_a_mint.key();
39    amm_pool.token_b_mint = ctx.accounts.token_b_mint.key();
40    amm_pool.token_a_vault = ctx.accounts.token_a_vault.key();
41    amm_pool.token_b_vault = ctx.accounts.token_b_vault.key();
42    amm_pool.lp_mint = ctx.accounts.lp_mint.key();
43    amm_pool.fee_rate = fee_rate;
44    amm_pool.protocol_fee_share = protocol_fee_share;
45    amm_pool.referrer_fee_share = referrer_fee_share;
46    amm_pool.protocol_fee_vault_a = ctx.accounts.protocol_fee_vault_a.key();
47    amm_pool.protocol_fee_vault_b = ctx.accounts.protocol_fee_vault_b.key();
48    amm_pool.reserves_a = 0;
49    amm_pool.reserves_b = 0;
50    amm_pool.price_a_cumulative_last_fee_update = 0;
51
52    emit!(AmmPoolCreated {
53        pool_address: ctx.accounts.amm_pool.key(),
54        token_a_mint: ctx.accounts.token_a_mint.key(),
55        token_b_mint: ctx.accounts.token_b_mint.key(),
56        lp_mint: ctx.accounts.lp_mint.key(),
57        fee_rate,
58    });
59
60    Ok(())
61}
62
63#[derive(Accounts)]
64pub struct CreateAmmPool<'info> {
65    #[account(mut)]
66    pub payer: Signer<'info>,
67
68    /// CHECK: The authority for the protocol, passed in to be stored.
69    pub authority: AccountInfo<'info>,
70
71    #[account(constraint = token_a_mint.key() < token_b_mint.key() @ DloomError::InvalidMintOrder)]
72    pub token_a_mint: InterfaceAccount<'info, Mint>,
73    pub token_b_mint: InterfaceAccount<'info, Mint>,
74
75    #[account(
76        init,
77        payer = payer,
78        space = 8 + 390,
79        seeds = [b"amm_pool", token_a_mint.key().as_ref(), token_b_mint.key().as_ref()],
80        bump
81    )]
82    pub amm_pool: Box<Account<'info, AmmPool>>,
83
84    #[account(
85        init,
86        payer = payer,
87        seeds = [b"lp_mint", amm_pool.key().as_ref()],
88        bump,
89        mint::decimals = 6,
90        mint::authority = amm_pool,
91        mint::token_program = token_program
92    )]
93    pub lp_mint: InterfaceAccount<'info, Mint>,
94
95    #[account(
96        init,
97        payer = payer,
98        seeds = [b"vault", amm_pool.key().as_ref(), token_a_mint.key().as_ref()],
99        bump,
100        token::mint = token_a_mint,
101        token::authority = amm_pool,
102        token::token_program = token_a_program
103    )]
104    pub token_a_vault: InterfaceAccount<'info, TokenAccount>,
105
106    #[account(
107        init,
108        payer = payer,
109        seeds = [b"vault", amm_pool.key().as_ref(), token_b_mint.key().as_ref()],
110        bump,
111        token::mint = token_b_mint,
112        token::authority = amm_pool,
113        token::token_program = token_b_program
114    )]
115    pub token_b_vault: InterfaceAccount<'info, TokenAccount>,
116
117    #[account(
118        init,
119        payer = payer,
120        seeds = [b"protocol_fee_vault", amm_pool.key().as_ref(), token_a_mint.key().as_ref()],
121        bump,
122        token::mint = token_a_mint,
123        token::authority = authority,
124        token::token_program = token_a_program
125    )]
126    pub protocol_fee_vault_a: InterfaceAccount<'info, TokenAccount>,
127
128    #[account(
129        init,
130        payer = payer,
131        seeds = [b"protocol_fee_vault", amm_pool.key().as_ref(), token_b_mint.key().as_ref()],
132        bump,
133        token::mint = token_b_mint,
134        token::authority = authority,
135        token::token_program = token_b_program
136    )]
137    pub protocol_fee_vault_b: InterfaceAccount<'info, TokenAccount>,
138
139    pub system_program: Program<'info, System>,
140    pub token_a_program: Interface<'info, TokenInterface>,
141    pub token_b_program: Interface<'info, TokenInterface>,
142    pub token_program: Interface<'info, TokenInterface>,
143
144    pub rent: Sysvar<'info, Rent>,
145}