manifest/program/processor/
global_withdraw.rs1use std::cell::RefMut;
2
3use borsh::{BorshDeserialize, BorshSerialize};
4use solana_program::{
5 account_info::AccountInfo, entrypoint::ProgramResult, program::invoke_signed, pubkey::Pubkey,
6};
7
8use crate::{
9 global_vault_seeds_with_bump,
10 logs::{emit_stack, GlobalWithdrawLog},
11 program::get_mut_dynamic_account,
12 quantities::{GlobalAtoms, WrapperU64},
13 state::GlobalRefMut,
14 validation::{get_global_vault_address, loaders::GlobalWithdrawContext},
15};
16
17#[derive(BorshDeserialize, BorshSerialize)]
18pub struct GlobalWithdrawParams {
19 pub amount_atoms: u64,
20 }
25
26impl GlobalWithdrawParams {
27 pub fn new(amount_atoms: u64) -> Self {
28 GlobalWithdrawParams { amount_atoms }
29 }
30}
31
32pub(crate) fn process_global_withdraw(
33 _program_id: &Pubkey,
34 accounts: &[AccountInfo],
35 data: &[u8],
36) -> ProgramResult {
37 let global_withdraw_context: GlobalWithdrawContext = GlobalWithdrawContext::load(accounts)?;
38 let GlobalWithdrawParams { amount_atoms } = GlobalWithdrawParams::try_from_slice(data)?;
39
40 let GlobalWithdrawContext {
41 payer,
42 global,
43 mint,
44 global_vault,
45 trader_token,
46 token_program,
47 } = global_withdraw_context;
48
49 let global_data: &mut RefMut<&mut [u8]> = &mut global.try_borrow_mut_data()?;
50 let mut global_dynamic_account: GlobalRefMut = get_mut_dynamic_account(global_data);
51 global_dynamic_account.withdraw_global(payer.key, GlobalAtoms::new(amount_atoms))?;
52
53 let (_, bump) = get_global_vault_address(mint.info.key);
54
55 if *global_vault.owner == spl_token_2022::id() {
57 invoke_signed(
58 &spl_token_2022::instruction::transfer_checked(
59 token_program.key,
60 global_vault.key,
61 mint.info.key,
62 trader_token.key,
63 global_vault.key,
64 &[],
65 amount_atoms,
66 mint.mint.decimals,
67 )?,
68 &[
69 token_program.as_ref().clone(),
70 trader_token.as_ref().clone(),
71 mint.as_ref().clone(),
72 global_vault.as_ref().clone(),
73 ],
74 global_vault_seeds_with_bump!(mint.info.key, bump),
75 )?;
76 } else {
77 invoke_signed(
78 &spl_token::instruction::transfer(
79 token_program.key,
80 global_vault.key,
81 trader_token.key,
82 global_vault.key,
83 &[],
84 amount_atoms,
85 )?,
86 &[
87 token_program.as_ref().clone(),
88 global_vault.as_ref().clone(),
89 trader_token.as_ref().clone(),
90 ],
91 global_vault_seeds_with_bump!(mint.info.key, bump),
92 )?;
93 }
94
95 emit_stack(GlobalWithdrawLog {
96 global: *global.key,
97 trader: *payer.key,
98 global_atoms: GlobalAtoms::new(amount_atoms),
99 })?;
100
101 Ok(())
102}