1use {
4 crate::{
5 extension::{
6 confidential_mint_burn, confidential_transfer, confidential_transfer_fee,
7 cpi_guard::{self, in_cpi},
8 default_account_state, group_member_pointer, group_pointer, interest_bearing_mint,
9 memo_transfer::{self, check_previous_sibling_instruction_is_memo},
10 metadata_pointer, pausable, permissioned_burn, reallocate, scaled_ui_amount,
11 token_group, token_metadata, transfer_fee, transfer_hook,
12 },
13 pod_instruction::{
14 decode_instruction_data_with_coption_pubkey, decode_instruction_data_with_coption_u64,
15 AmountCheckedData, AmountData, InitializeMintData, InitializeMultisigData,
16 PodTokenInstruction, SetAuthorityData,
17 },
18 },
19 solana_account_info::{next_account_info, AccountInfo},
20 solana_address::Address,
21 solana_clock::Clock,
22 solana_cpi::{invoke, invoke_signed, set_return_data},
23 solana_msg::msg,
24 solana_program_error::{ProgramError, ProgramResult},
25 solana_program_pack::Pack,
26 solana_rent::Rent,
27 solana_sdk_ids::system_program,
28 solana_system_interface::instruction as system_instruction,
29 solana_sysvar::{Sysvar, SysvarSerialize},
30 solana_zero_copy::unaligned::U64,
31 spl_token_2022_interface::{
32 check_program_account,
33 error::TokenError,
34 extension::{
35 confidential_mint_burn::ConfidentialMintBurn,
36 confidential_transfer::{ConfidentialTransferAccount, ConfidentialTransferMint},
37 confidential_transfer_fee::{
38 ConfidentialTransferFeeAmount, ConfidentialTransferFeeConfig,
39 },
40 cpi_guard::CpiGuard,
41 default_account_state::DefaultAccountState,
42 group_member_pointer::GroupMemberPointer,
43 group_pointer::GroupPointer,
44 immutable_owner::ImmutableOwner,
45 interest_bearing_mint::InterestBearingConfig,
46 memo_transfer::memo_required,
47 metadata_pointer::MetadataPointer,
48 mint_close_authority::MintCloseAuthority,
49 non_transferable::{NonTransferable, NonTransferableAccount},
50 pausable::{PausableAccount, PausableConfig},
51 permanent_delegate::{get_permanent_delegate, PermanentDelegate},
52 permissioned_burn::PermissionedBurnConfig,
53 scaled_ui_amount::ScaledUiAmountConfig,
54 transfer_fee::{TransferFeeAmount, TransferFeeConfig},
55 transfer_hook::{TransferHook, TransferHookAccount},
56 AccountType, BaseStateWithExtensions, BaseStateWithExtensionsMut, ExtensionType,
57 PodStateWithExtensions, PodStateWithExtensionsMut,
58 },
59 inline_spl_token,
60 instruction::{
61 decode_instruction_data, decode_instruction_type, is_valid_signer_index, AuthorityType,
62 MAX_SIGNERS,
63 },
64 native_mint,
65 pod::{PodAccount, PodCOption, PodMint, PodMultisig},
66 state::{Account, AccountState, Mint, PackedSizeOf},
67 },
68 spl_token_group_interface::instruction::TokenGroupInstruction,
69 spl_token_metadata_interface::instruction::TokenMetadataInstruction,
70 std::convert::{TryFrom, TryInto},
71};
72
73pub(crate) enum TransferInstruction {
74 Unchecked,
75 Checked { decimals: u8 },
76 CheckedWithFee { decimals: u8, fee: u64 },
77}
78
79pub(crate) enum InstructionVariant {
80 Unchecked,
81 Checked { decimals: u8 },
82}
83
84pub(crate) enum BurnInstructionVariant {
89 Standard,
90 Permissioned,
91}
92
93pub struct Processor {}
95impl Processor {
96 fn _process_initialize_mint(
97 accounts: &[AccountInfo],
98 decimals: u8,
99 mint_authority: &Address,
100 freeze_authority: PodCOption<Address>,
101 rent_sysvar_account: bool,
102 ) -> ProgramResult {
103 let account_info_iter = &mut accounts.iter();
104 let mint_info = next_account_info(account_info_iter)?;
105 let mint_data_len = mint_info.data_len();
106 let mut mint_data = mint_info.data.borrow_mut();
107
108 check_program_account(mint_info.owner)?;
109
110 let rent = if rent_sysvar_account {
111 Rent::from_account_info(next_account_info(account_info_iter)?)?
112 } else {
113 Rent::get()?
114 };
115
116 if !rent.is_exempt(mint_info.lamports(), mint_data_len) {
117 return Err(TokenError::NotRentExempt.into());
118 }
119
120 let mut mint = PodStateWithExtensionsMut::<PodMint>::unpack_uninitialized(&mut mint_data)?;
121 let extension_types = mint.get_extension_types()?;
122 if ExtensionType::try_calculate_account_len::<Mint>(&extension_types)? != mint_data_len {
123 return Err(ProgramError::InvalidAccountData);
124 }
125 ExtensionType::check_for_invalid_mint_extension_combinations(&extension_types)?;
126
127 if let Ok(default_account_state) = mint.get_extension_mut::<DefaultAccountState>() {
128 let default_account_state = AccountState::try_from(default_account_state.state)
129 .or(Err(ProgramError::InvalidAccountData))?;
130 if default_account_state == AccountState::Frozen && freeze_authority.is_none() {
131 return Err(TokenError::MintCannotFreeze.into());
132 }
133 }
134
135 mint.base.mint_authority = PodCOption::some(*mint_authority);
136 mint.base.decimals = decimals;
137 mint.base.is_initialized = true.into();
138 mint.base.freeze_authority = freeze_authority;
139 mint.init_account_type()?;
140
141 Ok(())
142 }
143
144 pub fn process_initialize_mint(
146 accounts: &[AccountInfo],
147 decimals: u8,
148 mint_authority: &Address,
149 freeze_authority: PodCOption<Address>,
150 ) -> ProgramResult {
151 Self::_process_initialize_mint(accounts, decimals, mint_authority, freeze_authority, true)
152 }
153
154 pub fn process_initialize_mint2(
157 accounts: &[AccountInfo],
158 decimals: u8,
159 mint_authority: &Address,
160 freeze_authority: PodCOption<Address>,
161 ) -> ProgramResult {
162 Self::_process_initialize_mint(accounts, decimals, mint_authority, freeze_authority, false)
163 }
164
165 fn _process_initialize_account(
166 accounts: &[AccountInfo],
167 owner: Option<&Address>,
168 rent_sysvar_account: bool,
169 ) -> ProgramResult {
170 let account_info_iter = &mut accounts.iter();
171 let new_account_info = next_account_info(account_info_iter)?;
172 let mint_info = next_account_info(account_info_iter)?;
173
174 check_program_account(new_account_info.owner)?;
175 check_program_account(mint_info.owner)?;
176
177 let owner = if let Some(owner) = owner {
178 owner
179 } else {
180 next_account_info(account_info_iter)?.key
181 };
182 let new_account_info_data_len = new_account_info.data_len();
183 let rent = if rent_sysvar_account {
184 Rent::from_account_info(next_account_info(account_info_iter)?)?
185 } else {
186 Rent::get()?
187 };
188
189 let mut account_data = new_account_info.data.borrow_mut();
190 let mut account =
192 PodStateWithExtensionsMut::<PodAccount>::unpack_uninitialized(&mut account_data)?;
193
194 if !rent.is_exempt(new_account_info.lamports(), new_account_info_data_len) {
195 return Err(TokenError::NotRentExempt.into());
196 }
197
198 let mint_data = mint_info.data.borrow();
200 let mint = PodStateWithExtensions::<PodMint>::unpack(&mint_data)
201 .map_err(|_| Into::<ProgramError>::into(TokenError::InvalidMint))?;
202 if mint
203 .get_extension::<PermanentDelegate>()
204 .map(|e| Option::<Address>::from(e.delegate).is_some())
205 .unwrap_or(false)
206 {
207 msg!("Warning: Mint has a permanent delegate, so tokens in this account may be seized at any time");
208 }
209 let required_extensions =
210 Self::get_required_account_extensions_from_unpacked_mint(mint_info.owner, &mint)?;
211 if ExtensionType::try_calculate_account_len::<Account>(&required_extensions)?
212 > new_account_info_data_len
213 {
214 return Err(ProgramError::InvalidAccountData);
215 }
216 for extension in required_extensions {
217 account.init_account_extension_from_type(extension)?;
218 }
219
220 let starting_state =
221 if let Ok(default_account_state) = mint.get_extension::<DefaultAccountState>() {
222 AccountState::try_from(default_account_state.state)
223 .or(Err(ProgramError::InvalidAccountData))?
224 } else {
225 AccountState::Initialized
226 };
227
228 account.base.mint = *mint_info.key;
229 account.base.owner = *owner;
230 account.base.close_authority = PodCOption::none();
231 account.base.delegate = PodCOption::none();
232 account.base.delegated_amount = 0.into();
233 account.base.state = starting_state.into();
234 if mint_info.key == &native_mint::id() {
235 let rent_exempt_reserve = rent.minimum_balance(new_account_info_data_len);
236 account.base.is_native = PodCOption::some(rent_exempt_reserve.into());
237 account.base.amount = new_account_info
238 .lamports()
239 .checked_sub(rent_exempt_reserve)
240 .ok_or(TokenError::Overflow)?
241 .into();
242 } else {
243 account.base.is_native = PodCOption::none();
244 account.base.amount = 0.into();
245 };
246
247 account.init_account_type()?;
248
249 Ok(())
250 }
251
252 pub fn process_initialize_account(accounts: &[AccountInfo]) -> ProgramResult {
255 Self::_process_initialize_account(accounts, None, true)
256 }
257
258 pub fn process_initialize_account2(accounts: &[AccountInfo], owner: &Address) -> ProgramResult {
261 Self::_process_initialize_account(accounts, Some(owner), true)
262 }
263
264 pub fn process_initialize_account3(accounts: &[AccountInfo], owner: &Address) -> ProgramResult {
267 Self::_process_initialize_account(accounts, Some(owner), false)
268 }
269
270 fn _process_initialize_multisig(
271 accounts: &[AccountInfo],
272 m: u8,
273 rent_sysvar_account: bool,
274 ) -> ProgramResult {
275 let account_info_iter = &mut accounts.iter();
276 let multisig_info = next_account_info(account_info_iter)?;
277
278 check_program_account(multisig_info.owner)?;
279
280 let multisig_info_data_len = multisig_info.data_len();
281 let rent = if rent_sysvar_account {
282 Rent::from_account_info(next_account_info(account_info_iter)?)?
283 } else {
284 Rent::get()?
285 };
286
287 let mut multisig_data = multisig_info.data.borrow_mut();
288 let multisig = bytemuck::try_from_bytes_mut::<PodMultisig>(&mut multisig_data)
289 .map_err(|_| ProgramError::InvalidArgument)?;
290 if bool::from(multisig.is_initialized) {
291 return Err(TokenError::AlreadyInUse.into());
292 }
293
294 if !rent.is_exempt(multisig_info.lamports(), multisig_info_data_len) {
295 return Err(TokenError::NotRentExempt.into());
296 }
297
298 let signer_infos = account_info_iter.as_slice();
299 multisig.m = m;
300 multisig.n = signer_infos.len() as u8;
301 if !is_valid_signer_index(multisig.n as usize) {
302 return Err(TokenError::InvalidNumberOfProvidedSigners.into());
303 }
304 if !is_valid_signer_index(multisig.m as usize) {
305 return Err(TokenError::InvalidNumberOfRequiredSigners.into());
306 }
307 for (i, signer_info) in signer_infos.iter().enumerate() {
308 multisig.signers[i] = *signer_info.key;
309 }
310 multisig.is_initialized = true.into();
311
312 Ok(())
313 }
314
315 pub fn process_initialize_multisig(accounts: &[AccountInfo], m: u8) -> ProgramResult {
318 Self::_process_initialize_multisig(accounts, m, true)
319 }
320
321 pub fn process_initialize_multisig2(accounts: &[AccountInfo], m: u8) -> ProgramResult {
324 Self::_process_initialize_multisig(accounts, m, false)
325 }
326
327 pub(crate) fn process_transfer(
329 program_id: &Address,
330 accounts: &[AccountInfo],
331 amount: u64,
332 transfer_instruction: TransferInstruction,
333 ) -> ProgramResult {
334 let account_info_iter = &mut accounts.iter();
335
336 let source_account_info = next_account_info(account_info_iter)?;
337
338 let expected_mint_info = match transfer_instruction {
339 TransferInstruction::Unchecked => None,
340 TransferInstruction::Checked { decimals }
341 | TransferInstruction::CheckedWithFee { decimals, .. } => {
342 Some((next_account_info(account_info_iter)?, decimals))
343 }
344 };
345
346 let destination_account_info = next_account_info(account_info_iter)?;
347 let authority_info = next_account_info(account_info_iter)?;
348 let authority_info_data_len = authority_info.data_len();
349
350 check_program_account(source_account_info.owner)?;
351 check_program_account(destination_account_info.owner)?;
352
353 let mut source_account_data = source_account_info.data.borrow_mut();
354 let mut source_account =
355 PodStateWithExtensionsMut::<PodAccount>::unpack(&mut source_account_data)?;
356 if source_account.base.is_frozen() {
357 return Err(TokenError::AccountFrozen.into());
358 }
359 let source_amount = u64::from(source_account.base.amount);
360 if source_amount < amount {
361 return Err(TokenError::InsufficientFunds.into());
362 }
363 if source_account
364 .get_extension::<NonTransferableAccount>()
365 .is_ok()
366 {
367 return Err(TokenError::NonTransferable.into());
368 }
369
370 let (calculated_fee, maybe_permanent_delegate, maybe_transfer_hook_program_id) =
371 if let Some((mint_info, expected_decimals)) = expected_mint_info {
372 check_program_account(mint_info.owner)?;
373
374 if &source_account.base.mint != mint_info.key {
375 return Err(TokenError::MintMismatch.into());
376 }
377
378 let mint_data = mint_info.try_borrow_data()?;
379 let mint = PodStateWithExtensions::<PodMint>::unpack(&mint_data)?;
380
381 if expected_decimals != mint.base.decimals {
382 return Err(TokenError::MintDecimalsMismatch.into());
383 }
384
385 let fee = if let Ok(transfer_fee_config) = mint.get_extension::<TransferFeeConfig>()
386 {
387 transfer_fee_config
388 .calculate_epoch_fee(Clock::get()?.epoch, amount)
389 .ok_or(TokenError::Overflow)?
390 } else {
391 0
392 };
393
394 if let Ok(extension) = mint.get_extension::<PausableConfig>() {
395 if extension.paused.into() {
396 return Err(TokenError::MintPaused.into());
397 }
398 }
399
400 let maybe_permanent_delegate = get_permanent_delegate(&mint);
401 let maybe_transfer_hook_program_id = transfer_hook::get_program_id(&mint);
402
403 (
404 fee,
405 maybe_permanent_delegate,
406 maybe_transfer_hook_program_id,
407 )
408 } else {
409 if source_account
412 .get_extension::<TransferHookAccount>()
413 .is_ok()
414 {
415 return Err(TokenError::MintRequiredForTransfer.into());
416 }
417
418 if source_account
421 .get_extension_mut::<TransferFeeAmount>()
422 .is_ok()
423 {
424 return Err(TokenError::MintRequiredForTransfer.into());
425 }
426
427 if source_account.get_extension::<PausableAccount>().is_ok() {
430 return Err(TokenError::MintRequiredForTransfer.into());
431 }
432
433 (0, None, None)
434 };
435 if let TransferInstruction::CheckedWithFee { fee, .. } = transfer_instruction {
436 if calculated_fee != fee {
437 msg!("Calculated fee {calculated_fee}, received {fee}");
438 return Err(TokenError::FeeMismatch.into());
439 }
440 }
441
442 let self_transfer = source_account_info.key == destination_account_info.key;
443 if let Ok(cpi_guard) = source_account.get_extension::<CpiGuard>() {
444 if *authority_info.key == source_account.base.owner
449 && cpi_guard.lock_cpi.into()
450 && in_cpi()
451 {
452 return Err(TokenError::CpiGuardTransferBlocked.into());
453 }
454 }
455 match (source_account.base.delegate, maybe_permanent_delegate) {
456 (_, Some(ref delegate)) if authority_info.key == delegate => Self::validate_owner(
457 program_id,
458 delegate,
459 authority_info,
460 authority_info_data_len,
461 account_info_iter.as_slice(),
462 )?,
463 (
464 PodCOption {
465 option: PodCOption::<Address>::SOME,
466 value: delegate,
467 },
468 _,
469 ) if authority_info.key == &delegate => {
470 Self::validate_owner(
471 program_id,
472 &delegate,
473 authority_info,
474 authority_info_data_len,
475 account_info_iter.as_slice(),
476 )?;
477 let delegated_amount = u64::from(source_account.base.delegated_amount);
478 if delegated_amount < amount {
479 return Err(TokenError::InsufficientFunds.into());
480 }
481 if !self_transfer {
482 source_account.base.delegated_amount = delegated_amount
483 .checked_sub(amount)
484 .ok_or(TokenError::Overflow)?
485 .into();
486 if u64::from(source_account.base.delegated_amount) == 0 {
487 source_account.base.delegate = PodCOption::none();
488 }
489 }
490 }
491 _ => {
492 Self::validate_owner(
493 program_id,
494 &source_account.base.owner,
495 authority_info,
496 authority_info_data_len,
497 account_info_iter.as_slice(),
498 )?;
499 }
500 }
501
502 if self_transfer {
505 if memo_required(&source_account) {
506 check_previous_sibling_instruction_is_memo()?;
507 }
508 return Ok(());
509 }
510
511 let mut destination_account_data = destination_account_info.data.borrow_mut();
513 let mut destination_account =
514 PodStateWithExtensionsMut::<PodAccount>::unpack(&mut destination_account_data)?;
515
516 if destination_account.base.is_frozen() {
517 return Err(TokenError::AccountFrozen.into());
518 }
519 if source_account.base.mint != destination_account.base.mint {
520 return Err(TokenError::MintMismatch.into());
521 }
522
523 if memo_required(&destination_account) {
524 check_previous_sibling_instruction_is_memo()?;
525 }
526
527 if let Ok(confidential_transfer_state) =
528 destination_account.get_extension::<ConfidentialTransferAccount>()
529 {
530 confidential_transfer_state.non_confidential_transfer_allowed()?
531 }
532
533 source_account.base.amount = source_amount
534 .checked_sub(amount)
535 .ok_or(TokenError::Overflow)?
536 .into();
537 let credited_amount = amount
538 .checked_sub(calculated_fee)
539 .ok_or(TokenError::Overflow)?;
540 destination_account.base.amount = u64::from(destination_account.base.amount)
541 .checked_add(credited_amount)
542 .ok_or(TokenError::Overflow)?
543 .into();
544 if calculated_fee > 0 {
545 if let Ok(extension) = destination_account.get_extension_mut::<TransferFeeAmount>() {
546 let new_withheld_amount = u64::from(extension.withheld_amount)
547 .checked_add(calculated_fee)
548 .ok_or(TokenError::Overflow)?;
549 extension.withheld_amount = new_withheld_amount.into();
550 } else {
551 return Err(TokenError::InvalidState.into());
555 }
556 }
557
558 if source_account.base.is_native() {
559 let source_starting_lamports = source_account_info.lamports();
560 **source_account_info.lamports.borrow_mut() = source_starting_lamports
561 .checked_sub(amount)
562 .ok_or(TokenError::Overflow)?;
563
564 let destination_starting_lamports = destination_account_info.lamports();
565 **destination_account_info.lamports.borrow_mut() = destination_starting_lamports
566 .checked_add(amount)
567 .ok_or(TokenError::Overflow)?;
568 }
569
570 if let Some(program_id) = maybe_transfer_hook_program_id {
571 if let Some((mint_info, _)) = expected_mint_info {
572 transfer_hook::set_transferring(&mut source_account)?;
574 transfer_hook::set_transferring(&mut destination_account)?;
575
576 drop(source_account_data);
578 drop(destination_account_data);
579 spl_transfer_hook_interface::onchain::invoke_execute(
580 &program_id,
581 source_account_info.clone(),
582 mint_info.clone(),
583 destination_account_info.clone(),
584 authority_info.clone(),
585 account_info_iter.as_slice(),
586 amount,
587 )?;
588
589 transfer_hook::unset_transferring(source_account_info)?;
591 transfer_hook::unset_transferring(destination_account_info)?;
592 } else {
593 return Err(TokenError::MintRequiredForTransfer.into());
594 }
595 }
596
597 Ok(())
598 }
599
600 pub(crate) fn process_approve(
602 program_id: &Address,
603 accounts: &[AccountInfo],
604 amount: u64,
605 instruction_variant: InstructionVariant,
606 ) -> ProgramResult {
607 let account_info_iter = &mut accounts.iter();
608
609 let source_account_info = next_account_info(account_info_iter)?;
610
611 check_program_account(source_account_info.owner)?;
612
613 let expected_mint_info =
614 if let InstructionVariant::Checked { decimals } = instruction_variant {
615 Some((next_account_info(account_info_iter)?, decimals))
616 } else {
617 None
618 };
619 let delegate_info = next_account_info(account_info_iter)?;
620 let owner_info = next_account_info(account_info_iter)?;
621 let owner_info_data_len = owner_info.data_len();
622
623 let mut source_account_data = source_account_info.data.borrow_mut();
624 let source_account =
625 PodStateWithExtensionsMut::<PodAccount>::unpack(&mut source_account_data)?;
626
627 if source_account.base.is_frozen() {
628 return Err(TokenError::AccountFrozen.into());
629 }
630
631 if let Some((mint_info, expected_decimals)) = expected_mint_info {
632 check_program_account(mint_info.owner)?;
633
634 if &source_account.base.mint != mint_info.key {
635 return Err(TokenError::MintMismatch.into());
636 }
637
638 let mint_data = mint_info.data.borrow();
639 let mint = PodStateWithExtensions::<PodMint>::unpack(&mint_data)?;
640 if expected_decimals != mint.base.decimals {
641 return Err(TokenError::MintDecimalsMismatch.into());
642 }
643 }
644
645 Self::validate_owner(
646 program_id,
647 &source_account.base.owner,
648 owner_info,
649 owner_info_data_len,
650 account_info_iter.as_slice(),
651 )?;
652
653 if let Ok(cpi_guard) = source_account.get_extension::<CpiGuard>() {
654 if cpi_guard.lock_cpi.into() && in_cpi() {
655 return Err(TokenError::CpiGuardApproveBlocked.into());
656 }
657 }
658
659 source_account.base.delegate = PodCOption::some(*delegate_info.key);
660 source_account.base.delegated_amount = amount.into();
661
662 Ok(())
663 }
664
665 pub fn process_revoke(program_id: &Address, accounts: &[AccountInfo]) -> ProgramResult {
667 let account_info_iter = &mut accounts.iter();
668 let source_account_info = next_account_info(account_info_iter)?;
669 let authority_info = next_account_info(account_info_iter)?;
670 let authority_info_data_len = authority_info.data_len();
671
672 check_program_account(source_account_info.owner)?;
673
674 let mut source_account_data = source_account_info.data.borrow_mut();
675 let source_account =
676 PodStateWithExtensionsMut::<PodAccount>::unpack(&mut source_account_data)?;
677 if source_account.base.is_frozen() {
678 return Err(TokenError::AccountFrozen.into());
679 }
680
681 Self::validate_owner(
682 program_id,
683 match &source_account.base.delegate {
684 PodCOption {
685 option: PodCOption::<Address>::SOME,
686 value: delegate,
687 } if authority_info.key == delegate => delegate,
688 _ => &source_account.base.owner,
689 },
690 authority_info,
691 authority_info_data_len,
692 account_info_iter.as_slice(),
693 )?;
694
695 source_account.base.delegate = PodCOption::none();
696 source_account.base.delegated_amount = 0.into();
697
698 Ok(())
699 }
700
701 pub fn process_set_authority(
703 program_id: &Address,
704 accounts: &[AccountInfo],
705 authority_type: AuthorityType,
706 new_authority: PodCOption<Address>,
707 ) -> ProgramResult {
708 let account_info_iter = &mut accounts.iter();
709 let account_info = next_account_info(account_info_iter)?;
710 let authority_info = next_account_info(account_info_iter)?;
711 let authority_info_data_len = authority_info.data_len();
712
713 check_program_account(account_info.owner)?;
714
715 let mut account_data = account_info.data.borrow_mut();
716 if let Ok(mut account) = PodStateWithExtensionsMut::<PodAccount>::unpack(&mut account_data)
717 {
718 if account.base.is_frozen() {
719 return Err(TokenError::AccountFrozen.into());
720 }
721
722 match authority_type {
723 AuthorityType::AccountOwner => {
724 Self::validate_owner(
725 program_id,
726 &account.base.owner,
727 authority_info,
728 authority_info_data_len,
729 account_info_iter.as_slice(),
730 )?;
731
732 if account.get_extension_mut::<ImmutableOwner>().is_ok() {
733 return Err(TokenError::ImmutableOwner.into());
734 }
735
736 if let Ok(cpi_guard) = account.get_extension::<CpiGuard>() {
737 if cpi_guard.lock_cpi.into() && in_cpi() {
738 return Err(TokenError::CpiGuardSetAuthorityBlocked.into());
739 } else if cpi_guard.lock_cpi.into() {
740 return Err(TokenError::CpiGuardOwnerChangeBlocked.into());
741 }
742 }
743
744 if let PodCOption {
745 option: PodCOption::<Address>::SOME,
746 value: authority,
747 } = new_authority
748 {
749 account.base.owner = authority;
750 } else {
751 return Err(TokenError::InvalidInstruction.into());
752 }
753
754 account.base.delegate = PodCOption::none();
755 account.base.delegated_amount = 0.into();
756
757 if account.base.is_native() {
758 account.base.close_authority = PodCOption::none();
759 }
760 }
761 AuthorityType::CloseAccount => {
762 let authority = account.base.close_authority.unwrap_or(account.base.owner);
763 Self::validate_owner(
764 program_id,
765 &authority,
766 authority_info,
767 authority_info_data_len,
768 account_info_iter.as_slice(),
769 )?;
770
771 if let Ok(cpi_guard) = account.get_extension::<CpiGuard>() {
772 if cpi_guard.lock_cpi.into() && in_cpi() && new_authority.is_some() {
773 return Err(TokenError::CpiGuardSetAuthorityBlocked.into());
774 }
775 }
776
777 account.base.close_authority = new_authority;
778 }
779 _ => {
780 return Err(TokenError::AuthorityTypeNotSupported.into());
781 }
782 }
783 } else if let Ok(mut mint) = PodStateWithExtensionsMut::<PodMint>::unpack(&mut account_data)
784 {
785 match authority_type {
786 AuthorityType::MintTokens => {
787 let mint_authority = mint
790 .base
791 .mint_authority
792 .ok_or(Into::<ProgramError>::into(TokenError::FixedSupply))?;
793 Self::validate_owner(
794 program_id,
795 &mint_authority,
796 authority_info,
797 authority_info_data_len,
798 account_info_iter.as_slice(),
799 )?;
800 mint.base.mint_authority = new_authority;
801 }
802 AuthorityType::FreezeAccount => {
803 let freeze_authority = mint
806 .base
807 .freeze_authority
808 .ok_or(Into::<ProgramError>::into(TokenError::MintCannotFreeze))?;
809 Self::validate_owner(
810 program_id,
811 &freeze_authority,
812 authority_info,
813 authority_info_data_len,
814 account_info_iter.as_slice(),
815 )?;
816 mint.base.freeze_authority = new_authority;
817 }
818 AuthorityType::CloseMint => {
819 let extension = mint.get_extension_mut::<MintCloseAuthority>()?;
820 let maybe_close_authority: Option<Address> = extension.close_authority.into();
821 let close_authority =
822 maybe_close_authority.ok_or(TokenError::AuthorityTypeNotSupported)?;
823 Self::validate_owner(
824 program_id,
825 &close_authority,
826 authority_info,
827 authority_info_data_len,
828 account_info_iter.as_slice(),
829 )?;
830 extension.close_authority = new_authority.try_into()?;
831 }
832 AuthorityType::TransferFeeConfig => {
833 let extension = mint.get_extension_mut::<TransferFeeConfig>()?;
834 let maybe_transfer_fee_config_authority: Option<Address> =
835 extension.transfer_fee_config_authority.into();
836 let transfer_fee_config_authority = maybe_transfer_fee_config_authority
837 .ok_or(TokenError::AuthorityTypeNotSupported)?;
838 Self::validate_owner(
839 program_id,
840 &transfer_fee_config_authority,
841 authority_info,
842 authority_info_data_len,
843 account_info_iter.as_slice(),
844 )?;
845 extension.transfer_fee_config_authority = new_authority.try_into()?;
846 }
847 AuthorityType::WithheldWithdraw => {
848 let extension = mint.get_extension_mut::<TransferFeeConfig>()?;
849 let maybe_withdraw_withheld_authority: Option<Address> =
850 extension.withdraw_withheld_authority.into();
851 let withdraw_withheld_authority = maybe_withdraw_withheld_authority
852 .ok_or(TokenError::AuthorityTypeNotSupported)?;
853 Self::validate_owner(
854 program_id,
855 &withdraw_withheld_authority,
856 authority_info,
857 authority_info_data_len,
858 account_info_iter.as_slice(),
859 )?;
860 extension.withdraw_withheld_authority = new_authority.try_into()?;
861 }
862 AuthorityType::InterestRate => {
863 let extension = mint.get_extension_mut::<InterestBearingConfig>()?;
864 let maybe_rate_authority: Option<Address> = extension.rate_authority.into();
865 let rate_authority =
866 maybe_rate_authority.ok_or(TokenError::AuthorityTypeNotSupported)?;
867 Self::validate_owner(
868 program_id,
869 &rate_authority,
870 authority_info,
871 authority_info_data_len,
872 account_info_iter.as_slice(),
873 )?;
874 extension.rate_authority = new_authority.try_into()?;
875 }
876 AuthorityType::PermanentDelegate => {
877 let extension = mint.get_extension_mut::<PermanentDelegate>()?;
878 let maybe_delegate: Option<Address> = extension.delegate.into();
879 let delegate = maybe_delegate.ok_or(TokenError::AuthorityTypeNotSupported)?;
880 Self::validate_owner(
881 program_id,
882 &delegate,
883 authority_info,
884 authority_info_data_len,
885 account_info_iter.as_slice(),
886 )?;
887 extension.delegate = new_authority.try_into()?;
888 }
889 AuthorityType::ConfidentialTransferMint => {
890 let extension = mint.get_extension_mut::<ConfidentialTransferMint>()?;
891 let maybe_confidential_transfer_mint_authority: Option<Address> =
892 extension.authority.into();
893 let confidential_transfer_mint_authority =
894 maybe_confidential_transfer_mint_authority
895 .ok_or(TokenError::AuthorityTypeNotSupported)?;
896 Self::validate_owner(
897 program_id,
898 &confidential_transfer_mint_authority,
899 authority_info,
900 authority_info_data_len,
901 account_info_iter.as_slice(),
902 )?;
903 extension.authority = new_authority.try_into()?;
904 }
905 AuthorityType::TransferHookProgramId => {
906 let extension = mint.get_extension_mut::<TransferHook>()?;
907 let maybe_authority: Option<Address> = extension.authority.into();
908 let authority = maybe_authority.ok_or(TokenError::AuthorityTypeNotSupported)?;
909 Self::validate_owner(
910 program_id,
911 &authority,
912 authority_info,
913 authority_info_data_len,
914 account_info_iter.as_slice(),
915 )?;
916 extension.authority = new_authority.try_into()?;
917 }
918 AuthorityType::ConfidentialTransferFeeConfig => {
919 let extension = mint.get_extension_mut::<ConfidentialTransferFeeConfig>()?;
920 let maybe_authority: Option<Address> = extension.authority.into();
921 let authority = maybe_authority.ok_or(TokenError::AuthorityTypeNotSupported)?;
922 Self::validate_owner(
923 program_id,
924 &authority,
925 authority_info,
926 authority_info_data_len,
927 account_info_iter.as_slice(),
928 )?;
929 extension.authority = new_authority.try_into()?;
930 }
931 AuthorityType::MetadataPointer => {
932 let extension = mint.get_extension_mut::<MetadataPointer>()?;
933 let maybe_authority: Option<Address> = extension.authority.into();
934 let authority = maybe_authority.ok_or(TokenError::AuthorityTypeNotSupported)?;
935 Self::validate_owner(
936 program_id,
937 &authority,
938 authority_info,
939 authority_info_data_len,
940 account_info_iter.as_slice(),
941 )?;
942 extension.authority = new_authority.try_into()?;
943 }
944 AuthorityType::GroupPointer => {
945 let extension = mint.get_extension_mut::<GroupPointer>()?;
946 let maybe_authority: Option<Address> = extension.authority.into();
947 let authority = maybe_authority.ok_or(TokenError::AuthorityTypeNotSupported)?;
948 Self::validate_owner(
949 program_id,
950 &authority,
951 authority_info,
952 authority_info_data_len,
953 account_info_iter.as_slice(),
954 )?;
955 extension.authority = new_authority.try_into()?;
956 }
957 AuthorityType::GroupMemberPointer => {
958 let extension = mint.get_extension_mut::<GroupMemberPointer>()?;
959 let maybe_authority: Option<Address> = extension.authority.into();
960 let authority = maybe_authority.ok_or(TokenError::AuthorityTypeNotSupported)?;
961 Self::validate_owner(
962 program_id,
963 &authority,
964 authority_info,
965 authority_info_data_len,
966 account_info_iter.as_slice(),
967 )?;
968 extension.authority = new_authority.try_into()?;
969 }
970 AuthorityType::ScaledUiAmount => {
971 let extension = mint.get_extension_mut::<ScaledUiAmountConfig>()?;
972 let maybe_authority: Option<Address> = extension.authority.into();
973 let authority = maybe_authority.ok_or(TokenError::AuthorityTypeNotSupported)?;
974 Self::validate_owner(
975 program_id,
976 &authority,
977 authority_info,
978 authority_info_data_len,
979 account_info_iter.as_slice(),
980 )?;
981 extension.authority = new_authority.try_into()?;
982 }
983 AuthorityType::Pause => {
984 let extension = mint.get_extension_mut::<PausableConfig>()?;
985 let maybe_authority: Option<Address> = extension.authority.into();
986 let authority = maybe_authority.ok_or(TokenError::AuthorityTypeNotSupported)?;
987 Self::validate_owner(
988 program_id,
989 &authority,
990 authority_info,
991 authority_info_data_len,
992 account_info_iter.as_slice(),
993 )?;
994 extension.authority = new_authority.try_into()?;
995 }
996 AuthorityType::PermissionedBurn => {
997 let extension = mint.get_extension_mut::<PermissionedBurnConfig>()?;
998 let maybe_authority: Option<Address> = extension.authority.into();
999 let authority = maybe_authority.ok_or(TokenError::AuthorityTypeNotSupported)?;
1000 Self::validate_owner(
1001 program_id,
1002 &authority,
1003 authority_info,
1004 authority_info_data_len,
1005 account_info_iter.as_slice(),
1006 )?;
1007 extension.authority = new_authority.try_into()?;
1008 }
1009 _ => {
1010 return Err(TokenError::AuthorityTypeNotSupported.into());
1011 }
1012 }
1013 } else {
1014 return Err(ProgramError::InvalidAccountData);
1015 }
1016
1017 Ok(())
1018 }
1019
1020 pub(crate) fn process_mint_to(
1022 program_id: &Address,
1023 accounts: &[AccountInfo],
1024 amount: u64,
1025 instruction_variant: InstructionVariant,
1026 ) -> ProgramResult {
1027 let account_info_iter = &mut accounts.iter();
1028 let mint_info = next_account_info(account_info_iter)?;
1029 let destination_account_info = next_account_info(account_info_iter)?;
1030 let owner_info = next_account_info(account_info_iter)?;
1031 let owner_info_data_len = owner_info.data_len();
1032
1033 check_program_account(mint_info.owner)?;
1034 check_program_account(destination_account_info.owner)?;
1035
1036 let mut destination_account_data = destination_account_info.data.borrow_mut();
1037 let destination_account =
1038 PodStateWithExtensionsMut::<PodAccount>::unpack(&mut destination_account_data)?;
1039 if destination_account.base.is_frozen() {
1040 return Err(TokenError::AccountFrozen.into());
1041 }
1042
1043 if destination_account.base.is_native() {
1044 return Err(TokenError::NativeNotSupported.into());
1045 }
1046 if mint_info.key != &destination_account.base.mint {
1047 return Err(TokenError::MintMismatch.into());
1048 }
1049
1050 let mut mint_data = mint_info.data.borrow_mut();
1051 let mint = PodStateWithExtensionsMut::<PodMint>::unpack(&mut mint_data)?;
1052
1053 if mint.get_extension::<NonTransferable>().is_ok()
1056 && (destination_account
1057 .get_extension::<ImmutableOwner>()
1058 .is_err()
1059 || destination_account
1060 .get_extension::<NonTransferableAccount>()
1061 .is_err())
1062 {
1063 return Err(TokenError::NonTransferableNeedsImmutableOwnership.into());
1068 }
1069
1070 if let Ok(extension) = mint.get_extension::<PausableConfig>() {
1071 if extension.paused.into() {
1072 return Err(TokenError::MintPaused.into());
1073 }
1074 }
1075
1076 if mint.get_extension::<ConfidentialMintBurn>().is_ok() {
1077 return Err(TokenError::IllegalMintBurnConversion.into());
1078 }
1079
1080 if let InstructionVariant::Checked { decimals } = instruction_variant {
1081 if decimals != mint.base.decimals {
1082 return Err(TokenError::MintDecimalsMismatch.into());
1083 }
1084 }
1085
1086 match &mint.base.mint_authority {
1087 PodCOption {
1088 option: PodCOption::<Address>::SOME,
1089 value: mint_authority,
1090 } => Self::validate_owner(
1091 program_id,
1092 mint_authority,
1093 owner_info,
1094 owner_info_data_len,
1095 account_info_iter.as_slice(),
1096 )?,
1097 _ => return Err(TokenError::FixedSupply.into()),
1098 }
1099
1100 destination_account.base.amount = u64::from(destination_account.base.amount)
1101 .checked_add(amount)
1102 .ok_or(TokenError::Overflow)?
1103 .into();
1104
1105 mint.base.supply = u64::from(mint.base.supply)
1106 .checked_add(amount)
1107 .ok_or(TokenError::Overflow)?
1108 .into();
1109
1110 Ok(())
1111 }
1112
1113 pub(crate) fn process_burn(
1115 program_id: &Address,
1116 accounts: &[AccountInfo],
1117 amount: u64,
1118 burn_variant: BurnInstructionVariant,
1119 instruction_variant: InstructionVariant,
1120 ) -> ProgramResult {
1121 let account_info_iter = &mut accounts.iter();
1122
1123 let source_account_info = next_account_info(account_info_iter)?;
1124 let mint_info = next_account_info(account_info_iter)?;
1125
1126 check_program_account(source_account_info.owner)?;
1127 check_program_account(mint_info.owner)?;
1128
1129 let (permissioned_burn_authority_info, authority_info) = match burn_variant {
1130 BurnInstructionVariant::Permissioned => {
1131 let permissioned_burn_authority_info = next_account_info(account_info_iter)?;
1132 let authority_info = next_account_info(account_info_iter)?;
1133 (Some(permissioned_burn_authority_info), authority_info)
1134 }
1135 BurnInstructionVariant::Standard => (None, next_account_info(account_info_iter)?),
1136 };
1137
1138 let authority_info_data_len = authority_info.data_len();
1139
1140 let mut mint_data = mint_info.data.borrow_mut();
1141 let mint = PodStateWithExtensionsMut::<PodMint>::unpack(&mut mint_data)?;
1142
1143 let permissioned_ext = mint.get_extension::<PermissionedBurnConfig>();
1144 let maybe_permissioned_burn_authority = permissioned_ext
1145 .as_ref()
1146 .ok()
1147 .and_then(|ext| Option::<Address>::from(ext.authority));
1148
1149 match burn_variant {
1150 BurnInstructionVariant::Standard => {
1151 if maybe_permissioned_burn_authority.is_some() {
1154 return Err(TokenError::InvalidInstruction.into());
1155 }
1156 }
1157 BurnInstructionVariant::Permissioned => {
1158 permissioned_ext.map_err(|_| TokenError::InvalidInstruction)?;
1159
1160 let expected_burn_authority =
1161 maybe_permissioned_burn_authority.ok_or_else(|| {
1162 msg!("Permissioned burn authority is None; use the standard burn");
1163 TokenError::InvalidInstruction
1164 })?;
1165
1166 let approver_ai =
1168 permissioned_burn_authority_info.ok_or(ProgramError::NotEnoughAccountKeys)?;
1169
1170 if !approver_ai.is_signer {
1171 return Err(ProgramError::MissingRequiredSignature);
1172 }
1173
1174 if *approver_ai.key != expected_burn_authority {
1175 return Err(ProgramError::InvalidAccountData);
1176 }
1177 }
1178 }
1179
1180 let mut source_account_data = source_account_info.data.borrow_mut();
1181 let source_account =
1182 PodStateWithExtensionsMut::<PodAccount>::unpack(&mut source_account_data)?;
1183
1184 if source_account.base.is_frozen() {
1185 return Err(TokenError::AccountFrozen.into());
1186 }
1187 if source_account.base.is_native() {
1188 return Err(TokenError::NativeNotSupported.into());
1189 }
1190 if u64::from(source_account.base.amount) < amount {
1191 return Err(TokenError::InsufficientFunds.into());
1192 }
1193 if mint_info.key != &source_account.base.mint {
1194 return Err(TokenError::MintMismatch.into());
1195 }
1196
1197 if let InstructionVariant::Checked { decimals } = instruction_variant {
1198 if decimals != mint.base.decimals {
1199 return Err(TokenError::MintDecimalsMismatch.into());
1200 }
1201 }
1202 if let Ok(extension) = mint.get_extension::<PausableConfig>() {
1203 if extension.paused.into() {
1204 return Err(TokenError::MintPaused.into());
1205 }
1206 }
1207
1208 if mint.get_extension::<ConfidentialMintBurn>().is_ok() {
1209 return Err(TokenError::IllegalMintBurnConversion.into());
1210 }
1211
1212 let maybe_permanent_delegate = get_permanent_delegate(&mint);
1213
1214 if let Ok(cpi_guard) = source_account.get_extension::<CpiGuard>() {
1215 if *authority_info.key == source_account.base.owner
1220 && cpi_guard.lock_cpi.into()
1221 && in_cpi()
1222 {
1223 return Err(TokenError::CpiGuardBurnBlocked.into());
1224 }
1225 }
1226
1227 if !source_account
1228 .base
1229 .is_owned_by_system_program_or_incinerator()
1230 {
1231 match (&source_account.base.delegate, maybe_permanent_delegate) {
1232 (_, Some(ref delegate)) if authority_info.key == delegate => Self::validate_owner(
1233 program_id,
1234 delegate,
1235 authority_info,
1236 authority_info_data_len,
1237 account_info_iter.as_slice(),
1238 )?,
1239 (
1240 PodCOption {
1241 option: PodCOption::<Address>::SOME,
1242 value: delegate,
1243 },
1244 _,
1245 ) if authority_info.key == delegate => {
1246 Self::validate_owner(
1247 program_id,
1248 delegate,
1249 authority_info,
1250 authority_info_data_len,
1251 account_info_iter.as_slice(),
1252 )?;
1253
1254 if u64::from(source_account.base.delegated_amount) < amount {
1255 return Err(TokenError::InsufficientFunds.into());
1256 }
1257 source_account.base.delegated_amount =
1258 u64::from(source_account.base.delegated_amount)
1259 .checked_sub(amount)
1260 .ok_or(TokenError::Overflow)?
1261 .into();
1262 if u64::from(source_account.base.delegated_amount) == 0 {
1263 source_account.base.delegate = PodCOption::none();
1264 }
1265 }
1266 _ => {
1267 Self::validate_owner(
1268 program_id,
1269 &source_account.base.owner,
1270 authority_info,
1271 authority_info_data_len,
1272 account_info_iter.as_slice(),
1273 )?;
1274 }
1275 }
1276 }
1277
1278 source_account.base.amount = u64::from(source_account.base.amount)
1279 .checked_sub(amount)
1280 .ok_or(TokenError::Overflow)?
1281 .into();
1282 mint.base.supply = u64::from(mint.base.supply)
1283 .checked_sub(amount)
1284 .ok_or(TokenError::Overflow)?
1285 .into();
1286
1287 Ok(())
1288 }
1289
1290 pub fn process_close_account(program_id: &Address, accounts: &[AccountInfo]) -> ProgramResult {
1292 let account_info_iter = &mut accounts.iter();
1293 let source_account_info = next_account_info(account_info_iter)?;
1294 let destination_account_info = next_account_info(account_info_iter)?;
1295 let authority_info = next_account_info(account_info_iter)?;
1296 let authority_info_data_len = authority_info.data_len();
1297
1298 check_program_account(source_account_info.owner)?;
1299
1300 if source_account_info.key == destination_account_info.key {
1301 return Err(ProgramError::InvalidAccountData);
1302 }
1303
1304 let source_account_data = source_account_info.data.borrow();
1305 if let Ok(source_account) =
1306 PodStateWithExtensions::<PodAccount>::unpack(&source_account_data)
1307 {
1308 if !source_account.base.is_native() && u64::from(source_account.base.amount) != 0 {
1309 return Err(TokenError::NonNativeHasBalance.into());
1310 }
1311
1312 let authority = source_account
1313 .base
1314 .close_authority
1315 .unwrap_or(source_account.base.owner);
1316
1317 if !source_account
1318 .base
1319 .is_owned_by_system_program_or_incinerator()
1320 {
1321 if let Ok(cpi_guard) = source_account.get_extension::<CpiGuard>() {
1322 if cpi_guard.lock_cpi.into()
1323 && in_cpi()
1324 && destination_account_info.key != &source_account.base.owner
1325 {
1326 return Err(TokenError::CpiGuardCloseAccountBlocked.into());
1327 }
1328 }
1329
1330 Self::validate_owner(
1331 program_id,
1332 &authority,
1333 authority_info,
1334 authority_info_data_len,
1335 account_info_iter.as_slice(),
1336 )?;
1337 } else if !solana_sdk_ids::incinerator::check_id(destination_account_info.key) {
1338 return Err(ProgramError::InvalidAccountData);
1339 }
1340
1341 if let Ok(confidential_transfer_state) =
1342 source_account.get_extension::<ConfidentialTransferAccount>()
1343 {
1344 confidential_transfer_state.closable()?
1345 }
1346
1347 if let Ok(confidential_transfer_fee_state) =
1348 source_account.get_extension::<ConfidentialTransferFeeAmount>()
1349 {
1350 confidential_transfer_fee_state.closable()?
1351 }
1352
1353 if let Ok(transfer_fee_state) = source_account.get_extension::<TransferFeeAmount>() {
1354 transfer_fee_state.closable()?
1355 }
1356 } else if let Ok(mint) = PodStateWithExtensions::<PodMint>::unpack(&source_account_data) {
1357 let extension = mint.get_extension::<MintCloseAuthority>()?;
1358 let maybe_authority: Option<Address> = extension.close_authority.into();
1359 let authority = maybe_authority.ok_or(TokenError::AuthorityTypeNotSupported)?;
1360 Self::validate_owner(
1361 program_id,
1362 &authority,
1363 authority_info,
1364 authority_info_data_len,
1365 account_info_iter.as_slice(),
1366 )?;
1367
1368 if u64::from(mint.base.supply) != 0 {
1369 return Err(TokenError::MintHasSupply.into());
1370 }
1371
1372 if let Ok(confidential_mint_burn) = mint.get_extension::<ConfidentialMintBurn>() {
1373 confidential_mint_burn.closable()?;
1374 }
1375 } else {
1376 return Err(ProgramError::UninitializedAccount);
1377 }
1378
1379 let destination_starting_lamports = destination_account_info.lamports();
1380 **destination_account_info.lamports.borrow_mut() = destination_starting_lamports
1381 .checked_add(source_account_info.lamports())
1382 .ok_or(TokenError::Overflow)?;
1383
1384 **source_account_info.lamports.borrow_mut() = 0;
1385 drop(source_account_data);
1386 delete_account(source_account_info)?;
1387
1388 Ok(())
1389 }
1390
1391 pub fn process_toggle_freeze_account(
1394 program_id: &Address,
1395 accounts: &[AccountInfo],
1396 freeze: bool,
1397 ) -> ProgramResult {
1398 let account_info_iter = &mut accounts.iter();
1399 let source_account_info = next_account_info(account_info_iter)?;
1400 let mint_info = next_account_info(account_info_iter)?;
1401 let authority_info = next_account_info(account_info_iter)?;
1402 let authority_info_data_len = authority_info.data_len();
1403
1404 check_program_account(source_account_info.owner)?;
1405 check_program_account(mint_info.owner)?;
1406
1407 let mut source_account_data = source_account_info.data.borrow_mut();
1408 let source_account =
1409 PodStateWithExtensionsMut::<PodAccount>::unpack(&mut source_account_data)?;
1410 if freeze && source_account.base.is_frozen() || !freeze && !source_account.base.is_frozen()
1411 {
1412 return Err(TokenError::InvalidState.into());
1413 }
1414 if source_account.base.is_native() {
1415 return Err(TokenError::NativeNotSupported.into());
1416 }
1417 if mint_info.key != &source_account.base.mint {
1418 return Err(TokenError::MintMismatch.into());
1419 }
1420
1421 let mint_data = mint_info.data.borrow();
1422 let mint = PodStateWithExtensions::<PodMint>::unpack(&mint_data)?;
1423 match &mint.base.freeze_authority {
1424 PodCOption {
1425 option: PodCOption::<Address>::SOME,
1426 value: authority,
1427 } => Self::validate_owner(
1428 program_id,
1429 authority,
1430 authority_info,
1431 authority_info_data_len,
1432 account_info_iter.as_slice(),
1433 ),
1434 _ => Err(TokenError::MintCannotFreeze.into()),
1435 }?;
1436
1437 source_account.base.state = if freeze {
1438 AccountState::Frozen.into()
1439 } else {
1440 AccountState::Initialized.into()
1441 };
1442
1443 Ok(())
1444 }
1445
1446 pub fn process_sync_native(accounts: &[AccountInfo]) -> ProgramResult {
1448 let account_info_iter = &mut accounts.iter();
1449 let native_account_info = next_account_info(account_info_iter)?;
1450
1451 check_program_account(native_account_info.owner)?;
1452
1453 let rent_exempt_reserve = if let Ok(rent_sysvar_info) = next_account_info(account_info_iter)
1454 {
1455 let rent = Rent::from_account_info(rent_sysvar_info)?;
1456 rent.minimum_balance(native_account_info.data_len())
1457 } else {
1458 Rent::get()?.minimum_balance(native_account_info.data_len())
1459 };
1460
1461 let mut native_account_data = native_account_info.data.borrow_mut();
1462 let native_account =
1463 PodStateWithExtensionsMut::<PodAccount>::unpack(&mut native_account_data)?;
1464
1465 match native_account.base.is_native {
1466 PodCOption {
1467 option: PodCOption::<U64>::SOME,
1468 ..
1469 } => {
1470 let new_amount = native_account_info
1471 .lamports()
1472 .checked_sub(rent_exempt_reserve)
1473 .ok_or(TokenError::Overflow)?;
1474 native_account.base.is_native = PodCOption::some(rent_exempt_reserve.into());
1475 native_account.base.amount = new_amount.into();
1476 }
1477 _ => return Err(TokenError::NonNativeNotSupported.into()),
1478 }
1479
1480 Ok(())
1481 }
1482
1483 pub fn process_initialize_mint_close_authority(
1487 accounts: &[AccountInfo],
1488 close_authority: PodCOption<Address>,
1489 ) -> ProgramResult {
1490 let account_info_iter = &mut accounts.iter();
1491 let mint_account_info = next_account_info(account_info_iter)?;
1492
1493 check_program_account(mint_account_info.owner)?;
1494
1495 let mut mint_data = mint_account_info.data.borrow_mut();
1496 let mut mint = PodStateWithExtensionsMut::<PodMint>::unpack_uninitialized(&mut mint_data)?;
1497 let extension = mint.init_extension::<MintCloseAuthority>(true)?;
1498 extension.close_authority = close_authority.try_into()?;
1499
1500 Ok(())
1501 }
1502
1503 pub fn process_get_account_data_size(
1506 accounts: &[AccountInfo],
1507 new_extension_types: &[ExtensionType],
1508 ) -> ProgramResult {
1509 if new_extension_types
1510 .iter()
1511 .any(|&t| t.get_account_type() != AccountType::Account)
1512 {
1513 return Err(TokenError::ExtensionTypeMismatch.into());
1514 }
1515
1516 let account_info_iter = &mut accounts.iter();
1517 let mint_account_info = next_account_info(account_info_iter)?;
1518
1519 check_program_account(mint_account_info.owner)?;
1520
1521 let mut account_extensions = Self::get_required_account_extensions(mint_account_info)?;
1522 account_extensions.extend_from_slice(new_extension_types);
1525
1526 let account_len = ExtensionType::try_calculate_account_len::<Account>(&account_extensions)?;
1527 set_return_data(&account_len.to_le_bytes());
1528
1529 Ok(())
1530 }
1531
1532 pub fn process_initialize_immutable_owner(accounts: &[AccountInfo]) -> ProgramResult {
1535 let account_info_iter = &mut accounts.iter();
1536 let token_account_info = next_account_info(account_info_iter)?;
1537
1538 check_program_account(token_account_info.owner)?;
1539
1540 let token_account_data = &mut token_account_info.data.borrow_mut();
1541 let mut token_account =
1542 PodStateWithExtensionsMut::<PodAccount>::unpack_uninitialized(token_account_data)?;
1543 token_account
1544 .init_extension::<ImmutableOwner>(true)
1545 .map(|_| ())
1546 }
1547
1548 pub fn process_amount_to_ui_amount(accounts: &[AccountInfo], amount: u64) -> ProgramResult {
1551 let account_info_iter = &mut accounts.iter();
1552 let mint_info = next_account_info(account_info_iter)?;
1553 check_program_account(mint_info.owner)?;
1554
1555 let mint_data = mint_info.data.borrow();
1556 let mint = PodStateWithExtensions::<PodMint>::unpack(&mint_data)
1557 .map_err(|_| Into::<ProgramError>::into(TokenError::InvalidMint))?;
1558 let ui_amount = if let Ok(extension) = mint.get_extension::<InterestBearingConfig>() {
1559 let unix_timestamp = Clock::get()?.unix_timestamp;
1560 extension
1561 .amount_to_ui_amount(amount, mint.base.decimals, unix_timestamp)
1562 .ok_or(ProgramError::InvalidArgument)?
1563 } else if let Ok(extension) = mint.get_extension::<ScaledUiAmountConfig>() {
1564 let unix_timestamp = Clock::get()?.unix_timestamp;
1565 extension
1566 .amount_to_ui_amount(amount, mint.base.decimals, unix_timestamp)
1567 .ok_or(ProgramError::InvalidArgument)?
1568 } else {
1569 crate::amount_to_ui_amount_string_trimmed(amount, mint.base.decimals)
1570 };
1571
1572 set_return_data(&ui_amount.into_bytes());
1573 Ok(())
1574 }
1575
1576 pub fn process_ui_amount_to_amount(accounts: &[AccountInfo], ui_amount: &str) -> ProgramResult {
1579 let account_info_iter = &mut accounts.iter();
1580 let mint_info = next_account_info(account_info_iter)?;
1581 check_program_account(mint_info.owner)?;
1582
1583 let mint_data = mint_info.data.borrow();
1584 let mint = PodStateWithExtensions::<PodMint>::unpack(&mint_data)
1585 .map_err(|_| Into::<ProgramError>::into(TokenError::InvalidMint))?;
1586 let amount = if let Ok(extension) = mint.get_extension::<InterestBearingConfig>() {
1587 let unix_timestamp = Clock::get()?.unix_timestamp;
1588 extension.try_ui_amount_into_amount(ui_amount, mint.base.decimals, unix_timestamp)?
1589 } else if let Ok(extension) = mint.get_extension::<ScaledUiAmountConfig>() {
1590 let unix_timestamp = Clock::get()?.unix_timestamp;
1591 extension.try_ui_amount_into_amount(ui_amount, mint.base.decimals, unix_timestamp)?
1592 } else {
1593 crate::try_ui_amount_into_amount(ui_amount.to_string(), mint.base.decimals)?
1594 };
1595
1596 set_return_data(&amount.to_le_bytes());
1597 Ok(())
1598 }
1599
1600 pub fn process_create_native_mint(accounts: &[AccountInfo]) -> ProgramResult {
1602 let account_info_iter = &mut accounts.iter();
1603 let payer_info = next_account_info(account_info_iter)?;
1604 let native_mint_info = next_account_info(account_info_iter)?;
1605 let system_program_info = next_account_info(account_info_iter)?;
1606
1607 if *native_mint_info.key != native_mint::id() {
1608 return Err(TokenError::InvalidMint.into());
1609 }
1610
1611 let rent = Rent::get()?;
1612 let new_minimum_balance = rent.minimum_balance(Mint::get_packed_len());
1613 let lamports_diff = new_minimum_balance.saturating_sub(native_mint_info.lamports());
1614 invoke(
1615 &system_instruction::transfer(payer_info.key, native_mint_info.key, lamports_diff),
1616 &[
1617 payer_info.clone(),
1618 native_mint_info.clone(),
1619 system_program_info.clone(),
1620 ],
1621 )?;
1622
1623 invoke_signed(
1624 &system_instruction::allocate(native_mint_info.key, Mint::get_packed_len() as u64),
1625 &[native_mint_info.clone(), system_program_info.clone()],
1626 &[native_mint::PROGRAM_ADDRESS_SEEDS],
1627 )?;
1628
1629 invoke_signed(
1630 &system_instruction::assign(native_mint_info.key, &crate::id()),
1631 &[native_mint_info.clone(), system_program_info.clone()],
1632 &[native_mint::PROGRAM_ADDRESS_SEEDS],
1633 )?;
1634
1635 Mint::pack(
1636 Mint {
1637 decimals: native_mint::DECIMALS,
1638 is_initialized: true,
1639 ..Mint::default()
1640 },
1641 &mut native_mint_info.data.borrow_mut(),
1642 )
1643 }
1644
1645 pub fn process_initialize_non_transferable_mint(accounts: &[AccountInfo]) -> ProgramResult {
1649 let account_info_iter = &mut accounts.iter();
1650 let mint_account_info = next_account_info(account_info_iter)?;
1651 check_program_account(mint_account_info.owner)?;
1652
1653 let mut mint_data = mint_account_info.data.borrow_mut();
1654 let mut mint = PodStateWithExtensionsMut::<PodMint>::unpack_uninitialized(&mut mint_data)?;
1655 mint.init_extension::<NonTransferable>(true)?;
1656
1657 Ok(())
1658 }
1659
1660 pub fn process_initialize_permanent_delegate(
1663 accounts: &[AccountInfo],
1664 delegate: &Address,
1665 ) -> ProgramResult {
1666 let account_info_iter = &mut accounts.iter();
1667 let mint_account_info = next_account_info(account_info_iter)?;
1668 check_program_account(mint_account_info.owner)?;
1669
1670 let mut mint_data = mint_account_info.data.borrow_mut();
1671 let mut mint = PodStateWithExtensionsMut::<PodMint>::unpack_uninitialized(&mut mint_data)?;
1672 let extension = mint.init_extension::<PermanentDelegate>(true)?;
1673 extension.delegate = Some(*delegate)
1674 .try_into()
1675 .map_err(|_| ProgramError::InvalidArgument)?;
1676
1677 Ok(())
1678 }
1679
1680 pub fn process_withdraw_excess_lamports(
1684 program_id: &Address,
1685 accounts: &[AccountInfo],
1686 ) -> ProgramResult {
1687 let account_info_iter = &mut accounts.iter();
1688
1689 let source_info = next_account_info(account_info_iter)?;
1690 let destination_info = next_account_info(account_info_iter)?;
1691 let authority_info = next_account_info(account_info_iter)?;
1692
1693 check_program_account(source_info.owner)?;
1694
1695 let source_data = source_info.data.borrow();
1696
1697 if let Ok(account) = PodStateWithExtensions::<PodAccount>::unpack(&source_data) {
1698 if account.base.is_native() {
1699 return Err(TokenError::NativeNotSupported.into());
1700 }
1701 Self::validate_owner(
1702 program_id,
1703 &account.base.owner,
1704 authority_info,
1705 authority_info.data_len(),
1706 account_info_iter.as_slice(),
1707 )?;
1708 } else if let Ok(mint) = PodStateWithExtensions::<PodMint>::unpack(&source_data) {
1709 match &mint.base.mint_authority {
1710 PodCOption {
1711 option: PodCOption::<Address>::SOME,
1712 value: mint_authority,
1713 } => {
1714 Self::validate_owner(
1715 program_id,
1716 mint_authority,
1717 authority_info,
1718 authority_info.data_len(),
1719 account_info_iter.as_slice(),
1720 )?;
1721 }
1722 PodCOption {
1723 option: PodCOption::<Address>::NONE,
1724 value: _,
1725 } if source_info.key == authority_info.key => {
1726 if !authority_info.is_signer {
1730 return Err(ProgramError::MissingRequiredSignature);
1731 }
1732 }
1733 _ => return Err(TokenError::AuthorityTypeNotSupported.into()),
1734 }
1735 } else if source_data.len() == PodMultisig::SIZE_OF {
1736 Self::validate_owner(
1737 program_id,
1738 source_info.key,
1739 authority_info,
1740 authority_info.data_len(),
1741 account_info_iter.as_slice(),
1742 )?;
1743 } else {
1744 return Err(TokenError::InvalidState.into());
1745 }
1746
1747 let source_rent_exempt_reserve = Rent::get()?.minimum_balance(source_info.data_len());
1748
1749 let transfer_amount = source_info
1750 .lamports()
1751 .checked_sub(source_rent_exempt_reserve)
1752 .ok_or(TokenError::NotRentExempt)?;
1753
1754 let source_starting_lamports = source_info.lamports();
1755 **source_info.lamports.borrow_mut() = source_starting_lamports
1756 .checked_sub(transfer_amount)
1757 .ok_or(TokenError::Overflow)?;
1758
1759 let destination_starting_lamports = destination_info.lamports();
1760 **destination_info.lamports.borrow_mut() = destination_starting_lamports
1761 .checked_add(transfer_amount)
1762 .ok_or(TokenError::Overflow)?;
1763
1764 Ok(())
1765 }
1766
1767 pub fn process_unwrap_lamports(
1770 program_id: &Address,
1771 accounts: &[AccountInfo],
1772 amount: PodCOption<u64>,
1773 ) -> ProgramResult {
1774 let account_info_iter = &mut accounts.iter();
1775 let source_account_info = next_account_info(account_info_iter)?;
1776 let destination_account_info = next_account_info(account_info_iter)?;
1777 let authority_info = next_account_info(account_info_iter)?;
1778 let authority_info_data_len = authority_info.data_len();
1779
1780 check_program_account(source_account_info.owner)?;
1781
1782 let mut source_account_data = source_account_info.data.borrow_mut();
1783 let source_account =
1784 PodStateWithExtensionsMut::<PodAccount>::unpack(&mut source_account_data)?;
1785
1786 let (amount, remaining_amount) = match amount {
1787 PodCOption {
1788 option: PodCOption::<u64>::SOME,
1789 value: amount,
1790 } => (
1791 amount,
1792 Into::<u64>::into(source_account.base.amount)
1793 .checked_sub(amount)
1794 .ok_or(TokenError::InsufficientFunds)?,
1795 ),
1796 PodCOption {
1797 option: PodCOption::<u64>::NONE,
1798 value: _,
1799 } => (source_account.base.amount.into(), 0),
1800 _ => return Err(ProgramError::InvalidInstructionData),
1801 };
1802
1803 if !source_account.base.is_native() {
1804 return Err(TokenError::NonNativeNotSupported.into());
1805 }
1806
1807 match source_account.base.delegate {
1808 PodCOption {
1809 option: PodCOption::<Address>::SOME,
1810 value: delegate,
1811 } if authority_info.key == &delegate => {
1812 Self::validate_owner(
1813 program_id,
1814 &delegate,
1815 authority_info,
1816 authority_info_data_len,
1817 account_info_iter.as_slice(),
1818 )?;
1819
1820 let delegated_amount = u64::from(source_account.base.delegated_amount);
1821
1822 source_account.base.delegated_amount = delegated_amount
1823 .checked_sub(amount)
1824 .ok_or(TokenError::InsufficientFunds)?
1825 .into();
1826
1827 if u64::from(source_account.base.delegated_amount) == 0 {
1828 source_account.base.delegate = PodCOption::none();
1829 }
1830 }
1831 _ => {
1832 Self::validate_owner(
1833 program_id,
1834 &source_account.base.owner,
1835 authority_info,
1836 authority_info_data_len,
1837 account_info_iter.as_slice(),
1838 )?;
1839 }
1840 }
1841
1842 if let Ok(cpi_guard) = source_account.get_extension::<CpiGuard>() {
1843 if cpi_guard.lock_cpi.into() && in_cpi() {
1844 return Err(TokenError::CpiGuardTransferBlocked.into());
1845 }
1846 }
1847
1848 if amount != 0 {
1849 source_account.base.amount = remaining_amount.into();
1850
1851 if source_account_info.key != destination_account_info.key {
1852 let source_starting_lamports = source_account_info.lamports();
1853 **source_account_info.lamports.borrow_mut() = source_starting_lamports
1854 .checked_sub(amount)
1855 .ok_or(TokenError::Overflow)?;
1856
1857 let destination_starting_lamports = destination_account_info.lamports();
1858 **destination_account_info.lamports.borrow_mut() = destination_starting_lamports
1859 .checked_add(amount)
1860 .ok_or(TokenError::Overflow)?;
1861 }
1862 }
1863
1864 Ok(())
1865 }
1866
1867 const IX_HEADER_SIZE: usize = 2;
1873
1874 pub fn process_batch(
1877 program_id: &Address,
1878 mut accounts: &[AccountInfo],
1879 mut data: &[u8],
1880 ) -> ProgramResult {
1881 loop {
1882 let header = data
1883 .get(..Self::IX_HEADER_SIZE)
1884 .ok_or(TokenError::InvalidInstruction)?;
1885
1886 let expected_accounts = header[0] as usize;
1887 let data_offset = Self::IX_HEADER_SIZE + header[1] as usize;
1888
1889 let ix_accounts = accounts
1890 .get(..expected_accounts)
1891 .ok_or(ProgramError::NotEnoughAccountKeys)?;
1892 let ix_data = data
1893 .get(Self::IX_HEADER_SIZE..data_offset)
1894 .ok_or(TokenError::InvalidInstruction)?;
1895
1896 Self::_process_inner(program_id, ix_accounts, ix_data)?;
1897
1898 if data_offset == data.len() {
1899 break;
1900 }
1901
1902 accounts = &accounts[expected_accounts..];
1903 data = &data[data_offset..];
1904 }
1905
1906 Ok(())
1907 }
1908
1909 pub fn process(program_id: &Address, accounts: &[AccountInfo], input: &[u8]) -> ProgramResult {
1911 if let Ok(PodTokenInstruction::Batch) = decode_instruction_type(input) {
1912 msg!("Instruction: Batch");
1913 Self::process_batch(program_id, accounts, &input[1..])
1914 } else {
1915 Self::_process_inner(program_id, accounts, input)
1916 }
1917 }
1918
1919 fn _process_inner(
1920 program_id: &Address,
1921 accounts: &[AccountInfo],
1922 input: &[u8],
1923 ) -> ProgramResult {
1924 if let Ok(instruction_type) = decode_instruction_type(input) {
1925 match instruction_type {
1926 PodTokenInstruction::InitializeMint => {
1927 msg!("Instruction: InitializeMint");
1928 let (data, freeze_authority) =
1929 decode_instruction_data_with_coption_pubkey::<InitializeMintData>(input)?;
1930 Self::process_initialize_mint(
1931 accounts,
1932 data.decimals,
1933 &data.mint_authority,
1934 freeze_authority,
1935 )
1936 }
1937 PodTokenInstruction::InitializeMint2 => {
1938 msg!("Instruction: InitializeMint2");
1939 let (data, freeze_authority) =
1940 decode_instruction_data_with_coption_pubkey::<InitializeMintData>(input)?;
1941 Self::process_initialize_mint2(
1942 accounts,
1943 data.decimals,
1944 &data.mint_authority,
1945 freeze_authority,
1946 )
1947 }
1948 PodTokenInstruction::InitializeAccount => {
1949 msg!("Instruction: InitializeAccount");
1950 Self::process_initialize_account(accounts)
1951 }
1952 PodTokenInstruction::InitializeAccount2 => {
1953 msg!("Instruction: InitializeAccount2");
1954 let owner = decode_instruction_data::<Address>(input)?;
1955 Self::process_initialize_account2(accounts, owner)
1956 }
1957 PodTokenInstruction::InitializeAccount3 => {
1958 msg!("Instruction: InitializeAccount3");
1959 let owner = decode_instruction_data::<Address>(input)?;
1960 Self::process_initialize_account3(accounts, owner)
1961 }
1962 PodTokenInstruction::InitializeMultisig => {
1963 msg!("Instruction: InitializeMultisig");
1964 let data = decode_instruction_data::<InitializeMultisigData>(input)?;
1965 Self::process_initialize_multisig(accounts, data.m)
1966 }
1967 PodTokenInstruction::InitializeMultisig2 => {
1968 msg!("Instruction: InitializeMultisig2");
1969 let data = decode_instruction_data::<InitializeMultisigData>(input)?;
1970 Self::process_initialize_multisig2(accounts, data.m)
1971 }
1972 #[allow(deprecated)]
1973 PodTokenInstruction::Transfer => {
1974 msg!("Instruction: Transfer");
1975 let data = decode_instruction_data::<AmountData>(input)?;
1976 Self::process_transfer(
1977 program_id,
1978 accounts,
1979 data.amount.into(),
1980 TransferInstruction::Unchecked,
1981 )
1982 }
1983 PodTokenInstruction::Approve => {
1984 msg!("Instruction: Approve");
1985 let data = decode_instruction_data::<AmountData>(input)?;
1986 Self::process_approve(
1987 program_id,
1988 accounts,
1989 data.amount.into(),
1990 InstructionVariant::Unchecked,
1991 )
1992 }
1993 PodTokenInstruction::Revoke => {
1994 msg!("Instruction: Revoke");
1995 Self::process_revoke(program_id, accounts)
1996 }
1997 PodTokenInstruction::SetAuthority => {
1998 msg!("Instruction: SetAuthority");
1999 let (data, new_authority) =
2000 decode_instruction_data_with_coption_pubkey::<SetAuthorityData>(input)?;
2001 Self::process_set_authority(
2002 program_id,
2003 accounts,
2004 AuthorityType::from(data.authority_type)?,
2005 new_authority,
2006 )
2007 }
2008 PodTokenInstruction::MintTo => {
2009 msg!("Instruction: MintTo");
2010 let data = decode_instruction_data::<AmountData>(input)?;
2011 Self::process_mint_to(
2012 program_id,
2013 accounts,
2014 data.amount.into(),
2015 InstructionVariant::Unchecked,
2016 )
2017 }
2018 PodTokenInstruction::Burn => {
2019 msg!("Instruction: Burn");
2020 let data = decode_instruction_data::<AmountData>(input)?;
2021 Self::process_burn(
2022 program_id,
2023 accounts,
2024 data.amount.into(),
2025 BurnInstructionVariant::Standard,
2026 InstructionVariant::Unchecked,
2027 )
2028 }
2029 PodTokenInstruction::CloseAccount => {
2030 msg!("Instruction: CloseAccount");
2031 Self::process_close_account(program_id, accounts)
2032 }
2033 PodTokenInstruction::FreezeAccount => {
2034 msg!("Instruction: FreezeAccount");
2035 Self::process_toggle_freeze_account(program_id, accounts, true)
2036 }
2037 PodTokenInstruction::ThawAccount => {
2038 msg!("Instruction: ThawAccount");
2039 Self::process_toggle_freeze_account(program_id, accounts, false)
2040 }
2041 PodTokenInstruction::TransferChecked => {
2042 msg!("Instruction: TransferChecked");
2043 let data = decode_instruction_data::<AmountCheckedData>(input)?;
2044 Self::process_transfer(
2045 program_id,
2046 accounts,
2047 data.amount.into(),
2048 TransferInstruction::Checked {
2049 decimals: data.decimals,
2050 },
2051 )
2052 }
2053 PodTokenInstruction::ApproveChecked => {
2054 msg!("Instruction: ApproveChecked");
2055 let data = decode_instruction_data::<AmountCheckedData>(input)?;
2056 Self::process_approve(
2057 program_id,
2058 accounts,
2059 data.amount.into(),
2060 InstructionVariant::Checked {
2061 decimals: data.decimals,
2062 },
2063 )
2064 }
2065 PodTokenInstruction::MintToChecked => {
2066 msg!("Instruction: MintToChecked");
2067 let data = decode_instruction_data::<AmountCheckedData>(input)?;
2068 Self::process_mint_to(
2069 program_id,
2070 accounts,
2071 data.amount.into(),
2072 InstructionVariant::Checked {
2073 decimals: data.decimals,
2074 },
2075 )
2076 }
2077 PodTokenInstruction::BurnChecked => {
2078 msg!("Instruction: BurnChecked");
2079 let data = decode_instruction_data::<AmountCheckedData>(input)?;
2080 Self::process_burn(
2081 program_id,
2082 accounts,
2083 data.amount.into(),
2084 BurnInstructionVariant::Standard,
2085 InstructionVariant::Checked {
2086 decimals: data.decimals,
2087 },
2088 )
2089 }
2090 PodTokenInstruction::SyncNative => {
2091 msg!("Instruction: SyncNative");
2092 Self::process_sync_native(accounts)
2093 }
2094 PodTokenInstruction::GetAccountDataSize => {
2095 msg!("Instruction: GetAccountDataSize");
2096 let extension_types = input[1..]
2097 .chunks(std::mem::size_of::<ExtensionType>())
2098 .map(ExtensionType::try_from)
2099 .collect::<Result<Vec<_>, _>>()?;
2100 Self::process_get_account_data_size(accounts, &extension_types)
2101 }
2102 PodTokenInstruction::InitializeMintCloseAuthority => {
2103 msg!("Instruction: InitializeMintCloseAuthority");
2104 let (_, close_authority) =
2105 decode_instruction_data_with_coption_pubkey::<()>(input)?;
2106 Self::process_initialize_mint_close_authority(accounts, close_authority)
2107 }
2108 PodTokenInstruction::TransferFeeExtension => {
2109 transfer_fee::processor::process_instruction(program_id, accounts, &input[1..])
2110 }
2111 PodTokenInstruction::ConfidentialTransferExtension => {
2112 confidential_transfer::processor::process_instruction(
2113 program_id,
2114 accounts,
2115 &input[1..],
2116 )
2117 }
2118 PodTokenInstruction::DefaultAccountStateExtension => {
2119 default_account_state::processor::process_instruction(
2120 program_id,
2121 accounts,
2122 &input[1..],
2123 )
2124 }
2125 PodTokenInstruction::InitializeImmutableOwner => {
2126 msg!("Instruction: InitializeImmutableOwner");
2127 Self::process_initialize_immutable_owner(accounts)
2128 }
2129 PodTokenInstruction::AmountToUiAmount => {
2130 msg!("Instruction: AmountToUiAmount");
2131 let data = decode_instruction_data::<AmountData>(input)?;
2132 Self::process_amount_to_ui_amount(accounts, data.amount.into())
2133 }
2134 PodTokenInstruction::UiAmountToAmount => {
2135 msg!("Instruction: UiAmountToAmount");
2136 let ui_amount = std::str::from_utf8(&input[1..])
2137 .map_err(|_| TokenError::InvalidInstruction)?;
2138 Self::process_ui_amount_to_amount(accounts, ui_amount)
2139 }
2140 PodTokenInstruction::Reallocate => {
2141 msg!("Instruction: Reallocate");
2142 let extension_types = input[1..]
2143 .chunks(std::mem::size_of::<ExtensionType>())
2144 .map(ExtensionType::try_from)
2145 .collect::<Result<Vec<_>, _>>()?;
2146 reallocate::process_reallocate(program_id, accounts, extension_types)
2147 }
2148 PodTokenInstruction::MemoTransferExtension => {
2149 memo_transfer::processor::process_instruction(program_id, accounts, &input[1..])
2150 }
2151 PodTokenInstruction::CreateNativeMint => {
2152 msg!("Instruction: CreateNativeMint");
2153 Self::process_create_native_mint(accounts)
2154 }
2155 PodTokenInstruction::InitializeNonTransferableMint => {
2156 msg!("Instruction: InitializeNonTransferableMint");
2157 Self::process_initialize_non_transferable_mint(accounts)
2158 }
2159 PodTokenInstruction::InterestBearingMintExtension => {
2160 interest_bearing_mint::processor::process_instruction(
2161 program_id,
2162 accounts,
2163 &input[1..],
2164 )
2165 }
2166 PodTokenInstruction::CpiGuardExtension => {
2167 cpi_guard::processor::process_instruction(program_id, accounts, &input[1..])
2168 }
2169 PodTokenInstruction::InitializePermanentDelegate => {
2170 msg!("Instruction: InitializePermanentDelegate");
2171 let delegate = decode_instruction_data::<Address>(input)?;
2172 Self::process_initialize_permanent_delegate(accounts, delegate)
2173 }
2174 PodTokenInstruction::TransferHookExtension => {
2175 transfer_hook::processor::process_instruction(program_id, accounts, &input[1..])
2176 }
2177 PodTokenInstruction::ConfidentialTransferFeeExtension => {
2178 confidential_transfer_fee::processor::process_instruction(
2179 program_id,
2180 accounts,
2181 &input[1..],
2182 )
2183 }
2184 PodTokenInstruction::WithdrawExcessLamports => {
2185 msg!("Instruction: WithdrawExcessLamports");
2186 Self::process_withdraw_excess_lamports(program_id, accounts)
2187 }
2188 PodTokenInstruction::MetadataPointerExtension => {
2189 metadata_pointer::processor::process_instruction(
2190 program_id,
2191 accounts,
2192 &input[1..],
2193 )
2194 }
2195 PodTokenInstruction::GroupPointerExtension => {
2196 group_pointer::processor::process_instruction(program_id, accounts, &input[1..])
2197 }
2198 PodTokenInstruction::GroupMemberPointerExtension => {
2199 group_member_pointer::processor::process_instruction(
2200 program_id,
2201 accounts,
2202 &input[1..],
2203 )
2204 }
2205 PodTokenInstruction::ConfidentialMintBurnExtension => {
2206 msg!("Instruction: ConfidentialMintBurnExtension");
2207 confidential_mint_burn::processor::process_instruction(
2208 program_id,
2209 accounts,
2210 &input[1..],
2211 )
2212 }
2213 PodTokenInstruction::ScaledUiAmountExtension => {
2214 msg!("Instruction: ScaledUiAmountExtension");
2215 scaled_ui_amount::processor::process_instruction(
2216 program_id,
2217 accounts,
2218 &input[1..],
2219 )
2220 }
2221 PodTokenInstruction::PausableExtension => {
2222 msg!("Instruction: PausableExtension");
2223 pausable::processor::process_instruction(program_id, accounts, &input[1..])
2224 }
2225 PodTokenInstruction::PermissionedBurnExtension => {
2226 msg!("Instruction: PermissionedBurnExtension");
2227 permissioned_burn::processor::process_instruction(
2228 program_id,
2229 accounts,
2230 &input[1..],
2231 )
2232 }
2233 PodTokenInstruction::UnwrapLamports => {
2234 msg!("Instruction: UnwrapLamports");
2235 let (_, amount) = decode_instruction_data_with_coption_u64::<()>(input)?;
2236 Self::process_unwrap_lamports(program_id, accounts, amount)
2237 }
2238 PodTokenInstruction::Batch => Err(TokenError::InvalidInstruction.into()),
2239 }
2240 } else if let Ok(instruction) = TokenMetadataInstruction::unpack(input) {
2241 token_metadata::processor::process_instruction(program_id, accounts, instruction)
2242 } else if let Ok(instruction) = TokenGroupInstruction::unpack(input) {
2243 token_group::processor::process_instruction(program_id, accounts, instruction)
2244 } else {
2245 Err(TokenError::InvalidInstruction.into())
2246 }
2247 }
2248
2249 pub fn validate_owner(
2251 program_id: &Address,
2252 expected_owner: &Address,
2253 owner_account_info: &AccountInfo,
2254 owner_account_data_len: usize,
2255 signers: &[AccountInfo],
2256 ) -> ProgramResult {
2257 if expected_owner != owner_account_info.key {
2258 return Err(TokenError::OwnerMismatch.into());
2259 }
2260
2261 let owned_by_token_program = program_id == owner_account_info.owner
2262 || owner_account_info.owner == &inline_spl_token::id()
2263 || owner_account_info.owner == &spl_token_2022_interface::id();
2264 if owned_by_token_program && owner_account_data_len == PodMultisig::SIZE_OF {
2265 let multisig_data = &owner_account_info.data.borrow();
2266 let multisig = bytemuck::try_from_bytes::<PodMultisig>(multisig_data)
2267 .map_err(|_| ProgramError::InvalidArgument)?;
2268 if !bool::from(multisig.is_initialized) {
2269 return Err(ProgramError::UninitializedAccount);
2270 }
2271 let mut num_signers = 0;
2272 let mut matched = [false; MAX_SIGNERS];
2273 for signer in signers.iter() {
2274 for (position, key) in multisig.signers[0..multisig.n as usize].iter().enumerate() {
2275 if key == signer.key && !matched[position] {
2276 if !signer.is_signer {
2277 return Err(ProgramError::MissingRequiredSignature);
2278 }
2279 matched[position] = true;
2280 num_signers += 1;
2281 }
2282 }
2283 }
2284 if num_signers < multisig.m {
2285 return Err(ProgramError::MissingRequiredSignature);
2286 }
2287 return Ok(());
2288 } else if !owner_account_info.is_signer {
2289 return Err(ProgramError::MissingRequiredSignature);
2290 }
2291 Ok(())
2292 }
2293
2294 fn get_required_account_extensions(
2295 mint_account_info: &AccountInfo,
2296 ) -> Result<Vec<ExtensionType>, ProgramError> {
2297 let mint_data = mint_account_info.data.borrow();
2298 let state = PodStateWithExtensions::<PodMint>::unpack(&mint_data)
2299 .map_err(|_| Into::<ProgramError>::into(TokenError::InvalidMint))?;
2300 Self::get_required_account_extensions_from_unpacked_mint(mint_account_info.owner, &state)
2301 }
2302
2303 fn get_required_account_extensions_from_unpacked_mint(
2304 token_program_id: &Address,
2305 state: &PodStateWithExtensions<PodMint>,
2306 ) -> Result<Vec<ExtensionType>, ProgramError> {
2307 check_program_account(token_program_id)?;
2308 let mint_extensions = state.get_extension_types()?;
2309 Ok(ExtensionType::get_required_init_account_extensions(
2310 &mint_extensions,
2311 ))
2312 }
2313}
2314
2315#[cfg(not(target_os = "solana"))]
2319fn delete_account(account_info: &AccountInfo) -> Result<(), ProgramError> {
2320 account_info.assign(&system_program::id());
2321 let mut account_data = account_info.data.borrow_mut();
2322 let data_len = account_data.len();
2323 unsafe {
2324 solana_program_memory::sol_memset(*account_data, 0, data_len);
2325 }
2326 Ok(())
2327}
2328
2329#[cfg(target_os = "solana")]
2331fn delete_account(account_info: &AccountInfo) -> Result<(), ProgramError> {
2332 account_info.assign(&system_program::id());
2333 account_info.resize(0)
2334}
2335
2336#[cfg(test)]
2337mod tests {
2338 use {
2339 super::*,
2340 serial_test::serial,
2341 solana_account::{
2342 create_account_for_test, create_is_signer_account_infos, Account as SolanaAccount,
2343 ReadableAccount,
2344 },
2345 solana_account_info::IntoAccountInfo,
2346 solana_clock::Clock,
2347 solana_instruction::{AccountMeta, Instruction},
2348 solana_program_option::COption,
2349 solana_sdk_ids::sysvar::rent,
2350 spl_token_2022_interface::{
2351 extension::{
2352 permissioned_burn, transfer_fee::instruction::initialize_transfer_fee_config,
2353 ExtensionType,
2354 },
2355 instruction::*,
2356 state::Multisig,
2357 },
2358 std::sync::{Arc, RwLock},
2359 };
2360
2361 lazy_static::lazy_static! {
2362 static ref EXPECTED_DATA: Arc<RwLock<Vec<u8>>> = Arc::new(RwLock::new(Vec::new()));
2363 }
2364
2365 fn set_expected_data(expected_data: Vec<u8>) {
2366 *EXPECTED_DATA.write().unwrap() = expected_data;
2367 }
2368
2369 struct SyscallStubs {}
2370 impl solana_sysvar::program_stubs::SyscallStubs for SyscallStubs {
2371 fn sol_log(&self, _message: &str) {}
2372
2373 fn sol_invoke_signed(
2374 &self,
2375 _instruction: &Instruction,
2376 _account_infos: &[AccountInfo],
2377 _signers_seeds: &[&[&[u8]]],
2378 ) -> ProgramResult {
2379 Err(ProgramError::Custom(42)) }
2381
2382 fn sol_get_clock_sysvar(&self, var_addr: *mut u8) -> u64 {
2383 unsafe {
2384 *(var_addr as *mut _ as *mut Clock) = Clock::default();
2385 }
2386 solana_program_entrypoint::SUCCESS
2387 }
2388
2389 fn sol_get_epoch_schedule_sysvar(&self, _var_addr: *mut u8) -> u64 {
2390 solana_instruction::error::UNSUPPORTED_SYSVAR
2391 }
2392
2393 #[allow(deprecated)]
2394 fn sol_get_fees_sysvar(&self, _var_addr: *mut u8) -> u64 {
2395 solana_instruction::error::UNSUPPORTED_SYSVAR
2396 }
2397
2398 fn sol_get_rent_sysvar(&self, var_addr: *mut u8) -> u64 {
2399 unsafe {
2400 *(var_addr as *mut _ as *mut Rent) = Rent::default();
2401 }
2402 solana_program_entrypoint::SUCCESS
2403 }
2404
2405 fn sol_set_return_data(&self, data: &[u8]) {
2406 assert_eq!(&*EXPECTED_DATA.read().unwrap(), data)
2407 }
2408 }
2409
2410 fn do_process_instruction(
2411 instruction: Instruction,
2412 accounts: Vec<&mut SolanaAccount>,
2413 ) -> ProgramResult {
2414 {
2415 use std::sync::Once;
2416 static ONCE: Once = Once::new();
2417
2418 ONCE.call_once(|| {
2419 solana_sysvar::program_stubs::set_syscall_stubs(Box::new(SyscallStubs {}));
2420 });
2421 }
2422
2423 let mut meta = instruction
2424 .accounts
2425 .iter()
2426 .zip(accounts)
2427 .map(|(account_meta, account)| (&account_meta.pubkey, account_meta.is_signer, account))
2428 .collect::<Vec<_>>();
2429
2430 let account_infos = create_is_signer_account_infos(&mut meta);
2431 Processor::process(&instruction.program_id, &account_infos, &instruction.data)
2432 }
2433
2434 fn do_process_instruction_dups(
2435 instruction: Instruction,
2436 account_infos: Vec<AccountInfo>,
2437 ) -> ProgramResult {
2438 {
2439 use std::sync::Once;
2440 static ONCE: Once = Once::new();
2441
2442 ONCE.call_once(|| {
2443 solana_sysvar::program_stubs::set_syscall_stubs(Box::new(SyscallStubs {}));
2444 });
2445 }
2446
2447 Processor::process(&instruction.program_id, &account_infos, &instruction.data)
2448 }
2449
2450 fn return_token_error_as_program_error() -> ProgramError {
2451 TokenError::MintMismatch.into()
2452 }
2453
2454 fn rent_sysvar() -> SolanaAccount {
2455 create_account_for_test(&Rent::default())
2456 }
2457
2458 fn mint_minimum_balance() -> u64 {
2459 Rent::default().minimum_balance(Mint::get_packed_len())
2460 }
2461
2462 fn account_minimum_balance() -> u64 {
2463 Rent::default().minimum_balance(Account::get_packed_len())
2464 }
2465
2466 fn multisig_minimum_balance() -> u64 {
2467 Rent::default().minimum_balance(Multisig::get_packed_len())
2468 }
2469
2470 fn batch_instruction(instructions: &[&Instruction]) -> Result<Instruction, ProgramError> {
2471 let mut accounts: Vec<AccountMeta> = vec![];
2473 let mut data: Vec<u8> = vec![0xff];
2475
2476 for instruction in instructions {
2477 if instruction.program_id.ne(&crate::ID) {
2479 return Err(ProgramError::IncorrectProgramId);
2480 }
2481
2482 data.push(instruction.accounts.len() as u8);
2483 data.push(instruction.data.len() as u8);
2484
2485 data.extend_from_slice(&instruction.data);
2486 accounts.extend_from_slice(&instruction.accounts);
2487 }
2488
2489 Ok(Instruction {
2490 program_id: crate::ID,
2491 data,
2492 accounts,
2493 })
2494 }
2495
2496 fn native_mint() -> SolanaAccount {
2497 let mut rent_sysvar = rent_sysvar();
2498 let mut mint_account =
2499 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &crate::id());
2500 do_process_instruction(
2501 initialize_mint(
2502 &crate::id(),
2503 &crate::native_mint::id(),
2504 &Address::default(),
2505 None,
2506 crate::native_mint::DECIMALS,
2507 )
2508 .unwrap(),
2509 vec![&mut mint_account, &mut rent_sysvar],
2510 )
2511 .unwrap();
2512 mint_account
2513 }
2514
2515 fn native_mint_to(account: &AccountInfo, amount: u64) -> ProgramResult {
2516 let mut buffer = account.try_borrow_mut_data()?;
2517 let mut account_account = Account::unpack(&buffer)?;
2518
2519 if !account_account.is_native() {
2520 return Err(TokenError::NonNativeNotSupported.into());
2521 }
2522
2523 let mut lamports = account.try_borrow_mut_lamports()?;
2524 **lamports += amount;
2525
2526 account_account.amount += amount;
2527
2528 Account::pack(account_account, &mut buffer)?;
2529
2530 Ok(())
2531 }
2532
2533 #[test]
2534 fn test_error_as_custom() {
2535 assert_eq!(
2536 return_token_error_as_program_error(),
2537 ProgramError::Custom(3)
2538 );
2539 }
2540
2541 #[test]
2542 fn test_unique_account_sizes() {
2543 assert_ne!(Mint::get_packed_len(), 0);
2544 assert_ne!(Mint::get_packed_len(), Account::get_packed_len());
2545 assert_ne!(Mint::get_packed_len(), Multisig::get_packed_len());
2546 assert_ne!(Account::get_packed_len(), 0);
2547 assert_ne!(Account::get_packed_len(), Multisig::get_packed_len());
2548 assert_ne!(Multisig::get_packed_len(), 0);
2549 }
2550
2551 #[test]
2552 fn test_initialize_mint() {
2553 let program_id = crate::id();
2554 let owner_key = Address::new_unique();
2555 let mint_key = Address::new_unique();
2556 let mut mint_account = SolanaAccount::new(42, Mint::get_packed_len(), &program_id);
2557 let mint2_key = Address::new_unique();
2558 let mut mint2_account =
2559 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
2560 let mut rent_sysvar = rent_sysvar();
2561
2562 assert_eq!(
2564 Err(TokenError::NotRentExempt.into()),
2565 do_process_instruction(
2566 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
2567 vec![&mut mint_account, &mut rent_sysvar]
2568 )
2569 );
2570
2571 mint_account.lamports = mint_minimum_balance();
2572
2573 do_process_instruction(
2575 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
2576 vec![&mut mint_account, &mut rent_sysvar],
2577 )
2578 .unwrap();
2579
2580 assert_eq!(
2582 Err(TokenError::AlreadyInUse.into()),
2583 do_process_instruction(
2584 initialize_mint(&program_id, &mint_key, &owner_key, None, 2,).unwrap(),
2585 vec![&mut mint_account, &mut rent_sysvar]
2586 )
2587 );
2588
2589 do_process_instruction(
2591 initialize_mint(&program_id, &mint2_key, &owner_key, Some(&owner_key), 2).unwrap(),
2592 vec![&mut mint2_account, &mut rent_sysvar],
2593 )
2594 .unwrap();
2595 let mint = Mint::unpack_unchecked(&mint2_account.data).unwrap();
2596 assert_eq!(mint.freeze_authority, COption::Some(owner_key));
2597 }
2598
2599 #[test]
2600 fn test_initialize_mint2() {
2601 let program_id = crate::id();
2602 let owner_key = Address::new_unique();
2603 let mint_key = Address::new_unique();
2604 let mut mint_account = SolanaAccount::new(42, Mint::get_packed_len(), &program_id);
2605 let mint2_key = Address::new_unique();
2606 let mut mint2_account =
2607 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
2608
2609 assert_eq!(
2611 Err(TokenError::NotRentExempt.into()),
2612 do_process_instruction(
2613 initialize_mint2(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
2614 vec![&mut mint_account]
2615 )
2616 );
2617
2618 mint_account.lamports = mint_minimum_balance();
2619
2620 do_process_instruction(
2622 initialize_mint2(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
2623 vec![&mut mint_account],
2624 )
2625 .unwrap();
2626
2627 assert_eq!(
2629 Err(TokenError::AlreadyInUse.into()),
2630 do_process_instruction(
2631 initialize_mint2(&program_id, &mint_key, &owner_key, None, 2,).unwrap(),
2632 vec![&mut mint_account]
2633 )
2634 );
2635
2636 do_process_instruction(
2638 initialize_mint2(&program_id, &mint2_key, &owner_key, Some(&owner_key), 2).unwrap(),
2639 vec![&mut mint2_account],
2640 )
2641 .unwrap();
2642 let mint = Mint::unpack_unchecked(&mint2_account.data).unwrap();
2643 assert_eq!(mint.freeze_authority, COption::Some(owner_key));
2644 }
2645
2646 #[test]
2647 fn test_initialize_mint_account() {
2648 let program_id = crate::id();
2649 let account_key = Address::new_unique();
2650 let mut account_account = SolanaAccount::new(42, Account::get_packed_len(), &program_id);
2651 let owner_key = Address::new_unique();
2652 let mut owner_account = SolanaAccount::default();
2653 let mint_key = Address::new_unique();
2654 let mut mint_account =
2655 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
2656 let mut rent_sysvar = rent_sysvar();
2657
2658 assert_eq!(
2660 Err(TokenError::NotRentExempt.into()),
2661 do_process_instruction(
2662 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
2663 vec![
2664 &mut account_account,
2665 &mut mint_account,
2666 &mut owner_account,
2667 &mut rent_sysvar
2668 ],
2669 )
2670 );
2671
2672 account_account.lamports = account_minimum_balance();
2673
2674 assert_eq!(
2676 Err(TokenError::InvalidMint.into()),
2677 do_process_instruction(
2678 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
2679 vec![
2680 &mut account_account,
2681 &mut mint_account,
2682 &mut owner_account,
2683 &mut rent_sysvar
2684 ],
2685 )
2686 );
2687
2688 do_process_instruction(
2690 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
2691 vec![&mut mint_account, &mut rent_sysvar],
2692 )
2693 .unwrap();
2694
2695 let not_program_id = Address::new_unique();
2697 mint_account.owner = not_program_id;
2698 assert_eq!(
2699 Err(ProgramError::IncorrectProgramId),
2700 do_process_instruction(
2701 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
2702 vec![
2703 &mut account_account,
2704 &mut mint_account,
2705 &mut owner_account,
2706 &mut rent_sysvar
2707 ],
2708 )
2709 );
2710 mint_account.owner = program_id;
2711
2712 do_process_instruction(
2714 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
2715 vec![
2716 &mut account_account,
2717 &mut mint_account,
2718 &mut owner_account,
2719 &mut rent_sysvar,
2720 ],
2721 )
2722 .unwrap();
2723
2724 assert_eq!(
2726 Err(TokenError::AlreadyInUse.into()),
2727 do_process_instruction(
2728 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
2729 vec![
2730 &mut account_account,
2731 &mut mint_account,
2732 &mut owner_account,
2733 &mut rent_sysvar
2734 ],
2735 )
2736 );
2737 }
2738
2739 #[test]
2740 fn test_transfer_dups() {
2741 let program_id = crate::id();
2742 let account1_key = Address::new_unique();
2743 let mut account1_account = SolanaAccount::new(
2744 account_minimum_balance(),
2745 Account::get_packed_len(),
2746 &program_id,
2747 );
2748 let mut account1_info: AccountInfo = (&account1_key, true, &mut account1_account).into();
2749 let account2_key = Address::new_unique();
2750 let mut account2_account = SolanaAccount::new(
2751 account_minimum_balance(),
2752 Account::get_packed_len(),
2753 &program_id,
2754 );
2755 let mut account2_info: AccountInfo = (&account2_key, false, &mut account2_account).into();
2756 let account3_key = Address::new_unique();
2757 let mut account3_account = SolanaAccount::new(
2758 account_minimum_balance(),
2759 Account::get_packed_len(),
2760 &program_id,
2761 );
2762 let account3_info: AccountInfo = (&account3_key, false, &mut account3_account).into();
2763 let account4_key = Address::new_unique();
2764 let mut account4_account = SolanaAccount::new(
2765 account_minimum_balance(),
2766 Account::get_packed_len(),
2767 &program_id,
2768 );
2769 let account4_info: AccountInfo = (&account4_key, true, &mut account4_account).into();
2770 let multisig_key = Address::new_unique();
2771 let mut multisig_account = SolanaAccount::new(
2772 multisig_minimum_balance(),
2773 Multisig::get_packed_len(),
2774 &program_id,
2775 );
2776 let multisig_info: AccountInfo = (&multisig_key, true, &mut multisig_account).into();
2777 let owner_key = Address::new_unique();
2778 let mut owner_account = SolanaAccount::default();
2779 let owner_info: AccountInfo = (&owner_key, true, &mut owner_account).into();
2780 let mint_key = Address::new_unique();
2781 let mut mint_account =
2782 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
2783 let mint_info: AccountInfo = (&mint_key, false, &mut mint_account).into();
2784 let rent_key = rent::id();
2785 let mut rent_sysvar = rent_sysvar();
2786 let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
2787
2788 do_process_instruction_dups(
2790 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
2791 vec![mint_info.clone(), rent_info.clone()],
2792 )
2793 .unwrap();
2794
2795 do_process_instruction_dups(
2797 initialize_account(&program_id, &account1_key, &mint_key, &account1_key).unwrap(),
2798 vec![
2799 account1_info.clone(),
2800 mint_info.clone(),
2801 account1_info.clone(),
2802 rent_info.clone(),
2803 ],
2804 )
2805 .unwrap();
2806
2807 do_process_instruction_dups(
2809 initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
2810 vec![
2811 account2_info.clone(),
2812 mint_info.clone(),
2813 owner_info.clone(),
2814 rent_info.clone(),
2815 ],
2816 )
2817 .unwrap();
2818
2819 do_process_instruction_dups(
2821 mint_to(&program_id, &mint_key, &account1_key, &owner_key, &[], 1000).unwrap(),
2822 vec![mint_info.clone(), account1_info.clone(), owner_info.clone()],
2823 )
2824 .unwrap();
2825
2826 do_process_instruction_dups(
2828 #[allow(deprecated)]
2829 transfer(
2830 &program_id,
2831 &account1_key,
2832 &account2_key,
2833 &account1_key,
2834 &[],
2835 500,
2836 )
2837 .unwrap(),
2838 vec![
2839 account1_info.clone(),
2840 account2_info.clone(),
2841 account1_info.clone(),
2842 ],
2843 )
2844 .unwrap();
2845
2846 do_process_instruction_dups(
2848 transfer_checked(
2849 &program_id,
2850 &account1_key,
2851 &mint_key,
2852 &account2_key,
2853 &account1_key,
2854 &[],
2855 500,
2856 2,
2857 )
2858 .unwrap(),
2859 vec![
2860 account1_info.clone(),
2861 mint_info.clone(),
2862 account2_info.clone(),
2863 account1_info.clone(),
2864 ],
2865 )
2866 .unwrap();
2867
2868 let mut account = Account::unpack_unchecked(&account1_info.data.borrow()).unwrap();
2870 account.amount = 1000;
2871 account.delegated_amount = 1000;
2872 account.delegate = COption::Some(account1_key);
2873 account.owner = owner_key;
2874 Account::pack(account, &mut account1_info.data.borrow_mut()).unwrap();
2875
2876 do_process_instruction_dups(
2877 #[allow(deprecated)]
2878 transfer(
2879 &program_id,
2880 &account1_key,
2881 &account2_key,
2882 &account1_key,
2883 &[],
2884 500,
2885 )
2886 .unwrap(),
2887 vec![
2888 account1_info.clone(),
2889 account2_info.clone(),
2890 account1_info.clone(),
2891 ],
2892 )
2893 .unwrap();
2894
2895 do_process_instruction_dups(
2897 transfer_checked(
2898 &program_id,
2899 &account1_key,
2900 &mint_key,
2901 &account2_key,
2902 &account1_key,
2903 &[],
2904 500,
2905 2,
2906 )
2907 .unwrap(),
2908 vec![
2909 account1_info.clone(),
2910 mint_info.clone(),
2911 account2_info.clone(),
2912 account1_info.clone(),
2913 ],
2914 )
2915 .unwrap();
2916
2917 do_process_instruction_dups(
2919 initialize_account(&program_id, &account3_key, &mint_key, &account2_key).unwrap(),
2920 vec![
2921 account3_info.clone(),
2922 mint_info.clone(),
2923 account2_info.clone(),
2924 rent_info.clone(),
2925 ],
2926 )
2927 .unwrap();
2928 do_process_instruction_dups(
2929 mint_to(&program_id, &mint_key, &account3_key, &owner_key, &[], 1000).unwrap(),
2930 vec![mint_info.clone(), account3_info.clone(), owner_info.clone()],
2931 )
2932 .unwrap();
2933
2934 account1_info.is_signer = false;
2935 account2_info.is_signer = true;
2936 do_process_instruction_dups(
2937 #[allow(deprecated)]
2938 transfer(
2939 &program_id,
2940 &account3_key,
2941 &account2_key,
2942 &account2_key,
2943 &[],
2944 500,
2945 )
2946 .unwrap(),
2947 vec![
2948 account3_info.clone(),
2949 account2_info.clone(),
2950 account2_info.clone(),
2951 ],
2952 )
2953 .unwrap();
2954
2955 do_process_instruction_dups(
2957 transfer_checked(
2958 &program_id,
2959 &account3_key,
2960 &mint_key,
2961 &account2_key,
2962 &account2_key,
2963 &[],
2964 500,
2965 2,
2966 )
2967 .unwrap(),
2968 vec![
2969 account3_info.clone(),
2970 mint_info.clone(),
2971 account2_info.clone(),
2972 account2_info.clone(),
2973 ],
2974 )
2975 .unwrap();
2976
2977 do_process_instruction_dups(
2979 initialize_multisig(&program_id, &multisig_key, &[&account4_key], 1).unwrap(),
2980 vec![
2981 multisig_info.clone(),
2982 rent_info.clone(),
2983 account4_info.clone(),
2984 ],
2985 )
2986 .unwrap();
2987
2988 do_process_instruction_dups(
2989 initialize_account(&program_id, &account4_key, &mint_key, &multisig_key).unwrap(),
2990 vec![
2991 account4_info.clone(),
2992 mint_info.clone(),
2993 multisig_info.clone(),
2994 rent_info.clone(),
2995 ],
2996 )
2997 .unwrap();
2998
2999 do_process_instruction_dups(
3000 mint_to(&program_id, &mint_key, &account4_key, &owner_key, &[], 1000).unwrap(),
3001 vec![mint_info.clone(), account4_info.clone(), owner_info.clone()],
3002 )
3003 .unwrap();
3004
3005 do_process_instruction_dups(
3007 #[allow(deprecated)]
3008 transfer(
3009 &program_id,
3010 &account4_key,
3011 &account2_key,
3012 &multisig_key,
3013 &[&account4_key],
3014 500,
3015 )
3016 .unwrap(),
3017 vec![
3018 account4_info.clone(),
3019 account2_info.clone(),
3020 multisig_info.clone(),
3021 account4_info.clone(),
3022 ],
3023 )
3024 .unwrap();
3025
3026 do_process_instruction_dups(
3028 transfer_checked(
3029 &program_id,
3030 &account4_key,
3031 &mint_key,
3032 &account2_key,
3033 &multisig_key,
3034 &[&account4_key],
3035 500,
3036 2,
3037 )
3038 .unwrap(),
3039 vec![
3040 account4_info.clone(),
3041 mint_info.clone(),
3042 account2_info.clone(),
3043 multisig_info.clone(),
3044 account4_info.clone(),
3045 ],
3046 )
3047 .unwrap();
3048 }
3049
3050 #[test]
3051 fn test_transfer() {
3052 let program_id = crate::id();
3053 let account_key = Address::new_unique();
3054 let mut account_account = SolanaAccount::new(
3055 account_minimum_balance(),
3056 Account::get_packed_len(),
3057 &program_id,
3058 );
3059 let account2_key = Address::new_unique();
3060 let mut account2_account = SolanaAccount::new(
3061 account_minimum_balance(),
3062 Account::get_packed_len(),
3063 &program_id,
3064 );
3065 let account3_key = Address::new_unique();
3066 let mut account3_account = SolanaAccount::new(
3067 account_minimum_balance(),
3068 Account::get_packed_len(),
3069 &program_id,
3070 );
3071 let delegate_key = Address::new_unique();
3072 let mut delegate_account = SolanaAccount::default();
3073 let mismatch_key = Address::new_unique();
3074 let mut mismatch_account = SolanaAccount::new(
3075 account_minimum_balance(),
3076 Account::get_packed_len(),
3077 &program_id,
3078 );
3079 let owner_key = Address::new_unique();
3080 let mut owner_account = SolanaAccount::default();
3081 let owner2_key = Address::new_unique();
3082 let mut owner2_account = SolanaAccount::default();
3083 let mint_key = Address::new_unique();
3084 let mut mint_account =
3085 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
3086 let mint2_key = Address::new_unique();
3087 let mut rent_sysvar = rent_sysvar();
3088
3089 do_process_instruction(
3091 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
3092 vec![&mut mint_account, &mut rent_sysvar],
3093 )
3094 .unwrap();
3095
3096 do_process_instruction(
3098 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
3099 vec![
3100 &mut account_account,
3101 &mut mint_account,
3102 &mut owner_account,
3103 &mut rent_sysvar,
3104 ],
3105 )
3106 .unwrap();
3107
3108 do_process_instruction(
3110 initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
3111 vec![
3112 &mut account2_account,
3113 &mut mint_account,
3114 &mut owner_account,
3115 &mut rent_sysvar,
3116 ],
3117 )
3118 .unwrap();
3119
3120 do_process_instruction(
3122 initialize_account(&program_id, &account3_key, &mint_key, &owner_key).unwrap(),
3123 vec![
3124 &mut account3_account,
3125 &mut mint_account,
3126 &mut owner_account,
3127 &mut rent_sysvar,
3128 ],
3129 )
3130 .unwrap();
3131
3132 do_process_instruction(
3134 initialize_account(&program_id, &mismatch_key, &mint_key, &owner_key).unwrap(),
3135 vec![
3136 &mut mismatch_account,
3137 &mut mint_account,
3138 &mut owner_account,
3139 &mut rent_sysvar,
3140 ],
3141 )
3142 .unwrap();
3143 let mut account = Account::unpack_unchecked(&mismatch_account.data).unwrap();
3144 account.mint = mint2_key;
3145 Account::pack(account, &mut mismatch_account.data).unwrap();
3146
3147 do_process_instruction(
3149 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
3150 vec![&mut mint_account, &mut account_account, &mut owner_account],
3151 )
3152 .unwrap();
3153
3154 #[allow(deprecated)]
3156 let mut instruction = transfer(
3157 &program_id,
3158 &account_key,
3159 &account2_key,
3160 &owner_key,
3161 &[],
3162 1000,
3163 )
3164 .unwrap();
3165 instruction.accounts[2].is_signer = false;
3166 assert_eq!(
3167 Err(ProgramError::MissingRequiredSignature),
3168 do_process_instruction(
3169 instruction,
3170 vec![
3171 &mut account_account,
3172 &mut account2_account,
3173 &mut owner_account,
3174 ],
3175 )
3176 );
3177
3178 assert_eq!(
3180 Err(TokenError::MintMismatch.into()),
3181 do_process_instruction(
3182 #[allow(deprecated)]
3183 transfer(
3184 &program_id,
3185 &account_key,
3186 &mismatch_key,
3187 &owner_key,
3188 &[],
3189 1000
3190 )
3191 .unwrap(),
3192 vec![
3193 &mut account_account,
3194 &mut mismatch_account,
3195 &mut owner_account,
3196 ],
3197 )
3198 );
3199
3200 assert_eq!(
3202 Err(TokenError::OwnerMismatch.into()),
3203 do_process_instruction(
3204 #[allow(deprecated)]
3205 transfer(
3206 &program_id,
3207 &account_key,
3208 &account2_key,
3209 &owner2_key,
3210 &[],
3211 1000
3212 )
3213 .unwrap(),
3214 vec![
3215 &mut account_account,
3216 &mut account2_account,
3217 &mut owner2_account,
3218 ],
3219 )
3220 );
3221
3222 let not_program_id = Address::new_unique();
3224 account_account.owner = not_program_id;
3225 assert_eq!(
3226 Err(ProgramError::IncorrectProgramId),
3227 do_process_instruction(
3228 #[allow(deprecated)]
3229 transfer(&program_id, &account_key, &account2_key, &owner_key, &[], 0,).unwrap(),
3230 vec![
3231 &mut account_account,
3232 &mut account2_account,
3233 &mut owner2_account,
3234 ],
3235 )
3236 );
3237 account_account.owner = program_id;
3238
3239 let not_program_id = Address::new_unique();
3241 account2_account.owner = not_program_id;
3242 assert_eq!(
3243 Err(ProgramError::IncorrectProgramId),
3244 do_process_instruction(
3245 #[allow(deprecated)]
3246 transfer(&program_id, &account_key, &account2_key, &owner_key, &[], 0,).unwrap(),
3247 vec![
3248 &mut account_account,
3249 &mut account2_account,
3250 &mut owner2_account,
3251 ],
3252 )
3253 );
3254 account2_account.owner = program_id;
3255
3256 do_process_instruction(
3258 #[allow(deprecated)]
3259 transfer(
3260 &program_id,
3261 &account_key,
3262 &account2_key,
3263 &owner_key,
3264 &[],
3265 1000,
3266 )
3267 .unwrap(),
3268 vec![
3269 &mut account_account,
3270 &mut account2_account,
3271 &mut owner_account,
3272 ],
3273 )
3274 .unwrap();
3275
3276 assert_eq!(
3278 Err(TokenError::InsufficientFunds.into()),
3279 do_process_instruction(
3280 #[allow(deprecated)]
3281 transfer(&program_id, &account_key, &account2_key, &owner_key, &[], 1).unwrap(),
3282 vec![
3283 &mut account_account,
3284 &mut account2_account,
3285 &mut owner_account,
3286 ],
3287 )
3288 );
3289
3290 do_process_instruction(
3292 #[allow(deprecated)]
3293 transfer(
3294 &program_id,
3295 &account2_key,
3296 &account_key,
3297 &owner_key,
3298 &[],
3299 500,
3300 )
3301 .unwrap(),
3302 vec![
3303 &mut account2_account,
3304 &mut account_account,
3305 &mut owner_account,
3306 ],
3307 )
3308 .unwrap();
3309
3310 assert_eq!(
3312 Err(TokenError::MintDecimalsMismatch.into()),
3313 do_process_instruction(
3314 transfer_checked(
3315 &program_id,
3316 &account2_key,
3317 &mint_key,
3318 &account_key,
3319 &owner_key,
3320 &[],
3321 1,
3322 10 )
3324 .unwrap(),
3325 vec![
3326 &mut account2_account,
3327 &mut mint_account,
3328 &mut account_account,
3329 &mut owner_account,
3330 ],
3331 )
3332 );
3333
3334 assert_eq!(
3336 Err(TokenError::MintMismatch.into()),
3337 do_process_instruction(
3338 transfer_checked(
3339 &program_id,
3340 &account2_key,
3341 &account3_key, &account_key,
3343 &owner_key,
3344 &[],
3345 1,
3346 2
3347 )
3348 .unwrap(),
3349 vec![
3350 &mut account2_account,
3351 &mut account3_account, &mut account_account,
3353 &mut owner_account,
3354 ],
3355 )
3356 );
3357 do_process_instruction(
3359 transfer_checked(
3360 &program_id,
3361 &account2_key,
3362 &mint_key,
3363 &account_key,
3364 &owner_key,
3365 &[],
3366 500,
3367 2,
3368 )
3369 .unwrap(),
3370 vec![
3371 &mut account2_account,
3372 &mut mint_account,
3373 &mut account_account,
3374 &mut owner_account,
3375 ],
3376 )
3377 .unwrap();
3378
3379 assert_eq!(
3381 Err(TokenError::InsufficientFunds.into()),
3382 do_process_instruction(
3383 #[allow(deprecated)]
3384 transfer(&program_id, &account2_key, &account_key, &owner_key, &[], 1).unwrap(),
3385 vec![
3386 &mut account2_account,
3387 &mut account_account,
3388 &mut owner_account,
3389 ],
3390 )
3391 );
3392
3393 do_process_instruction(
3395 approve(
3396 &program_id,
3397 &account_key,
3398 &delegate_key,
3399 &owner_key,
3400 &[],
3401 100,
3402 )
3403 .unwrap(),
3404 vec![
3405 &mut account_account,
3406 &mut delegate_account,
3407 &mut owner_account,
3408 ],
3409 )
3410 .unwrap();
3411
3412 assert_eq!(
3414 Err(TokenError::OwnerMismatch.into()),
3415 do_process_instruction(
3416 #[allow(deprecated)]
3417 transfer(
3418 &program_id,
3419 &account_key,
3420 &account2_key,
3421 &owner2_key, &[],
3423 1,
3424 )
3425 .unwrap(),
3426 vec![
3427 &mut account_account,
3428 &mut account2_account,
3429 &mut owner2_account,
3430 ],
3431 )
3432 );
3433
3434 assert_eq!(
3436 Err(TokenError::InsufficientFunds.into()),
3437 do_process_instruction(
3438 #[allow(deprecated)]
3439 transfer(
3440 &program_id,
3441 &account_key,
3442 &account2_key,
3443 &delegate_key,
3444 &[],
3445 101
3446 )
3447 .unwrap(),
3448 vec![
3449 &mut account_account,
3450 &mut account2_account,
3451 &mut delegate_account,
3452 ],
3453 )
3454 );
3455
3456 do_process_instruction(
3458 #[allow(deprecated)]
3459 transfer(
3460 &program_id,
3461 &account_key,
3462 &account2_key,
3463 &delegate_key,
3464 &[],
3465 100,
3466 )
3467 .unwrap(),
3468 vec![
3469 &mut account_account,
3470 &mut account2_account,
3471 &mut delegate_account,
3472 ],
3473 )
3474 .unwrap();
3475
3476 assert_eq!(
3478 Err(TokenError::OwnerMismatch.into()),
3479 do_process_instruction(
3480 #[allow(deprecated)]
3481 transfer(
3482 &program_id,
3483 &account_key,
3484 &account2_key,
3485 &delegate_key,
3486 &[],
3487 1
3488 )
3489 .unwrap(),
3490 vec![
3491 &mut account_account,
3492 &mut account2_account,
3493 &mut delegate_account,
3494 ],
3495 )
3496 );
3497
3498 do_process_instruction(
3500 #[allow(deprecated)]
3501 transfer(
3502 &program_id,
3503 &account_key,
3504 &account2_key,
3505 &owner_key,
3506 &[],
3507 900,
3508 )
3509 .unwrap(),
3510 vec![
3511 &mut account_account,
3512 &mut account2_account,
3513 &mut owner_account,
3514 ],
3515 )
3516 .unwrap();
3517
3518 do_process_instruction(
3520 approve(
3521 &program_id,
3522 &account_key,
3523 &delegate_key,
3524 &owner_key,
3525 &[],
3526 100,
3527 )
3528 .unwrap(),
3529 vec![
3530 &mut account_account,
3531 &mut delegate_account,
3532 &mut owner_account,
3533 ],
3534 )
3535 .unwrap();
3536
3537 assert_eq!(
3539 Err(TokenError::InsufficientFunds.into()),
3540 do_process_instruction(
3541 #[allow(deprecated)]
3542 transfer(
3543 &program_id,
3544 &account_key,
3545 &account2_key,
3546 &delegate_key,
3547 &[],
3548 100
3549 )
3550 .unwrap(),
3551 vec![
3552 &mut account_account,
3553 &mut account2_account,
3554 &mut delegate_account,
3555 ],
3556 )
3557 );
3558 }
3559
3560 #[test]
3561 fn test_self_transfer() {
3562 let program_id = crate::id();
3563 let account_key = Address::new_unique();
3564 let mut account_account = SolanaAccount::new(
3565 account_minimum_balance(),
3566 Account::get_packed_len(),
3567 &program_id,
3568 );
3569 let account2_key = Address::new_unique();
3570 let mut account2_account = SolanaAccount::new(
3571 account_minimum_balance(),
3572 Account::get_packed_len(),
3573 &program_id,
3574 );
3575 let account3_key = Address::new_unique();
3576 let mut account3_account = SolanaAccount::new(
3577 account_minimum_balance(),
3578 Account::get_packed_len(),
3579 &program_id,
3580 );
3581 let delegate_key = Address::new_unique();
3582 let mut delegate_account = SolanaAccount::default();
3583 let owner_key = Address::new_unique();
3584 let mut owner_account = SolanaAccount::default();
3585 let owner2_key = Address::new_unique();
3586 let mut owner2_account = SolanaAccount::default();
3587 let mint_key = Address::new_unique();
3588 let mut mint_account =
3589 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
3590 let mut rent_sysvar = rent_sysvar();
3591
3592 do_process_instruction(
3594 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
3595 vec![&mut mint_account, &mut rent_sysvar],
3596 )
3597 .unwrap();
3598
3599 do_process_instruction(
3601 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
3602 vec![
3603 &mut account_account,
3604 &mut mint_account,
3605 &mut owner_account,
3606 &mut rent_sysvar,
3607 ],
3608 )
3609 .unwrap();
3610
3611 do_process_instruction(
3613 initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
3614 vec![
3615 &mut account2_account,
3616 &mut mint_account,
3617 &mut owner_account,
3618 &mut rent_sysvar,
3619 ],
3620 )
3621 .unwrap();
3622
3623 do_process_instruction(
3625 initialize_account(&program_id, &account3_key, &mint_key, &owner_key).unwrap(),
3626 vec![
3627 &mut account3_account,
3628 &mut mint_account,
3629 &mut owner_account,
3630 &mut rent_sysvar,
3631 ],
3632 )
3633 .unwrap();
3634
3635 do_process_instruction(
3637 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
3638 vec![&mut mint_account, &mut account_account, &mut owner_account],
3639 )
3640 .unwrap();
3641
3642 let account_info = (&account_key, false, &mut account_account).into_account_info();
3643 let account3_info = (&account3_key, false, &mut account3_account).into_account_info();
3644 let delegate_info = (&delegate_key, true, &mut delegate_account).into_account_info();
3645 let owner_info = (&owner_key, true, &mut owner_account).into_account_info();
3646 let owner2_info = (&owner2_key, true, &mut owner2_account).into_account_info();
3647 let mint_info = (&mint_key, false, &mut mint_account).into_account_info();
3648
3649 #[allow(deprecated)]
3651 let instruction = transfer(
3652 &program_id,
3653 account_info.key,
3654 account_info.key,
3655 owner_info.key,
3656 &[],
3657 1000,
3658 )
3659 .unwrap();
3660 assert_eq!(
3661 Ok(()),
3662 Processor::process(
3663 &instruction.program_id,
3664 &[
3665 account_info.clone(),
3666 account_info.clone(),
3667 owner_info.clone(),
3668 ],
3669 &instruction.data,
3670 )
3671 );
3672 let account = Account::unpack_unchecked(&account_info.try_borrow_data().unwrap()).unwrap();
3674 assert_eq!(account.amount, 1000);
3675
3676 let instruction = transfer_checked(
3678 &program_id,
3679 account_info.key,
3680 mint_info.key,
3681 account_info.key,
3682 owner_info.key,
3683 &[],
3684 1000,
3685 2,
3686 )
3687 .unwrap();
3688 assert_eq!(
3689 Ok(()),
3690 Processor::process(
3691 &instruction.program_id,
3692 &[
3693 account_info.clone(),
3694 mint_info.clone(),
3695 account_info.clone(),
3696 owner_info.clone(),
3697 ],
3698 &instruction.data,
3699 )
3700 );
3701 let account = Account::unpack_unchecked(&account_info.try_borrow_data().unwrap()).unwrap();
3703 assert_eq!(account.amount, 1000);
3704
3705 let mut owner_no_sign_info = owner_info.clone();
3707 #[allow(deprecated)]
3708 let mut instruction = transfer(
3709 &program_id,
3710 account_info.key,
3711 account_info.key,
3712 owner_no_sign_info.key,
3713 &[],
3714 1000,
3715 )
3716 .unwrap();
3717 instruction.accounts[2].is_signer = false;
3718 owner_no_sign_info.is_signer = false;
3719 assert_eq!(
3720 Err(ProgramError::MissingRequiredSignature),
3721 Processor::process(
3722 &instruction.program_id,
3723 &[
3724 account_info.clone(),
3725 account_info.clone(),
3726 owner_no_sign_info.clone(),
3727 ],
3728 &instruction.data,
3729 )
3730 );
3731
3732 let mut instruction = transfer_checked(
3734 &program_id,
3735 account_info.key,
3736 mint_info.key,
3737 account_info.key,
3738 owner_no_sign_info.key,
3739 &[],
3740 1000,
3741 2,
3742 )
3743 .unwrap();
3744 instruction.accounts[3].is_signer = false;
3745 assert_eq!(
3746 Err(ProgramError::MissingRequiredSignature),
3747 Processor::process(
3748 &instruction.program_id,
3749 &[
3750 account_info.clone(),
3751 mint_info.clone(),
3752 account_info.clone(),
3753 owner_no_sign_info,
3754 ],
3755 &instruction.data,
3756 )
3757 );
3758
3759 #[allow(deprecated)]
3761 let instruction = transfer(
3762 &program_id,
3763 account_info.key,
3764 account_info.key,
3765 owner2_info.key,
3766 &[],
3767 1000,
3768 )
3769 .unwrap();
3770 assert_eq!(
3771 Err(TokenError::OwnerMismatch.into()),
3772 Processor::process(
3773 &instruction.program_id,
3774 &[
3775 account_info.clone(),
3776 account_info.clone(),
3777 owner2_info.clone(),
3778 ],
3779 &instruction.data,
3780 )
3781 );
3782
3783 let instruction = transfer_checked(
3785 &program_id,
3786 account_info.key,
3787 mint_info.key,
3788 account_info.key,
3789 owner2_info.key,
3790 &[],
3791 1000,
3792 2,
3793 )
3794 .unwrap();
3795 assert_eq!(
3796 Err(TokenError::OwnerMismatch.into()),
3797 Processor::process(
3798 &instruction.program_id,
3799 &[
3800 account_info.clone(),
3801 mint_info.clone(),
3802 account_info.clone(),
3803 owner2_info.clone(),
3804 ],
3805 &instruction.data,
3806 )
3807 );
3808
3809 #[allow(deprecated)]
3811 let instruction = transfer(
3812 &program_id,
3813 account_info.key,
3814 account_info.key,
3815 owner_info.key,
3816 &[],
3817 1001,
3818 )
3819 .unwrap();
3820 assert_eq!(
3821 Err(TokenError::InsufficientFunds.into()),
3822 Processor::process(
3823 &instruction.program_id,
3824 &[
3825 account_info.clone(),
3826 account_info.clone(),
3827 owner_info.clone(),
3828 ],
3829 &instruction.data,
3830 )
3831 );
3832
3833 let instruction = transfer_checked(
3835 &program_id,
3836 account_info.key,
3837 mint_info.key,
3838 account_info.key,
3839 owner_info.key,
3840 &[],
3841 1001,
3842 2,
3843 )
3844 .unwrap();
3845 assert_eq!(
3846 Err(TokenError::InsufficientFunds.into()),
3847 Processor::process(
3848 &instruction.program_id,
3849 &[
3850 account_info.clone(),
3851 mint_info.clone(),
3852 account_info.clone(),
3853 owner_info.clone(),
3854 ],
3855 &instruction.data,
3856 )
3857 );
3858
3859 let instruction = transfer_checked(
3861 &program_id,
3862 account_info.key,
3863 mint_info.key,
3864 account_info.key,
3865 owner_info.key,
3866 &[],
3867 1,
3868 10, )
3870 .unwrap();
3871 assert_eq!(
3872 Err(TokenError::MintDecimalsMismatch.into()),
3873 Processor::process(
3874 &instruction.program_id,
3875 &[
3876 account_info.clone(),
3877 mint_info.clone(),
3878 account_info.clone(),
3879 owner_info.clone(),
3880 ],
3881 &instruction.data,
3882 )
3883 );
3884
3885 let instruction = transfer_checked(
3887 &program_id,
3888 account_info.key,
3889 account3_info.key, account_info.key,
3891 owner_info.key,
3892 &[],
3893 1,
3894 2,
3895 )
3896 .unwrap();
3897 assert_eq!(
3898 Err(TokenError::MintMismatch.into()),
3899 Processor::process(
3900 &instruction.program_id,
3901 &[
3902 account_info.clone(),
3903 account3_info.clone(), account_info.clone(),
3905 owner_info.clone(),
3906 ],
3907 &instruction.data,
3908 )
3909 );
3910
3911 let instruction = approve(
3913 &program_id,
3914 account_info.key,
3915 delegate_info.key,
3916 owner_info.key,
3917 &[],
3918 100,
3919 )
3920 .unwrap();
3921 Processor::process(
3922 &instruction.program_id,
3923 &[
3924 account_info.clone(),
3925 delegate_info.clone(),
3926 owner_info.clone(),
3927 ],
3928 &instruction.data,
3929 )
3930 .unwrap();
3931
3932 #[allow(deprecated)]
3934 let instruction = transfer(
3935 &program_id,
3936 account_info.key,
3937 account_info.key,
3938 delegate_info.key,
3939 &[],
3940 100,
3941 )
3942 .unwrap();
3943 assert_eq!(
3944 Ok(()),
3945 Processor::process(
3946 &instruction.program_id,
3947 &[
3948 account_info.clone(),
3949 account_info.clone(),
3950 delegate_info.clone(),
3951 ],
3952 &instruction.data,
3953 )
3954 );
3955 let account = Account::unpack_unchecked(&account_info.try_borrow_data().unwrap()).unwrap();
3957 assert_eq!(account.amount, 1000);
3958 assert_eq!(account.delegated_amount, 100);
3959
3960 let instruction = transfer_checked(
3962 &program_id,
3963 account_info.key,
3964 mint_info.key,
3965 account_info.key,
3966 delegate_info.key,
3967 &[],
3968 100,
3969 2,
3970 )
3971 .unwrap();
3972 assert_eq!(
3973 Ok(()),
3974 Processor::process(
3975 &instruction.program_id,
3976 &[
3977 account_info.clone(),
3978 mint_info.clone(),
3979 account_info.clone(),
3980 delegate_info.clone(),
3981 ],
3982 &instruction.data,
3983 )
3984 );
3985 let account = Account::unpack_unchecked(&account_info.try_borrow_data().unwrap()).unwrap();
3987 assert_eq!(account.amount, 1000);
3988 assert_eq!(account.delegated_amount, 100);
3989
3990 #[allow(deprecated)]
3992 let instruction = transfer(
3993 &program_id,
3994 account_info.key,
3995 account_info.key,
3996 delegate_info.key,
3997 &[],
3998 101,
3999 )
4000 .unwrap();
4001 assert_eq!(
4002 Err(TokenError::InsufficientFunds.into()),
4003 Processor::process(
4004 &instruction.program_id,
4005 &[
4006 account_info.clone(),
4007 account_info.clone(),
4008 delegate_info.clone(),
4009 ],
4010 &instruction.data,
4011 )
4012 );
4013
4014 let instruction = transfer_checked(
4016 &program_id,
4017 account_info.key,
4018 mint_info.key,
4019 account_info.key,
4020 delegate_info.key,
4021 &[],
4022 101,
4023 2,
4024 )
4025 .unwrap();
4026 assert_eq!(
4027 Err(TokenError::InsufficientFunds.into()),
4028 Processor::process(
4029 &instruction.program_id,
4030 &[
4031 account_info.clone(),
4032 mint_info.clone(),
4033 account_info.clone(),
4034 delegate_info.clone(),
4035 ],
4036 &instruction.data,
4037 )
4038 );
4039
4040 #[allow(deprecated)]
4042 let instruction = transfer(
4043 &program_id,
4044 account_info.key,
4045 account_info.key,
4046 owner_info.key,
4047 &[],
4048 1000,
4049 )
4050 .unwrap();
4051 assert_eq!(
4052 Ok(()),
4053 Processor::process(
4054 &instruction.program_id,
4055 &[
4056 account_info.clone(),
4057 account_info.clone(),
4058 owner_info.clone(),
4059 ],
4060 &instruction.data,
4061 )
4062 );
4063 let account = Account::unpack_unchecked(&account_info.try_borrow_data().unwrap()).unwrap();
4065 assert_eq!(account.amount, 1000);
4066
4067 let instruction = transfer_checked(
4069 &program_id,
4070 account_info.key,
4071 mint_info.key,
4072 account_info.key,
4073 owner_info.key,
4074 &[],
4075 1000,
4076 2,
4077 )
4078 .unwrap();
4079 assert_eq!(
4080 Ok(()),
4081 Processor::process(
4082 &instruction.program_id,
4083 &[
4084 account_info.clone(),
4085 mint_info.clone(),
4086 account_info.clone(),
4087 owner_info.clone(),
4088 ],
4089 &instruction.data,
4090 )
4091 );
4092 let account = Account::unpack_unchecked(&account_info.try_borrow_data().unwrap()).unwrap();
4094 assert_eq!(account.amount, 1000);
4095 }
4096
4097 #[test]
4098 fn test_unwrap_lamports_dups() {
4099 let program_id = crate::id();
4100 let account1_key = Address::new_unique();
4101 let mut account1_account = SolanaAccount::new(
4102 account_minimum_balance(),
4103 Account::get_packed_len(),
4104 &program_id,
4105 );
4106 let mut account1_info: AccountInfo = (&account1_key, true, &mut account1_account).into();
4107 let account2_key = Address::new_unique();
4108 let mut account2_account = SolanaAccount::new(
4109 account_minimum_balance(),
4110 Account::get_packed_len(),
4111 &program_id,
4112 );
4113 let mut account2_info: AccountInfo = (&account2_key, false, &mut account2_account).into();
4114 let account3_key = Address::new_unique();
4115 let mut account3_account = SolanaAccount::new(
4116 account_minimum_balance(),
4117 Account::get_packed_len(),
4118 &program_id,
4119 );
4120 let account3_info: AccountInfo = (&account3_key, false, &mut account3_account).into();
4121 let account4_key = Address::new_unique();
4122 let mut account4_account = SolanaAccount::new(
4123 account_minimum_balance(),
4124 Account::get_packed_len(),
4125 &program_id,
4126 );
4127 let account4_info: AccountInfo = (&account4_key, true, &mut account4_account).into();
4128 let multisig_key = Address::new_unique();
4129 let mut multisig_account = SolanaAccount::new(
4130 multisig_minimum_balance(),
4131 Multisig::get_packed_len(),
4132 &program_id,
4133 );
4134 let multisig_info: AccountInfo = (&multisig_key, true, &mut multisig_account).into();
4135 let owner_key = Address::new_unique();
4136 let mut owner_account = SolanaAccount::default();
4137 let owner_info: AccountInfo = (&owner_key, true, &mut owner_account).into();
4138 let mint_key = native_mint::id();
4139 let mut mint_account = native_mint();
4140 let mint_info: AccountInfo = (&mint_key, false, &mut mint_account).into();
4141 let rent_key = rent::id();
4142 let mut rent_sysvar = rent_sysvar();
4143 let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
4144
4145 do_process_instruction_dups(
4147 initialize_account(&program_id, &account1_key, &mint_key, &account1_key).unwrap(),
4148 vec![
4149 account1_info.clone(),
4150 mint_info.clone(),
4151 account1_info.clone(),
4152 rent_info.clone(),
4153 ],
4154 )
4155 .unwrap();
4156
4157 do_process_instruction_dups(
4159 initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
4160 vec![
4161 account2_info.clone(),
4162 mint_info.clone(),
4163 owner_info.clone(),
4164 rent_info.clone(),
4165 ],
4166 )
4167 .unwrap();
4168
4169 native_mint_to(&account1_info, 1000).unwrap();
4171
4172 do_process_instruction_dups(
4174 unwrap_lamports(
4175 &program_id,
4176 &account1_key,
4177 &account2_key,
4178 &account1_key,
4179 &[],
4180 Some(500),
4181 )
4182 .unwrap(),
4183 vec![
4184 account1_info.clone(),
4185 account2_info.clone(),
4186 account1_info.clone(),
4187 ],
4188 )
4189 .unwrap();
4190
4191 do_process_instruction_dups(
4193 initialize_account(&program_id, &account3_key, &mint_key, &account2_key).unwrap(),
4194 vec![
4195 account3_info.clone(),
4196 mint_info.clone(),
4197 account2_info.clone(),
4198 rent_info.clone(),
4199 ],
4200 )
4201 .unwrap();
4202 native_mint_to(&account3_info, 1000).unwrap();
4203
4204 account1_info.is_signer = false;
4205 account2_info.is_signer = true;
4206 do_process_instruction_dups(
4207 unwrap_lamports(
4208 &program_id,
4209 &account3_key,
4210 &account2_key,
4211 &account2_key,
4212 &[],
4213 Some(500),
4214 )
4215 .unwrap(),
4216 vec![
4217 account3_info.clone(),
4218 account2_info.clone(),
4219 account2_info.clone(),
4220 ],
4221 )
4222 .unwrap();
4223
4224 do_process_instruction_dups(
4226 initialize_multisig(&program_id, &multisig_key, &[&account4_key], 1).unwrap(),
4227 vec![
4228 multisig_info.clone(),
4229 rent_info.clone(),
4230 account4_info.clone(),
4231 ],
4232 )
4233 .unwrap();
4234
4235 do_process_instruction_dups(
4236 initialize_account(&program_id, &account4_key, &mint_key, &multisig_key).unwrap(),
4237 vec![
4238 account4_info.clone(),
4239 mint_info.clone(),
4240 multisig_info.clone(),
4241 rent_info.clone(),
4242 ],
4243 )
4244 .unwrap();
4245 native_mint_to(&account4_info, 1000).unwrap();
4246
4247 do_process_instruction_dups(
4249 unwrap_lamports(
4250 &program_id,
4251 &account4_key,
4252 &account2_key,
4253 &multisig_key,
4254 &[&account4_key],
4255 Some(500),
4256 )
4257 .unwrap(),
4258 vec![
4259 account4_info.clone(),
4260 account2_info.clone(),
4261 multisig_info.clone(),
4262 account4_info.clone(),
4263 ],
4264 )
4265 .unwrap();
4266 }
4267
4268 #[test]
4269 fn test_unwrap_lamports() {
4270 let program_id = crate::id();
4271 let zero_space_rent_exempt_balance = Rent::default().minimum_balance(0);
4272 let account_key = Address::new_unique();
4273 let mut account_account = SolanaAccount::new(
4274 account_minimum_balance(),
4275 Account::get_packed_len(),
4276 &program_id,
4277 );
4278 let account2_key = Address::new_unique();
4279 let mut account2_account = SolanaAccount::new(
4280 zero_space_rent_exempt_balance,
4281 Account::get_packed_len(),
4282 &program_id,
4283 );
4284 let mismatch_account_key = Address::new_unique();
4285 let mut mismatch_account_account = SolanaAccount::new(
4286 account_minimum_balance(),
4287 Account::get_packed_len(),
4288 &program_id,
4289 );
4290 let owner_key = Address::new_unique();
4291 let mut owner_account = SolanaAccount::default();
4292 let owner2_key = Address::new_unique();
4293 let mut owner2_account = SolanaAccount::default();
4294 let mint_key = native_mint::id();
4295 let mut mint_account = native_mint();
4296 let mismatch_mint_key = Address::new_unique();
4297 let mut mismatch_mint_account =
4298 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
4299 let mut rent_sysvar = rent_sysvar();
4300
4301 do_process_instruction(
4303 initialize_mint(&program_id, &mismatch_mint_key, &owner_key, None, 2).unwrap(),
4304 vec![&mut mismatch_mint_account, &mut rent_sysvar],
4305 )
4306 .unwrap();
4307
4308 do_process_instruction(
4310 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
4311 vec![
4312 &mut account_account,
4313 &mut mint_account,
4314 &mut owner_account,
4315 &mut rent_sysvar,
4316 ],
4317 )
4318 .unwrap();
4319
4320 do_process_instruction(
4322 initialize_account(
4323 &program_id,
4324 &mismatch_account_key,
4325 &mismatch_mint_key,
4326 &owner_key,
4327 )
4328 .unwrap(),
4329 vec![
4330 &mut mismatch_account_account,
4331 &mut mismatch_mint_account,
4332 &mut owner_account,
4333 &mut rent_sysvar,
4334 ],
4335 )
4336 .unwrap();
4337
4338 let account_info = (&account_key, false, &mut account_account).into();
4340 native_mint_to(&account_info, 1000).unwrap();
4341
4342 let mut instruction = unwrap_lamports(
4344 &program_id,
4345 &account_key,
4346 &account2_key,
4347 &owner_key,
4348 &[],
4349 Some(1000),
4350 )
4351 .unwrap();
4352 instruction.accounts[2].is_signer = false;
4353 assert_eq!(
4354 Err(ProgramError::MissingRequiredSignature),
4355 do_process_instruction(
4356 instruction,
4357 vec![
4358 &mut account_account,
4359 &mut account2_account,
4360 &mut owner_account,
4361 ],
4362 )
4363 );
4364
4365 assert_eq!(
4367 Err(TokenError::NonNativeNotSupported.into()),
4368 do_process_instruction(
4369 unwrap_lamports(
4370 &program_id,
4371 &mismatch_account_key,
4372 &account_key,
4373 &owner_key,
4374 &[],
4375 None
4376 )
4377 .unwrap(),
4378 vec![
4379 &mut mismatch_account_account,
4380 &mut account_account,
4381 &mut owner_account,
4382 ],
4383 )
4384 );
4385
4386 assert_eq!(
4388 Err(TokenError::OwnerMismatch.into()),
4389 do_process_instruction(
4390 unwrap_lamports(
4391 &program_id,
4392 &account_key,
4393 &account2_key,
4394 &owner2_key,
4395 &[],
4396 Some(1000)
4397 )
4398 .unwrap(),
4399 vec![
4400 &mut account_account,
4401 &mut account2_account,
4402 &mut owner2_account,
4403 ],
4404 )
4405 );
4406
4407 let not_program_id = Address::new_unique();
4409 account_account.owner = not_program_id;
4410 assert_eq!(
4411 Err(ProgramError::IncorrectProgramId),
4412 do_process_instruction(
4413 unwrap_lamports(
4414 &program_id,
4415 &account_key,
4416 &account2_key,
4417 &owner_key,
4418 &[],
4419 Some(0)
4420 )
4421 .unwrap(),
4422 vec![
4423 &mut account_account,
4424 &mut account2_account,
4425 &mut owner2_account,
4426 ],
4427 )
4428 );
4429 account_account.owner = program_id;
4430
4431 do_process_instruction(
4433 unwrap_lamports(
4434 &program_id,
4435 &account_key,
4436 &account2_key,
4437 &owner_key,
4438 &[],
4439 Some(500),
4440 )
4441 .unwrap(),
4442 vec![
4443 &mut account_account,
4444 &mut account2_account,
4445 &mut owner_account,
4446 ],
4447 )
4448 .unwrap();
4449 let account = Account::unpack_unchecked(&account_account.data).unwrap();
4451 assert_eq!(account.amount, 500);
4452 assert_eq!(account_account.lamports(), 500 + account_minimum_balance());
4454 assert_eq!(
4455 account2_account.lamports(),
4456 zero_space_rent_exempt_balance + 500
4457 );
4458
4459 assert_eq!(
4461 Err(TokenError::InsufficientFunds.into()),
4462 do_process_instruction(
4463 unwrap_lamports(
4464 &program_id,
4465 &account_key,
4466 &account2_key,
4467 &owner_key,
4468 &[],
4469 Some(501)
4470 )
4471 .unwrap(),
4472 vec![
4473 &mut account_account,
4474 &mut account2_account,
4475 &mut owner_account,
4476 ],
4477 )
4478 );
4479
4480 do_process_instruction(
4482 unwrap_lamports(
4483 &program_id,
4484 &account_key,
4485 &account2_key,
4486 &owner_key,
4487 &[],
4488 None,
4489 )
4490 .unwrap(),
4491 vec![
4492 &mut account_account,
4493 &mut account2_account,
4494 &mut owner_account,
4495 ],
4496 )
4497 .unwrap();
4498 let account = Account::unpack_unchecked(&account_account.data).unwrap();
4500 assert_eq!(account.amount, 0);
4501 assert_eq!(account_account.lamports(), account_minimum_balance());
4503 assert_eq!(
4504 account2_account.lamports(),
4505 zero_space_rent_exempt_balance + 500 + 500
4506 );
4507 }
4508
4509 #[test]
4510 fn test_self_unwrap_lamports() {
4511 let program_id = crate::id();
4512 let account_key = Address::new_unique();
4513 let mut account_account = SolanaAccount::new(
4514 account_minimum_balance(),
4515 Account::get_packed_len(),
4516 &program_id,
4517 );
4518 let mismatch_account_key = Address::new_unique();
4519 let mut mismatch_account_account = SolanaAccount::new(
4520 account_minimum_balance(),
4521 Account::get_packed_len(),
4522 &program_id,
4523 );
4524 let owner_key = Address::new_unique();
4525 let mut owner_account = SolanaAccount::default();
4526 let owner2_key = Address::new_unique();
4527 let mut owner2_account = SolanaAccount::default();
4528 let mint_key = native_mint::id();
4529 let mut mint_account = native_mint();
4530 let mismatch_mint_key = Address::new_unique();
4531 let mut mismatch_mint_account =
4532 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
4533 let mut rent_sysvar = rent_sysvar();
4534
4535 do_process_instruction(
4537 initialize_mint(&program_id, &mismatch_mint_key, &owner_key, None, 2).unwrap(),
4538 vec![&mut mismatch_mint_account, &mut rent_sysvar],
4539 )
4540 .unwrap();
4541
4542 do_process_instruction(
4544 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
4545 vec![
4546 &mut account_account,
4547 &mut mint_account,
4548 &mut owner_account,
4549 &mut rent_sysvar,
4550 ],
4551 )
4552 .unwrap();
4553
4554 do_process_instruction(
4556 initialize_account(
4557 &program_id,
4558 &mismatch_account_key,
4559 &mismatch_mint_key,
4560 &owner_key,
4561 )
4562 .unwrap(),
4563 vec![
4564 &mut mismatch_account_account,
4565 &mut mismatch_mint_account,
4566 &mut owner_account,
4567 &mut rent_sysvar,
4568 ],
4569 )
4570 .unwrap();
4571
4572 let account_info = (&account_key, false, &mut account_account).into_account_info();
4573 let mismatch_account_info =
4574 (&mismatch_account_key, false, &mut mismatch_account_account).into_account_info();
4575 let owner_info = (&owner_key, true, &mut owner_account).into_account_info();
4576 let owner2_info = (&owner2_key, true, &mut owner2_account).into_account_info();
4577
4578 native_mint_to(&account_info, 1000).unwrap();
4580
4581 let instruction = unwrap_lamports(
4583 &program_id,
4584 account_info.key,
4585 account_info.key,
4586 owner_info.key,
4587 &[],
4588 Some(500),
4589 )
4590 .unwrap();
4591 assert_eq!(
4592 Ok(()),
4593 Processor::process(
4594 &instruction.program_id,
4595 &[
4596 account_info.clone(),
4597 account_info.clone(),
4598 owner_info.clone(),
4599 ],
4600 &instruction.data,
4601 )
4602 );
4603 let account = Account::unpack_unchecked(&account_info.try_borrow_data().unwrap()).unwrap();
4605 assert_eq!(account.amount, 500);
4606 assert_eq!(account_info.lamports(), 1000 + account_minimum_balance());
4608
4609 let instruction = unwrap_lamports(
4611 &program_id,
4612 account_info.key,
4613 account_info.key,
4614 owner_info.key,
4615 &[],
4616 Some(501),
4617 )
4618 .unwrap();
4619 assert_eq!(
4620 Err(TokenError::InsufficientFunds.into()),
4621 Processor::process(
4622 &instruction.program_id,
4623 &[
4624 account_info.clone(),
4625 account_info.clone(),
4626 owner_info.clone(),
4627 ],
4628 &instruction.data,
4629 )
4630 );
4631
4632 let mut owner_no_sign_info = owner_info.clone();
4634 let mut instruction = unwrap_lamports(
4635 &program_id,
4636 account_info.key,
4637 account_info.key,
4638 owner_no_sign_info.key,
4639 &[],
4640 Some(500),
4641 )
4642 .unwrap();
4643 instruction.accounts[2].is_signer = false;
4644 owner_no_sign_info.is_signer = false;
4645 assert_eq!(
4646 Err(ProgramError::MissingRequiredSignature),
4647 Processor::process(
4648 &instruction.program_id,
4649 &[
4650 account_info.clone(),
4651 account_info.clone(),
4652 owner_no_sign_info.clone(),
4653 ],
4654 &instruction.data,
4655 )
4656 );
4657
4658 let instruction = unwrap_lamports(
4660 &program_id,
4661 mismatch_account_info.key,
4662 mismatch_account_info.key,
4663 owner_info.key,
4664 &[],
4665 None,
4666 )
4667 .unwrap();
4668 assert_eq!(
4669 Err(TokenError::NonNativeNotSupported.into()),
4670 Processor::process(
4671 &instruction.program_id,
4672 &[
4673 mismatch_account_info.clone(),
4674 mismatch_account_info.clone(),
4675 owner_info.clone(),
4676 ],
4677 &instruction.data,
4678 )
4679 );
4680
4681 let instruction = unwrap_lamports(
4683 &program_id,
4684 account_info.key,
4685 account_info.key,
4686 owner2_info.key,
4687 &[],
4688 Some(500),
4689 )
4690 .unwrap();
4691 assert_eq!(
4692 Err(TokenError::OwnerMismatch.into()),
4693 Processor::process(
4694 &instruction.program_id,
4695 &[
4696 account_info.clone(),
4697 account_info.clone(),
4698 owner2_info.clone(),
4699 ],
4700 &instruction.data,
4701 )
4702 );
4703
4704 let instruction = unwrap_lamports(
4706 &program_id,
4707 account_info.key,
4708 account_info.key,
4709 owner_info.key,
4710 &[],
4711 None,
4712 )
4713 .unwrap();
4714 assert_eq!(
4715 Ok(()),
4716 Processor::process(
4717 &instruction.program_id,
4718 &[
4719 account_info.clone(),
4720 account_info.clone(),
4721 owner_info.clone(),
4722 ],
4723 &instruction.data,
4724 )
4725 );
4726 let account = Account::unpack_unchecked(&account_info.try_borrow_data().unwrap()).unwrap();
4728 assert_eq!(account.amount, 0);
4729 assert_eq!(account_info.lamports(), 1000 + account_minimum_balance());
4731 }
4732
4733 #[test]
4734 fn test_mintable_token_with_zero_supply() {
4735 let program_id = crate::id();
4736 let account_key = Address::new_unique();
4737 let mut account_account = SolanaAccount::new(
4738 account_minimum_balance(),
4739 Account::get_packed_len(),
4740 &program_id,
4741 );
4742 let owner_key = Address::new_unique();
4743 let mut owner_account = SolanaAccount::default();
4744 let mint_key = Address::new_unique();
4745 let mut mint_account =
4746 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
4747 let mut rent_sysvar = rent_sysvar();
4748
4749 let decimals = 2;
4751 do_process_instruction(
4752 initialize_mint(&program_id, &mint_key, &owner_key, None, decimals).unwrap(),
4753 vec![&mut mint_account, &mut rent_sysvar],
4754 )
4755 .unwrap();
4756 let mint = Mint::unpack_unchecked(&mint_account.data).unwrap();
4757 assert_eq!(
4758 mint,
4759 Mint {
4760 mint_authority: COption::Some(owner_key),
4761 supply: 0,
4762 decimals,
4763 is_initialized: true,
4764 freeze_authority: COption::None,
4765 }
4766 );
4767
4768 do_process_instruction(
4770 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
4771 vec![
4772 &mut account_account,
4773 &mut mint_account,
4774 &mut owner_account,
4775 &mut rent_sysvar,
4776 ],
4777 )
4778 .unwrap();
4779
4780 do_process_instruction(
4782 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 42).unwrap(),
4783 vec![&mut mint_account, &mut account_account, &mut owner_account],
4784 )
4785 .unwrap();
4786 let _ = Mint::unpack(&mint_account.data).unwrap();
4787 let account = Account::unpack_unchecked(&account_account.data).unwrap();
4788 assert_eq!(account.amount, 42);
4789
4790 assert_eq!(
4792 Err(TokenError::MintDecimalsMismatch.into()),
4793 do_process_instruction(
4794 mint_to_checked(
4795 &program_id,
4796 &mint_key,
4797 &account_key,
4798 &owner_key,
4799 &[],
4800 42,
4801 decimals + 1
4802 )
4803 .unwrap(),
4804 vec![&mut mint_account, &mut account_account, &mut owner_account],
4805 )
4806 );
4807
4808 let _ = Mint::unpack(&mint_account.data).unwrap();
4809 let account = Account::unpack_unchecked(&account_account.data).unwrap();
4810 assert_eq!(account.amount, 42);
4811
4812 do_process_instruction(
4814 mint_to_checked(
4815 &program_id,
4816 &mint_key,
4817 &account_key,
4818 &owner_key,
4819 &[],
4820 42,
4821 decimals,
4822 )
4823 .unwrap(),
4824 vec![&mut mint_account, &mut account_account, &mut owner_account],
4825 )
4826 .unwrap();
4827 let _ = Mint::unpack(&mint_account.data).unwrap();
4828 let account = Account::unpack_unchecked(&account_account.data).unwrap();
4829 assert_eq!(account.amount, 84);
4830 }
4831
4832 #[test]
4833 fn test_approve_dups() {
4834 let program_id = crate::id();
4835 let account1_key = Address::new_unique();
4836 let mut account1_account = SolanaAccount::new(
4837 account_minimum_balance(),
4838 Account::get_packed_len(),
4839 &program_id,
4840 );
4841 let account1_info: AccountInfo = (&account1_key, true, &mut account1_account).into();
4842 let account2_key = Address::new_unique();
4843 let mut account2_account = SolanaAccount::new(
4844 account_minimum_balance(),
4845 Account::get_packed_len(),
4846 &program_id,
4847 );
4848 let account2_info: AccountInfo = (&account2_key, false, &mut account2_account).into();
4849 let account3_key = Address::new_unique();
4850 let mut account3_account = SolanaAccount::new(
4851 account_minimum_balance(),
4852 Account::get_packed_len(),
4853 &program_id,
4854 );
4855 let account3_info: AccountInfo = (&account3_key, true, &mut account3_account).into();
4856 let multisig_key = Address::new_unique();
4857 let mut multisig_account = SolanaAccount::new(
4858 multisig_minimum_balance(),
4859 Multisig::get_packed_len(),
4860 &program_id,
4861 );
4862 let multisig_info: AccountInfo = (&multisig_key, true, &mut multisig_account).into();
4863 let owner_key = Address::new_unique();
4864 let mut owner_account = SolanaAccount::default();
4865 let owner_info: AccountInfo = (&owner_key, true, &mut owner_account).into();
4866 let mint_key = Address::new_unique();
4867 let mut mint_account =
4868 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
4869 let mint_info: AccountInfo = (&mint_key, false, &mut mint_account).into();
4870 let rent_key = rent::id();
4871 let mut rent_sysvar = rent_sysvar();
4872 let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
4873
4874 do_process_instruction_dups(
4876 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
4877 vec![mint_info.clone(), rent_info.clone()],
4878 )
4879 .unwrap();
4880
4881 do_process_instruction_dups(
4883 initialize_account(&program_id, &account1_key, &mint_key, &account1_key).unwrap(),
4884 vec![
4885 account1_info.clone(),
4886 mint_info.clone(),
4887 account1_info.clone(),
4888 rent_info.clone(),
4889 ],
4890 )
4891 .unwrap();
4892
4893 do_process_instruction_dups(
4895 initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
4896 vec![
4897 account2_info.clone(),
4898 mint_info.clone(),
4899 owner_info.clone(),
4900 rent_info.clone(),
4901 ],
4902 )
4903 .unwrap();
4904
4905 do_process_instruction_dups(
4907 mint_to(&program_id, &mint_key, &account1_key, &owner_key, &[], 1000).unwrap(),
4908 vec![mint_info.clone(), account1_info.clone(), owner_info.clone()],
4909 )
4910 .unwrap();
4911
4912 do_process_instruction_dups(
4914 approve(
4915 &program_id,
4916 &account1_key,
4917 &account2_key,
4918 &account1_key,
4919 &[],
4920 500,
4921 )
4922 .unwrap(),
4923 vec![
4924 account1_info.clone(),
4925 account2_info.clone(),
4926 account1_info.clone(),
4927 ],
4928 )
4929 .unwrap();
4930
4931 do_process_instruction_dups(
4933 approve_checked(
4934 &program_id,
4935 &account1_key,
4936 &mint_key,
4937 &account2_key,
4938 &account1_key,
4939 &[],
4940 500,
4941 2,
4942 )
4943 .unwrap(),
4944 vec![
4945 account1_info.clone(),
4946 mint_info.clone(),
4947 account2_info.clone(),
4948 account1_info.clone(),
4949 ],
4950 )
4951 .unwrap();
4952
4953 do_process_instruction_dups(
4955 revoke(&program_id, &account1_key, &account1_key, &[]).unwrap(),
4956 vec![account1_info.clone(), account1_info.clone()],
4957 )
4958 .unwrap();
4959
4960 do_process_instruction_dups(
4962 initialize_multisig(&program_id, &multisig_key, &[&account3_key], 1).unwrap(),
4963 vec![
4964 multisig_info.clone(),
4965 rent_info.clone(),
4966 account3_info.clone(),
4967 ],
4968 )
4969 .unwrap();
4970
4971 do_process_instruction_dups(
4972 initialize_account(&program_id, &account3_key, &mint_key, &multisig_key).unwrap(),
4973 vec![
4974 account3_info.clone(),
4975 mint_info.clone(),
4976 multisig_info.clone(),
4977 rent_info.clone(),
4978 ],
4979 )
4980 .unwrap();
4981
4982 do_process_instruction_dups(
4983 mint_to(&program_id, &mint_key, &account3_key, &owner_key, &[], 1000).unwrap(),
4984 vec![mint_info.clone(), account3_info.clone(), owner_info.clone()],
4985 )
4986 .unwrap();
4987
4988 do_process_instruction_dups(
4990 approve(
4991 &program_id,
4992 &account3_key,
4993 &account2_key,
4994 &multisig_key,
4995 &[&account3_key],
4996 500,
4997 )
4998 .unwrap(),
4999 vec![
5000 account3_info.clone(),
5001 account2_info.clone(),
5002 multisig_info.clone(),
5003 account3_info.clone(),
5004 ],
5005 )
5006 .unwrap();
5007
5008 do_process_instruction_dups(
5010 approve_checked(
5011 &program_id,
5012 &account3_key,
5013 &mint_key,
5014 &account2_key,
5015 &multisig_key,
5016 &[&account3_key],
5017 500,
5018 2,
5019 )
5020 .unwrap(),
5021 vec![
5022 account3_info.clone(),
5023 mint_info.clone(),
5024 account2_info.clone(),
5025 multisig_info.clone(),
5026 account3_info.clone(),
5027 ],
5028 )
5029 .unwrap();
5030
5031 do_process_instruction_dups(
5033 revoke(&program_id, &account3_key, &multisig_key, &[&account3_key]).unwrap(),
5034 vec![
5035 account3_info.clone(),
5036 multisig_info.clone(),
5037 account3_info.clone(),
5038 ],
5039 )
5040 .unwrap();
5041
5042 do_process_instruction_dups(
5044 approve_checked(
5045 &program_id,
5046 &account2_key,
5047 &mint_key,
5048 &account2_key,
5049 &owner_key,
5050 &[],
5051 500,
5052 2,
5053 )
5054 .unwrap(),
5055 vec![
5056 account2_info.clone(),
5057 mint_info.clone(),
5058 account2_info.clone(),
5059 owner_info.clone(),
5060 ],
5061 )
5062 .unwrap();
5063
5064 let account2_info: AccountInfo = (&account2_key, true, &mut account2_account).into();
5066 do_process_instruction_dups(
5067 revoke(&program_id, &account2_key, &account2_key, &[]).unwrap(),
5068 vec![account2_info.clone(), account2_info.clone()],
5069 )
5070 .unwrap();
5071 }
5072
5073 #[test]
5074 fn test_approve() {
5075 let program_id = crate::id();
5076 let account_key = Address::new_unique();
5077 let mut account_account = SolanaAccount::new(
5078 account_minimum_balance(),
5079 Account::get_packed_len(),
5080 &program_id,
5081 );
5082 let account2_key = Address::new_unique();
5083 let mut account2_account = SolanaAccount::new(
5084 account_minimum_balance(),
5085 Account::get_packed_len(),
5086 &program_id,
5087 );
5088 let delegate_key = Address::new_unique();
5089 let mut delegate_account = SolanaAccount::default();
5090 let owner_key = Address::new_unique();
5091 let mut owner_account = SolanaAccount::default();
5092 let owner2_key = Address::new_unique();
5093 let mut owner2_account = SolanaAccount::default();
5094 let mint_key = Address::new_unique();
5095 let mut mint_account =
5096 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
5097 let mut rent_sysvar = rent_sysvar();
5098
5099 do_process_instruction(
5101 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
5102 vec![&mut mint_account, &mut rent_sysvar],
5103 )
5104 .unwrap();
5105
5106 do_process_instruction(
5108 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
5109 vec![
5110 &mut account_account,
5111 &mut mint_account,
5112 &mut owner_account,
5113 &mut rent_sysvar,
5114 ],
5115 )
5116 .unwrap();
5117
5118 do_process_instruction(
5120 initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
5121 vec![
5122 &mut account2_account,
5123 &mut mint_account,
5124 &mut owner_account,
5125 &mut rent_sysvar,
5126 ],
5127 )
5128 .unwrap();
5129
5130 do_process_instruction(
5132 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
5133 vec![&mut mint_account, &mut account_account, &mut owner_account],
5134 )
5135 .unwrap();
5136
5137 let mut instruction = approve(
5139 &program_id,
5140 &account_key,
5141 &delegate_key,
5142 &owner_key,
5143 &[],
5144 100,
5145 )
5146 .unwrap();
5147 instruction.accounts[2].is_signer = false;
5148 assert_eq!(
5149 Err(ProgramError::MissingRequiredSignature),
5150 do_process_instruction(
5151 instruction,
5152 vec![
5153 &mut account_account,
5154 &mut delegate_account,
5155 &mut owner_account,
5156 ],
5157 )
5158 );
5159
5160 assert_eq!(
5162 Err(TokenError::OwnerMismatch.into()),
5163 do_process_instruction(
5164 approve(
5165 &program_id,
5166 &account_key,
5167 &delegate_key,
5168 &owner2_key,
5169 &[],
5170 100
5171 )
5172 .unwrap(),
5173 vec![
5174 &mut account_account,
5175 &mut delegate_account,
5176 &mut owner2_account,
5177 ],
5178 )
5179 );
5180
5181 do_process_instruction(
5183 approve(
5184 &program_id,
5185 &account_key,
5186 &delegate_key,
5187 &owner_key,
5188 &[],
5189 100,
5190 )
5191 .unwrap(),
5192 vec![
5193 &mut account_account,
5194 &mut delegate_account,
5195 &mut owner_account,
5196 ],
5197 )
5198 .unwrap();
5199
5200 assert_eq!(
5202 Err(TokenError::MintDecimalsMismatch.into()),
5203 do_process_instruction(
5204 approve_checked(
5205 &program_id,
5206 &account_key,
5207 &mint_key,
5208 &delegate_key,
5209 &owner_key,
5210 &[],
5211 100,
5212 0 )
5214 .unwrap(),
5215 vec![
5216 &mut account_account,
5217 &mut mint_account,
5218 &mut delegate_account,
5219 &mut owner_account,
5220 ],
5221 )
5222 );
5223
5224 assert_eq!(
5226 Err(TokenError::MintMismatch.into()),
5227 do_process_instruction(
5228 approve_checked(
5229 &program_id,
5230 &account_key,
5231 &account2_key, &delegate_key,
5233 &owner_key,
5234 &[],
5235 100,
5236 0
5237 )
5238 .unwrap(),
5239 vec![
5240 &mut account_account,
5241 &mut account2_account, &mut delegate_account,
5243 &mut owner_account,
5244 ],
5245 )
5246 );
5247
5248 do_process_instruction(
5250 approve_checked(
5251 &program_id,
5252 &account_key,
5253 &mint_key,
5254 &delegate_key,
5255 &owner_key,
5256 &[],
5257 100,
5258 2,
5259 )
5260 .unwrap(),
5261 vec![
5262 &mut account_account,
5263 &mut mint_account,
5264 &mut delegate_account,
5265 &mut owner_account,
5266 ],
5267 )
5268 .unwrap();
5269
5270 do_process_instruction(
5272 revoke(&program_id, &account_key, &owner_key, &[]).unwrap(),
5273 vec![&mut account_account, &mut owner_account],
5274 )
5275 .unwrap();
5276
5277 do_process_instruction(
5279 approve_checked(
5280 &program_id,
5281 &account_key,
5282 &mint_key,
5283 &delegate_key,
5284 &owner_key,
5285 &[],
5286 100,
5287 2,
5288 )
5289 .unwrap(),
5290 vec![
5291 &mut account_account,
5292 &mut mint_account,
5293 &mut delegate_account,
5294 &mut owner_account,
5295 ],
5296 )
5297 .unwrap();
5298
5299 do_process_instruction(
5301 revoke(&program_id, &account_key, &delegate_key, &[]).unwrap(),
5302 vec![&mut account_account, &mut delegate_account],
5303 )
5304 .unwrap();
5305
5306 assert_eq!(
5308 Err(TokenError::OwnerMismatch.into()),
5309 do_process_instruction(
5310 revoke(&program_id, &account_key, &delegate_key, &[]).unwrap(),
5311 vec![&mut account_account, &mut delegate_account],
5312 )
5313 );
5314 }
5315
5316 #[test]
5317 fn test_set_authority_dups() {
5318 let program_id = crate::id();
5319 let account1_key = Address::new_unique();
5320 let mut account1_account = SolanaAccount::new(
5321 account_minimum_balance(),
5322 Account::get_packed_len(),
5323 &program_id,
5324 );
5325 let account1_info: AccountInfo = (&account1_key, true, &mut account1_account).into();
5326 let owner_key = Address::new_unique();
5327 let mint_key = Address::new_unique();
5328 let mut mint_account =
5329 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
5330 let mint_info: AccountInfo = (&mint_key, true, &mut mint_account).into();
5331 let rent_key = rent::id();
5332 let mut rent_sysvar = rent_sysvar();
5333 let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
5334
5335 do_process_instruction_dups(
5337 initialize_mint(&program_id, &mint_key, &mint_key, Some(&mint_key), 2).unwrap(),
5338 vec![mint_info.clone(), rent_info.clone()],
5339 )
5340 .unwrap();
5341
5342 do_process_instruction_dups(
5344 initialize_account(&program_id, &account1_key, &mint_key, &account1_key).unwrap(),
5345 vec![
5346 account1_info.clone(),
5347 mint_info.clone(),
5348 account1_info.clone(),
5349 rent_info.clone(),
5350 ],
5351 )
5352 .unwrap();
5353
5354 do_process_instruction_dups(
5356 set_authority(
5357 &program_id,
5358 &mint_key,
5359 Some(&owner_key),
5360 AuthorityType::MintTokens,
5361 &mint_key,
5362 &[],
5363 )
5364 .unwrap(),
5365 vec![mint_info.clone(), mint_info.clone()],
5366 )
5367 .unwrap();
5368
5369 do_process_instruction_dups(
5371 set_authority(
5372 &program_id,
5373 &mint_key,
5374 Some(&owner_key),
5375 AuthorityType::FreezeAccount,
5376 &mint_key,
5377 &[],
5378 )
5379 .unwrap(),
5380 vec![mint_info.clone(), mint_info.clone()],
5381 )
5382 .unwrap();
5383
5384 do_process_instruction_dups(
5386 set_authority(
5387 &program_id,
5388 &account1_key,
5389 Some(&owner_key),
5390 AuthorityType::AccountOwner,
5391 &account1_key,
5392 &[],
5393 )
5394 .unwrap(),
5395 vec![account1_info.clone(), account1_info.clone()],
5396 )
5397 .unwrap();
5398
5399 let mut account = Account::unpack_unchecked(&account1_info.data.borrow()).unwrap();
5401 account.close_authority = COption::Some(account1_key);
5402 Account::pack(account, &mut account1_info.data.borrow_mut()).unwrap();
5403
5404 do_process_instruction_dups(
5405 set_authority(
5406 &program_id,
5407 &account1_key,
5408 Some(&owner_key),
5409 AuthorityType::CloseAccount,
5410 &account1_key,
5411 &[],
5412 )
5413 .unwrap(),
5414 vec![account1_info.clone(), account1_info.clone()],
5415 )
5416 .unwrap();
5417 }
5418
5419 #[test]
5420 fn test_set_authority() {
5421 let program_id = crate::id();
5422 let account_key = Address::new_unique();
5423 let mut account_account = SolanaAccount::new(
5424 account_minimum_balance(),
5425 Account::get_packed_len(),
5426 &program_id,
5427 );
5428 let account2_key = Address::new_unique();
5429 let mut account2_account = SolanaAccount::new(
5430 account_minimum_balance(),
5431 Account::get_packed_len(),
5432 &program_id,
5433 );
5434 let owner_key = Address::new_unique();
5435 let mut owner_account = SolanaAccount::default();
5436 let owner2_key = Address::new_unique();
5437 let mut owner2_account = SolanaAccount::default();
5438 let owner3_key = Address::new_unique();
5439 let mut owner3_account = SolanaAccount::default();
5440 let mint_key = Address::new_unique();
5441 let mut mint_account =
5442 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
5443 let mint2_key = Address::new_unique();
5444 let mut mint2_account =
5445 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
5446 let mut rent_sysvar = rent_sysvar();
5447
5448 do_process_instruction(
5450 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
5451 vec![&mut mint_account, &mut rent_sysvar],
5452 )
5453 .unwrap();
5454
5455 do_process_instruction(
5457 initialize_mint(&program_id, &mint2_key, &owner_key, Some(&owner_key), 2).unwrap(),
5458 vec![&mut mint2_account, &mut rent_sysvar],
5459 )
5460 .unwrap();
5461
5462 assert_eq!(
5464 Err(ProgramError::InvalidAccountData),
5465 do_process_instruction(
5466 set_authority(
5467 &program_id,
5468 &account_key,
5469 Some(&owner2_key),
5470 AuthorityType::AccountOwner,
5471 &owner_key,
5472 &[]
5473 )
5474 .unwrap(),
5475 vec![&mut account_account, &mut owner_account],
5476 )
5477 );
5478
5479 do_process_instruction(
5481 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
5482 vec![
5483 &mut account_account,
5484 &mut mint_account,
5485 &mut owner_account,
5486 &mut rent_sysvar,
5487 ],
5488 )
5489 .unwrap();
5490
5491 do_process_instruction(
5493 initialize_account(&program_id, &account2_key, &mint2_key, &owner_key).unwrap(),
5494 vec![
5495 &mut account2_account,
5496 &mut mint2_account,
5497 &mut owner_account,
5498 &mut rent_sysvar,
5499 ],
5500 )
5501 .unwrap();
5502
5503 assert_eq!(
5505 Err(TokenError::OwnerMismatch.into()),
5506 do_process_instruction(
5507 set_authority(
5508 &program_id,
5509 &account_key,
5510 Some(&owner_key),
5511 AuthorityType::AccountOwner,
5512 &owner2_key,
5513 &[]
5514 )
5515 .unwrap(),
5516 vec![&mut account_account, &mut owner2_account],
5517 )
5518 );
5519
5520 let mut instruction = set_authority(
5522 &program_id,
5523 &account_key,
5524 Some(&owner2_key),
5525 AuthorityType::AccountOwner,
5526 &owner_key,
5527 &[],
5528 )
5529 .unwrap();
5530 instruction.accounts[1].is_signer = false;
5531 assert_eq!(
5532 Err(ProgramError::MissingRequiredSignature),
5533 do_process_instruction(instruction, vec![&mut account_account, &mut owner_account,],)
5534 );
5535
5536 assert_eq!(
5538 Err(TokenError::AuthorityTypeNotSupported.into()),
5539 do_process_instruction(
5540 set_authority(
5541 &program_id,
5542 &account_key,
5543 Some(&owner2_key),
5544 AuthorityType::FreezeAccount,
5545 &owner_key,
5546 &[],
5547 )
5548 .unwrap(),
5549 vec![&mut account_account, &mut owner_account],
5550 )
5551 );
5552
5553 assert_eq!(
5555 Err(TokenError::InvalidInstruction.into()),
5556 do_process_instruction(
5557 set_authority(
5558 &program_id,
5559 &account_key,
5560 None,
5561 AuthorityType::AccountOwner,
5562 &owner_key,
5563 &[],
5564 )
5565 .unwrap(),
5566 vec![&mut account_account, &mut owner_account],
5567 )
5568 );
5569
5570 do_process_instruction(
5572 approve(
5573 &program_id,
5574 &account_key,
5575 &owner2_key,
5576 &owner_key,
5577 &[],
5578 u64::MAX,
5579 )
5580 .unwrap(),
5581 vec![
5582 &mut account_account,
5583 &mut owner2_account,
5584 &mut owner_account,
5585 ],
5586 )
5587 .unwrap();
5588 let account = Account::unpack_unchecked(&account_account.data).unwrap();
5589 assert_eq!(account.delegate, COption::Some(owner2_key));
5590 assert_eq!(account.delegated_amount, u64::MAX);
5591
5592 do_process_instruction(
5594 set_authority(
5595 &program_id,
5596 &account_key,
5597 Some(&owner3_key),
5598 AuthorityType::AccountOwner,
5599 &owner_key,
5600 &[],
5601 )
5602 .unwrap(),
5603 vec![&mut account_account, &mut owner_account],
5604 )
5605 .unwrap();
5606
5607 let account = Account::unpack_unchecked(&account_account.data).unwrap();
5609 assert_eq!(account.delegate, COption::None);
5610 assert_eq!(account.delegated_amount, 0);
5611
5612 do_process_instruction(
5614 set_authority(
5615 &program_id,
5616 &account_key,
5617 Some(&owner2_key),
5618 AuthorityType::AccountOwner,
5619 &owner3_key,
5620 &[],
5621 )
5622 .unwrap(),
5623 vec![&mut account_account, &mut owner3_account],
5624 )
5625 .unwrap();
5626
5627 do_process_instruction(
5629 set_authority(
5630 &program_id,
5631 &account_key,
5632 Some(&owner2_key),
5633 AuthorityType::CloseAccount,
5634 &owner2_key,
5635 &[],
5636 )
5637 .unwrap(),
5638 vec![&mut account_account, &mut owner2_account],
5639 )
5640 .unwrap();
5641
5642 do_process_instruction(
5644 set_authority(
5645 &program_id,
5646 &account_key,
5647 None,
5648 AuthorityType::CloseAccount,
5649 &owner2_key,
5650 &[],
5651 )
5652 .unwrap(),
5653 vec![&mut account_account, &mut owner2_account],
5654 )
5655 .unwrap();
5656
5657 assert_eq!(
5659 Err(TokenError::OwnerMismatch.into()),
5660 do_process_instruction(
5661 set_authority(
5662 &program_id,
5663 &mint_key,
5664 Some(&owner3_key),
5665 AuthorityType::MintTokens,
5666 &owner2_key,
5667 &[]
5668 )
5669 .unwrap(),
5670 vec![&mut mint_account, &mut owner2_account],
5671 )
5672 );
5673
5674 let mut instruction = set_authority(
5676 &program_id,
5677 &mint_key,
5678 Some(&owner2_key),
5679 AuthorityType::MintTokens,
5680 &owner_key,
5681 &[],
5682 )
5683 .unwrap();
5684 instruction.accounts[1].is_signer = false;
5685 assert_eq!(
5686 Err(ProgramError::MissingRequiredSignature),
5687 do_process_instruction(instruction, vec![&mut mint_account, &mut owner_account],)
5688 );
5689
5690 assert_eq!(
5692 Err(TokenError::MintCannotFreeze.into()),
5693 do_process_instruction(
5694 set_authority(
5695 &program_id,
5696 &mint_key,
5697 Some(&owner2_key),
5698 AuthorityType::FreezeAccount,
5699 &owner_key,
5700 &[],
5701 )
5702 .unwrap(),
5703 vec![&mut mint_account, &mut owner_account],
5704 )
5705 );
5706
5707 do_process_instruction(
5709 set_authority(
5710 &program_id,
5711 &mint_key,
5712 Some(&owner2_key),
5713 AuthorityType::MintTokens,
5714 &owner_key,
5715 &[],
5716 )
5717 .unwrap(),
5718 vec![&mut mint_account, &mut owner_account],
5719 )
5720 .unwrap();
5721
5722 do_process_instruction(
5724 set_authority(
5725 &program_id,
5726 &mint_key,
5727 None,
5728 AuthorityType::MintTokens,
5729 &owner2_key,
5730 &[],
5731 )
5732 .unwrap(),
5733 vec![&mut mint_account, &mut owner2_account],
5734 )
5735 .unwrap();
5736
5737 assert_eq!(
5739 Err(TokenError::FixedSupply.into()),
5740 do_process_instruction(
5741 set_authority(
5742 &program_id,
5743 &mint2_key,
5744 Some(&owner2_key),
5745 AuthorityType::MintTokens,
5746 &owner_key,
5747 &[]
5748 )
5749 .unwrap(),
5750 vec![&mut mint_account, &mut owner_account],
5751 )
5752 );
5753
5754 do_process_instruction(
5756 set_authority(
5757 &program_id,
5758 &mint2_key,
5759 Some(&owner2_key),
5760 AuthorityType::FreezeAccount,
5761 &owner_key,
5762 &[],
5763 )
5764 .unwrap(),
5765 vec![&mut mint2_account, &mut owner_account],
5766 )
5767 .unwrap();
5768
5769 do_process_instruction(
5771 set_authority(
5772 &program_id,
5773 &mint2_key,
5774 None,
5775 AuthorityType::FreezeAccount,
5776 &owner2_key,
5777 &[],
5778 )
5779 .unwrap(),
5780 vec![&mut mint2_account, &mut owner2_account],
5781 )
5782 .unwrap();
5783
5784 assert_eq!(
5785 Err(TokenError::MintCannotFreeze.into()),
5786 do_process_instruction(
5787 set_authority(
5788 &program_id,
5789 &mint2_key,
5790 Some(&owner2_key),
5791 AuthorityType::FreezeAccount,
5792 &owner_key,
5793 &[],
5794 )
5795 .unwrap(),
5796 vec![&mut mint2_account, &mut owner2_account],
5797 )
5798 );
5799 }
5800
5801 #[test]
5802 fn test_set_authority_with_immutable_owner_extension() {
5803 let program_id = crate::id();
5804 let account_key = Address::new_unique();
5805
5806 let account_len =
5807 ExtensionType::try_calculate_account_len::<Account>(&[ExtensionType::ImmutableOwner])
5808 .unwrap();
5809 let mut account_account = SolanaAccount::new(
5810 Rent::default().minimum_balance(account_len),
5811 account_len,
5812 &program_id,
5813 );
5814 let owner_key = Address::new_unique();
5815 let mut owner_account = SolanaAccount::default();
5816 let owner2_key = Address::new_unique();
5817
5818 let mint_key = Address::new_unique();
5819 let mut mint_account =
5820 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
5821 let mut rent_sysvar = rent_sysvar();
5822
5823 assert_eq!(
5825 Ok(()),
5826 do_process_instruction(
5827 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
5828 vec![&mut mint_account, &mut rent_sysvar],
5829 )
5830 );
5831
5832 assert_eq!(
5834 Ok(()),
5835 do_process_instruction(
5836 initialize_immutable_owner(&program_id, &account_key).unwrap(),
5837 vec![&mut account_account],
5838 )
5839 );
5840 assert_eq!(
5841 Ok(()),
5842 do_process_instruction(
5843 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
5844 vec![
5845 &mut account_account,
5846 &mut mint_account,
5847 &mut owner_account,
5848 &mut rent_sysvar,
5849 ],
5850 )
5851 );
5852
5853 assert_eq!(
5855 Err(TokenError::ImmutableOwner.into()),
5856 do_process_instruction(
5857 set_authority(
5858 &program_id,
5859 &account_key,
5860 Some(&owner2_key),
5861 AuthorityType::AccountOwner,
5862 &owner_key,
5863 &[],
5864 )
5865 .unwrap(),
5866 vec![&mut account_account, &mut owner_account],
5867 )
5868 );
5869 }
5870
5871 #[test]
5872 fn test_mint_to_dups() {
5873 let program_id = crate::id();
5874 let account1_key = Address::new_unique();
5875 let mut account1_account = SolanaAccount::new(
5876 account_minimum_balance(),
5877 Account::get_packed_len(),
5878 &program_id,
5879 );
5880 let account1_info: AccountInfo = (&account1_key, true, &mut account1_account).into();
5881 let owner_key = Address::new_unique();
5882 let mut owner_account = SolanaAccount::default();
5883 let owner_info: AccountInfo = (&owner_key, true, &mut owner_account).into();
5884 let mint_key = Address::new_unique();
5885 let mut mint_account =
5886 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
5887 let mint_info: AccountInfo = (&mint_key, true, &mut mint_account).into();
5888 let rent_key = rent::id();
5889 let mut rent_sysvar = rent_sysvar();
5890 let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
5891
5892 do_process_instruction_dups(
5894 initialize_mint(&program_id, &mint_key, &mint_key, None, 2).unwrap(),
5895 vec![mint_info.clone(), rent_info.clone()],
5896 )
5897 .unwrap();
5898
5899 do_process_instruction_dups(
5901 initialize_account(&program_id, &account1_key, &mint_key, &owner_key).unwrap(),
5902 vec![
5903 account1_info.clone(),
5904 mint_info.clone(),
5905 owner_info.clone(),
5906 rent_info.clone(),
5907 ],
5908 )
5909 .unwrap();
5910
5911 do_process_instruction_dups(
5913 mint_to(&program_id, &mint_key, &account1_key, &mint_key, &[], 42).unwrap(),
5914 vec![mint_info.clone(), account1_info.clone(), mint_info.clone()],
5915 )
5916 .unwrap();
5917
5918 do_process_instruction_dups(
5920 mint_to_checked(&program_id, &mint_key, &account1_key, &mint_key, &[], 42, 2).unwrap(),
5921 vec![mint_info.clone(), account1_info.clone(), mint_info.clone()],
5922 )
5923 .unwrap();
5924
5925 let mut mint = Mint::unpack_unchecked(&mint_info.data.borrow()).unwrap();
5927 mint.mint_authority = COption::Some(account1_key);
5928 Mint::pack(mint, &mut mint_info.data.borrow_mut()).unwrap();
5929 do_process_instruction_dups(
5930 mint_to(
5931 &program_id,
5932 &mint_key,
5933 &account1_key,
5934 &account1_key,
5935 &[],
5936 42,
5937 )
5938 .unwrap(),
5939 vec![
5940 mint_info.clone(),
5941 account1_info.clone(),
5942 account1_info.clone(),
5943 ],
5944 )
5945 .unwrap();
5946
5947 do_process_instruction_dups(
5949 mint_to(
5950 &program_id,
5951 &mint_key,
5952 &account1_key,
5953 &account1_key,
5954 &[],
5955 42,
5956 )
5957 .unwrap(),
5958 vec![
5959 mint_info.clone(),
5960 account1_info.clone(),
5961 account1_info.clone(),
5962 ],
5963 )
5964 .unwrap();
5965 }
5966
5967 #[test]
5968 fn test_mint_to() {
5969 let program_id = crate::id();
5970 let account_key = Address::new_unique();
5971 let mut account_account = SolanaAccount::new(
5972 account_minimum_balance(),
5973 Account::get_packed_len(),
5974 &program_id,
5975 );
5976 let account2_key = Address::new_unique();
5977 let mut account2_account = SolanaAccount::new(
5978 account_minimum_balance(),
5979 Account::get_packed_len(),
5980 &program_id,
5981 );
5982 let account3_key = Address::new_unique();
5983 let mut account3_account = SolanaAccount::new(
5984 account_minimum_balance(),
5985 Account::get_packed_len(),
5986 &program_id,
5987 );
5988 let mismatch_key = Address::new_unique();
5989 let mut mismatch_account = SolanaAccount::new(
5990 account_minimum_balance(),
5991 Account::get_packed_len(),
5992 &program_id,
5993 );
5994 let owner_key = Address::new_unique();
5995 let mut owner_account = SolanaAccount::default();
5996 let owner2_key = Address::new_unique();
5997 let mut owner2_account = SolanaAccount::default();
5998 let mint_key = Address::new_unique();
5999 let mut mint_account =
6000 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
6001 let mint2_key = Address::new_unique();
6002 let uninitialized_key = Address::new_unique();
6003 let mut uninitialized_account = SolanaAccount::new(
6004 account_minimum_balance(),
6005 Account::get_packed_len(),
6006 &program_id,
6007 );
6008 let mut rent_sysvar = rent_sysvar();
6009
6010 do_process_instruction(
6012 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
6013 vec![&mut mint_account, &mut rent_sysvar],
6014 )
6015 .unwrap();
6016
6017 do_process_instruction(
6019 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
6020 vec![
6021 &mut account_account,
6022 &mut mint_account,
6023 &mut owner_account,
6024 &mut rent_sysvar,
6025 ],
6026 )
6027 .unwrap();
6028
6029 do_process_instruction(
6031 initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
6032 vec![
6033 &mut account2_account,
6034 &mut mint_account,
6035 &mut owner_account,
6036 &mut rent_sysvar,
6037 ],
6038 )
6039 .unwrap();
6040
6041 do_process_instruction(
6043 initialize_account(&program_id, &account3_key, &mint_key, &owner_key).unwrap(),
6044 vec![
6045 &mut account3_account,
6046 &mut mint_account,
6047 &mut owner_account,
6048 &mut rent_sysvar,
6049 ],
6050 )
6051 .unwrap();
6052
6053 do_process_instruction(
6055 initialize_account(&program_id, &mismatch_key, &mint_key, &owner_key).unwrap(),
6056 vec![
6057 &mut mismatch_account,
6058 &mut mint_account,
6059 &mut owner_account,
6060 &mut rent_sysvar,
6061 ],
6062 )
6063 .unwrap();
6064 let mut account = Account::unpack_unchecked(&mismatch_account.data).unwrap();
6065 account.mint = mint2_key;
6066 Account::pack(account, &mut mismatch_account.data).unwrap();
6067
6068 do_process_instruction(
6070 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 42).unwrap(),
6071 vec![&mut mint_account, &mut account_account, &mut owner_account],
6072 )
6073 .unwrap();
6074
6075 let mint = Mint::unpack_unchecked(&mint_account.data).unwrap();
6076 assert_eq!(mint.supply, 42);
6077 let account = Account::unpack_unchecked(&account_account.data).unwrap();
6078 assert_eq!(account.amount, 42);
6079
6080 do_process_instruction(
6082 mint_to(&program_id, &mint_key, &account2_key, &owner_key, &[], 42).unwrap(),
6083 vec![&mut mint_account, &mut account2_account, &mut owner_account],
6084 )
6085 .unwrap();
6086
6087 let mint = Mint::unpack_unchecked(&mint_account.data).unwrap();
6088 assert_eq!(mint.supply, 84);
6089 let account = Account::unpack_unchecked(&account2_account.data).unwrap();
6090 assert_eq!(account.amount, 42);
6091
6092 let mut instruction =
6094 mint_to(&program_id, &mint_key, &account2_key, &owner_key, &[], 42).unwrap();
6095 instruction.accounts[2].is_signer = false;
6096 assert_eq!(
6097 Err(ProgramError::MissingRequiredSignature),
6098 do_process_instruction(
6099 instruction,
6100 vec![&mut mint_account, &mut account2_account, &mut owner_account],
6101 )
6102 );
6103
6104 assert_eq!(
6106 Err(TokenError::MintMismatch.into()),
6107 do_process_instruction(
6108 mint_to(&program_id, &mint_key, &mismatch_key, &owner_key, &[], 42).unwrap(),
6109 vec![&mut mint_account, &mut mismatch_account, &mut owner_account],
6110 )
6111 );
6112
6113 assert_eq!(
6115 Err(TokenError::OwnerMismatch.into()),
6116 do_process_instruction(
6117 mint_to(&program_id, &mint_key, &account2_key, &owner2_key, &[], 42).unwrap(),
6118 vec![
6119 &mut mint_account,
6120 &mut account2_account,
6121 &mut owner2_account,
6122 ],
6123 )
6124 );
6125
6126 let not_program_id = Address::new_unique();
6128 mint_account.owner = not_program_id;
6129 assert_eq!(
6130 Err(ProgramError::IncorrectProgramId),
6131 do_process_instruction(
6132 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 0).unwrap(),
6133 vec![&mut mint_account, &mut account_account, &mut owner_account],
6134 )
6135 );
6136 mint_account.owner = program_id;
6137
6138 let not_program_id = Address::new_unique();
6140 account_account.owner = not_program_id;
6141 assert_eq!(
6142 Err(ProgramError::IncorrectProgramId),
6143 do_process_instruction(
6144 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 0).unwrap(),
6145 vec![&mut mint_account, &mut account_account, &mut owner_account],
6146 )
6147 );
6148 account_account.owner = program_id;
6149
6150 assert_eq!(
6152 Err(ProgramError::UninitializedAccount),
6153 do_process_instruction(
6154 mint_to(
6155 &program_id,
6156 &mint_key,
6157 &uninitialized_key,
6158 &owner_key,
6159 &[],
6160 42
6161 )
6162 .unwrap(),
6163 vec![
6164 &mut mint_account,
6165 &mut uninitialized_account,
6166 &mut owner_account,
6167 ],
6168 )
6169 );
6170
6171 do_process_instruction(
6173 set_authority(
6174 &program_id,
6175 &mint_key,
6176 None,
6177 AuthorityType::MintTokens,
6178 &owner_key,
6179 &[],
6180 )
6181 .unwrap(),
6182 vec![&mut mint_account, &mut owner_account],
6183 )
6184 .unwrap();
6185 assert_eq!(
6186 Err(TokenError::FixedSupply.into()),
6187 do_process_instruction(
6188 mint_to(&program_id, &mint_key, &account2_key, &owner_key, &[], 42).unwrap(),
6189 vec![&mut mint_account, &mut account2_account, &mut owner_account],
6190 )
6191 );
6192 }
6193
6194 #[test]
6195 fn test_batch_with_invalid_count() {
6196 let program_id = crate::id();
6197 let account_key = Address::new_unique();
6198 let mut account_account = SolanaAccount::new(
6199 account_minimum_balance(),
6200 Account::get_packed_len(),
6201 &program_id,
6202 );
6203 let mint_account_key = Address::new_unique();
6204 let mut mint_account =
6205 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
6206 let mint_owner = Address::new_unique();
6207 let account_owner = Address::new_unique();
6208 let mut account_owner_account = SolanaAccount::default();
6209 let rent_key = rent::id();
6210 let mut rent_sysvar = rent_sysvar();
6211 let account_info: AccountInfo = (&account_key, true, &mut account_account).into();
6212 let mint_account_info: AccountInfo = (&mint_account_key, true, &mut mint_account).into();
6213 let account_owner_info: AccountInfo =
6214 (&account_owner, true, &mut account_owner_account).into();
6215 let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
6216
6217 let initialize_mint_instruction =
6218 initialize_mint(&program_id, &mint_account_key, &mint_owner, None, 9).unwrap();
6219
6220 let initialize_account_instruction =
6221 initialize_account3(&program_id, &account_key, &mint_account_key, &account_owner)
6222 .unwrap();
6223
6224 let close_account_instruction = close_account(
6225 &program_id,
6226 &account_key,
6227 &account_owner,
6228 &account_owner,
6229 &[],
6230 )
6231 .unwrap();
6232
6233 let mut batch_instr = batch_instruction(&[
6234 &initialize_mint_instruction,
6235 &initialize_account_instruction,
6236 &close_account_instruction,
6237 ])
6238 .unwrap();
6239
6240 batch_instr.data.pop();
6242
6243 let temp_mint_data = mint_account_info.data.borrow().to_vec();
6244 let temp_account_data = account_info.data.borrow().to_vec();
6245
6246 assert_eq!(
6247 Err(TokenError::InvalidInstruction.into()),
6248 do_process_instruction_dups(
6249 batch_instr,
6250 vec![
6251 mint_account_info.clone(),
6252 rent_info.clone(),
6253 account_info.clone(),
6254 mint_account_info.clone(),
6255 account_info.clone(),
6256 account_owner_info.clone(),
6257 account_owner_info.clone(),
6258 ]
6259 )
6260 );
6261
6262 mint_account_info
6264 .data
6265 .borrow_mut()
6266 .copy_from_slice(&temp_mint_data);
6267 account_info
6268 .data
6269 .borrow_mut()
6270 .copy_from_slice(&temp_account_data);
6271
6272 let batch_instr = batch_instruction(&[
6273 &initialize_mint_instruction,
6274 &initialize_account_instruction,
6275 &close_account_instruction,
6276 ])
6277 .unwrap();
6278
6279 assert_eq!(
6280 Err(ProgramError::NotEnoughAccountKeys),
6281 do_process_instruction_dups(
6282 batch_instr,
6283 vec![
6284 mint_account_info.clone(),
6285 rent_info.clone(),
6286 account_info.clone(),
6287 ] )
6289 );
6290
6291 mint_account_info
6293 .data
6294 .borrow_mut()
6295 .copy_from_slice(&temp_mint_data);
6296 account_info
6297 .data
6298 .borrow_mut()
6299 .copy_from_slice(&temp_account_data);
6300
6301 let batch_instruction = batch_instruction(&[
6302 &initialize_mint_instruction,
6303 &initialize_account_instruction,
6304 &close_account_instruction,
6305 ])
6306 .unwrap();
6307
6308 do_process_instruction_dups(
6309 batch_instruction,
6310 vec![
6311 mint_account_info.clone(),
6312 rent_info.clone(),
6313 account_info.clone(),
6314 mint_account_info.clone(),
6315 account_info.clone(),
6316 account_owner_info.clone(),
6317 account_owner_info.clone(),
6318 ],
6319 )
6320 .unwrap();
6321 }
6322
6323 #[test]
6324 fn test_batch_in_batch() {
6325 let program_id = crate::id();
6326 let mint_account_key = Address::new_unique();
6327 let mut mint_account =
6328 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
6329 let mint_owner = Address::new_unique();
6330 let mut mint_owner_account = SolanaAccount::default();
6331 let rent_key = rent::id();
6332 let mut rent_sysvar = rent_sysvar();
6333
6334 let mint_account_info: AccountInfo = (&mint_account_key, true, &mut mint_account).into();
6335 let mint_owner_info: AccountInfo = (&mint_owner, true, &mut mint_owner_account).into();
6336 let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
6337
6338 let initialize_mint_instruction = initialize_mint(
6339 &program_id,
6340 &mint_account_key,
6341 &mint_owner,
6342 Some(&mint_owner),
6343 9,
6344 )
6345 .unwrap();
6346
6347 let set_authority_instruction = set_authority(
6348 &program_id,
6349 &mint_account_key,
6350 None,
6351 AuthorityType::FreezeAccount,
6352 &mint_owner,
6353 &[],
6354 )
6355 .unwrap();
6356
6357 let batch_instr = batch_instruction(&[&set_authority_instruction]).unwrap();
6358
6359 let batch_in_batch_instruction =
6360 batch_instruction(&[&batch_instr, &initialize_mint_instruction]).unwrap();
6361
6362 let temp_mint_account_data = mint_account_info.data.borrow().to_vec();
6363
6364 assert_eq!(
6365 Err(TokenError::InvalidInstruction.into()),
6366 do_process_instruction_dups(
6367 batch_in_batch_instruction,
6368 vec![
6369 mint_account_info.clone(),
6370 rent_info.clone(),
6371 mint_account_info.clone(),
6372 mint_owner_info.clone(),
6373 ]
6374 )
6375 );
6376
6377 mint_account_info
6379 .data
6380 .borrow_mut()
6381 .copy_from_slice(&temp_mint_account_data);
6382
6383 do_process_instruction_dups(
6384 initialize_mint_instruction,
6385 vec![mint_account_info.clone(), rent_info.clone()],
6386 )
6387 .unwrap();
6388
6389 do_process_instruction_dups(
6390 batch_instr,
6391 vec![mint_account_info.clone(), mint_owner_info.clone()],
6392 )
6393 .unwrap();
6394 }
6395
6396 #[test]
6397 #[allow(deprecated)]
6398 fn test_batch_initialize_mint_swap() {
6399 let program_id = crate::id();
6400 let account1_key = Address::new_unique();
6401 let mut account1_account = SolanaAccount::new(
6402 account_minimum_balance(),
6403 Account::get_packed_len(),
6404 &program_id,
6405 );
6406 let account2_key = Address::new_unique();
6407 let mut account2_account = SolanaAccount::new(
6408 account_minimum_balance(),
6409 Account::get_packed_len(),
6410 &program_id,
6411 );
6412 let account3_key = Address::new_unique();
6413 let mut account3_account = SolanaAccount::new(
6414 account_minimum_balance(),
6415 Account::get_packed_len(),
6416 &program_id,
6417 );
6418 let account4_key = Address::new_unique();
6419 let mut account4_account = SolanaAccount::new(
6420 account_minimum_balance(),
6421 Account::get_packed_len(),
6422 &program_id,
6423 );
6424 let mint_account1_key = Address::new_unique();
6425 let mut mint1_account =
6426 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
6427 let mint_account2_key = Address::new_unique();
6428 let mut mint2_account = SolanaAccount::new(
6429 mint_minimum_balance(),
6430 Mint::get_packed_len(),
6431 &Address::new_unique(),
6432 );
6433 let mint_owner = Address::new_unique();
6434 let mut mint_owner_account = SolanaAccount::default();
6435 let account_owner = Address::new_unique();
6436 let mut account_owner_account = SolanaAccount::default();
6437 let rent_key = rent::id();
6438 let mut rent_sysvar = rent_sysvar();
6439
6440 let account1_info: AccountInfo = (&account1_key, true, &mut account1_account).into();
6441 let account2_info: AccountInfo = (&account2_key, true, &mut account2_account).into();
6442 let account3_info: AccountInfo = (&account3_key, true, &mut account3_account).into();
6443 let account4_info: AccountInfo = (&account4_key, true, &mut account4_account).into();
6444 let mint_account1_info: AccountInfo = (&mint_account1_key, true, &mut mint1_account).into();
6445 let mint_account2_info: AccountInfo = (&mint_account2_key, true, &mut mint2_account).into();
6446 let mint_owner_info: AccountInfo = (&mint_owner, true, &mut mint_owner_account).into();
6447 let account_owner_info: AccountInfo =
6448 (&account_owner, true, &mut account_owner_account).into();
6449 let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
6450
6451 let initialize_mint_1_instruction =
6452 initialize_mint(&program_id, &mint_account1_key, &mint_owner, None, 9).unwrap();
6453 let initialize_mint_2_instruction =
6454 initialize_mint(&program_id, &mint_account2_key, &mint_owner, None, 9).unwrap();
6455
6456 let initialize_account_1_instruction = initialize_account3(
6457 &program_id,
6458 &account1_key,
6459 &mint_account1_key,
6460 &account_owner,
6461 )
6462 .unwrap();
6463 let initialize_account_2_instruction = initialize_account3(
6464 &program_id,
6465 &account2_key,
6466 &mint_account2_key,
6467 &account_owner,
6468 )
6469 .unwrap();
6470
6471 let initialize_account_3_instruction = initialize_account3(
6472 &program_id,
6473 &account3_key,
6474 &mint_account1_key,
6475 &account_owner,
6476 )
6477 .unwrap();
6478 let initialize_account_4_instruction = initialize_account3(
6479 &program_id,
6480 &account4_key,
6481 &mint_account2_key,
6482 &account_owner,
6483 )
6484 .unwrap();
6485
6486 let mint_to_1_instruction = mint_to(
6487 &program_id,
6488 &mint_account1_key,
6489 &account1_key,
6490 &mint_owner,
6491 &[],
6492 1000,
6493 )
6494 .unwrap();
6495 let mint_to_2_instruction = mint_to_checked(
6496 &program_id,
6497 &mint_account2_key,
6498 &account2_key,
6499 &mint_owner,
6500 &[],
6501 1000,
6502 9,
6503 )
6504 .unwrap();
6505 let mint_to_2_with_invalid_decimals = mint_to_checked(
6506 &program_id,
6507 &mint_account2_key,
6508 &account2_key,
6509 &mint_owner,
6510 &[],
6511 1000,
6512 8,
6513 )
6514 .unwrap();
6515
6516 let transfer_to_3_instruction = transfer(
6517 &program_id,
6518 &account1_key,
6519 &account3_key,
6520 &account_owner,
6521 &[],
6522 500,
6523 )
6524 .unwrap();
6525 let transfer_to_3_with_invalid_amount = transfer(
6526 &program_id,
6527 &account1_key,
6528 &account3_key,
6529 &account_owner,
6530 &[],
6531 501,
6532 )
6533 .unwrap();
6534 let transfer_4_instruction = transfer_checked(
6535 &program_id,
6536 &account2_key,
6537 &mint_account2_key,
6538 &account4_key,
6539 &account_owner,
6540 &[],
6541 500,
6542 9,
6543 )
6544 .unwrap();
6545
6546 let batch_1_instruction = batch_instruction(&[&initialize_mint_1_instruction]).unwrap();
6547
6548 do_process_instruction_dups(
6549 batch_1_instruction,
6550 vec![mint_account1_info.clone(), rent_info.clone()],
6551 )
6552 .unwrap();
6553
6554 let temp_mint1_data = mint_account1_info.data.borrow().to_vec();
6555 let temp_account1_data = account1_info.data.borrow().to_vec();
6556 let temp_account2_data = account2_info.data.borrow().to_vec();
6557
6558 let batch_2_fail_instruction = batch_instruction(&[
6560 &initialize_mint_2_instruction,
6561 &initialize_account_1_instruction,
6562 &initialize_account_2_instruction,
6563 &initialize_account_3_instruction,
6564 &initialize_account_4_instruction,
6565 ])
6566 .unwrap();
6567
6568 assert_eq!(
6569 Err(ProgramError::IncorrectProgramId),
6570 do_process_instruction_dups(
6571 batch_2_fail_instruction,
6572 vec![
6573 mint_account2_info.clone(),
6574 rent_info.clone(),
6575 account1_info.clone(),
6576 mint_account1_info.clone(),
6577 account2_info.clone(),
6578 mint_account2_info.clone(),
6579 account3_info.clone(),
6580 mint_account1_info.clone(),
6581 account4_info.clone(),
6582 mint_account2_info.clone(),
6583 ],
6584 )
6585 );
6586
6587 mint_account1_info
6589 .data
6590 .borrow_mut()
6591 .copy_from_slice(&temp_mint1_data);
6592 account1_info
6593 .data
6594 .borrow_mut()
6595 .copy_from_slice(&temp_account1_data);
6596 account2_info
6597 .data
6598 .borrow_mut()
6599 .copy_from_slice(&temp_account2_data);
6600
6601 let mut mint2_account =
6603 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
6604 let mint_account2_info: AccountInfo = (&mint_account2_key, true, &mut mint2_account).into();
6605
6606 let batch_2_success_instruction = batch_instruction(&[
6608 &initialize_mint_2_instruction,
6609 &initialize_account_1_instruction,
6610 &initialize_account_2_instruction,
6611 &initialize_account_3_instruction,
6612 &initialize_account_4_instruction,
6613 ])
6614 .unwrap();
6615
6616 do_process_instruction_dups(
6617 batch_2_success_instruction,
6618 vec![
6619 mint_account2_info.clone(),
6620 rent_info.clone(),
6621 account1_info.clone(),
6622 mint_account1_info.clone(),
6623 account2_info.clone(),
6624 mint_account2_info.clone(),
6625 account3_info.clone(),
6626 mint_account1_info.clone(),
6627 account4_info.clone(),
6628 mint_account2_info.clone(),
6629 ],
6630 )
6631 .unwrap();
6632
6633 let temp_mint1_data = mint_account1_info.data.borrow().to_vec();
6634 let temp_account1_data = account1_info.data.borrow().to_vec();
6635 let temp_mint2_data = mint_account2_info.data.borrow().to_vec();
6636 let temp_account2_data = account2_info.data.borrow().to_vec();
6637
6638 let batch_3_fail_instruction = batch_instruction(&[
6640 &mint_to_1_instruction,
6641 &mint_to_2_instruction,
6642 &mint_to_2_with_invalid_decimals,
6643 ])
6644 .unwrap();
6645
6646 assert_eq!(
6647 Err(TokenError::MintDecimalsMismatch.into()),
6648 do_process_instruction_dups(
6649 batch_3_fail_instruction,
6650 vec![
6651 mint_account1_info.clone(),
6652 account1_info.clone(),
6653 mint_owner_info.clone(),
6654 mint_account2_info.clone(),
6655 account2_info.clone(),
6656 mint_owner_info.clone(),
6657 mint_account2_info.clone(),
6658 account2_info.clone(),
6659 mint_owner_info.clone(),
6660 ],
6661 )
6662 );
6663
6664 mint_account1_info
6666 .data
6667 .borrow_mut()
6668 .copy_from_slice(&temp_mint1_data);
6669 account1_info
6670 .data
6671 .borrow_mut()
6672 .copy_from_slice(&temp_account1_data);
6673 mint_account2_info
6674 .data
6675 .borrow_mut()
6676 .copy_from_slice(&temp_mint2_data);
6677 account2_info
6678 .data
6679 .borrow_mut()
6680 .copy_from_slice(&temp_account2_data);
6681
6682 let batch_3_success_instruction =
6684 batch_instruction(&[&mint_to_1_instruction, &mint_to_2_instruction]).unwrap();
6685
6686 do_process_instruction_dups(
6687 batch_3_success_instruction,
6688 vec![
6689 mint_account1_info.clone(),
6690 account1_info.clone(),
6691 mint_owner_info.clone(),
6692 mint_account2_info.clone(),
6693 account2_info.clone(),
6694 mint_owner_info.clone(),
6695 ],
6696 )
6697 .unwrap();
6698
6699 let temp_account1_data = account1_info.data.borrow().to_vec();
6700 let temp_account3_data = account3_info.data.borrow().to_vec();
6701 let temp_account2_data = account2_info.data.borrow().to_vec();
6702 let temp_account4_data = account4_info.data.borrow().to_vec();
6703
6704 let batch_4_fail_instruction = batch_instruction(&[
6705 &transfer_to_3_instruction,
6706 &transfer_to_3_with_invalid_amount,
6707 &transfer_4_instruction,
6708 ])
6709 .unwrap();
6710
6711 assert_eq!(
6712 Err(TokenError::InsufficientFunds.into()),
6713 do_process_instruction_dups(
6714 batch_4_fail_instruction,
6715 vec![
6716 account1_info.clone(),
6717 account3_info.clone(),
6718 account_owner_info.clone(),
6719 account1_info.clone(),
6720 account3_info.clone(),
6721 account_owner_info.clone(),
6722 account2_info.clone(),
6723 mint_account2_info.clone(),
6724 account4_info.clone(),
6725 account_owner_info.clone(),
6726 ],
6727 )
6728 );
6729
6730 account1_info
6732 .data
6733 .borrow_mut()
6734 .copy_from_slice(&temp_account1_data);
6735 account3_info
6736 .data
6737 .borrow_mut()
6738 .copy_from_slice(&temp_account3_data);
6739 account2_info
6740 .data
6741 .borrow_mut()
6742 .copy_from_slice(&temp_account2_data);
6743 account4_info
6744 .data
6745 .borrow_mut()
6746 .copy_from_slice(&temp_account4_data);
6747
6748 let batch_4_success_instruction =
6750 batch_instruction(&[&transfer_to_3_instruction, &transfer_4_instruction]).unwrap();
6751
6752 do_process_instruction_dups(
6753 batch_4_success_instruction,
6754 vec![
6755 account1_info.clone(),
6756 account3_info.clone(),
6757 account_owner_info.clone(),
6758 account2_info.clone(),
6759 mint_account2_info.clone(),
6760 account4_info.clone(),
6761 account_owner_info.clone(),
6762 ],
6763 )
6764 .unwrap();
6765 }
6766
6767 #[test]
6768 fn test_burn_dups() {
6769 let program_id = crate::id();
6770 let account1_key = Address::new_unique();
6771 let mut account1_account = SolanaAccount::new(
6772 account_minimum_balance(),
6773 Account::get_packed_len(),
6774 &program_id,
6775 );
6776 let account1_info: AccountInfo = (&account1_key, true, &mut account1_account).into();
6777 let owner_key = Address::new_unique();
6778 let mut owner_account = SolanaAccount::default();
6779 let owner_info: AccountInfo = (&owner_key, true, &mut owner_account).into();
6780 let mint_key = Address::new_unique();
6781 let mut mint_account =
6782 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
6783 let mint_info: AccountInfo = (&mint_key, true, &mut mint_account).into();
6784 let rent_key = rent::id();
6785 let mut rent_sysvar = rent_sysvar();
6786 let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
6787
6788 do_process_instruction_dups(
6790 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
6791 vec![mint_info.clone(), rent_info.clone()],
6792 )
6793 .unwrap();
6794
6795 do_process_instruction_dups(
6797 initialize_account(&program_id, &account1_key, &mint_key, &account1_key).unwrap(),
6798 vec![
6799 account1_info.clone(),
6800 mint_info.clone(),
6801 account1_info.clone(),
6802 rent_info.clone(),
6803 ],
6804 )
6805 .unwrap();
6806
6807 do_process_instruction_dups(
6809 mint_to(&program_id, &mint_key, &account1_key, &owner_key, &[], 1000).unwrap(),
6810 vec![mint_info.clone(), account1_info.clone(), owner_info.clone()],
6811 )
6812 .unwrap();
6813
6814 do_process_instruction_dups(
6816 burn(
6817 &program_id,
6818 &mint_key,
6819 &account1_key,
6820 &account1_key,
6821 &[],
6822 500,
6823 )
6824 .unwrap(),
6825 vec![
6826 account1_info.clone(),
6827 mint_info.clone(),
6828 account1_info.clone(),
6829 ],
6830 )
6831 .unwrap();
6832
6833 do_process_instruction_dups(
6835 burn_checked(
6836 &program_id,
6837 &account1_key,
6838 &mint_key,
6839 &account1_key,
6840 &[],
6841 500,
6842 2,
6843 )
6844 .unwrap(),
6845 vec![
6846 account1_info.clone(),
6847 mint_info.clone(),
6848 account1_info.clone(),
6849 ],
6850 )
6851 .unwrap();
6852
6853 do_process_instruction_dups(
6855 mint_to(&program_id, &mint_key, &account1_key, &owner_key, &[], 1000).unwrap(),
6856 vec![mint_info.clone(), account1_info.clone(), owner_info.clone()],
6857 )
6858 .unwrap();
6859 let mut account = Account::unpack_unchecked(&account1_info.data.borrow()).unwrap();
6860 account.owner = mint_key;
6861 Account::pack(account, &mut account1_info.data.borrow_mut()).unwrap();
6862 do_process_instruction_dups(
6863 burn(&program_id, &account1_key, &mint_key, &mint_key, &[], 500).unwrap(),
6864 vec![account1_info.clone(), mint_info.clone(), mint_info.clone()],
6865 )
6866 .unwrap();
6867
6868 do_process_instruction_dups(
6870 burn_checked(
6871 &program_id,
6872 &account1_key,
6873 &mint_key,
6874 &mint_key,
6875 &[],
6876 500,
6877 2,
6878 )
6879 .unwrap(),
6880 vec![account1_info.clone(), mint_info.clone(), mint_info.clone()],
6881 )
6882 .unwrap();
6883
6884 do_process_instruction_dups(
6886 mint_to(&program_id, &mint_key, &account1_key, &owner_key, &[], 1000).unwrap(),
6887 vec![mint_info.clone(), account1_info.clone(), owner_info.clone()],
6888 )
6889 .unwrap();
6890 let mut account = Account::unpack_unchecked(&account1_info.data.borrow()).unwrap();
6891 account.delegated_amount = 1000;
6892 account.delegate = COption::Some(account1_key);
6893 account.owner = owner_key;
6894 Account::pack(account, &mut account1_info.data.borrow_mut()).unwrap();
6895 do_process_instruction_dups(
6896 burn(
6897 &program_id,
6898 &account1_key,
6899 &mint_key,
6900 &account1_key,
6901 &[],
6902 500,
6903 )
6904 .unwrap(),
6905 vec![
6906 account1_info.clone(),
6907 mint_info.clone(),
6908 account1_info.clone(),
6909 ],
6910 )
6911 .unwrap();
6912
6913 do_process_instruction_dups(
6915 burn_checked(
6916 &program_id,
6917 &account1_key,
6918 &mint_key,
6919 &account1_key,
6920 &[],
6921 500,
6922 2,
6923 )
6924 .unwrap(),
6925 vec![
6926 account1_info.clone(),
6927 mint_info.clone(),
6928 account1_info.clone(),
6929 ],
6930 )
6931 .unwrap();
6932
6933 do_process_instruction_dups(
6935 mint_to(&program_id, &mint_key, &account1_key, &owner_key, &[], 1000).unwrap(),
6936 vec![mint_info.clone(), account1_info.clone(), owner_info.clone()],
6937 )
6938 .unwrap();
6939 let mut account = Account::unpack_unchecked(&account1_info.data.borrow()).unwrap();
6940 account.delegated_amount = 1000;
6941 account.delegate = COption::Some(mint_key);
6942 account.owner = owner_key;
6943 Account::pack(account, &mut account1_info.data.borrow_mut()).unwrap();
6944 do_process_instruction_dups(
6945 burn(&program_id, &account1_key, &mint_key, &mint_key, &[], 500).unwrap(),
6946 vec![account1_info.clone(), mint_info.clone(), mint_info.clone()],
6947 )
6948 .unwrap();
6949
6950 do_process_instruction_dups(
6952 burn_checked(
6953 &program_id,
6954 &account1_key,
6955 &mint_key,
6956 &mint_key,
6957 &[],
6958 500,
6959 2,
6960 )
6961 .unwrap(),
6962 vec![account1_info.clone(), mint_info.clone(), mint_info.clone()],
6963 )
6964 .unwrap();
6965 }
6966
6967 #[test]
6968 fn test_burn() {
6969 let program_id = crate::id();
6970 let account_key = Address::new_unique();
6971 let mut account_account = SolanaAccount::new(
6972 account_minimum_balance(),
6973 Account::get_packed_len(),
6974 &program_id,
6975 );
6976 let account2_key = Address::new_unique();
6977 let mut account2_account = SolanaAccount::new(
6978 account_minimum_balance(),
6979 Account::get_packed_len(),
6980 &program_id,
6981 );
6982 let account3_key = Address::new_unique();
6983 let mut account3_account = SolanaAccount::new(
6984 account_minimum_balance(),
6985 Account::get_packed_len(),
6986 &program_id,
6987 );
6988 let delegate_key = Address::new_unique();
6989 let mut delegate_account = SolanaAccount::default();
6990 let mismatch_key = Address::new_unique();
6991 let mut mismatch_account = SolanaAccount::new(
6992 account_minimum_balance(),
6993 Account::get_packed_len(),
6994 &program_id,
6995 );
6996 let owner_key = Address::new_unique();
6997 let mut owner_account = SolanaAccount::default();
6998 let owner2_key = Address::new_unique();
6999 let mut owner2_account = SolanaAccount::default();
7000 let mint_key = Address::new_unique();
7001 let mut mint_account =
7002 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
7003 let mint2_key = Address::new_unique();
7004 let mut rent_sysvar = rent_sysvar();
7005
7006 do_process_instruction(
7008 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
7009 vec![&mut mint_account, &mut rent_sysvar],
7010 )
7011 .unwrap();
7012
7013 do_process_instruction(
7015 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
7016 vec![
7017 &mut account_account,
7018 &mut mint_account,
7019 &mut owner_account,
7020 &mut rent_sysvar,
7021 ],
7022 )
7023 .unwrap();
7024
7025 do_process_instruction(
7027 initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
7028 vec![
7029 &mut account2_account,
7030 &mut mint_account,
7031 &mut owner_account,
7032 &mut rent_sysvar,
7033 ],
7034 )
7035 .unwrap();
7036
7037 do_process_instruction(
7039 initialize_account(&program_id, &account3_key, &mint_key, &owner_key).unwrap(),
7040 vec![
7041 &mut account3_account,
7042 &mut mint_account,
7043 &mut owner_account,
7044 &mut rent_sysvar,
7045 ],
7046 )
7047 .unwrap();
7048
7049 do_process_instruction(
7051 initialize_account(&program_id, &mismatch_key, &mint_key, &owner_key).unwrap(),
7052 vec![
7053 &mut mismatch_account,
7054 &mut mint_account,
7055 &mut owner_account,
7056 &mut rent_sysvar,
7057 ],
7058 )
7059 .unwrap();
7060
7061 do_process_instruction(
7063 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
7064 vec![&mut mint_account, &mut account_account, &mut owner_account],
7065 )
7066 .unwrap();
7067
7068 do_process_instruction(
7070 mint_to(&program_id, &mint_key, &mismatch_key, &owner_key, &[], 1000).unwrap(),
7071 vec![&mut mint_account, &mut mismatch_account, &mut owner_account],
7072 )
7073 .unwrap();
7074 let mut account = Account::unpack_unchecked(&mismatch_account.data).unwrap();
7075 account.mint = mint2_key;
7076 Account::pack(account, &mut mismatch_account.data).unwrap();
7077
7078 let mut instruction =
7080 burn(&program_id, &account_key, &mint_key, &delegate_key, &[], 42).unwrap();
7081 instruction.accounts[1].is_signer = false;
7082 assert_eq!(
7083 Err(TokenError::OwnerMismatch.into()),
7084 do_process_instruction(
7085 instruction,
7086 vec![
7087 &mut account_account,
7088 &mut mint_account,
7089 &mut delegate_account
7090 ],
7091 )
7092 );
7093
7094 assert_eq!(
7096 Err(TokenError::OwnerMismatch.into()),
7097 do_process_instruction(
7098 burn(&program_id, &account_key, &mint_key, &owner2_key, &[], 42).unwrap(),
7099 vec![&mut account_account, &mut mint_account, &mut owner2_account],
7100 )
7101 );
7102
7103 let not_program_id = Address::new_unique();
7105 account_account.owner = not_program_id;
7106 assert_eq!(
7107 Err(ProgramError::IncorrectProgramId),
7108 do_process_instruction(
7109 burn(&program_id, &account_key, &mint_key, &owner_key, &[], 0).unwrap(),
7110 vec![&mut account_account, &mut mint_account, &mut owner_account],
7111 )
7112 );
7113 account_account.owner = program_id;
7114
7115 let not_program_id = Address::new_unique();
7117 mint_account.owner = not_program_id;
7118 assert_eq!(
7119 Err(ProgramError::IncorrectProgramId),
7120 do_process_instruction(
7121 burn(&program_id, &account_key, &mint_key, &owner_key, &[], 0).unwrap(),
7122 vec![&mut account_account, &mut mint_account, &mut owner_account],
7123 )
7124 );
7125 mint_account.owner = program_id;
7126
7127 assert_eq!(
7129 Err(TokenError::MintMismatch.into()),
7130 do_process_instruction(
7131 burn(&program_id, &mismatch_key, &mint_key, &owner_key, &[], 42).unwrap(),
7132 vec![&mut mismatch_account, &mut mint_account, &mut owner_account],
7133 )
7134 );
7135
7136 do_process_instruction(
7138 burn(&program_id, &account_key, &mint_key, &owner_key, &[], 21).unwrap(),
7139 vec![&mut account_account, &mut mint_account, &mut owner_account],
7140 )
7141 .unwrap();
7142
7143 assert_eq!(
7145 Err(TokenError::MintDecimalsMismatch.into()),
7146 do_process_instruction(
7147 burn_checked(&program_id, &account_key, &mint_key, &owner_key, &[], 21, 3).unwrap(),
7148 vec![&mut account_account, &mut mint_account, &mut owner_account],
7149 )
7150 );
7151
7152 do_process_instruction(
7154 burn_checked(&program_id, &account_key, &mint_key, &owner_key, &[], 21, 2).unwrap(),
7155 vec![&mut account_account, &mut mint_account, &mut owner_account],
7156 )
7157 .unwrap();
7158
7159 let mint = Mint::unpack_unchecked(&mint_account.data).unwrap();
7160 assert_eq!(mint.supply, 2000 - 42);
7161 let account = Account::unpack_unchecked(&account_account.data).unwrap();
7162 assert_eq!(account.amount, 1000 - 42);
7163
7164 assert_eq!(
7166 Err(TokenError::InsufficientFunds.into()),
7167 do_process_instruction(
7168 burn(
7169 &program_id,
7170 &account_key,
7171 &mint_key,
7172 &owner_key,
7173 &[],
7174 100_000_000
7175 )
7176 .unwrap(),
7177 vec![&mut account_account, &mut mint_account, &mut owner_account],
7178 )
7179 );
7180
7181 do_process_instruction(
7183 approve(
7184 &program_id,
7185 &account_key,
7186 &delegate_key,
7187 &owner_key,
7188 &[],
7189 84,
7190 )
7191 .unwrap(),
7192 vec![
7193 &mut account_account,
7194 &mut delegate_account,
7195 &mut owner_account,
7196 ],
7197 )
7198 .unwrap();
7199
7200 assert_eq!(
7202 Err(TokenError::OwnerMismatch.into()),
7203 do_process_instruction(
7204 burn(
7205 &program_id,
7206 &account_key,
7207 &mint_key,
7208 &owner2_key, &[],
7210 1,
7211 )
7212 .unwrap(),
7213 vec![&mut account_account, &mut mint_account, &mut owner2_account],
7214 )
7215 );
7216
7217 assert_eq!(
7219 Err(TokenError::InsufficientFunds.into()),
7220 do_process_instruction(
7221 burn(&program_id, &account_key, &mint_key, &delegate_key, &[], 85).unwrap(),
7222 vec![
7223 &mut account_account,
7224 &mut mint_account,
7225 &mut delegate_account
7226 ],
7227 )
7228 );
7229
7230 do_process_instruction(
7232 burn(&program_id, &account_key, &mint_key, &delegate_key, &[], 84).unwrap(),
7233 vec![
7234 &mut account_account,
7235 &mut mint_account,
7236 &mut delegate_account,
7237 ],
7238 )
7239 .unwrap();
7240
7241 let mint = Mint::unpack_unchecked(&mint_account.data).unwrap();
7243 assert_eq!(mint.supply, 2000 - 42 - 84);
7244 let account = Account::unpack_unchecked(&account_account.data).unwrap();
7245 assert_eq!(account.amount, 1000 - 42 - 84);
7246
7247 assert_eq!(
7249 Err(TokenError::OwnerMismatch.into()),
7250 do_process_instruction(
7251 burn(&program_id, &account_key, &mint_key, &delegate_key, &[], 1).unwrap(),
7252 vec![
7253 &mut account_account,
7254 &mut mint_account,
7255 &mut delegate_account
7256 ],
7257 )
7258 );
7259 }
7260
7261 #[test]
7262 fn test_multisig() {
7263 let program_id = crate::id();
7264 let mint_key = Address::new_unique();
7265 let mut mint_account =
7266 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
7267 let account_key = Address::new_unique();
7268 let mut account = SolanaAccount::new(
7269 account_minimum_balance(),
7270 Account::get_packed_len(),
7271 &program_id,
7272 );
7273 let account2_key = Address::new_unique();
7274 let mut account2_account = SolanaAccount::new(
7275 account_minimum_balance(),
7276 Account::get_packed_len(),
7277 &program_id,
7278 );
7279 let owner_key = Address::new_unique();
7280 let mut owner_account = SolanaAccount::default();
7281 let multisig_key = Address::new_unique();
7282 let mut multisig_account = SolanaAccount::new(42, Multisig::get_packed_len(), &program_id);
7283 let mut empty_multisig_account =
7284 SolanaAccount::new(42, Multisig::get_packed_len(), &program_id);
7285 let multisig_delegate_key = Address::new_unique();
7286 let mut multisig_delegate_account = SolanaAccount::new(
7287 multisig_minimum_balance(),
7288 Multisig::get_packed_len(),
7289 &program_id,
7290 );
7291 let signer_keys = vec![Address::new_unique(); MAX_SIGNERS];
7292 let signer_key_refs: Vec<&Address> = signer_keys.iter().collect();
7293 let mut signer_accounts = vec![SolanaAccount::new(0, 0, &program_id); MAX_SIGNERS];
7294 let mut rent_sysvar = rent_sysvar();
7295
7296 let account_info_iter = &mut signer_accounts.iter_mut();
7298 assert_eq!(
7299 Err(TokenError::NotRentExempt.into()),
7300 do_process_instruction(
7301 initialize_multisig(&program_id, &multisig_key, &[&signer_keys[0]], 1).unwrap(),
7302 vec![
7303 &mut multisig_account,
7304 &mut rent_sysvar,
7305 account_info_iter.next().unwrap(),
7306 ],
7307 )
7308 );
7309
7310 multisig_account.lamports = multisig_minimum_balance();
7311 let mut multisig_account2 = multisig_account.clone();
7312
7313 let account_info_iter = &mut signer_accounts.iter_mut();
7315 do_process_instruction(
7316 initialize_multisig(&program_id, &multisig_key, &[&signer_keys[0]], 1).unwrap(),
7317 vec![
7318 &mut multisig_account,
7319 &mut rent_sysvar,
7320 account_info_iter.next().unwrap(),
7321 ],
7322 )
7323 .unwrap();
7324
7325 let account_info_iter = &mut signer_accounts.iter_mut();
7327 do_process_instruction(
7328 initialize_multisig2(&program_id, &multisig_key, &[&signer_keys[0]], 1).unwrap(),
7329 vec![&mut multisig_account2, account_info_iter.next().unwrap()],
7330 )
7331 .unwrap();
7332
7333 let account_info_iter = &mut signer_accounts.iter_mut();
7335 do_process_instruction(
7336 initialize_multisig(
7337 &program_id,
7338 &multisig_delegate_key,
7339 &signer_key_refs,
7340 MAX_SIGNERS as u8,
7341 )
7342 .unwrap(),
7343 vec![
7344 &mut multisig_delegate_account,
7345 &mut rent_sysvar,
7346 account_info_iter.next().unwrap(),
7347 account_info_iter.next().unwrap(),
7348 account_info_iter.next().unwrap(),
7349 account_info_iter.next().unwrap(),
7350 account_info_iter.next().unwrap(),
7351 account_info_iter.next().unwrap(),
7352 account_info_iter.next().unwrap(),
7353 account_info_iter.next().unwrap(),
7354 account_info_iter.next().unwrap(),
7355 account_info_iter.next().unwrap(),
7356 account_info_iter.next().unwrap(),
7357 ],
7358 )
7359 .unwrap();
7360
7361 do_process_instruction(
7363 initialize_mint(&program_id, &mint_key, &multisig_key, None, 2).unwrap(),
7364 vec![&mut mint_account, &mut rent_sysvar],
7365 )
7366 .unwrap();
7367
7368 do_process_instruction(
7370 initialize_account(&program_id, &account_key, &mint_key, &multisig_key).unwrap(),
7371 vec![
7372 &mut account,
7373 &mut mint_account,
7374 &mut multisig_account,
7375 &mut rent_sysvar,
7376 ],
7377 )
7378 .unwrap();
7379
7380 do_process_instruction(
7382 initialize_account(
7383 &program_id,
7384 &account2_key,
7385 &mint_key,
7386 &multisig_delegate_key,
7387 )
7388 .unwrap(),
7389 vec![
7390 &mut account2_account,
7391 &mut mint_account,
7392 &mut multisig_account,
7393 &mut rent_sysvar,
7394 ],
7395 )
7396 .unwrap();
7397
7398 let account_info_iter = &mut signer_accounts.iter_mut();
7400 do_process_instruction(
7401 mint_to(
7402 &program_id,
7403 &mint_key,
7404 &account_key,
7405 &multisig_key,
7406 &[&signer_keys[0]],
7407 1000,
7408 )
7409 .unwrap(),
7410 vec![
7411 &mut mint_account,
7412 &mut account,
7413 &mut multisig_account,
7414 account_info_iter.next().unwrap(),
7415 ],
7416 )
7417 .unwrap();
7418
7419 let account_info_iter = &mut signer_accounts.iter_mut();
7421 assert_eq!(
7422 ProgramError::UninitializedAccount,
7423 do_process_instruction(
7424 approve(
7425 &program_id,
7426 &account_key,
7427 &multisig_delegate_key,
7428 &multisig_key,
7429 &[],
7430 100,
7431 )
7432 .unwrap(),
7433 vec![
7434 &mut account,
7435 &mut multisig_delegate_account,
7436 &mut empty_multisig_account,
7437 account_info_iter.next().unwrap(),
7438 ],
7439 )
7440 .unwrap_err(),
7441 );
7442
7443 let account_info_iter = &mut signer_accounts.iter_mut();
7445 do_process_instruction(
7446 approve(
7447 &program_id,
7448 &account_key,
7449 &multisig_delegate_key,
7450 &multisig_key,
7451 &[&signer_keys[0]],
7452 100,
7453 )
7454 .unwrap(),
7455 vec![
7456 &mut account,
7457 &mut multisig_delegate_account,
7458 &mut multisig_account,
7459 account_info_iter.next().unwrap(),
7460 ],
7461 )
7462 .unwrap();
7463
7464 let account_info_iter = &mut signer_accounts.iter_mut();
7466 do_process_instruction(
7467 #[allow(deprecated)]
7468 transfer(
7469 &program_id,
7470 &account_key,
7471 &account2_key,
7472 &multisig_key,
7473 &[&signer_keys[0]],
7474 42,
7475 )
7476 .unwrap(),
7477 vec![
7478 &mut account,
7479 &mut account2_account,
7480 &mut multisig_account,
7481 account_info_iter.next().unwrap(),
7482 ],
7483 )
7484 .unwrap();
7485
7486 let account_info_iter = &mut signer_accounts.iter_mut();
7488 do_process_instruction(
7489 #[allow(deprecated)]
7490 transfer(
7491 &program_id,
7492 &account_key,
7493 &account2_key,
7494 &multisig_delegate_key,
7495 &signer_key_refs,
7496 42,
7497 )
7498 .unwrap(),
7499 vec![
7500 &mut account,
7501 &mut account2_account,
7502 &mut multisig_delegate_account,
7503 account_info_iter.next().unwrap(),
7504 account_info_iter.next().unwrap(),
7505 account_info_iter.next().unwrap(),
7506 account_info_iter.next().unwrap(),
7507 account_info_iter.next().unwrap(),
7508 account_info_iter.next().unwrap(),
7509 account_info_iter.next().unwrap(),
7510 account_info_iter.next().unwrap(),
7511 account_info_iter.next().unwrap(),
7512 account_info_iter.next().unwrap(),
7513 account_info_iter.next().unwrap(),
7514 ],
7515 )
7516 .unwrap();
7517
7518 let account_info_iter = &mut signer_accounts.iter_mut();
7520 do_process_instruction(
7521 mint_to(
7522 &program_id,
7523 &mint_key,
7524 &account2_key,
7525 &multisig_key,
7526 &[&signer_keys[0]],
7527 42,
7528 )
7529 .unwrap(),
7530 vec![
7531 &mut mint_account,
7532 &mut account2_account,
7533 &mut multisig_account,
7534 account_info_iter.next().unwrap(),
7535 ],
7536 )
7537 .unwrap();
7538
7539 let account_info_iter = &mut signer_accounts.iter_mut();
7541 do_process_instruction(
7542 burn(
7543 &program_id,
7544 &account_key,
7545 &mint_key,
7546 &multisig_key,
7547 &[&signer_keys[0]],
7548 42,
7549 )
7550 .unwrap(),
7551 vec![
7552 &mut account,
7553 &mut mint_account,
7554 &mut multisig_account,
7555 account_info_iter.next().unwrap(),
7556 ],
7557 )
7558 .unwrap();
7559
7560 let account_info_iter = &mut signer_accounts.iter_mut();
7562 do_process_instruction(
7563 burn(
7564 &program_id,
7565 &account_key,
7566 &mint_key,
7567 &multisig_delegate_key,
7568 &signer_key_refs,
7569 42,
7570 )
7571 .unwrap(),
7572 vec![
7573 &mut account,
7574 &mut mint_account,
7575 &mut multisig_delegate_account,
7576 account_info_iter.next().unwrap(),
7577 account_info_iter.next().unwrap(),
7578 account_info_iter.next().unwrap(),
7579 account_info_iter.next().unwrap(),
7580 account_info_iter.next().unwrap(),
7581 account_info_iter.next().unwrap(),
7582 account_info_iter.next().unwrap(),
7583 account_info_iter.next().unwrap(),
7584 account_info_iter.next().unwrap(),
7585 account_info_iter.next().unwrap(),
7586 account_info_iter.next().unwrap(),
7587 ],
7588 )
7589 .unwrap();
7590
7591 let account3_key = Address::new_unique();
7593 let mut account3_account = SolanaAccount::new(
7594 account_minimum_balance(),
7595 Account::get_packed_len(),
7596 &program_id,
7597 );
7598 let mint2_key = Address::new_unique();
7599 let mut mint2_account =
7600 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
7601 do_process_instruction(
7602 initialize_mint(
7603 &program_id,
7604 &mint2_key,
7605 &multisig_key,
7606 Some(&multisig_key),
7607 2,
7608 )
7609 .unwrap(),
7610 vec![&mut mint2_account, &mut rent_sysvar],
7611 )
7612 .unwrap();
7613 do_process_instruction(
7614 initialize_account(&program_id, &account3_key, &mint2_key, &owner_key).unwrap(),
7615 vec![
7616 &mut account3_account,
7617 &mut mint2_account,
7618 &mut owner_account,
7619 &mut rent_sysvar,
7620 ],
7621 )
7622 .unwrap();
7623 let account_info_iter = &mut signer_accounts.iter_mut();
7624 do_process_instruction(
7625 mint_to(
7626 &program_id,
7627 &mint2_key,
7628 &account3_key,
7629 &multisig_key,
7630 &[&signer_keys[0]],
7631 1000,
7632 )
7633 .unwrap(),
7634 vec![
7635 &mut mint2_account,
7636 &mut account3_account,
7637 &mut multisig_account,
7638 account_info_iter.next().unwrap(),
7639 ],
7640 )
7641 .unwrap();
7642 let account_info_iter = &mut signer_accounts.iter_mut();
7643 do_process_instruction(
7644 freeze_account(
7645 &program_id,
7646 &account3_key,
7647 &mint2_key,
7648 &multisig_key,
7649 &[&signer_keys[0]],
7650 )
7651 .unwrap(),
7652 vec![
7653 &mut account3_account,
7654 &mut mint2_account,
7655 &mut multisig_account,
7656 account_info_iter.next().unwrap(),
7657 ],
7658 )
7659 .unwrap();
7660
7661 let account_info_iter = &mut signer_accounts.iter_mut();
7663 do_process_instruction(
7664 set_authority(
7665 &program_id,
7666 &mint_key,
7667 Some(&owner_key),
7668 AuthorityType::MintTokens,
7669 &multisig_key,
7670 &[&signer_keys[0]],
7671 )
7672 .unwrap(),
7673 vec![
7674 &mut mint_account,
7675 &mut multisig_account,
7676 account_info_iter.next().unwrap(),
7677 ],
7678 )
7679 .unwrap();
7680
7681 let account_info_iter = &mut signer_accounts.iter_mut();
7683 do_process_instruction(
7684 set_authority(
7685 &program_id,
7686 &account_key,
7687 Some(&owner_key),
7688 AuthorityType::AccountOwner,
7689 &multisig_key,
7690 &[&signer_keys[0]],
7691 )
7692 .unwrap(),
7693 vec![
7694 &mut account,
7695 &mut multisig_account,
7696 account_info_iter.next().unwrap(),
7697 ],
7698 )
7699 .unwrap();
7700 }
7701
7702 #[test]
7703 fn test_permissioned_burn_none_authority_errors() {
7704 let program_id = crate::id();
7705 let mint_key = Address::new_unique();
7706 let owner_key = Address::new_unique();
7707 let burn_authority_key = Address::new_unique();
7708 let account_key = Address::new_unique();
7709
7710 let mint_size =
7711 ExtensionType::try_calculate_account_len::<PodMint>(&[ExtensionType::PermissionedBurn])
7712 .unwrap();
7713
7714 let mut mint_account = SolanaAccount::new(
7715 Rent::default().minimum_balance(mint_size),
7716 mint_size,
7717 &program_id,
7718 );
7719 let mut account_account = SolanaAccount::new(
7720 account_minimum_balance(),
7721 Account::get_packed_len(),
7722 &program_id,
7723 );
7724 let mut owner_account = SolanaAccount::default();
7725 let mut burn_authority_account = SolanaAccount::default();
7726 let mut rent_sysvar = rent_sysvar();
7727
7728 do_process_instruction(
7729 permissioned_burn::instruction::initialize(&program_id, &mint_key, &burn_authority_key)
7730 .unwrap(),
7731 vec![&mut mint_account],
7732 )
7733 .unwrap();
7734 do_process_instruction(
7735 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
7736 vec![&mut mint_account, &mut rent_sysvar],
7737 )
7738 .unwrap();
7739
7740 do_process_instruction(
7742 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
7743 vec![
7744 &mut account_account,
7745 &mut mint_account,
7746 &mut owner_account,
7747 &mut rent_sysvar,
7748 ],
7749 )
7750 .unwrap();
7751 do_process_instruction(
7752 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 10).unwrap(),
7753 vec![&mut mint_account, &mut account_account, &mut owner_account],
7754 )
7755 .unwrap();
7756
7757 do_process_instruction(
7759 set_authority(
7760 &program_id,
7761 &mint_key,
7762 None,
7763 AuthorityType::PermissionedBurn,
7764 &burn_authority_key,
7765 &[],
7766 )
7767 .unwrap(),
7768 vec![&mut mint_account, &mut burn_authority_account],
7769 )
7770 .unwrap();
7771
7772 assert_eq!(
7774 Err(TokenError::InvalidInstruction.into()),
7775 do_process_instruction(
7776 permissioned_burn::instruction::burn(
7777 &program_id,
7778 &account_key,
7779 &mint_key,
7780 &burn_authority_key,
7781 &owner_key,
7782 &[],
7783 1
7784 )
7785 .unwrap(),
7786 vec![
7787 &mut account_account,
7788 &mut mint_account,
7789 &mut burn_authority_account,
7790 &mut owner_account
7791 ],
7792 )
7793 );
7794
7795 assert_eq!(
7797 Ok(()),
7798 do_process_instruction(
7799 burn(&program_id, &account_key, &mint_key, &owner_key, &[], 1).unwrap(),
7800 vec![&mut account_account, &mut mint_account, &mut owner_account],
7801 )
7802 );
7803 }
7804
7805 #[test]
7806 fn test_validate_owner() {
7807 let program_id = crate::id();
7808 let owner_key = Address::new_unique();
7809 let account_to_validate = Address::new_unique();
7810 let mut signer_keys = [Address::default(); MAX_SIGNERS];
7811 for signer_key in signer_keys.iter_mut().take(MAX_SIGNERS) {
7812 *signer_key = Address::new_unique();
7813 }
7814 let mut signer_lamports = 0;
7815 let mut signer_data = vec![];
7816 let mut signers = vec![
7817 AccountInfo::new(
7818 &owner_key,
7819 true,
7820 false,
7821 &mut signer_lamports,
7822 &mut signer_data,
7823 &program_id,
7824 false,
7825 );
7826 MAX_SIGNERS + 1
7827 ];
7828 for (signer, key) in signers.iter_mut().zip(&signer_keys) {
7829 signer.key = key;
7830 }
7831 let mut lamports = 0;
7832 let mut data = vec![0; Multisig::get_packed_len()];
7833 let mut multisig = Multisig::unpack_unchecked(&data).unwrap();
7834 multisig.m = MAX_SIGNERS as u8;
7835 multisig.n = MAX_SIGNERS as u8;
7836 multisig.signers = signer_keys;
7837 multisig.is_initialized = true;
7838 Multisig::pack(multisig, &mut data).unwrap();
7839 let owner_account_info = AccountInfo::new(
7840 &owner_key,
7841 false,
7842 false,
7843 &mut lamports,
7844 &mut data,
7845 &program_id,
7846 false,
7847 );
7848
7849 {
7852 let mut lamports = 0;
7853 let mut data = vec![0; Account::get_packed_len()];
7854 let mut account = Account::unpack_unchecked(&data).unwrap();
7855 account.owner = account_to_validate;
7856 Account::pack(account, &mut data).unwrap();
7857 let account_info = AccountInfo::new(
7858 &account_to_validate,
7859 true,
7860 false,
7861 &mut lamports,
7862 &mut data,
7863 &program_id,
7864 false,
7865 );
7866 let account_info_data_len = account_info.data_len();
7867 let mut borrowed_data = account_info.try_borrow_mut_data().unwrap();
7868 Processor::validate_owner(
7869 &program_id,
7870 &account_to_validate,
7871 &account_info,
7872 account_info_data_len,
7873 &[],
7874 )
7875 .unwrap();
7876 borrowed_data[0] = 1;
7878 }
7879
7880 Processor::validate_owner(
7882 &program_id,
7883 &owner_key,
7884 &owner_account_info,
7885 owner_account_info.data_len(),
7886 &signers,
7887 )
7888 .unwrap();
7889
7890 {
7892 let tokenkeg_id = inline_spl_token::id();
7893 let mut lamports = 0;
7894 let mut data = vec![0; Multisig::get_packed_len()];
7895 let mut multisig = Multisig::unpack_unchecked(&data).unwrap();
7896 multisig.m = MAX_SIGNERS as u8;
7897 multisig.n = MAX_SIGNERS as u8;
7898 multisig.signers = signer_keys;
7899 multisig.is_initialized = true;
7900 Multisig::pack(multisig, &mut data).unwrap();
7901 let tokenkeg_multisig_info = AccountInfo::new(
7902 &owner_key,
7903 false,
7904 false,
7905 &mut lamports,
7906 &mut data,
7907 &tokenkeg_id,
7908 false,
7909 );
7910 Processor::validate_owner(
7911 &program_id,
7912 &owner_key,
7913 &tokenkeg_multisig_info,
7914 tokenkeg_multisig_info.data_len(),
7915 &signers,
7916 )
7917 .unwrap();
7918 }
7919
7920 {
7922 let mut multisig =
7923 Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
7924 multisig.m = 1;
7925 Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
7926 }
7927 Processor::validate_owner(
7928 &program_id,
7929 &owner_key,
7930 &owner_account_info,
7931 owner_account_info.data_len(),
7932 &signers,
7933 )
7934 .unwrap();
7935
7936 {
7938 let mut multisig =
7939 Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
7940 multisig.m = 2;
7941 multisig.n = 1;
7942 Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
7943 }
7944 assert_eq!(
7945 Err(ProgramError::MissingRequiredSignature),
7946 Processor::validate_owner(
7947 &program_id,
7948 &owner_key,
7949 &owner_account_info,
7950 owner_account_info.data_len(),
7951 &signers
7952 )
7953 );
7954
7955 {
7957 let mut multisig =
7958 Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
7959 multisig.m = 0;
7960 multisig.n = 11;
7961 Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
7962 }
7963 Processor::validate_owner(
7964 &program_id,
7965 &owner_key,
7966 &owner_account_info,
7967 owner_account_info.data_len(),
7968 &signers,
7969 )
7970 .unwrap();
7971
7972 {
7974 let mut multisig =
7975 Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
7976 multisig.m = 2;
7977 multisig.n = 11;
7978 Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
7979 }
7980 assert_eq!(
7981 Err(ProgramError::MissingRequiredSignature),
7982 Processor::validate_owner(
7983 &program_id,
7984 &owner_key,
7985 &owner_account_info,
7986 owner_account_info.data_len(),
7987 &[]
7988 )
7989 );
7990 {
7992 let mut multisig =
7993 Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
7994 multisig.m = 2;
7995 multisig.n = 11;
7996 Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
7997 }
7998 assert_eq!(
7999 Err(ProgramError::MissingRequiredSignature),
8000 Processor::validate_owner(
8001 &program_id,
8002 &owner_key,
8003 &owner_account_info,
8004 owner_account_info.data_len(),
8005 &signers[0..1]
8006 )
8007 );
8008
8009 {
8011 let mut multisig =
8012 Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
8013 multisig.m = 2;
8014 multisig.n = 11;
8015 Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
8016 }
8017 Processor::validate_owner(
8018 &program_id,
8019 &owner_key,
8020 &owner_account_info,
8021 owner_account_info.data_len(),
8022 &signers[5..7],
8023 )
8024 .unwrap();
8025
8026 {
8028 let mut multisig =
8029 Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
8030 multisig.m = 11;
8031 multisig.n = 11;
8032 Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
8033 }
8034 signers[5].is_signer = false;
8035 assert_eq!(
8036 Err(ProgramError::MissingRequiredSignature),
8037 Processor::validate_owner(
8038 &program_id,
8039 &owner_key,
8040 &owner_account_info,
8041 owner_account_info.data_len(),
8042 &signers
8043 )
8044 );
8045 signers[5].is_signer = true;
8046
8047 {
8049 let mut signer_lamports = 0;
8050 let mut signer_data = vec![];
8051 let signers = vec![
8052 AccountInfo::new(
8053 &signer_keys[5],
8054 true,
8055 false,
8056 &mut signer_lamports,
8057 &mut signer_data,
8058 &program_id,
8059 false,
8060 );
8061 MAX_SIGNERS + 1
8062 ];
8063 let mut multisig =
8064 Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
8065 multisig.m = 11;
8066 multisig.n = 11;
8067 Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
8068 assert_eq!(
8069 Err(ProgramError::MissingRequiredSignature),
8070 Processor::validate_owner(
8071 &program_id,
8072 &owner_key,
8073 &owner_account_info,
8074 owner_account_info.data_len(),
8075 &signers
8076 )
8077 );
8078 }
8079 }
8080
8081 #[test]
8082 fn test_owner_close_account_dups() {
8083 let program_id = crate::id();
8084 let owner_key = Address::new_unique();
8085 let mint_key = Address::new_unique();
8086 let mut mint_account =
8087 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
8088 let mint_info: AccountInfo = (&mint_key, false, &mut mint_account).into();
8089 let rent_key = rent::id();
8090 let mut rent_sysvar = rent_sysvar();
8091 let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
8092
8093 do_process_instruction_dups(
8095 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
8096 vec![mint_info.clone(), rent_info.clone()],
8097 )
8098 .unwrap();
8099
8100 let to_close_key = Address::new_unique();
8101 let mut to_close_account = SolanaAccount::new(
8102 account_minimum_balance(),
8103 Account::get_packed_len(),
8104 &program_id,
8105 );
8106 let to_close_account_info: AccountInfo =
8107 (&to_close_key, true, &mut to_close_account).into();
8108 let destination_account_key = Address::new_unique();
8109 let mut destination_account = SolanaAccount::new(
8110 account_minimum_balance(),
8111 Account::get_packed_len(),
8112 &program_id,
8113 );
8114 let destination_account_info: AccountInfo =
8115 (&destination_account_key, true, &mut destination_account).into();
8116 do_process_instruction_dups(
8118 initialize_account(&program_id, &to_close_key, &mint_key, &to_close_key).unwrap(),
8119 vec![
8120 to_close_account_info.clone(),
8121 mint_info.clone(),
8122 to_close_account_info.clone(),
8123 rent_info.clone(),
8124 ],
8125 )
8126 .unwrap();
8127
8128 do_process_instruction_dups(
8130 close_account(
8131 &program_id,
8132 &to_close_key,
8133 &destination_account_key,
8134 &to_close_key,
8135 &[],
8136 )
8137 .unwrap(),
8138 vec![
8139 to_close_account_info.clone(),
8140 destination_account_info.clone(),
8141 to_close_account_info.clone(),
8142 ],
8143 )
8144 .unwrap();
8145 assert_eq!(*to_close_account_info.data.borrow(), &[0u8; Account::LEN]);
8146 }
8147
8148 #[test]
8149 fn test_close_authority_close_account_dups() {
8150 let program_id = crate::id();
8151 let owner_key = Address::new_unique();
8152 let mint_key = Address::new_unique();
8153 let mut mint_account =
8154 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
8155 let mint_info: AccountInfo = (&mint_key, false, &mut mint_account).into();
8156 let rent_key = rent::id();
8157 let mut rent_sysvar = rent_sysvar();
8158 let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
8159
8160 do_process_instruction_dups(
8162 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
8163 vec![mint_info.clone(), rent_info.clone()],
8164 )
8165 .unwrap();
8166
8167 let to_close_key = Address::new_unique();
8168 let mut to_close_account = SolanaAccount::new(
8169 account_minimum_balance(),
8170 Account::get_packed_len(),
8171 &program_id,
8172 );
8173 let to_close_account_info: AccountInfo =
8174 (&to_close_key, true, &mut to_close_account).into();
8175 let destination_account_key = Address::new_unique();
8176 let mut destination_account = SolanaAccount::new(
8177 account_minimum_balance(),
8178 Account::get_packed_len(),
8179 &program_id,
8180 );
8181 let destination_account_info: AccountInfo =
8182 (&destination_account_key, true, &mut destination_account).into();
8183 do_process_instruction_dups(
8185 initialize_account(&program_id, &to_close_key, &mint_key, &to_close_key).unwrap(),
8186 vec![
8187 to_close_account_info.clone(),
8188 mint_info.clone(),
8189 to_close_account_info.clone(),
8190 rent_info.clone(),
8191 ],
8192 )
8193 .unwrap();
8194 let mut account = Account::unpack_unchecked(&to_close_account_info.data.borrow()).unwrap();
8195 account.close_authority = COption::Some(to_close_key);
8196 account.owner = owner_key;
8197 Account::pack(account, &mut to_close_account_info.data.borrow_mut()).unwrap();
8198 do_process_instruction_dups(
8199 close_account(
8200 &program_id,
8201 &to_close_key,
8202 &destination_account_key,
8203 &to_close_key,
8204 &[],
8205 )
8206 .unwrap(),
8207 vec![
8208 to_close_account_info.clone(),
8209 destination_account_info.clone(),
8210 to_close_account_info.clone(),
8211 ],
8212 )
8213 .unwrap();
8214 assert_eq!(*to_close_account_info.data.borrow(), &[0u8; Account::LEN]);
8215 }
8216
8217 #[test]
8218 fn test_close_account() {
8219 let program_id = crate::id();
8220 let mint_key = Address::new_unique();
8221 let mut mint_account =
8222 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
8223 let account_key = Address::new_unique();
8224 let mut account_account = SolanaAccount::new(
8225 account_minimum_balance(),
8226 Account::get_packed_len(),
8227 &program_id,
8228 );
8229 let account2_key = Address::new_unique();
8230 let mut account2_account = SolanaAccount::new(
8231 account_minimum_balance() + 42,
8232 Account::get_packed_len(),
8233 &program_id,
8234 );
8235 let account3_key = Address::new_unique();
8236 let mut account3_account = SolanaAccount::new(
8237 account_minimum_balance(),
8238 Account::get_packed_len(),
8239 &program_id,
8240 );
8241 let owner_key = Address::new_unique();
8242 let mut owner_account = SolanaAccount::default();
8243 let owner2_key = Address::new_unique();
8244 let mut owner2_account = SolanaAccount::default();
8245 let mut rent_sysvar = rent_sysvar();
8246
8247 assert_eq!(
8249 Err(ProgramError::UninitializedAccount),
8250 do_process_instruction(
8251 close_account(&program_id, &account_key, &account3_key, &owner2_key, &[]).unwrap(),
8252 vec![
8253 &mut account_account,
8254 &mut account3_account,
8255 &mut owner2_account,
8256 ],
8257 )
8258 );
8259
8260 do_process_instruction(
8262 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
8263 vec![&mut mint_account, &mut rent_sysvar],
8264 )
8265 .unwrap();
8266 do_process_instruction(
8267 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
8268 vec![
8269 &mut account_account,
8270 &mut mint_account,
8271 &mut owner_account,
8272 &mut rent_sysvar,
8273 ],
8274 )
8275 .unwrap();
8276 do_process_instruction(
8277 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 42).unwrap(),
8278 vec![
8279 &mut mint_account,
8280 &mut account_account,
8281 &mut owner_account,
8282 &mut rent_sysvar,
8283 ],
8284 )
8285 .unwrap();
8286 let account = Account::unpack_unchecked(&account_account.data).unwrap();
8287 assert_eq!(account.amount, 42);
8288
8289 do_process_instruction(
8291 initialize_account(
8292 &program_id,
8293 &account2_key,
8294 &crate::native_mint::id(),
8295 &owner_key,
8296 )
8297 .unwrap(),
8298 vec![
8299 &mut account2_account,
8300 &mut mint_account,
8301 &mut owner_account,
8302 &mut rent_sysvar,
8303 ],
8304 )
8305 .unwrap();
8306 let account = Account::unpack_unchecked(&account2_account.data).unwrap();
8307 assert!(account.is_native());
8308 assert_eq!(account.amount, 42);
8309
8310 assert_eq!(
8312 Err(TokenError::NonNativeHasBalance.into()),
8313 do_process_instruction(
8314 close_account(&program_id, &account_key, &account3_key, &owner_key, &[]).unwrap(),
8315 vec![
8316 &mut account_account,
8317 &mut account3_account,
8318 &mut owner_account,
8319 ],
8320 )
8321 );
8322 assert_eq!(account_account.lamports, account_minimum_balance());
8323
8324 do_process_instruction(
8326 burn(&program_id, &account_key, &mint_key, &owner_key, &[], 42).unwrap(),
8327 vec![&mut account_account, &mut mint_account, &mut owner_account],
8328 )
8329 .unwrap();
8330
8331 assert_eq!(
8333 Err(TokenError::OwnerMismatch.into()),
8334 do_process_instruction(
8335 close_account(&program_id, &account_key, &account3_key, &owner2_key, &[]).unwrap(),
8336 vec![
8337 &mut account_account,
8338 &mut account3_account,
8339 &mut owner2_account,
8340 ],
8341 )
8342 );
8343
8344 do_process_instruction(
8346 close_account(&program_id, &account_key, &account3_key, &owner_key, &[]).unwrap(),
8347 vec![
8348 &mut account_account,
8349 &mut account3_account,
8350 &mut owner_account,
8351 ],
8352 )
8353 .unwrap();
8354 assert_eq!(account_account.lamports, 0);
8355 assert_eq!(account3_account.lamports, 2 * account_minimum_balance());
8356 let account = Account::unpack_unchecked(&account_account.data).unwrap();
8357 assert_eq!(account.amount, 0);
8358
8359 let account_key = Address::new_unique();
8361 let mut account_account = SolanaAccount::new(
8362 account_minimum_balance(),
8363 Account::get_packed_len(),
8364 &program_id,
8365 );
8366 let owner2_key = Address::new_unique();
8367 let mut owner2_account = SolanaAccount::new(
8368 account_minimum_balance(),
8369 Account::get_packed_len(),
8370 &program_id,
8371 );
8372 do_process_instruction(
8373 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
8374 vec![
8375 &mut account_account,
8376 &mut mint_account,
8377 &mut owner_account,
8378 &mut rent_sysvar,
8379 ],
8380 )
8381 .unwrap();
8382 account_account.lamports = 2;
8383
8384 do_process_instruction(
8385 set_authority(
8386 &program_id,
8387 &account_key,
8388 Some(&owner2_key),
8389 AuthorityType::CloseAccount,
8390 &owner_key,
8391 &[],
8392 )
8393 .unwrap(),
8394 vec![&mut account_account, &mut owner_account],
8395 )
8396 .unwrap();
8397
8398 assert_eq!(
8400 Err(TokenError::OwnerMismatch.into()),
8401 do_process_instruction(
8402 close_account(&program_id, &account_key, &account3_key, &owner_key, &[]).unwrap(),
8403 vec![
8404 &mut account_account,
8405 &mut account3_account,
8406 &mut owner_account,
8407 ],
8408 )
8409 );
8410
8411 do_process_instruction(
8413 close_account(&program_id, &account_key, &account3_key, &owner2_key, &[]).unwrap(),
8414 vec![
8415 &mut account_account,
8416 &mut account3_account,
8417 &mut owner2_account,
8418 ],
8419 )
8420 .unwrap();
8421 assert_eq!(account_account.lamports, 0);
8422 assert_eq!(account3_account.lamports, 2 * account_minimum_balance() + 2);
8423 let account = Account::unpack_unchecked(&account_account.data).unwrap();
8424 assert_eq!(account.amount, 0);
8425
8426 do_process_instruction(
8428 close_account(&program_id, &account2_key, &account3_key, &owner_key, &[]).unwrap(),
8429 vec![
8430 &mut account2_account,
8431 &mut account3_account,
8432 &mut owner_account,
8433 ],
8434 )
8435 .unwrap();
8436 assert_eq!(account2_account.data, [0u8; Account::LEN]);
8437 assert_eq!(
8438 account3_account.lamports,
8439 3 * account_minimum_balance() + 2 + 42
8440 );
8441 }
8442
8443 #[test]
8444 fn test_native_token() {
8445 let program_id = crate::id();
8446 let mut mint_account = native_mint();
8447 let account_key = Address::new_unique();
8448 let mut account_account = SolanaAccount::new(
8449 account_minimum_balance() + 40,
8450 Account::get_packed_len(),
8451 &program_id,
8452 );
8453 let account2_key = Address::new_unique();
8454 let mut account2_account = SolanaAccount::new(
8455 account_minimum_balance(),
8456 Account::get_packed_len(),
8457 &program_id,
8458 );
8459 let account3_key = Address::new_unique();
8460 let mut account3_account = SolanaAccount::new(account_minimum_balance(), 0, &program_id);
8461 let owner_key = Address::new_unique();
8462 let mut owner_account = SolanaAccount::default();
8463 let owner2_key = Address::new_unique();
8464 let mut owner2_account = SolanaAccount::default();
8465 let owner3_key = Address::new_unique();
8466 let mut rent_sysvar = rent_sysvar();
8467
8468 do_process_instruction(
8470 initialize_account(
8471 &program_id,
8472 &account_key,
8473 &crate::native_mint::id(),
8474 &owner_key,
8475 )
8476 .unwrap(),
8477 vec![
8478 &mut account_account,
8479 &mut mint_account,
8480 &mut owner_account,
8481 &mut rent_sysvar,
8482 ],
8483 )
8484 .unwrap();
8485 let account = Account::unpack_unchecked(&account_account.data).unwrap();
8486 assert!(account.is_native());
8487 assert_eq!(account.amount, 40);
8488
8489 do_process_instruction(
8491 initialize_account(
8492 &program_id,
8493 &account2_key,
8494 &crate::native_mint::id(),
8495 &owner_key,
8496 )
8497 .unwrap(),
8498 vec![
8499 &mut account2_account,
8500 &mut mint_account,
8501 &mut owner_account,
8502 &mut rent_sysvar,
8503 ],
8504 )
8505 .unwrap();
8506 let account = Account::unpack_unchecked(&account2_account.data).unwrap();
8507 assert!(account.is_native());
8508 assert_eq!(account.amount, 0);
8509
8510 assert_eq!(
8512 Err(TokenError::NativeNotSupported.into()),
8513 do_process_instruction(
8514 mint_to(
8515 &program_id,
8516 &crate::native_mint::id(),
8517 &account_key,
8518 &owner_key,
8519 &[],
8520 42
8521 )
8522 .unwrap(),
8523 vec![&mut mint_account, &mut account_account, &mut owner_account],
8524 )
8525 );
8526
8527 let bogus_mint_key = Address::new_unique();
8529 let mut bogus_mint_account =
8530 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
8531 do_process_instruction(
8532 initialize_mint(&program_id, &bogus_mint_key, &owner_key, None, 2).unwrap(),
8533 vec![&mut bogus_mint_account, &mut rent_sysvar],
8534 )
8535 .unwrap();
8536
8537 assert_eq!(
8538 Err(TokenError::NativeNotSupported.into()),
8539 do_process_instruction(
8540 burn(
8541 &program_id,
8542 &account_key,
8543 &bogus_mint_key,
8544 &owner_key,
8545 &[],
8546 42
8547 )
8548 .unwrap(),
8549 vec![
8550 &mut account_account,
8551 &mut bogus_mint_account,
8552 &mut owner_account
8553 ],
8554 )
8555 );
8556
8557 assert_eq!(
8559 Err(TokenError::InsufficientFunds.into()),
8560 do_process_instruction(
8561 #[allow(deprecated)]
8562 transfer(
8563 &program_id,
8564 &account_key,
8565 &account2_key,
8566 &owner_key,
8567 &[],
8568 50,
8569 )
8570 .unwrap(),
8571 vec![
8572 &mut account_account,
8573 &mut account2_account,
8574 &mut owner_account,
8575 ],
8576 )
8577 );
8578
8579 do_process_instruction(
8581 #[allow(deprecated)]
8582 transfer(
8583 &program_id,
8584 &account_key,
8585 &account2_key,
8586 &owner_key,
8587 &[],
8588 40,
8589 )
8590 .unwrap(),
8591 vec![
8592 &mut account_account,
8593 &mut account2_account,
8594 &mut owner_account,
8595 ],
8596 )
8597 .unwrap();
8598 assert_eq!(account_account.lamports, account_minimum_balance());
8599 let account = Account::unpack_unchecked(&account_account.data).unwrap();
8600 assert!(account.is_native());
8601 assert_eq!(account.amount, 0);
8602 assert_eq!(account2_account.lamports, account_minimum_balance() + 40);
8603 let account = Account::unpack_unchecked(&account2_account.data).unwrap();
8604 assert!(account.is_native());
8605 assert_eq!(account.amount, 40);
8606
8607 do_process_instruction(
8609 set_authority(
8610 &program_id,
8611 &account_key,
8612 Some(&owner3_key),
8613 AuthorityType::CloseAccount,
8614 &owner_key,
8615 &[],
8616 )
8617 .unwrap(),
8618 vec![&mut account_account, &mut owner_account],
8619 )
8620 .unwrap();
8621 let account = Account::unpack_unchecked(&account_account.data).unwrap();
8622 assert_eq!(account.close_authority, COption::Some(owner3_key));
8623
8624 do_process_instruction(
8626 set_authority(
8627 &program_id,
8628 &account_key,
8629 Some(&owner2_key),
8630 AuthorityType::AccountOwner,
8631 &owner_key,
8632 &[],
8633 )
8634 .unwrap(),
8635 vec![&mut account_account, &mut owner_account],
8636 )
8637 .unwrap();
8638
8639 let account = Account::unpack_unchecked(&account_account.data).unwrap();
8641 assert_eq!(account.close_authority, COption::None);
8642
8643 do_process_instruction(
8645 close_account(&program_id, &account_key, &account3_key, &owner2_key, &[]).unwrap(),
8646 vec![
8647 &mut account_account,
8648 &mut account3_account,
8649 &mut owner2_account,
8650 ],
8651 )
8652 .unwrap();
8653 assert_eq!(account_account.lamports, 0);
8654 assert_eq!(account3_account.lamports, 2 * account_minimum_balance());
8655 assert_eq!(account_account.data, [0u8; Account::LEN]);
8656 }
8657
8658 #[test]
8659 fn test_overflow() {
8660 let program_id = crate::id();
8661 let account_key = Address::new_unique();
8662 let mut account_account = SolanaAccount::new(
8663 account_minimum_balance(),
8664 Account::get_packed_len(),
8665 &program_id,
8666 );
8667 let account2_key = Address::new_unique();
8668 let mut account2_account = SolanaAccount::new(
8669 account_minimum_balance(),
8670 Account::get_packed_len(),
8671 &program_id,
8672 );
8673 let owner_key = Address::new_unique();
8674 let mut owner_account = SolanaAccount::default();
8675 let owner2_key = Address::new_unique();
8676 let mut owner2_account = SolanaAccount::default();
8677 let mint_owner_key = Address::new_unique();
8678 let mut mint_owner_account = SolanaAccount::default();
8679 let mint_key = Address::new_unique();
8680 let mut mint_account =
8681 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
8682 let mut rent_sysvar = rent_sysvar();
8683
8684 do_process_instruction(
8686 initialize_mint(&program_id, &mint_key, &mint_owner_key, None, 2).unwrap(),
8687 vec![&mut mint_account, &mut rent_sysvar],
8688 )
8689 .unwrap();
8690
8691 do_process_instruction(
8693 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
8694 vec![
8695 &mut account_account,
8696 &mut mint_account,
8697 &mut owner_account,
8698 &mut rent_sysvar,
8699 ],
8700 )
8701 .unwrap();
8702
8703 do_process_instruction(
8705 initialize_account(&program_id, &account2_key, &mint_key, &owner2_key).unwrap(),
8706 vec![
8707 &mut account2_account,
8708 &mut mint_account,
8709 &mut owner2_account,
8710 &mut rent_sysvar,
8711 ],
8712 )
8713 .unwrap();
8714
8715 do_process_instruction(
8717 mint_to(
8718 &program_id,
8719 &mint_key,
8720 &account_key,
8721 &mint_owner_key,
8722 &[],
8723 u64::MAX,
8724 )
8725 .unwrap(),
8726 vec![
8727 &mut mint_account,
8728 &mut account_account,
8729 &mut mint_owner_account,
8730 ],
8731 )
8732 .unwrap();
8733 let account = Account::unpack_unchecked(&account_account.data).unwrap();
8734 assert_eq!(account.amount, u64::MAX);
8735
8736 assert_eq!(
8738 Err(TokenError::Overflow.into()),
8739 do_process_instruction(
8740 mint_to(
8741 &program_id,
8742 &mint_key,
8743 &account_key,
8744 &mint_owner_key,
8745 &[],
8746 1,
8747 )
8748 .unwrap(),
8749 vec![
8750 &mut mint_account,
8751 &mut account_account,
8752 &mut mint_owner_account,
8753 ],
8754 )
8755 );
8756 let account = Account::unpack_unchecked(&account_account.data).unwrap();
8757 assert_eq!(account.amount, u64::MAX);
8758
8759 assert_eq!(
8761 Err(TokenError::Overflow.into()),
8762 do_process_instruction(
8763 mint_to(
8764 &program_id,
8765 &mint_key,
8766 &account2_key,
8767 &mint_owner_key,
8768 &[],
8769 1,
8770 )
8771 .unwrap(),
8772 vec![
8773 &mut mint_account,
8774 &mut account2_account,
8775 &mut mint_owner_account,
8776 ],
8777 )
8778 );
8779
8780 do_process_instruction(
8782 burn(&program_id, &account_key, &mint_key, &owner_key, &[], 100).unwrap(),
8783 vec![&mut account_account, &mut mint_account, &mut owner_account],
8784 )
8785 .unwrap();
8786 let account = Account::unpack_unchecked(&account_account.data).unwrap();
8787 assert_eq!(account.amount, u64::MAX - 100);
8788
8789 do_process_instruction(
8790 mint_to(
8791 &program_id,
8792 &mint_key,
8793 &account_key,
8794 &mint_owner_key,
8795 &[],
8796 100,
8797 )
8798 .unwrap(),
8799 vec![
8800 &mut mint_account,
8801 &mut account_account,
8802 &mut mint_owner_account,
8803 ],
8804 )
8805 .unwrap();
8806 let account = Account::unpack_unchecked(&account_account.data).unwrap();
8807 assert_eq!(account.amount, u64::MAX);
8808
8809 let mut account = Account::unpack_unchecked(&account2_account.data).unwrap();
8811 account.amount = 1;
8812 Account::pack(account, &mut account2_account.data).unwrap();
8813
8814 assert_eq!(
8815 Err(TokenError::Overflow.into()),
8816 do_process_instruction(
8817 #[allow(deprecated)]
8818 transfer(
8819 &program_id,
8820 &account2_key,
8821 &account_key,
8822 &owner2_key,
8823 &[],
8824 1,
8825 )
8826 .unwrap(),
8827 vec![
8828 &mut account2_account,
8829 &mut account_account,
8830 &mut owner2_account,
8831 ],
8832 )
8833 );
8834 }
8835
8836 #[test]
8837 fn test_frozen() {
8838 let program_id = crate::id();
8839 let account_key = Address::new_unique();
8840 let mut account_account = SolanaAccount::new(
8841 account_minimum_balance(),
8842 Account::get_packed_len(),
8843 &program_id,
8844 );
8845 let account2_key = Address::new_unique();
8846 let mut account2_account = SolanaAccount::new(
8847 account_minimum_balance(),
8848 Account::get_packed_len(),
8849 &program_id,
8850 );
8851 let owner_key = Address::new_unique();
8852 let mut owner_account = SolanaAccount::default();
8853 let mint_key = Address::new_unique();
8854 let mut mint_account =
8855 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
8856 let mut rent_sysvar = rent_sysvar();
8857
8858 do_process_instruction(
8860 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
8861 vec![&mut mint_account, &mut rent_sysvar],
8862 )
8863 .unwrap();
8864
8865 do_process_instruction(
8867 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
8868 vec![
8869 &mut account_account,
8870 &mut mint_account,
8871 &mut owner_account,
8872 &mut rent_sysvar,
8873 ],
8874 )
8875 .unwrap();
8876
8877 do_process_instruction(
8879 initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
8880 vec![
8881 &mut account2_account,
8882 &mut mint_account,
8883 &mut owner_account,
8884 &mut rent_sysvar,
8885 ],
8886 )
8887 .unwrap();
8888
8889 do_process_instruction(
8891 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
8892 vec![&mut mint_account, &mut account_account, &mut owner_account],
8893 )
8894 .unwrap();
8895
8896 let mut account = Account::unpack_unchecked(&account2_account.data).unwrap();
8898 account.state = AccountState::Frozen;
8899 Account::pack(account, &mut account2_account.data).unwrap();
8900 assert_eq!(
8901 Err(TokenError::AccountFrozen.into()),
8902 do_process_instruction(
8903 #[allow(deprecated)]
8904 transfer(
8905 &program_id,
8906 &account_key,
8907 &account2_key,
8908 &owner_key,
8909 &[],
8910 500,
8911 )
8912 .unwrap(),
8913 vec![
8914 &mut account_account,
8915 &mut account2_account,
8916 &mut owner_account,
8917 ],
8918 )
8919 );
8920
8921 let mut account = Account::unpack_unchecked(&account_account.data).unwrap();
8922 account.state = AccountState::Initialized;
8923 Account::pack(account, &mut account_account.data).unwrap();
8924 let mut account = Account::unpack_unchecked(&account2_account.data).unwrap();
8925 account.state = AccountState::Frozen;
8926 Account::pack(account, &mut account2_account.data).unwrap();
8927 assert_eq!(
8928 Err(TokenError::AccountFrozen.into()),
8929 do_process_instruction(
8930 #[allow(deprecated)]
8931 transfer(
8932 &program_id,
8933 &account_key,
8934 &account2_key,
8935 &owner_key,
8936 &[],
8937 500,
8938 )
8939 .unwrap(),
8940 vec![
8941 &mut account_account,
8942 &mut account2_account,
8943 &mut owner_account,
8944 ],
8945 )
8946 );
8947
8948 let mut account = Account::unpack_unchecked(&account_account.data).unwrap();
8950 account.state = AccountState::Frozen;
8951 Account::pack(account, &mut account_account.data).unwrap();
8952 let delegate_key = Address::new_unique();
8953 let mut delegate_account = SolanaAccount::default();
8954 assert_eq!(
8955 Err(TokenError::AccountFrozen.into()),
8956 do_process_instruction(
8957 approve(
8958 &program_id,
8959 &account_key,
8960 &delegate_key,
8961 &owner_key,
8962 &[],
8963 100
8964 )
8965 .unwrap(),
8966 vec![
8967 &mut account_account,
8968 &mut delegate_account,
8969 &mut owner_account,
8970 ],
8971 )
8972 );
8973
8974 let mut account = Account::unpack_unchecked(&account_account.data).unwrap();
8976 account.delegate = COption::Some(delegate_key);
8977 account.delegated_amount = 100;
8978 Account::pack(account, &mut account_account.data).unwrap();
8979 assert_eq!(
8980 Err(TokenError::AccountFrozen.into()),
8981 do_process_instruction(
8982 revoke(&program_id, &account_key, &owner_key, &[]).unwrap(),
8983 vec![&mut account_account, &mut owner_account],
8984 )
8985 );
8986
8987 let new_owner_key = Address::new_unique();
8989 assert_eq!(
8990 Err(TokenError::AccountFrozen.into()),
8991 do_process_instruction(
8992 set_authority(
8993 &program_id,
8994 &account_key,
8995 Some(&new_owner_key),
8996 AuthorityType::AccountOwner,
8997 &owner_key,
8998 &[]
8999 )
9000 .unwrap(),
9001 vec![&mut account_account, &mut owner_account,],
9002 )
9003 );
9004
9005 assert_eq!(
9007 Err(TokenError::AccountFrozen.into()),
9008 do_process_instruction(
9009 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 100).unwrap(),
9010 vec![&mut mint_account, &mut account_account, &mut owner_account,],
9011 )
9012 );
9013
9014 assert_eq!(
9016 Err(TokenError::AccountFrozen.into()),
9017 do_process_instruction(
9018 burn(&program_id, &account_key, &mint_key, &owner_key, &[], 100).unwrap(),
9019 vec![&mut account_account, &mut mint_account, &mut owner_account],
9020 )
9021 );
9022 }
9023
9024 #[test]
9025 fn test_freeze_thaw_dups() {
9026 let program_id = crate::id();
9027 let account1_key = Address::new_unique();
9028 let mut account1_account = SolanaAccount::new(
9029 account_minimum_balance(),
9030 Account::get_packed_len(),
9031 &program_id,
9032 );
9033 let account1_info: AccountInfo = (&account1_key, true, &mut account1_account).into();
9034 let owner_key = Address::new_unique();
9035 let mint_key = Address::new_unique();
9036 let mut mint_account =
9037 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
9038 let mint_info: AccountInfo = (&mint_key, true, &mut mint_account).into();
9039 let rent_key = rent::id();
9040 let mut rent_sysvar = rent_sysvar();
9041 let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
9042
9043 do_process_instruction_dups(
9045 initialize_mint(&program_id, &mint_key, &owner_key, Some(&account1_key), 2).unwrap(),
9046 vec![mint_info.clone(), rent_info.clone()],
9047 )
9048 .unwrap();
9049
9050 do_process_instruction_dups(
9052 initialize_account(&program_id, &account1_key, &mint_key, &account1_key).unwrap(),
9053 vec![
9054 account1_info.clone(),
9055 mint_info.clone(),
9056 account1_info.clone(),
9057 rent_info.clone(),
9058 ],
9059 )
9060 .unwrap();
9061
9062 do_process_instruction_dups(
9064 freeze_account(&program_id, &account1_key, &mint_key, &account1_key, &[]).unwrap(),
9065 vec![
9066 account1_info.clone(),
9067 mint_info.clone(),
9068 account1_info.clone(),
9069 ],
9070 )
9071 .unwrap();
9072
9073 let mut account = Account::unpack_unchecked(&account1_info.data.borrow()).unwrap();
9075 account.state = AccountState::Frozen;
9076 Account::pack(account, &mut account1_info.data.borrow_mut()).unwrap();
9077 do_process_instruction_dups(
9078 thaw_account(&program_id, &account1_key, &mint_key, &account1_key, &[]).unwrap(),
9079 vec![
9080 account1_info.clone(),
9081 mint_info.clone(),
9082 account1_info.clone(),
9083 ],
9084 )
9085 .unwrap();
9086 }
9087
9088 #[test]
9089 fn test_freeze_account() {
9090 let program_id = crate::id();
9091 let account_key = Address::new_unique();
9092 let mut account_account = SolanaAccount::new(
9093 account_minimum_balance(),
9094 Account::get_packed_len(),
9095 &program_id,
9096 );
9097 let account_owner_key = Address::new_unique();
9098 let mut account_owner_account = SolanaAccount::default();
9099 let owner_key = Address::new_unique();
9100 let mut owner_account = SolanaAccount::default();
9101 let owner2_key = Address::new_unique();
9102 let mut owner2_account = SolanaAccount::default();
9103 let mint_key = Address::new_unique();
9104 let mut mint_account =
9105 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
9106 let mut rent_sysvar = rent_sysvar();
9107
9108 do_process_instruction(
9110 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
9111 vec![&mut mint_account, &mut rent_sysvar],
9112 )
9113 .unwrap();
9114
9115 do_process_instruction(
9117 initialize_account(&program_id, &account_key, &mint_key, &account_owner_key).unwrap(),
9118 vec![
9119 &mut account_account,
9120 &mut mint_account,
9121 &mut account_owner_account,
9122 &mut rent_sysvar,
9123 ],
9124 )
9125 .unwrap();
9126
9127 do_process_instruction(
9129 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
9130 vec![&mut mint_account, &mut account_account, &mut owner_account],
9131 )
9132 .unwrap();
9133
9134 assert_eq!(
9136 Err(TokenError::MintCannotFreeze.into()),
9137 do_process_instruction(
9138 freeze_account(&program_id, &account_key, &mint_key, &owner_key, &[]).unwrap(),
9139 vec![&mut account_account, &mut mint_account, &mut owner_account],
9140 )
9141 );
9142
9143 let mut mint = Mint::unpack_unchecked(&mint_account.data).unwrap();
9145 mint.freeze_authority = COption::Some(owner_key);
9146 Mint::pack(mint, &mut mint_account.data).unwrap();
9147 assert_eq!(
9148 Err(TokenError::OwnerMismatch.into()),
9149 do_process_instruction(
9150 freeze_account(&program_id, &account_key, &mint_key, &owner2_key, &[]).unwrap(),
9151 vec![&mut account_account, &mut mint_account, &mut owner2_account],
9152 )
9153 );
9154
9155 assert_eq!(
9157 Err(TokenError::InvalidState.into()),
9158 do_process_instruction(
9159 thaw_account(&program_id, &account_key, &mint_key, &owner2_key, &[]).unwrap(),
9160 vec![&mut account_account, &mut mint_account, &mut owner2_account],
9161 )
9162 );
9163
9164 do_process_instruction(
9166 freeze_account(&program_id, &account_key, &mint_key, &owner_key, &[]).unwrap(),
9167 vec![&mut account_account, &mut mint_account, &mut owner_account],
9168 )
9169 .unwrap();
9170 let account = Account::unpack_unchecked(&account_account.data).unwrap();
9171 assert_eq!(account.state, AccountState::Frozen);
9172
9173 assert_eq!(
9175 Err(TokenError::InvalidState.into()),
9176 do_process_instruction(
9177 freeze_account(&program_id, &account_key, &mint_key, &owner_key, &[]).unwrap(),
9178 vec![&mut account_account, &mut mint_account, &mut owner_account],
9179 )
9180 );
9181
9182 assert_eq!(
9184 Err(TokenError::OwnerMismatch.into()),
9185 do_process_instruction(
9186 thaw_account(&program_id, &account_key, &mint_key, &owner2_key, &[]).unwrap(),
9187 vec![&mut account_account, &mut mint_account, &mut owner2_account],
9188 )
9189 );
9190
9191 do_process_instruction(
9193 thaw_account(&program_id, &account_key, &mint_key, &owner_key, &[]).unwrap(),
9194 vec![&mut account_account, &mut mint_account, &mut owner_account],
9195 )
9196 .unwrap();
9197 let account = Account::unpack_unchecked(&account_account.data).unwrap();
9198 assert_eq!(account.state, AccountState::Initialized);
9199 }
9200
9201 #[test]
9202 fn test_initialize_account2_and_3() {
9203 let program_id = crate::id();
9204 let account_key = Address::new_unique();
9205 let mut account_account = SolanaAccount::new(
9206 account_minimum_balance(),
9207 Account::get_packed_len(),
9208 &program_id,
9209 );
9210 let mut account2_account = SolanaAccount::new(
9211 account_minimum_balance(),
9212 Account::get_packed_len(),
9213 &program_id,
9214 );
9215 let mut account3_account = SolanaAccount::new(
9216 account_minimum_balance(),
9217 Account::get_packed_len(),
9218 &program_id,
9219 );
9220 let owner_key = Address::new_unique();
9221 let mut owner_account = SolanaAccount::default();
9222 let mint_key = Address::new_unique();
9223 let mut mint_account =
9224 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
9225 let mut rent_sysvar = rent_sysvar();
9226
9227 do_process_instruction(
9229 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
9230 vec![&mut mint_account, &mut rent_sysvar],
9231 )
9232 .unwrap();
9233
9234 do_process_instruction(
9235 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
9236 vec![
9237 &mut account_account,
9238 &mut mint_account,
9239 &mut owner_account,
9240 &mut rent_sysvar,
9241 ],
9242 )
9243 .unwrap();
9244
9245 do_process_instruction(
9246 initialize_account2(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
9247 vec![&mut account2_account, &mut mint_account, &mut rent_sysvar],
9248 )
9249 .unwrap();
9250
9251 assert_eq!(account_account, account2_account);
9252
9253 do_process_instruction(
9254 initialize_account3(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
9255 vec![&mut account3_account, &mut mint_account],
9256 )
9257 .unwrap();
9258
9259 assert_eq!(account_account, account3_account);
9260 }
9261
9262 #[test]
9263 fn initialize_account_on_non_transferable_mint() {
9264 let program_id = crate::id();
9265 let account = Address::new_unique();
9266 let account_len = ExtensionType::try_calculate_account_len::<Mint>(&[
9267 ExtensionType::NonTransferableAccount,
9268 ])
9269 .unwrap();
9270 let mut account_without_enough_length = SolanaAccount::new(
9271 Rent::default().minimum_balance(account_len),
9272 account_len,
9273 &program_id,
9274 );
9275
9276 let account2 = Address::new_unique();
9277 let account2_len = ExtensionType::try_calculate_account_len::<Mint>(&[
9278 ExtensionType::NonTransferableAccount,
9279 ExtensionType::ImmutableOwner,
9280 ])
9281 .unwrap();
9282 let mut account_with_enough_length = SolanaAccount::new(
9283 Rent::default().minimum_balance(account2_len),
9284 account2_len,
9285 &program_id,
9286 );
9287
9288 let owner_key = Address::new_unique();
9289 let mut owner_account = SolanaAccount::default();
9290 let mint_key = Address::new_unique();
9291 let mint_len =
9292 ExtensionType::try_calculate_account_len::<Mint>(&[ExtensionType::NonTransferable])
9293 .unwrap();
9294 let mut mint_account = SolanaAccount::new(
9295 Rent::default().minimum_balance(mint_len),
9296 mint_len,
9297 &program_id,
9298 );
9299 let mut rent_sysvar = rent_sysvar();
9300
9301 assert_eq!(
9303 Ok(()),
9304 do_process_instruction(
9305 initialize_non_transferable_mint(&program_id, &mint_key).unwrap(),
9306 vec![&mut mint_account],
9307 )
9308 );
9309 assert_eq!(
9310 Ok(()),
9311 do_process_instruction(
9312 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
9313 vec![&mut mint_account, &mut rent_sysvar]
9314 )
9315 );
9316
9317 assert_eq!(
9320 Err(ProgramError::InvalidAccountData),
9321 do_process_instruction(
9322 initialize_account(&program_id, &account, &mint_key, &owner_key).unwrap(),
9323 vec![
9324 &mut account_without_enough_length,
9325 &mut mint_account,
9326 &mut owner_account,
9327 &mut rent_sysvar,
9328 ]
9329 )
9330 );
9331
9332 assert_eq!(
9334 Ok(()),
9335 do_process_instruction(
9336 initialize_account(&program_id, &account2, &mint_key, &owner_key).unwrap(),
9337 vec![
9338 &mut account_with_enough_length,
9339 &mut mint_account,
9340 &mut owner_account,
9341 &mut rent_sysvar,
9342 ]
9343 )
9344 );
9345 }
9346
9347 #[test]
9348 fn test_sync_native() {
9349 let program_id = crate::id();
9350 let mint_key = Address::new_unique();
9351 let mut mint_account =
9352 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
9353 let native_account_key = Address::new_unique();
9354 let lamports = 40;
9355 let mut native_account = SolanaAccount::new(
9356 account_minimum_balance() + lamports,
9357 Account::get_packed_len(),
9358 &program_id,
9359 );
9360 let non_native_account_key = Address::new_unique();
9361 let mut non_native_account = SolanaAccount::new(
9362 account_minimum_balance() + 50,
9363 Account::get_packed_len(),
9364 &program_id,
9365 );
9366
9367 let owner_key = Address::new_unique();
9368 let mut owner_account = SolanaAccount::default();
9369 let mut rent_sysvar = rent_sysvar();
9370
9371 do_process_instruction(
9373 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
9374 vec![&mut mint_account, &mut rent_sysvar],
9375 )
9376 .unwrap();
9377
9378 do_process_instruction(
9380 initialize_account(&program_id, &non_native_account_key, &mint_key, &owner_key)
9381 .unwrap(),
9382 vec![
9383 &mut non_native_account,
9384 &mut mint_account,
9385 &mut owner_account,
9386 &mut rent_sysvar,
9387 ],
9388 )
9389 .unwrap();
9390
9391 let account = Account::unpack_unchecked(&non_native_account.data).unwrap();
9392 assert!(!account.is_native());
9393 assert_eq!(account.amount, 0);
9394
9395 assert_eq!(
9397 Err(TokenError::NonNativeNotSupported.into()),
9398 do_process_instruction(
9399 sync_native(&program_id, &non_native_account_key,).unwrap(),
9400 vec![&mut non_native_account],
9401 )
9402 );
9403
9404 assert_eq!(
9406 Err(ProgramError::UninitializedAccount),
9407 do_process_instruction(
9408 sync_native(&program_id, &native_account_key,).unwrap(),
9409 vec![&mut native_account],
9410 )
9411 );
9412
9413 do_process_instruction(
9415 initialize_account(
9416 &program_id,
9417 &native_account_key,
9418 &crate::native_mint::id(),
9419 &owner_key,
9420 )
9421 .unwrap(),
9422 vec![
9423 &mut native_account,
9424 &mut mint_account,
9425 &mut owner_account,
9426 &mut rent_sysvar,
9427 ],
9428 )
9429 .unwrap();
9430
9431 let not_program_id = Address::new_unique();
9433 native_account.owner = not_program_id;
9434 assert_eq!(
9435 Err(ProgramError::IncorrectProgramId),
9436 do_process_instruction(
9437 sync_native(&program_id, &native_account_key,).unwrap(),
9438 vec![&mut native_account],
9439 )
9440 );
9441 native_account.owner = program_id;
9442
9443 let account = Account::unpack_unchecked(&native_account.data).unwrap();
9444 assert!(account.is_native());
9445 assert_eq!(account.amount, lamports);
9446
9447 do_process_instruction(
9449 sync_native(&program_id, &native_account_key).unwrap(),
9450 vec![&mut native_account],
9451 )
9452 .unwrap();
9453 let account = Account::unpack_unchecked(&native_account.data).unwrap();
9454 assert_eq!(account.amount, lamports);
9455
9456 let new_lamports = lamports + 50;
9458 native_account.lamports = account_minimum_balance() + new_lamports;
9459
9460 do_process_instruction(
9462 sync_native(&program_id, &native_account_key).unwrap(),
9463 vec![&mut native_account],
9464 )
9465 .unwrap();
9466 let account = Account::unpack_unchecked(&native_account.data).unwrap();
9467 assert_eq!(account.amount, new_lamports);
9468
9469 native_account.lamports -= 1;
9471
9472 do_process_instruction(
9474 sync_native(&program_id, &native_account_key).unwrap(),
9475 vec![&mut native_account],
9476 )
9477 .unwrap();
9478 let account = Account::unpack_unchecked(&native_account.data).unwrap();
9479 assert_eq!(account.amount, new_lamports - 1);
9480 }
9481
9482 #[test]
9483 #[serial]
9484 fn test_get_account_data_size() {
9485 let program_id = crate::id();
9487 let owner_key = Address::new_unique();
9488 let mut owner_account = SolanaAccount::default();
9489 let mut rent_sysvar = rent_sysvar();
9490
9491 let mut mint_account =
9493 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
9494 let mint_key = Address::new_unique();
9495 do_process_instruction(
9496 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
9497 vec![&mut mint_account, &mut rent_sysvar],
9498 )
9499 .unwrap();
9500
9501 set_expected_data(
9502 ExtensionType::try_calculate_account_len::<Account>(&[])
9503 .unwrap()
9504 .to_le_bytes()
9505 .to_vec(),
9506 );
9507 do_process_instruction(
9508 get_account_data_size(&program_id, &mint_key, &[]).unwrap(),
9509 vec![&mut mint_account],
9510 )
9511 .unwrap();
9512
9513 set_expected_data(
9514 ExtensionType::try_calculate_account_len::<Account>(&[
9515 ExtensionType::TransferFeeAmount,
9516 ])
9517 .unwrap()
9518 .to_le_bytes()
9519 .to_vec(),
9520 );
9521 do_process_instruction(
9522 get_account_data_size(
9523 &program_id,
9524 &mint_key,
9525 &[
9526 ExtensionType::TransferFeeAmount,
9527 ExtensionType::TransferFeeAmount, ],
9529 )
9530 .unwrap(),
9531 vec![&mut mint_account],
9532 )
9533 .unwrap();
9534
9535 let mut mint_account = native_mint();
9537 set_expected_data(
9538 ExtensionType::try_calculate_account_len::<Account>(&[])
9539 .unwrap()
9540 .to_le_bytes()
9541 .to_vec(),
9542 );
9543 do_process_instruction(
9544 get_account_data_size(&program_id, &mint_key, &[]).unwrap(),
9545 vec![&mut mint_account],
9546 )
9547 .unwrap();
9548
9549 let mint_len =
9551 ExtensionType::try_calculate_account_len::<Mint>(&[ExtensionType::TransferFeeConfig])
9552 .unwrap();
9553 let mut extended_mint_account = SolanaAccount::new(
9554 Rent::default().minimum_balance(mint_len),
9555 mint_len,
9556 &program_id,
9557 );
9558 let extended_mint_key = Address::new_unique();
9559 do_process_instruction(
9560 initialize_transfer_fee_config(&program_id, &extended_mint_key, None, None, 10, 4242)
9561 .unwrap(),
9562 vec![&mut extended_mint_account],
9563 )
9564 .unwrap();
9565 do_process_instruction(
9566 initialize_mint(&program_id, &extended_mint_key, &owner_key, None, 2).unwrap(),
9567 vec![&mut extended_mint_account, &mut rent_sysvar],
9568 )
9569 .unwrap();
9570
9571 set_expected_data(
9572 ExtensionType::try_calculate_account_len::<Account>(&[
9573 ExtensionType::TransferFeeAmount,
9574 ])
9575 .unwrap()
9576 .to_le_bytes()
9577 .to_vec(),
9578 );
9579 do_process_instruction(
9580 get_account_data_size(&program_id, &mint_key, &[]).unwrap(),
9581 vec![&mut extended_mint_account],
9582 )
9583 .unwrap();
9584
9585 do_process_instruction(
9586 get_account_data_size(
9587 &program_id,
9588 &mint_key,
9589 &[ExtensionType::TransferFeeAmount],
9591 )
9592 .unwrap(),
9593 vec![&mut extended_mint_account],
9594 )
9595 .unwrap();
9596
9597 let mut invalid_mint_account = SolanaAccount::new(
9599 account_minimum_balance(),
9600 Account::get_packed_len(),
9601 &program_id,
9602 );
9603 let invalid_mint_key = Address::new_unique();
9604 do_process_instruction(
9605 initialize_account(&program_id, &invalid_mint_key, &mint_key, &owner_key).unwrap(),
9606 vec![
9607 &mut invalid_mint_account,
9608 &mut mint_account,
9609 &mut owner_account,
9610 &mut rent_sysvar,
9611 ],
9612 )
9613 .unwrap();
9614
9615 assert_eq!(
9616 do_process_instruction(
9617 get_account_data_size(&program_id, &invalid_mint_key, &[]).unwrap(),
9618 vec![&mut invalid_mint_account],
9619 ),
9620 Err(TokenError::InvalidMint.into())
9621 );
9622
9623 let invalid_program_id = Address::new_unique();
9625 let mut invalid_mint_account =
9626 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
9627 let invalid_mint_key = Address::new_unique();
9628 let mut instruction =
9629 initialize_mint(&program_id, &invalid_mint_key, &owner_key, None, 2).unwrap();
9630 instruction.program_id = invalid_program_id;
9631 do_process_instruction(
9632 instruction,
9633 vec![&mut invalid_mint_account, &mut rent_sysvar],
9634 )
9635 .unwrap();
9636
9637 invalid_mint_account.owner = invalid_program_id;
9638
9639 assert_eq!(
9640 do_process_instruction(
9641 get_account_data_size(&program_id, &invalid_mint_key, &[]).unwrap(),
9642 vec![&mut invalid_mint_account],
9643 ),
9644 Err(ProgramError::IncorrectProgramId)
9645 );
9646
9647 assert_eq!(
9649 do_process_instruction(
9650 get_account_data_size(&program_id, &mint_key, &[ExtensionType::Uninitialized])
9651 .unwrap(),
9652 vec![&mut mint_account],
9653 ),
9654 Err(TokenError::ExtensionTypeMismatch.into())
9655 );
9656 assert_eq!(
9657 do_process_instruction(
9658 get_account_data_size(
9659 &program_id,
9660 &mint_key,
9661 &[
9662 ExtensionType::MemoTransfer,
9663 ExtensionType::MintCloseAuthority
9664 ]
9665 )
9666 .unwrap(),
9667 vec![&mut mint_account],
9668 ),
9669 Err(TokenError::ExtensionTypeMismatch.into())
9670 );
9671 }
9672
9673 #[test]
9674 #[serial]
9675 fn test_amount_to_ui_amount() {
9676 let program_id = crate::id();
9677 let owner_key = Address::new_unique();
9678 let mint_key = Address::new_unique();
9679 let mut mint_account =
9680 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
9681 let mut rent_sysvar = rent_sysvar();
9682
9683 assert_eq!(
9685 Err(TokenError::InvalidMint.into()),
9686 do_process_instruction(
9687 amount_to_ui_amount(&program_id, &mint_key, 110).unwrap(),
9688 vec![&mut mint_account],
9689 )
9690 );
9691
9692 do_process_instruction(
9694 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
9695 vec![&mut mint_account, &mut rent_sysvar],
9696 )
9697 .unwrap();
9698
9699 set_expected_data("0.23".as_bytes().to_vec());
9700 do_process_instruction(
9701 amount_to_ui_amount(&program_id, &mint_key, 23).unwrap(),
9702 vec![&mut mint_account],
9703 )
9704 .unwrap();
9705
9706 set_expected_data("1.1".as_bytes().to_vec());
9707 do_process_instruction(
9708 amount_to_ui_amount(&program_id, &mint_key, 110).unwrap(),
9709 vec![&mut mint_account],
9710 )
9711 .unwrap();
9712
9713 set_expected_data("42".as_bytes().to_vec());
9714 do_process_instruction(
9715 amount_to_ui_amount(&program_id, &mint_key, 4200).unwrap(),
9716 vec![&mut mint_account],
9717 )
9718 .unwrap();
9719
9720 set_expected_data("0".as_bytes().to_vec());
9721 do_process_instruction(
9722 amount_to_ui_amount(&program_id, &mint_key, 0).unwrap(),
9723 vec![&mut mint_account],
9724 )
9725 .unwrap();
9726 }
9727
9728 #[test]
9729 #[serial]
9730 fn test_ui_amount_to_amount() {
9731 let program_id = crate::id();
9732 let owner_key = Address::new_unique();
9733 let mint_key = Address::new_unique();
9734 let mut mint_account =
9735 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
9736 let mut rent_sysvar = rent_sysvar();
9737
9738 assert_eq!(
9740 Err(TokenError::InvalidMint.into()),
9741 do_process_instruction(
9742 ui_amount_to_amount(&program_id, &mint_key, "1.1").unwrap(),
9743 vec![&mut mint_account],
9744 )
9745 );
9746
9747 do_process_instruction(
9749 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
9750 vec![&mut mint_account, &mut rent_sysvar],
9751 )
9752 .unwrap();
9753
9754 set_expected_data(23u64.to_le_bytes().to_vec());
9755 do_process_instruction(
9756 ui_amount_to_amount(&program_id, &mint_key, "0.23").unwrap(),
9757 vec![&mut mint_account],
9758 )
9759 .unwrap();
9760
9761 set_expected_data(20u64.to_le_bytes().to_vec());
9762 do_process_instruction(
9763 ui_amount_to_amount(&program_id, &mint_key, "0.20").unwrap(),
9764 vec![&mut mint_account],
9765 )
9766 .unwrap();
9767
9768 set_expected_data(20u64.to_le_bytes().to_vec());
9769 do_process_instruction(
9770 ui_amount_to_amount(&program_id, &mint_key, "0.2000").unwrap(),
9771 vec![&mut mint_account],
9772 )
9773 .unwrap();
9774
9775 set_expected_data(20u64.to_le_bytes().to_vec());
9776 do_process_instruction(
9777 ui_amount_to_amount(&program_id, &mint_key, ".20").unwrap(),
9778 vec![&mut mint_account],
9779 )
9780 .unwrap();
9781
9782 set_expected_data(110u64.to_le_bytes().to_vec());
9783 do_process_instruction(
9784 ui_amount_to_amount(&program_id, &mint_key, "1.1").unwrap(),
9785 vec![&mut mint_account],
9786 )
9787 .unwrap();
9788
9789 set_expected_data(110u64.to_le_bytes().to_vec());
9790 do_process_instruction(
9791 ui_amount_to_amount(&program_id, &mint_key, "1.10").unwrap(),
9792 vec![&mut mint_account],
9793 )
9794 .unwrap();
9795
9796 set_expected_data(4200u64.to_le_bytes().to_vec());
9797 do_process_instruction(
9798 ui_amount_to_amount(&program_id, &mint_key, "42").unwrap(),
9799 vec![&mut mint_account],
9800 )
9801 .unwrap();
9802
9803 set_expected_data(4200u64.to_le_bytes().to_vec());
9804 do_process_instruction(
9805 ui_amount_to_amount(&program_id, &mint_key, "42.").unwrap(),
9806 vec![&mut mint_account],
9807 )
9808 .unwrap();
9809
9810 set_expected_data(0u64.to_le_bytes().to_vec());
9811 do_process_instruction(
9812 ui_amount_to_amount(&program_id, &mint_key, "0").unwrap(),
9813 vec![&mut mint_account],
9814 )
9815 .unwrap();
9816
9817 assert_eq!(
9819 Err(ProgramError::InvalidArgument),
9820 do_process_instruction(
9821 ui_amount_to_amount(&program_id, &mint_key, "").unwrap(),
9822 vec![&mut mint_account],
9823 )
9824 );
9825 assert_eq!(
9826 Err(ProgramError::InvalidArgument),
9827 do_process_instruction(
9828 ui_amount_to_amount(&program_id, &mint_key, ".").unwrap(),
9829 vec![&mut mint_account],
9830 )
9831 );
9832 assert_eq!(
9833 Err(ProgramError::InvalidArgument),
9834 do_process_instruction(
9835 ui_amount_to_amount(&program_id, &mint_key, "0.111").unwrap(),
9836 vec![&mut mint_account],
9837 )
9838 );
9839 assert_eq!(
9840 Err(ProgramError::InvalidArgument),
9841 do_process_instruction(
9842 ui_amount_to_amount(&program_id, &mint_key, "0.t").unwrap(),
9843 vec![&mut mint_account],
9844 )
9845 );
9846 }
9847
9848 #[test]
9849 #[serial]
9850 fn test_withdraw_excess_lamports_from_multisig() {
9851 {
9852 use std::sync::Once;
9853 static ONCE: Once = Once::new();
9854
9855 ONCE.call_once(|| {
9856 solana_sysvar::program_stubs::set_syscall_stubs(Box::new(SyscallStubs {}));
9857 });
9858 }
9859 let program_id = crate::id();
9860
9861 let mut lamports = 0;
9862 let mut destination_data = vec![];
9863 let system_program_id = system_program::id();
9864 let destination_key = Address::new_unique();
9865 let destination_info = AccountInfo::new(
9866 &destination_key,
9867 true,
9868 false,
9869 &mut lamports,
9870 &mut destination_data,
9871 &system_program_id,
9872 false,
9873 );
9874
9875 let multisig_key = Address::new_unique();
9876 let mut multisig_account = SolanaAccount::new(0, Multisig::get_packed_len(), &program_id);
9877 let excess_lamports = 4_000_000_000_000;
9878 multisig_account.lamports = excess_lamports + multisig_minimum_balance();
9879 let mut signer_keys = [Address::default(); MAX_SIGNERS];
9880
9881 for signer_key in signer_keys.iter_mut().take(MAX_SIGNERS) {
9882 *signer_key = Address::new_unique();
9883 }
9884 let signer_refs: Vec<&Address> = signer_keys.iter().collect();
9885 let mut signer_lamports = 0;
9886 let mut signer_data = vec![];
9887 let mut signers: Vec<AccountInfo<'_>> = vec![
9888 AccountInfo::new(
9889 &destination_key,
9890 true,
9891 false,
9892 &mut signer_lamports,
9893 &mut signer_data,
9894 &program_id,
9895 false,
9896 );
9897 MAX_SIGNERS + 1
9898 ];
9899 for (signer, key) in signers.iter_mut().zip(&signer_keys) {
9900 signer.key = key;
9901 }
9902
9903 let mut multisig =
9904 Multisig::unpack_unchecked(&vec![0; Multisig::get_packed_len()]).unwrap();
9905 multisig.m = MAX_SIGNERS as u8;
9906 multisig.n = MAX_SIGNERS as u8;
9907 multisig.signers = signer_keys;
9908 multisig.is_initialized = true;
9909 Multisig::pack(multisig, &mut multisig_account.data).unwrap();
9910
9911 let multisig_info: AccountInfo = (&multisig_key, true, &mut multisig_account).into();
9912
9913 let mut signers_infos = vec![
9914 multisig_info.clone(),
9915 destination_info.clone(),
9916 multisig_info.clone(),
9917 ];
9918 signers_infos.extend(signers);
9919 do_process_instruction_dups(
9920 withdraw_excess_lamports(
9921 &program_id,
9922 &multisig_key,
9923 &destination_key,
9924 &multisig_key,
9925 &signer_refs,
9926 )
9927 .unwrap(),
9928 signers_infos,
9929 )
9930 .unwrap();
9931
9932 assert_eq!(destination_info.lamports(), excess_lamports);
9933 }
9934
9935 #[test]
9936 #[serial]
9937 fn test_withdraw_excess_lamports_from_account() {
9938 let excess_lamports = 4_000_000_000_000;
9939
9940 let program_id = crate::id();
9941 let account_key = Address::new_unique();
9942 let mut account_account = SolanaAccount::new(
9943 excess_lamports + account_minimum_balance(),
9944 Account::get_packed_len(),
9945 &program_id,
9946 );
9947
9948 let system_program_id = system_program::id();
9949 let owner_key = Address::new_unique();
9950
9951 let mut destination_lamports = 0;
9952 let mut destination_data = vec![];
9953 let destination_key = Address::new_unique();
9954 let destination_info = AccountInfo::new(
9955 &destination_key,
9956 true,
9957 false,
9958 &mut destination_lamports,
9959 &mut destination_data,
9960 &system_program_id,
9961 false,
9962 );
9963 let mint_key = Address::new_unique();
9964 let mut mint_account =
9965 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
9966
9967 let mut rent_sysvar = rent_sysvar();
9968 do_process_instruction(
9969 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
9970 vec![&mut mint_account, &mut rent_sysvar],
9971 )
9972 .unwrap();
9973
9974 let mint_info = AccountInfo::new(
9975 &mint_key,
9976 true,
9977 false,
9978 &mut mint_account.lamports,
9979 &mut mint_account.data,
9980 &program_id,
9981 false,
9982 );
9983
9984 let account_info: AccountInfo = (&account_key, true, &mut account_account).into();
9985
9986 do_process_instruction_dups(
9987 initialize_account3(&program_id, &account_key, &mint_key, &account_key).unwrap(),
9988 vec![account_info.clone(), mint_info.clone()],
9989 )
9990 .unwrap();
9991
9992 do_process_instruction_dups(
9993 withdraw_excess_lamports(
9994 &program_id,
9995 &account_key,
9996 &destination_key,
9997 &account_key,
9998 &[],
9999 )
10000 .unwrap(),
10001 vec![
10002 account_info.clone(),
10003 destination_info.clone(),
10004 account_info.clone(),
10005 ],
10006 )
10007 .unwrap();
10008
10009 assert_eq!(destination_info.lamports(), excess_lamports);
10010 }
10011
10012 #[test]
10013 #[serial]
10014 fn test_withdraw_excess_lamports_from_mint() {
10015 let excess_lamports = 4_000_000_000_000;
10016
10017 let program_id = crate::id();
10018 let system_program_id = system_program::id();
10019
10020 let mut destination_lamports = 0;
10021 let mut destination_data = vec![];
10022 let destination_key = Address::new_unique();
10023 let destination_info = AccountInfo::new(
10024 &destination_key,
10025 true,
10026 false,
10027 &mut destination_lamports,
10028 &mut destination_data,
10029 &system_program_id,
10030 false,
10031 );
10032 let mint_key = Address::new_unique();
10033 let mut mint_account = SolanaAccount::new(
10034 excess_lamports + mint_minimum_balance(),
10035 Mint::get_packed_len(),
10036 &program_id,
10037 );
10038 let mut rent_sysvar = rent_sysvar();
10039
10040 do_process_instruction(
10041 initialize_mint(&program_id, &mint_key, &mint_key, None, 2).unwrap(),
10042 vec![&mut mint_account, &mut rent_sysvar],
10043 )
10044 .unwrap();
10045
10046 let mint_info: AccountInfo = (&mint_key, true, &mut mint_account).into();
10047
10048 do_process_instruction_dups(
10049 withdraw_excess_lamports(&program_id, &mint_key, &destination_key, &mint_key, &[])
10050 .unwrap(),
10051 vec![
10052 mint_info.clone(),
10053 destination_info.clone(),
10054 mint_info.clone(),
10055 ],
10056 )
10057 .unwrap();
10058
10059 assert_eq!(destination_info.lamports(), excess_lamports);
10060 }
10061
10062 #[test]
10063 #[serial]
10064 fn test_withdraw_excess_lamports_from_mint_with_no_mint_authority() {
10065 let excess_lamports = 4_000_000_000_000;
10066
10067 let program_id = crate::id();
10068 let system_program_id = system_program::id();
10069
10070 let mut destination_lamports = 0;
10071 let mut destination_data = vec![];
10072 let destination_key = Address::new_unique();
10073 let destination_info = AccountInfo::new(
10074 &destination_key,
10075 true,
10076 false,
10077 &mut destination_lamports,
10078 &mut destination_data,
10079 &system_program_id,
10080 false,
10081 );
10082 let mint_key = Address::new_unique();
10083 let mut mint_account = SolanaAccount::new(
10084 excess_lamports + mint_minimum_balance(),
10085 Mint::get_packed_len(),
10086 &program_id,
10087 );
10088 let mut mint_authority_lamports = 0;
10089 let mut mint_authority_data = vec![];
10090 let mint_authority_key = Address::new_unique();
10091 let mint_authority_info = AccountInfo::new(
10092 &mint_authority_key,
10093 true,
10094 false,
10095 &mut mint_authority_lamports,
10096 &mut mint_authority_data,
10097 &system_program_id,
10098 false,
10099 );
10100 let mut rent_sysvar = rent_sysvar();
10101
10102 do_process_instruction(
10103 initialize_mint(&program_id, &mint_key, &mint_authority_key, None, 2).unwrap(),
10104 vec![&mut mint_account, &mut rent_sysvar],
10105 )
10106 .unwrap();
10107
10108 let mint_info: AccountInfo = (&mint_key, true, &mut mint_account).into();
10109
10110 assert_eq!(
10113 Err(TokenError::OwnerMismatch.into()),
10114 do_process_instruction_dups(
10115 withdraw_excess_lamports(&program_id, &mint_key, &destination_key, &mint_key, &[])
10116 .unwrap(),
10117 vec![
10118 mint_info.clone(),
10119 destination_info.clone(),
10120 mint_info.clone(),
10121 ],
10122 )
10123 );
10124
10125 do_process_instruction_dups(
10126 set_authority(
10127 &program_id,
10128 &mint_key,
10129 None,
10130 AuthorityType::MintTokens,
10131 &mint_authority_key,
10132 &[],
10133 )
10134 .unwrap(),
10135 vec![mint_info.clone(), mint_authority_info.clone()],
10136 )
10137 .unwrap();
10138
10139 assert_eq!(
10141 Err(TokenError::AuthorityTypeNotSupported.into()),
10142 do_process_instruction_dups(
10143 withdraw_excess_lamports(
10144 &program_id,
10145 &mint_key,
10146 &destination_key,
10147 &mint_authority_key,
10148 &[]
10149 )
10150 .unwrap(),
10151 vec![
10152 mint_info.clone(),
10153 destination_info.clone(),
10154 mint_authority_info.clone(),
10155 ],
10156 )
10157 );
10158
10159 do_process_instruction_dups(
10160 withdraw_excess_lamports(&program_id, &mint_key, &destination_key, &mint_key, &[])
10161 .unwrap(),
10162 vec![
10163 mint_info.clone(),
10164 destination_info.clone(),
10165 mint_info.clone(),
10166 ],
10167 )
10168 .unwrap();
10169
10170 assert_eq!(destination_info.lamports(), excess_lamports);
10171 }
10172}