manifest/program/processor/
global_deposit.rs

1use std::cell::RefMut;
2
3use borsh::{BorshDeserialize, BorshSerialize};
4use solana_program::{account_info::AccountInfo, entrypoint::ProgramResult, pubkey::Pubkey};
5
6use crate::{
7    logs::{emit_stack, GlobalDepositLog},
8    program::get_mut_dynamic_account,
9    quantities::{GlobalAtoms, WrapperU64},
10    state::GlobalRefMut,
11    validation::loaders::GlobalDepositContext,
12};
13
14use super::invoke;
15
16#[derive(BorshDeserialize, BorshSerialize)]
17pub struct GlobalDepositParams {
18    pub amount_atoms: u64,
19    // No trader index hint because global account is small so there is not much
20    // benefit from hinted indices, unlike the market which can get large. Also,
21    // seats are not permanent like on a market due to eviction, so it is more
22    // likely that a client could send a bad request. Just look it up for them.
23}
24
25impl GlobalDepositParams {
26    pub fn new(amount_atoms: u64) -> Self {
27        GlobalDepositParams { amount_atoms }
28    }
29}
30
31pub(crate) fn process_global_deposit(
32    _program_id: &Pubkey,
33    accounts: &[AccountInfo],
34    data: &[u8],
35) -> ProgramResult {
36    let global_deposit_context: GlobalDepositContext = GlobalDepositContext::load(accounts)?;
37    let GlobalDepositParams { amount_atoms } = GlobalDepositParams::try_from_slice(data)?;
38    // Due to transfer fees, this might not be what you expect.
39    let mut deposited_amount_atoms: u64 = amount_atoms;
40
41    let GlobalDepositContext {
42        payer,
43        global,
44        mint,
45        global_vault,
46        trader_token: trader_token_account,
47        token_program,
48    } = global_deposit_context;
49
50    let global_data: &mut RefMut<&mut [u8]> = &mut global.try_borrow_mut_data()?;
51    let mut global_dynamic_account: GlobalRefMut = get_mut_dynamic_account(global_data);
52    global_dynamic_account.deposit_global(payer.key, GlobalAtoms::new(amount_atoms))?;
53
54    // Do the token transfer
55    if *global_vault.owner == spl_token_2022::id() {
56        let before_vault_balance_atoms: u64 = global_vault.get_balance_atoms();
57        invoke(
58            &spl_token_2022::instruction::transfer_checked(
59                token_program.key,
60                trader_token_account.key,
61                mint.info.key,
62                global_vault.key,
63                payer.key,
64                &[],
65                amount_atoms,
66                mint.mint.decimals,
67            )?,
68            &[
69                token_program.as_ref().clone(),
70                trader_token_account.as_ref().clone(),
71                mint.as_ref().clone(),
72                global_vault.as_ref().clone(),
73                payer.as_ref().clone(),
74            ],
75        )?;
76
77        let after_vault_balance_atoms: u64 = global_vault.get_balance_atoms();
78        deposited_amount_atoms = after_vault_balance_atoms
79            .checked_sub(before_vault_balance_atoms)
80            .unwrap();
81    } else {
82        invoke(
83            &spl_token::instruction::transfer(
84                token_program.key,
85                trader_token_account.key,
86                global_vault.key,
87                payer.key,
88                &[],
89                amount_atoms,
90            )?,
91            &[
92                token_program.as_ref().clone(),
93                trader_token_account.as_ref().clone(),
94                global_vault.as_ref().clone(),
95                payer.as_ref().clone(),
96            ],
97        )?;
98    }
99
100    emit_stack(GlobalDepositLog {
101        global: *global.key,
102        trader: *payer.key,
103        global_atoms: GlobalAtoms::new(deposited_amount_atoms),
104    })?;
105
106    Ok(())
107}