1use {
4 crate::{
5 check_program_account,
6 error::TokenError,
7 extension::{
8 confidential_mint_burn::{self, ConfidentialMintBurn},
9 confidential_transfer::{self, ConfidentialTransferAccount, ConfidentialTransferMint},
10 confidential_transfer_fee::{
11 self, ConfidentialTransferFeeAmount, ConfidentialTransferFeeConfig,
12 },
13 cpi_guard::{self, in_cpi, CpiGuard},
14 default_account_state::{self, DefaultAccountState},
15 group_member_pointer::{self, GroupMemberPointer},
16 group_pointer::{self, GroupPointer},
17 immutable_owner::ImmutableOwner,
18 interest_bearing_mint::{self, InterestBearingConfig},
19 memo_transfer::{self, check_previous_sibling_instruction_is_memo, memo_required},
20 metadata_pointer::{self, MetadataPointer},
21 mint_close_authority::MintCloseAuthority,
22 non_transferable::{NonTransferable, NonTransferableAccount},
23 pausable::{self, PausableAccount, PausableConfig},
24 permanent_delegate::{get_permanent_delegate, PermanentDelegate},
25 reallocate,
26 scaled_ui_amount::{self, ScaledUiAmountConfig},
27 token_group, token_metadata,
28 transfer_fee::{self, TransferFeeAmount, TransferFeeConfig},
29 transfer_hook::{self, TransferHook, TransferHookAccount},
30 AccountType, BaseStateWithExtensions, BaseStateWithExtensionsMut, ExtensionType,
31 PodStateWithExtensions, PodStateWithExtensionsMut,
32 },
33 instruction::{
34 decode_instruction_data, decode_instruction_type, is_valid_signer_index, AuthorityType,
35 MAX_SIGNERS,
36 },
37 native_mint,
38 pod::{PodAccount, PodCOption, PodMint, PodMultisig},
39 pod_instruction::{
40 decode_instruction_data_with_coption_pubkey, AmountCheckedData, AmountData,
41 InitializeMintData, InitializeMultisigData, PodTokenInstruction, SetAuthorityData,
42 },
43 state::{Account, AccountState, Mint, PackedSizeOf},
44 },
45 solana_program::{
46 account_info::{next_account_info, AccountInfo},
47 clock::Clock,
48 entrypoint::ProgramResult,
49 msg,
50 program::{invoke, invoke_signed, set_return_data},
51 program_error::ProgramError,
52 program_pack::Pack,
53 pubkey::Pubkey,
54 system_instruction, system_program,
55 sysvar::{rent::Rent, Sysvar},
56 },
57 spl_pod::{
58 bytemuck::{pod_from_bytes, pod_from_bytes_mut},
59 primitives::{PodBool, PodU64},
60 },
61 spl_token_group_interface::instruction::TokenGroupInstruction,
62 spl_token_metadata_interface::instruction::TokenMetadataInstruction,
63 std::convert::{TryFrom, TryInto},
64};
65
66pub struct Processor {}
68impl Processor {
69 fn _process_initialize_mint(
70 accounts: &[AccountInfo],
71 decimals: u8,
72 mint_authority: &Pubkey,
73 freeze_authority: PodCOption<Pubkey>,
74 rent_sysvar_account: bool,
75 ) -> ProgramResult {
76 let account_info_iter = &mut accounts.iter();
77 let mint_info = next_account_info(account_info_iter)?;
78 let mint_data_len = mint_info.data_len();
79 let mut mint_data = mint_info.data.borrow_mut();
80 let rent = if rent_sysvar_account {
81 Rent::from_account_info(next_account_info(account_info_iter)?)?
82 } else {
83 Rent::get()?
84 };
85
86 if !rent.is_exempt(mint_info.lamports(), mint_data_len) {
87 return Err(TokenError::NotRentExempt.into());
88 }
89
90 let mut mint = PodStateWithExtensionsMut::<PodMint>::unpack_uninitialized(&mut mint_data)?;
91 let extension_types = mint.get_extension_types()?;
92 if ExtensionType::try_calculate_account_len::<Mint>(&extension_types)? != mint_data_len {
93 return Err(ProgramError::InvalidAccountData);
94 }
95 ExtensionType::check_for_invalid_mint_extension_combinations(&extension_types)?;
96
97 if let Ok(default_account_state) = mint.get_extension_mut::<DefaultAccountState>() {
98 let default_account_state = AccountState::try_from(default_account_state.state)
99 .or(Err(ProgramError::InvalidAccountData))?;
100 if default_account_state == AccountState::Frozen && freeze_authority.is_none() {
101 return Err(TokenError::MintCannotFreeze.into());
102 }
103 }
104
105 mint.base.mint_authority = PodCOption::some(*mint_authority);
106 mint.base.decimals = decimals;
107 mint.base.is_initialized = PodBool::from_bool(true);
108 mint.base.freeze_authority = freeze_authority;
109 mint.init_account_type()?;
110
111 Ok(())
112 }
113
114 pub fn process_initialize_mint(
116 accounts: &[AccountInfo],
117 decimals: u8,
118 mint_authority: &Pubkey,
119 freeze_authority: PodCOption<Pubkey>,
120 ) -> ProgramResult {
121 Self::_process_initialize_mint(accounts, decimals, mint_authority, freeze_authority, true)
122 }
123
124 pub fn process_initialize_mint2(
127 accounts: &[AccountInfo],
128 decimals: u8,
129 mint_authority: &Pubkey,
130 freeze_authority: PodCOption<Pubkey>,
131 ) -> ProgramResult {
132 Self::_process_initialize_mint(accounts, decimals, mint_authority, freeze_authority, false)
133 }
134
135 fn _process_initialize_account(
136 accounts: &[AccountInfo],
137 owner: Option<&Pubkey>,
138 rent_sysvar_account: bool,
139 ) -> ProgramResult {
140 let account_info_iter = &mut accounts.iter();
141 let new_account_info = next_account_info(account_info_iter)?;
142 let mint_info = next_account_info(account_info_iter)?;
143 let owner = if let Some(owner) = owner {
144 owner
145 } else {
146 next_account_info(account_info_iter)?.key
147 };
148 let new_account_info_data_len = new_account_info.data_len();
149 let rent = if rent_sysvar_account {
150 Rent::from_account_info(next_account_info(account_info_iter)?)?
151 } else {
152 Rent::get()?
153 };
154
155 let mut account_data = new_account_info.data.borrow_mut();
156 let mut account =
158 PodStateWithExtensionsMut::<PodAccount>::unpack_uninitialized(&mut account_data)?;
159
160 if !rent.is_exempt(new_account_info.lamports(), new_account_info_data_len) {
161 return Err(TokenError::NotRentExempt.into());
162 }
163
164 let mint_data = mint_info.data.borrow();
166 let mint = PodStateWithExtensions::<PodMint>::unpack(&mint_data)
167 .map_err(|_| Into::<ProgramError>::into(TokenError::InvalidMint))?;
168 if mint
169 .get_extension::<PermanentDelegate>()
170 .map(|e| Option::<Pubkey>::from(e.delegate).is_some())
171 .unwrap_or(false)
172 {
173 msg!("Warning: Mint has a permanent delegate, so tokens in this account may be seized at any time");
174 }
175 let required_extensions =
176 Self::get_required_account_extensions_from_unpacked_mint(mint_info.owner, &mint)?;
177 if ExtensionType::try_calculate_account_len::<Account>(&required_extensions)?
178 > new_account_info_data_len
179 {
180 return Err(ProgramError::InvalidAccountData);
181 }
182 for extension in required_extensions {
183 account.init_account_extension_from_type(extension)?;
184 }
185
186 let starting_state =
187 if let Ok(default_account_state) = mint.get_extension::<DefaultAccountState>() {
188 AccountState::try_from(default_account_state.state)
189 .or(Err(ProgramError::InvalidAccountData))?
190 } else {
191 AccountState::Initialized
192 };
193
194 account.base.mint = *mint_info.key;
195 account.base.owner = *owner;
196 account.base.close_authority = PodCOption::none();
197 account.base.delegate = PodCOption::none();
198 account.base.delegated_amount = 0.into();
199 account.base.state = starting_state.into();
200 if mint_info.key == &native_mint::id() {
201 let rent_exempt_reserve = rent.minimum_balance(new_account_info_data_len);
202 account.base.is_native = PodCOption::some(rent_exempt_reserve.into());
203 account.base.amount = new_account_info
204 .lamports()
205 .checked_sub(rent_exempt_reserve)
206 .ok_or(TokenError::Overflow)?
207 .into();
208 } else {
209 account.base.is_native = PodCOption::none();
210 account.base.amount = 0.into();
211 };
212
213 account.init_account_type()?;
214
215 Ok(())
216 }
217
218 pub fn process_initialize_account(accounts: &[AccountInfo]) -> ProgramResult {
221 Self::_process_initialize_account(accounts, None, true)
222 }
223
224 pub fn process_initialize_account2(accounts: &[AccountInfo], owner: &Pubkey) -> ProgramResult {
227 Self::_process_initialize_account(accounts, Some(owner), true)
228 }
229
230 pub fn process_initialize_account3(accounts: &[AccountInfo], owner: &Pubkey) -> ProgramResult {
233 Self::_process_initialize_account(accounts, Some(owner), false)
234 }
235
236 fn _process_initialize_multisig(
237 accounts: &[AccountInfo],
238 m: u8,
239 rent_sysvar_account: bool,
240 ) -> ProgramResult {
241 let account_info_iter = &mut accounts.iter();
242 let multisig_info = next_account_info(account_info_iter)?;
243 let multisig_info_data_len = multisig_info.data_len();
244 let rent = if rent_sysvar_account {
245 Rent::from_account_info(next_account_info(account_info_iter)?)?
246 } else {
247 Rent::get()?
248 };
249
250 let mut multisig_data = multisig_info.data.borrow_mut();
251 let multisig = pod_from_bytes_mut::<PodMultisig>(&mut multisig_data)?;
252 if bool::from(multisig.is_initialized) {
253 return Err(TokenError::AlreadyInUse.into());
254 }
255
256 if !rent.is_exempt(multisig_info.lamports(), multisig_info_data_len) {
257 return Err(TokenError::NotRentExempt.into());
258 }
259
260 let signer_infos = account_info_iter.as_slice();
261 multisig.m = m;
262 multisig.n = signer_infos.len() as u8;
263 if !is_valid_signer_index(multisig.n as usize) {
264 return Err(TokenError::InvalidNumberOfProvidedSigners.into());
265 }
266 if !is_valid_signer_index(multisig.m as usize) {
267 return Err(TokenError::InvalidNumberOfRequiredSigners.into());
268 }
269 for (i, signer_info) in signer_infos.iter().enumerate() {
270 multisig.signers[i] = *signer_info.key;
271 }
272 multisig.is_initialized = true.into();
273
274 Ok(())
275 }
276
277 pub fn process_initialize_multisig(accounts: &[AccountInfo], m: u8) -> ProgramResult {
280 Self::_process_initialize_multisig(accounts, m, true)
281 }
282
283 pub fn process_initialize_multisig2(accounts: &[AccountInfo], m: u8) -> ProgramResult {
286 Self::_process_initialize_multisig(accounts, m, false)
287 }
288
289 pub fn process_transfer(
291 program_id: &Pubkey,
292 accounts: &[AccountInfo],
293 amount: u64,
294 expected_decimals: Option<u8>,
295 expected_fee: Option<u64>,
296 ) -> ProgramResult {
297 let account_info_iter = &mut accounts.iter();
298
299 let source_account_info = next_account_info(account_info_iter)?;
300
301 let expected_mint_info = if let Some(expected_decimals) = expected_decimals {
302 Some((next_account_info(account_info_iter)?, expected_decimals))
303 } else {
304 assert!(expected_fee.is_none());
307 None
308 };
309
310 let destination_account_info = next_account_info(account_info_iter)?;
311 let authority_info = next_account_info(account_info_iter)?;
312 let authority_info_data_len = authority_info.data_len();
313
314 let mut source_account_data = source_account_info.data.borrow_mut();
315 let mut source_account =
316 PodStateWithExtensionsMut::<PodAccount>::unpack(&mut source_account_data)?;
317 if source_account.base.is_frozen() {
318 return Err(TokenError::AccountFrozen.into());
319 }
320 let source_amount = u64::from(source_account.base.amount);
321 if source_amount < amount {
322 return Err(TokenError::InsufficientFunds.into());
323 }
324 if source_account
325 .get_extension::<NonTransferableAccount>()
326 .is_ok()
327 {
328 return Err(TokenError::NonTransferable.into());
329 }
330
331 let (fee, maybe_permanent_delegate, maybe_transfer_hook_program_id) =
332 if let Some((mint_info, expected_decimals)) = expected_mint_info {
333 if &source_account.base.mint != mint_info.key {
334 return Err(TokenError::MintMismatch.into());
335 }
336
337 let mint_data = mint_info.try_borrow_data()?;
338 let mint = PodStateWithExtensions::<PodMint>::unpack(&mint_data)?;
339
340 if expected_decimals != mint.base.decimals {
341 return Err(TokenError::MintDecimalsMismatch.into());
342 }
343
344 let fee = if let Ok(transfer_fee_config) = mint.get_extension::<TransferFeeConfig>()
345 {
346 transfer_fee_config
347 .calculate_epoch_fee(Clock::get()?.epoch, amount)
348 .ok_or(TokenError::Overflow)?
349 } else {
350 0
351 };
352
353 if let Ok(extension) = mint.get_extension::<PausableConfig>() {
354 if extension.paused.into() {
355 return Err(TokenError::MintPaused.into());
356 }
357 }
358
359 let maybe_permanent_delegate = get_permanent_delegate(&mint);
360 let maybe_transfer_hook_program_id = transfer_hook::get_program_id(&mint);
361
362 (
363 fee,
364 maybe_permanent_delegate,
365 maybe_transfer_hook_program_id,
366 )
367 } else {
368 if source_account
371 .get_extension::<TransferHookAccount>()
372 .is_ok()
373 {
374 return Err(TokenError::MintRequiredForTransfer.into());
375 }
376
377 if source_account
380 .get_extension_mut::<TransferFeeAmount>()
381 .is_ok()
382 {
383 return Err(TokenError::MintRequiredForTransfer.into());
384 }
385
386 if source_account.get_extension::<PausableAccount>().is_ok() {
389 return Err(TokenError::MintRequiredForTransfer.into());
390 }
391
392 (0, None, None)
393 };
394 if let Some(expected_fee) = expected_fee {
395 if expected_fee != fee {
396 msg!("Calculated fee {}, received {}", fee, expected_fee);
397 return Err(TokenError::FeeMismatch.into());
398 }
399 }
400
401 let self_transfer = source_account_info.key == destination_account_info.key;
402 if let Ok(cpi_guard) = source_account.get_extension::<CpiGuard>() {
403 if *authority_info.key == source_account.base.owner
408 && cpi_guard.lock_cpi.into()
409 && in_cpi()
410 {
411 return Err(TokenError::CpiGuardTransferBlocked.into());
412 }
413 }
414 match (source_account.base.delegate, maybe_permanent_delegate) {
415 (_, Some(ref delegate)) if authority_info.key == delegate => Self::validate_owner(
416 program_id,
417 delegate,
418 authority_info,
419 authority_info_data_len,
420 account_info_iter.as_slice(),
421 )?,
422 (
423 PodCOption {
424 option: PodCOption::<Pubkey>::SOME,
425 value: delegate,
426 },
427 _,
428 ) if authority_info.key == &delegate => {
429 Self::validate_owner(
430 program_id,
431 &delegate,
432 authority_info,
433 authority_info_data_len,
434 account_info_iter.as_slice(),
435 )?;
436 let delegated_amount = u64::from(source_account.base.delegated_amount);
437 if delegated_amount < amount {
438 return Err(TokenError::InsufficientFunds.into());
439 }
440 if !self_transfer {
441 source_account.base.delegated_amount = delegated_amount
442 .checked_sub(amount)
443 .ok_or(TokenError::Overflow)?
444 .into();
445 if u64::from(source_account.base.delegated_amount) == 0 {
446 source_account.base.delegate = PodCOption::none();
447 }
448 }
449 }
450 _ => {
451 Self::validate_owner(
452 program_id,
453 &source_account.base.owner,
454 authority_info,
455 authority_info_data_len,
456 account_info_iter.as_slice(),
457 )?;
458 }
459 }
460
461 check_program_account(source_account_info.owner)?;
465 check_program_account(destination_account_info.owner)?;
466
467 if self_transfer {
470 if memo_required(&source_account) {
471 check_previous_sibling_instruction_is_memo()?;
472 }
473 return Ok(());
474 }
475
476 let mut destination_account_data = destination_account_info.data.borrow_mut();
478 let mut destination_account =
479 PodStateWithExtensionsMut::<PodAccount>::unpack(&mut destination_account_data)?;
480
481 if destination_account.base.is_frozen() {
482 return Err(TokenError::AccountFrozen.into());
483 }
484 if source_account.base.mint != destination_account.base.mint {
485 return Err(TokenError::MintMismatch.into());
486 }
487
488 if memo_required(&destination_account) {
489 check_previous_sibling_instruction_is_memo()?;
490 }
491
492 if let Ok(confidential_transfer_state) =
493 destination_account.get_extension::<ConfidentialTransferAccount>()
494 {
495 confidential_transfer_state.non_confidential_transfer_allowed()?
496 }
497
498 source_account.base.amount = source_amount
499 .checked_sub(amount)
500 .ok_or(TokenError::Overflow)?
501 .into();
502 let credited_amount = amount.checked_sub(fee).ok_or(TokenError::Overflow)?;
503 destination_account.base.amount = u64::from(destination_account.base.amount)
504 .checked_add(credited_amount)
505 .ok_or(TokenError::Overflow)?
506 .into();
507 if fee > 0 {
508 if let Ok(extension) = destination_account.get_extension_mut::<TransferFeeAmount>() {
509 let new_withheld_amount = u64::from(extension.withheld_amount)
510 .checked_add(fee)
511 .ok_or(TokenError::Overflow)?;
512 extension.withheld_amount = new_withheld_amount.into();
513 } else {
514 return Err(TokenError::InvalidState.into());
518 }
519 }
520
521 if source_account.base.is_native() {
522 let source_starting_lamports = source_account_info.lamports();
523 **source_account_info.lamports.borrow_mut() = source_starting_lamports
524 .checked_sub(amount)
525 .ok_or(TokenError::Overflow)?;
526
527 let destination_starting_lamports = destination_account_info.lamports();
528 **destination_account_info.lamports.borrow_mut() = destination_starting_lamports
529 .checked_add(amount)
530 .ok_or(TokenError::Overflow)?;
531 }
532
533 if let Some(program_id) = maybe_transfer_hook_program_id {
534 if let Some((mint_info, _)) = expected_mint_info {
535 transfer_hook::set_transferring(&mut source_account)?;
537 transfer_hook::set_transferring(&mut destination_account)?;
538
539 drop(source_account_data);
541 drop(destination_account_data);
542 spl_transfer_hook_interface::onchain::invoke_execute(
543 &program_id,
544 source_account_info.clone(),
545 mint_info.clone(),
546 destination_account_info.clone(),
547 authority_info.clone(),
548 account_info_iter.as_slice(),
549 amount,
550 )?;
551
552 transfer_hook::unset_transferring(source_account_info)?;
554 transfer_hook::unset_transferring(destination_account_info)?;
555 } else {
556 return Err(TokenError::MintRequiredForTransfer.into());
557 }
558 }
559
560 Ok(())
561 }
562
563 pub fn process_approve(
565 program_id: &Pubkey,
566 accounts: &[AccountInfo],
567 amount: u64,
568 expected_decimals: Option<u8>,
569 ) -> ProgramResult {
570 let account_info_iter = &mut accounts.iter();
571
572 let source_account_info = next_account_info(account_info_iter)?;
573
574 let expected_mint_info = if let Some(expected_decimals) = expected_decimals {
575 Some((next_account_info(account_info_iter)?, expected_decimals))
576 } else {
577 None
578 };
579 let delegate_info = next_account_info(account_info_iter)?;
580 let owner_info = next_account_info(account_info_iter)?;
581 let owner_info_data_len = owner_info.data_len();
582
583 let mut source_account_data = source_account_info.data.borrow_mut();
584 let source_account =
585 PodStateWithExtensionsMut::<PodAccount>::unpack(&mut source_account_data)?;
586
587 if source_account.base.is_frozen() {
588 return Err(TokenError::AccountFrozen.into());
589 }
590
591 if let Some((mint_info, expected_decimals)) = expected_mint_info {
592 if &source_account.base.mint != mint_info.key {
593 return Err(TokenError::MintMismatch.into());
594 }
595
596 let mint_data = mint_info.data.borrow();
597 let mint = PodStateWithExtensions::<PodMint>::unpack(&mint_data)?;
598 if expected_decimals != mint.base.decimals {
599 return Err(TokenError::MintDecimalsMismatch.into());
600 }
601 }
602
603 Self::validate_owner(
604 program_id,
605 &source_account.base.owner,
606 owner_info,
607 owner_info_data_len,
608 account_info_iter.as_slice(),
609 )?;
610
611 if let Ok(cpi_guard) = source_account.get_extension::<CpiGuard>() {
612 if cpi_guard.lock_cpi.into() && in_cpi() {
613 return Err(TokenError::CpiGuardApproveBlocked.into());
614 }
615 }
616
617 source_account.base.delegate = PodCOption::some(*delegate_info.key);
618 source_account.base.delegated_amount = amount.into();
619
620 Ok(())
621 }
622
623 pub fn process_revoke(program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult {
625 let account_info_iter = &mut accounts.iter();
626 let source_account_info = next_account_info(account_info_iter)?;
627 let authority_info = next_account_info(account_info_iter)?;
628 let authority_info_data_len = authority_info.data_len();
629
630 let mut source_account_data = source_account_info.data.borrow_mut();
631 let source_account =
632 PodStateWithExtensionsMut::<PodAccount>::unpack(&mut source_account_data)?;
633 if source_account.base.is_frozen() {
634 return Err(TokenError::AccountFrozen.into());
635 }
636
637 Self::validate_owner(
638 program_id,
639 match &source_account.base.delegate {
640 PodCOption {
641 option: PodCOption::<Pubkey>::SOME,
642 value: delegate,
643 } if authority_info.key == delegate => delegate,
644 _ => &source_account.base.owner,
645 },
646 authority_info,
647 authority_info_data_len,
648 account_info_iter.as_slice(),
649 )?;
650
651 source_account.base.delegate = PodCOption::none();
652 source_account.base.delegated_amount = 0.into();
653
654 Ok(())
655 }
656
657 pub fn process_set_authority(
659 program_id: &Pubkey,
660 accounts: &[AccountInfo],
661 authority_type: AuthorityType,
662 new_authority: PodCOption<Pubkey>,
663 ) -> ProgramResult {
664 let account_info_iter = &mut accounts.iter();
665 let account_info = next_account_info(account_info_iter)?;
666 let authority_info = next_account_info(account_info_iter)?;
667 let authority_info_data_len = authority_info.data_len();
668
669 let mut account_data = account_info.data.borrow_mut();
670 if let Ok(mut account) = PodStateWithExtensionsMut::<PodAccount>::unpack(&mut account_data)
671 {
672 if account.base.is_frozen() {
673 return Err(TokenError::AccountFrozen.into());
674 }
675
676 match authority_type {
677 AuthorityType::AccountOwner => {
678 Self::validate_owner(
679 program_id,
680 &account.base.owner,
681 authority_info,
682 authority_info_data_len,
683 account_info_iter.as_slice(),
684 )?;
685
686 if account.get_extension_mut::<ImmutableOwner>().is_ok() {
687 return Err(TokenError::ImmutableOwner.into());
688 }
689
690 if let Ok(cpi_guard) = account.get_extension::<CpiGuard>() {
691 if cpi_guard.lock_cpi.into() && in_cpi() {
692 return Err(TokenError::CpiGuardSetAuthorityBlocked.into());
693 } else if cpi_guard.lock_cpi.into() {
694 return Err(TokenError::CpiGuardOwnerChangeBlocked.into());
695 }
696 }
697
698 if let PodCOption {
699 option: PodCOption::<Pubkey>::SOME,
700 value: authority,
701 } = new_authority
702 {
703 account.base.owner = authority;
704 } else {
705 return Err(TokenError::InvalidInstruction.into());
706 }
707
708 account.base.delegate = PodCOption::none();
709 account.base.delegated_amount = 0.into();
710
711 if account.base.is_native() {
712 account.base.close_authority = PodCOption::none();
713 }
714 }
715 AuthorityType::CloseAccount => {
716 let authority = account.base.close_authority.unwrap_or(account.base.owner);
717 Self::validate_owner(
718 program_id,
719 &authority,
720 authority_info,
721 authority_info_data_len,
722 account_info_iter.as_slice(),
723 )?;
724
725 if let Ok(cpi_guard) = account.get_extension::<CpiGuard>() {
726 if cpi_guard.lock_cpi.into() && in_cpi() && new_authority.is_some() {
727 return Err(TokenError::CpiGuardSetAuthorityBlocked.into());
728 }
729 }
730
731 account.base.close_authority = new_authority;
732 }
733 _ => {
734 return Err(TokenError::AuthorityTypeNotSupported.into());
735 }
736 }
737 } else if let Ok(mut mint) = PodStateWithExtensionsMut::<PodMint>::unpack(&mut account_data)
738 {
739 match authority_type {
740 AuthorityType::MintTokens => {
741 let mint_authority = mint
744 .base
745 .mint_authority
746 .ok_or(Into::<ProgramError>::into(TokenError::FixedSupply))?;
747 Self::validate_owner(
748 program_id,
749 &mint_authority,
750 authority_info,
751 authority_info_data_len,
752 account_info_iter.as_slice(),
753 )?;
754 mint.base.mint_authority = new_authority;
755 }
756 AuthorityType::FreezeAccount => {
757 let freeze_authority = mint
760 .base
761 .freeze_authority
762 .ok_or(Into::<ProgramError>::into(TokenError::MintCannotFreeze))?;
763 Self::validate_owner(
764 program_id,
765 &freeze_authority,
766 authority_info,
767 authority_info_data_len,
768 account_info_iter.as_slice(),
769 )?;
770 mint.base.freeze_authority = new_authority;
771 }
772 AuthorityType::CloseMint => {
773 let extension = mint.get_extension_mut::<MintCloseAuthority>()?;
774 let maybe_close_authority: Option<Pubkey> = extension.close_authority.into();
775 let close_authority =
776 maybe_close_authority.ok_or(TokenError::AuthorityTypeNotSupported)?;
777 Self::validate_owner(
778 program_id,
779 &close_authority,
780 authority_info,
781 authority_info_data_len,
782 account_info_iter.as_slice(),
783 )?;
784 extension.close_authority = new_authority.try_into()?;
785 }
786 AuthorityType::TransferFeeConfig => {
787 let extension = mint.get_extension_mut::<TransferFeeConfig>()?;
788 let maybe_transfer_fee_config_authority: Option<Pubkey> =
789 extension.transfer_fee_config_authority.into();
790 let transfer_fee_config_authority = maybe_transfer_fee_config_authority
791 .ok_or(TokenError::AuthorityTypeNotSupported)?;
792 Self::validate_owner(
793 program_id,
794 &transfer_fee_config_authority,
795 authority_info,
796 authority_info_data_len,
797 account_info_iter.as_slice(),
798 )?;
799 extension.transfer_fee_config_authority = new_authority.try_into()?;
800 }
801 AuthorityType::WithheldWithdraw => {
802 let extension = mint.get_extension_mut::<TransferFeeConfig>()?;
803 let maybe_withdraw_withheld_authority: Option<Pubkey> =
804 extension.withdraw_withheld_authority.into();
805 let withdraw_withheld_authority = maybe_withdraw_withheld_authority
806 .ok_or(TokenError::AuthorityTypeNotSupported)?;
807 Self::validate_owner(
808 program_id,
809 &withdraw_withheld_authority,
810 authority_info,
811 authority_info_data_len,
812 account_info_iter.as_slice(),
813 )?;
814 extension.withdraw_withheld_authority = new_authority.try_into()?;
815 }
816 AuthorityType::InterestRate => {
817 let extension = mint.get_extension_mut::<InterestBearingConfig>()?;
818 let maybe_rate_authority: Option<Pubkey> = extension.rate_authority.into();
819 let rate_authority =
820 maybe_rate_authority.ok_or(TokenError::AuthorityTypeNotSupported)?;
821 Self::validate_owner(
822 program_id,
823 &rate_authority,
824 authority_info,
825 authority_info_data_len,
826 account_info_iter.as_slice(),
827 )?;
828 extension.rate_authority = new_authority.try_into()?;
829 }
830 AuthorityType::PermanentDelegate => {
831 let extension = mint.get_extension_mut::<PermanentDelegate>()?;
832 let maybe_delegate: Option<Pubkey> = extension.delegate.into();
833 let delegate = maybe_delegate.ok_or(TokenError::AuthorityTypeNotSupported)?;
834 Self::validate_owner(
835 program_id,
836 &delegate,
837 authority_info,
838 authority_info_data_len,
839 account_info_iter.as_slice(),
840 )?;
841 extension.delegate = new_authority.try_into()?;
842 }
843 AuthorityType::ConfidentialTransferMint => {
844 let extension = mint.get_extension_mut::<ConfidentialTransferMint>()?;
845 let maybe_confidential_transfer_mint_authority: Option<Pubkey> =
846 extension.authority.into();
847 let confidential_transfer_mint_authority =
848 maybe_confidential_transfer_mint_authority
849 .ok_or(TokenError::AuthorityTypeNotSupported)?;
850 Self::validate_owner(
851 program_id,
852 &confidential_transfer_mint_authority,
853 authority_info,
854 authority_info_data_len,
855 account_info_iter.as_slice(),
856 )?;
857 extension.authority = new_authority.try_into()?;
858 }
859 AuthorityType::TransferHookProgramId => {
860 let extension = mint.get_extension_mut::<TransferHook>()?;
861 let maybe_authority: Option<Pubkey> = extension.authority.into();
862 let authority = maybe_authority.ok_or(TokenError::AuthorityTypeNotSupported)?;
863 Self::validate_owner(
864 program_id,
865 &authority,
866 authority_info,
867 authority_info_data_len,
868 account_info_iter.as_slice(),
869 )?;
870 extension.authority = new_authority.try_into()?;
871 }
872 AuthorityType::ConfidentialTransferFeeConfig => {
873 let extension = mint.get_extension_mut::<ConfidentialTransferFeeConfig>()?;
874 let maybe_authority: Option<Pubkey> = extension.authority.into();
875 let authority = maybe_authority.ok_or(TokenError::AuthorityTypeNotSupported)?;
876 Self::validate_owner(
877 program_id,
878 &authority,
879 authority_info,
880 authority_info_data_len,
881 account_info_iter.as_slice(),
882 )?;
883 extension.authority = new_authority.try_into()?;
884 }
885 AuthorityType::MetadataPointer => {
886 let extension = mint.get_extension_mut::<MetadataPointer>()?;
887 let maybe_authority: Option<Pubkey> = extension.authority.into();
888 let authority = maybe_authority.ok_or(TokenError::AuthorityTypeNotSupported)?;
889 Self::validate_owner(
890 program_id,
891 &authority,
892 authority_info,
893 authority_info_data_len,
894 account_info_iter.as_slice(),
895 )?;
896 extension.authority = new_authority.try_into()?;
897 }
898 AuthorityType::GroupPointer => {
899 let extension = mint.get_extension_mut::<GroupPointer>()?;
900 let maybe_authority: Option<Pubkey> = extension.authority.into();
901 let authority = maybe_authority.ok_or(TokenError::AuthorityTypeNotSupported)?;
902 Self::validate_owner(
903 program_id,
904 &authority,
905 authority_info,
906 authority_info_data_len,
907 account_info_iter.as_slice(),
908 )?;
909 extension.authority = new_authority.try_into()?;
910 }
911 AuthorityType::GroupMemberPointer => {
912 let extension = mint.get_extension_mut::<GroupMemberPointer>()?;
913 let maybe_authority: Option<Pubkey> = extension.authority.into();
914 let authority = maybe_authority.ok_or(TokenError::AuthorityTypeNotSupported)?;
915 Self::validate_owner(
916 program_id,
917 &authority,
918 authority_info,
919 authority_info_data_len,
920 account_info_iter.as_slice(),
921 )?;
922 extension.authority = new_authority.try_into()?;
923 }
924 AuthorityType::ScaledUiAmount => {
925 let extension = mint.get_extension_mut::<ScaledUiAmountConfig>()?;
926 let maybe_authority: Option<Pubkey> = extension.authority.into();
927 let authority = maybe_authority.ok_or(TokenError::AuthorityTypeNotSupported)?;
928 Self::validate_owner(
929 program_id,
930 &authority,
931 authority_info,
932 authority_info_data_len,
933 account_info_iter.as_slice(),
934 )?;
935 extension.authority = new_authority.try_into()?;
936 }
937 AuthorityType::Pause => {
938 let extension = mint.get_extension_mut::<PausableConfig>()?;
939 let maybe_authority: Option<Pubkey> = extension.authority.into();
940 let authority = maybe_authority.ok_or(TokenError::AuthorityTypeNotSupported)?;
941 Self::validate_owner(
942 program_id,
943 &authority,
944 authority_info,
945 authority_info_data_len,
946 account_info_iter.as_slice(),
947 )?;
948 extension.authority = new_authority.try_into()?;
949 }
950 _ => {
951 return Err(TokenError::AuthorityTypeNotSupported.into());
952 }
953 }
954 } else {
955 return Err(ProgramError::InvalidAccountData);
956 }
957
958 Ok(())
959 }
960
961 pub fn process_mint_to(
963 program_id: &Pubkey,
964 accounts: &[AccountInfo],
965 amount: u64,
966 expected_decimals: Option<u8>,
967 ) -> ProgramResult {
968 let account_info_iter = &mut accounts.iter();
969 let mint_info = next_account_info(account_info_iter)?;
970 let destination_account_info = next_account_info(account_info_iter)?;
971 let owner_info = next_account_info(account_info_iter)?;
972 let owner_info_data_len = owner_info.data_len();
973
974 let mut destination_account_data = destination_account_info.data.borrow_mut();
975 let destination_account =
976 PodStateWithExtensionsMut::<PodAccount>::unpack(&mut destination_account_data)?;
977 if destination_account.base.is_frozen() {
978 return Err(TokenError::AccountFrozen.into());
979 }
980
981 if destination_account.base.is_native() {
982 return Err(TokenError::NativeNotSupported.into());
983 }
984 if mint_info.key != &destination_account.base.mint {
985 return Err(TokenError::MintMismatch.into());
986 }
987
988 let mut mint_data = mint_info.data.borrow_mut();
989 let mint = PodStateWithExtensionsMut::<PodMint>::unpack(&mut mint_data)?;
990
991 if mint.get_extension::<NonTransferable>().is_ok()
994 && destination_account
995 .get_extension::<ImmutableOwner>()
996 .is_err()
997 {
998 return Err(TokenError::NonTransferableNeedsImmutableOwnership.into());
999 }
1000
1001 if let Ok(extension) = mint.get_extension::<PausableConfig>() {
1002 if extension.paused.into() {
1003 return Err(TokenError::MintPaused.into());
1004 }
1005 }
1006
1007 if mint.get_extension::<ConfidentialMintBurn>().is_ok() {
1008 return Err(TokenError::IllegalMintBurnConversion.into());
1009 }
1010
1011 if let Some(expected_decimals) = expected_decimals {
1012 if expected_decimals != mint.base.decimals {
1013 return Err(TokenError::MintDecimalsMismatch.into());
1014 }
1015 }
1016
1017 match &mint.base.mint_authority {
1018 PodCOption {
1019 option: PodCOption::<Pubkey>::SOME,
1020 value: mint_authority,
1021 } => Self::validate_owner(
1022 program_id,
1023 mint_authority,
1024 owner_info,
1025 owner_info_data_len,
1026 account_info_iter.as_slice(),
1027 )?,
1028 _ => return Err(TokenError::FixedSupply.into()),
1029 }
1030
1031 check_program_account(mint_info.owner)?;
1035 check_program_account(destination_account_info.owner)?;
1036
1037 destination_account.base.amount = u64::from(destination_account.base.amount)
1038 .checked_add(amount)
1039 .ok_or(TokenError::Overflow)?
1040 .into();
1041
1042 mint.base.supply = u64::from(mint.base.supply)
1043 .checked_add(amount)
1044 .ok_or(TokenError::Overflow)?
1045 .into();
1046
1047 Ok(())
1048 }
1049
1050 pub fn process_burn(
1052 program_id: &Pubkey,
1053 accounts: &[AccountInfo],
1054 amount: u64,
1055 expected_decimals: Option<u8>,
1056 ) -> ProgramResult {
1057 let account_info_iter = &mut accounts.iter();
1058
1059 let source_account_info = next_account_info(account_info_iter)?;
1060 let mint_info = next_account_info(account_info_iter)?;
1061 let authority_info = next_account_info(account_info_iter)?;
1062 let authority_info_data_len = authority_info.data_len();
1063
1064 let mut source_account_data = source_account_info.data.borrow_mut();
1065 let source_account =
1066 PodStateWithExtensionsMut::<PodAccount>::unpack(&mut source_account_data)?;
1067 let mut mint_data = mint_info.data.borrow_mut();
1068 let mint = PodStateWithExtensionsMut::<PodMint>::unpack(&mut mint_data)?;
1069
1070 if source_account.base.is_frozen() {
1071 return Err(TokenError::AccountFrozen.into());
1072 }
1073 if source_account.base.is_native() {
1074 return Err(TokenError::NativeNotSupported.into());
1075 }
1076 if u64::from(source_account.base.amount) < amount {
1077 return Err(TokenError::InsufficientFunds.into());
1078 }
1079 if mint_info.key != &source_account.base.mint {
1080 return Err(TokenError::MintMismatch.into());
1081 }
1082
1083 if let Some(expected_decimals) = expected_decimals {
1084 if expected_decimals != mint.base.decimals {
1085 return Err(TokenError::MintDecimalsMismatch.into());
1086 }
1087 }
1088 if let Ok(extension) = mint.get_extension::<PausableConfig>() {
1089 if extension.paused.into() {
1090 return Err(TokenError::MintPaused.into());
1091 }
1092 }
1093 let maybe_permanent_delegate = get_permanent_delegate(&mint);
1094
1095 if let Ok(cpi_guard) = source_account.get_extension::<CpiGuard>() {
1096 if *authority_info.key == source_account.base.owner
1101 && cpi_guard.lock_cpi.into()
1102 && in_cpi()
1103 {
1104 return Err(TokenError::CpiGuardBurnBlocked.into());
1105 }
1106 }
1107
1108 if !source_account
1109 .base
1110 .is_owned_by_system_program_or_incinerator()
1111 {
1112 match (&source_account.base.delegate, maybe_permanent_delegate) {
1113 (_, Some(ref delegate)) if authority_info.key == delegate => Self::validate_owner(
1114 program_id,
1115 delegate,
1116 authority_info,
1117 authority_info_data_len,
1118 account_info_iter.as_slice(),
1119 )?,
1120 (
1121 PodCOption {
1122 option: PodCOption::<Pubkey>::SOME,
1123 value: delegate,
1124 },
1125 _,
1126 ) if authority_info.key == delegate => {
1127 Self::validate_owner(
1128 program_id,
1129 delegate,
1130 authority_info,
1131 authority_info_data_len,
1132 account_info_iter.as_slice(),
1133 )?;
1134
1135 if u64::from(source_account.base.delegated_amount) < amount {
1136 return Err(TokenError::InsufficientFunds.into());
1137 }
1138 source_account.base.delegated_amount =
1139 u64::from(source_account.base.delegated_amount)
1140 .checked_sub(amount)
1141 .ok_or(TokenError::Overflow)?
1142 .into();
1143 if u64::from(source_account.base.delegated_amount) == 0 {
1144 source_account.base.delegate = PodCOption::none();
1145 }
1146 }
1147 _ => {
1148 Self::validate_owner(
1149 program_id,
1150 &source_account.base.owner,
1151 authority_info,
1152 authority_info_data_len,
1153 account_info_iter.as_slice(),
1154 )?;
1155 }
1156 }
1157 }
1158
1159 check_program_account(source_account_info.owner)?;
1163 check_program_account(mint_info.owner)?;
1164
1165 source_account.base.amount = u64::from(source_account.base.amount)
1166 .checked_sub(amount)
1167 .ok_or(TokenError::Overflow)?
1168 .into();
1169 mint.base.supply = u64::from(mint.base.supply)
1170 .checked_sub(amount)
1171 .ok_or(TokenError::Overflow)?
1172 .into();
1173
1174 Ok(())
1175 }
1176
1177 pub fn process_close_account(program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult {
1179 let account_info_iter = &mut accounts.iter();
1180 let source_account_info = next_account_info(account_info_iter)?;
1181 let destination_account_info = next_account_info(account_info_iter)?;
1182 let authority_info = next_account_info(account_info_iter)?;
1183 let authority_info_data_len = authority_info.data_len();
1184
1185 if source_account_info.key == destination_account_info.key {
1186 return Err(ProgramError::InvalidAccountData);
1187 }
1188
1189 let source_account_data = source_account_info.data.borrow();
1190 if let Ok(source_account) =
1191 PodStateWithExtensions::<PodAccount>::unpack(&source_account_data)
1192 {
1193 if !source_account.base.is_native() && u64::from(source_account.base.amount) != 0 {
1194 return Err(TokenError::NonNativeHasBalance.into());
1195 }
1196
1197 let authority = source_account
1198 .base
1199 .close_authority
1200 .unwrap_or(source_account.base.owner);
1201
1202 if !source_account
1203 .base
1204 .is_owned_by_system_program_or_incinerator()
1205 {
1206 if let Ok(cpi_guard) = source_account.get_extension::<CpiGuard>() {
1207 if cpi_guard.lock_cpi.into()
1208 && in_cpi()
1209 && destination_account_info.key != &source_account.base.owner
1210 {
1211 return Err(TokenError::CpiGuardCloseAccountBlocked.into());
1212 }
1213 }
1214
1215 Self::validate_owner(
1216 program_id,
1217 &authority,
1218 authority_info,
1219 authority_info_data_len,
1220 account_info_iter.as_slice(),
1221 )?;
1222 } else if !solana_program::incinerator::check_id(destination_account_info.key) {
1223 return Err(ProgramError::InvalidAccountData);
1224 }
1225
1226 if let Ok(confidential_transfer_state) =
1227 source_account.get_extension::<ConfidentialTransferAccount>()
1228 {
1229 confidential_transfer_state.closable()?
1230 }
1231
1232 if let Ok(confidential_transfer_fee_state) =
1233 source_account.get_extension::<ConfidentialTransferFeeAmount>()
1234 {
1235 confidential_transfer_fee_state.closable()?
1236 }
1237
1238 if let Ok(transfer_fee_state) = source_account.get_extension::<TransferFeeAmount>() {
1239 transfer_fee_state.closable()?
1240 }
1241 } else if let Ok(mint) = PodStateWithExtensions::<PodMint>::unpack(&source_account_data) {
1242 let extension = mint.get_extension::<MintCloseAuthority>()?;
1243 let maybe_authority: Option<Pubkey> = extension.close_authority.into();
1244 let authority = maybe_authority.ok_or(TokenError::AuthorityTypeNotSupported)?;
1245 Self::validate_owner(
1246 program_id,
1247 &authority,
1248 authority_info,
1249 authority_info_data_len,
1250 account_info_iter.as_slice(),
1251 )?;
1252
1253 if u64::from(mint.base.supply) != 0 {
1254 return Err(TokenError::MintHasSupply.into());
1255 }
1256 } else {
1257 return Err(ProgramError::UninitializedAccount);
1258 }
1259
1260 let destination_starting_lamports = destination_account_info.lamports();
1261 **destination_account_info.lamports.borrow_mut() = destination_starting_lamports
1262 .checked_add(source_account_info.lamports())
1263 .ok_or(TokenError::Overflow)?;
1264
1265 **source_account_info.lamports.borrow_mut() = 0;
1266 drop(source_account_data);
1267 delete_account(source_account_info)?;
1268
1269 Ok(())
1270 }
1271
1272 pub fn process_toggle_freeze_account(
1275 program_id: &Pubkey,
1276 accounts: &[AccountInfo],
1277 freeze: bool,
1278 ) -> ProgramResult {
1279 let account_info_iter = &mut accounts.iter();
1280 let source_account_info = next_account_info(account_info_iter)?;
1281 let mint_info = next_account_info(account_info_iter)?;
1282 let authority_info = next_account_info(account_info_iter)?;
1283 let authority_info_data_len = authority_info.data_len();
1284
1285 let mut source_account_data = source_account_info.data.borrow_mut();
1286 let source_account =
1287 PodStateWithExtensionsMut::<PodAccount>::unpack(&mut source_account_data)?;
1288 if freeze && source_account.base.is_frozen() || !freeze && !source_account.base.is_frozen()
1289 {
1290 return Err(TokenError::InvalidState.into());
1291 }
1292 if source_account.base.is_native() {
1293 return Err(TokenError::NativeNotSupported.into());
1294 }
1295 if mint_info.key != &source_account.base.mint {
1296 return Err(TokenError::MintMismatch.into());
1297 }
1298
1299 let mint_data = mint_info.data.borrow();
1300 let mint = PodStateWithExtensions::<PodMint>::unpack(&mint_data)?;
1301 match &mint.base.freeze_authority {
1302 PodCOption {
1303 option: PodCOption::<Pubkey>::SOME,
1304 value: authority,
1305 } => Self::validate_owner(
1306 program_id,
1307 authority,
1308 authority_info,
1309 authority_info_data_len,
1310 account_info_iter.as_slice(),
1311 ),
1312 _ => Err(TokenError::MintCannotFreeze.into()),
1313 }?;
1314
1315 source_account.base.state = if freeze {
1316 AccountState::Frozen.into()
1317 } else {
1318 AccountState::Initialized.into()
1319 };
1320
1321 Ok(())
1322 }
1323
1324 pub fn process_sync_native(accounts: &[AccountInfo]) -> ProgramResult {
1326 let account_info_iter = &mut accounts.iter();
1327 let native_account_info = next_account_info(account_info_iter)?;
1328
1329 check_program_account(native_account_info.owner)?;
1330 let mut native_account_data = native_account_info.data.borrow_mut();
1331 let native_account =
1332 PodStateWithExtensionsMut::<PodAccount>::unpack(&mut native_account_data)?;
1333
1334 match native_account.base.is_native {
1335 PodCOption {
1336 option: PodCOption::<PodU64>::SOME,
1337 value: amount,
1338 } => {
1339 let new_amount = native_account_info
1340 .lamports()
1341 .checked_sub(u64::from(amount))
1342 .ok_or(TokenError::Overflow)?;
1343 if new_amount < u64::from(native_account.base.amount) {
1344 return Err(TokenError::InvalidState.into());
1345 }
1346 native_account.base.amount = new_amount.into();
1347 }
1348 _ => return Err(TokenError::NonNativeNotSupported.into()),
1349 }
1350
1351 Ok(())
1352 }
1353
1354 pub fn process_initialize_mint_close_authority(
1358 accounts: &[AccountInfo],
1359 close_authority: PodCOption<Pubkey>,
1360 ) -> ProgramResult {
1361 let account_info_iter = &mut accounts.iter();
1362 let mint_account_info = next_account_info(account_info_iter)?;
1363
1364 let mut mint_data = mint_account_info.data.borrow_mut();
1365 let mut mint = PodStateWithExtensionsMut::<PodMint>::unpack_uninitialized(&mut mint_data)?;
1366 let extension = mint.init_extension::<MintCloseAuthority>(true)?;
1367 extension.close_authority = close_authority.try_into()?;
1368
1369 Ok(())
1370 }
1371
1372 pub fn process_get_account_data_size(
1375 accounts: &[AccountInfo],
1376 new_extension_types: &[ExtensionType],
1377 ) -> ProgramResult {
1378 if new_extension_types
1379 .iter()
1380 .any(|&t| t.get_account_type() != AccountType::Account)
1381 {
1382 return Err(TokenError::ExtensionTypeMismatch.into());
1383 }
1384
1385 let account_info_iter = &mut accounts.iter();
1386 let mint_account_info = next_account_info(account_info_iter)?;
1387
1388 let mut account_extensions = Self::get_required_account_extensions(mint_account_info)?;
1389 account_extensions.extend_from_slice(new_extension_types);
1392
1393 let account_len = ExtensionType::try_calculate_account_len::<Account>(&account_extensions)?;
1394 set_return_data(&account_len.to_le_bytes());
1395
1396 Ok(())
1397 }
1398
1399 pub fn process_initialize_immutable_owner(accounts: &[AccountInfo]) -> ProgramResult {
1402 let account_info_iter = &mut accounts.iter();
1403 let token_account_info = next_account_info(account_info_iter)?;
1404 let token_account_data = &mut token_account_info.data.borrow_mut();
1405 let mut token_account =
1406 PodStateWithExtensionsMut::<PodAccount>::unpack_uninitialized(token_account_data)?;
1407 token_account
1408 .init_extension::<ImmutableOwner>(true)
1409 .map(|_| ())
1410 }
1411
1412 pub fn process_amount_to_ui_amount(accounts: &[AccountInfo], amount: u64) -> ProgramResult {
1415 let account_info_iter = &mut accounts.iter();
1416 let mint_info = next_account_info(account_info_iter)?;
1417 check_program_account(mint_info.owner)?;
1418
1419 let mint_data = mint_info.data.borrow();
1420 let mint = PodStateWithExtensions::<PodMint>::unpack(&mint_data)
1421 .map_err(|_| Into::<ProgramError>::into(TokenError::InvalidMint))?;
1422 let ui_amount = if let Ok(extension) = mint.get_extension::<InterestBearingConfig>() {
1423 let unix_timestamp = Clock::get()?.unix_timestamp;
1424 extension
1425 .amount_to_ui_amount(amount, mint.base.decimals, unix_timestamp)
1426 .ok_or(ProgramError::InvalidArgument)?
1427 } else if let Ok(extension) = mint.get_extension::<ScaledUiAmountConfig>() {
1428 let unix_timestamp = Clock::get()?.unix_timestamp;
1429 extension
1430 .amount_to_ui_amount(amount, mint.base.decimals, unix_timestamp)
1431 .ok_or(ProgramError::InvalidArgument)?
1432 } else {
1433 crate::amount_to_ui_amount_string_trimmed(amount, mint.base.decimals)
1434 };
1435
1436 set_return_data(&ui_amount.into_bytes());
1437 Ok(())
1438 }
1439
1440 pub fn process_ui_amount_to_amount(accounts: &[AccountInfo], ui_amount: &str) -> ProgramResult {
1443 let account_info_iter = &mut accounts.iter();
1444 let mint_info = next_account_info(account_info_iter)?;
1445 check_program_account(mint_info.owner)?;
1446
1447 let mint_data = mint_info.data.borrow();
1448 let mint = PodStateWithExtensions::<PodMint>::unpack(&mint_data)
1449 .map_err(|_| Into::<ProgramError>::into(TokenError::InvalidMint))?;
1450 let amount = if let Ok(extension) = mint.get_extension::<InterestBearingConfig>() {
1451 let unix_timestamp = Clock::get()?.unix_timestamp;
1452 extension.try_ui_amount_into_amount(ui_amount, mint.base.decimals, unix_timestamp)?
1453 } else if let Ok(extension) = mint.get_extension::<ScaledUiAmountConfig>() {
1454 let unix_timestamp = Clock::get()?.unix_timestamp;
1455 extension.try_ui_amount_into_amount(ui_amount, mint.base.decimals, unix_timestamp)?
1456 } else {
1457 crate::try_ui_amount_into_amount(ui_amount.to_string(), mint.base.decimals)?
1458 };
1459
1460 set_return_data(&amount.to_le_bytes());
1461 Ok(())
1462 }
1463
1464 pub fn process_create_native_mint(accounts: &[AccountInfo]) -> ProgramResult {
1466 let account_info_iter = &mut accounts.iter();
1467 let payer_info = next_account_info(account_info_iter)?;
1468 let native_mint_info = next_account_info(account_info_iter)?;
1469 let system_program_info = next_account_info(account_info_iter)?;
1470
1471 if *native_mint_info.key != native_mint::id() {
1472 return Err(TokenError::InvalidMint.into());
1473 }
1474
1475 let rent = Rent::get()?;
1476 let new_minimum_balance = rent.minimum_balance(Mint::get_packed_len());
1477 let lamports_diff = new_minimum_balance.saturating_sub(native_mint_info.lamports());
1478 invoke(
1479 &system_instruction::transfer(payer_info.key, native_mint_info.key, lamports_diff),
1480 &[
1481 payer_info.clone(),
1482 native_mint_info.clone(),
1483 system_program_info.clone(),
1484 ],
1485 )?;
1486
1487 invoke_signed(
1488 &system_instruction::allocate(native_mint_info.key, Mint::get_packed_len() as u64),
1489 &[native_mint_info.clone(), system_program_info.clone()],
1490 &[native_mint::PROGRAM_ADDRESS_SEEDS],
1491 )?;
1492
1493 invoke_signed(
1494 &system_instruction::assign(native_mint_info.key, &crate::id()),
1495 &[native_mint_info.clone(), system_program_info.clone()],
1496 &[native_mint::PROGRAM_ADDRESS_SEEDS],
1497 )?;
1498
1499 Mint::pack(
1500 Mint {
1501 decimals: native_mint::DECIMALS,
1502 is_initialized: true,
1503 ..Mint::default()
1504 },
1505 &mut native_mint_info.data.borrow_mut(),
1506 )
1507 }
1508
1509 pub fn process_initialize_non_transferable_mint(accounts: &[AccountInfo]) -> ProgramResult {
1513 let account_info_iter = &mut accounts.iter();
1514 let mint_account_info = next_account_info(account_info_iter)?;
1515
1516 let mut mint_data = mint_account_info.data.borrow_mut();
1517 let mut mint = PodStateWithExtensionsMut::<PodMint>::unpack_uninitialized(&mut mint_data)?;
1518 mint.init_extension::<NonTransferable>(true)?;
1519
1520 Ok(())
1521 }
1522
1523 pub fn process_initialize_permanent_delegate(
1526 accounts: &[AccountInfo],
1527 delegate: &Pubkey,
1528 ) -> ProgramResult {
1529 let account_info_iter = &mut accounts.iter();
1530 let mint_account_info = next_account_info(account_info_iter)?;
1531
1532 let mut mint_data = mint_account_info.data.borrow_mut();
1533 let mut mint = PodStateWithExtensionsMut::<PodMint>::unpack_uninitialized(&mut mint_data)?;
1534 let extension = mint.init_extension::<PermanentDelegate>(true)?;
1535 extension.delegate = Some(*delegate).try_into()?;
1536
1537 Ok(())
1538 }
1539
1540 pub fn process_withdraw_excess_lamports(
1544 program_id: &Pubkey,
1545 accounts: &[AccountInfo],
1546 ) -> ProgramResult {
1547 let account_info_iter = &mut accounts.iter();
1548
1549 let source_info = next_account_info(account_info_iter)?;
1550 let destination_info = next_account_info(account_info_iter)?;
1551 let authority_info = next_account_info(account_info_iter)?;
1552
1553 let source_data = source_info.data.borrow();
1554
1555 if let Ok(account) = PodStateWithExtensions::<PodAccount>::unpack(&source_data) {
1556 if account.base.is_native() {
1557 return Err(TokenError::NativeNotSupported.into());
1558 }
1559 Self::validate_owner(
1560 program_id,
1561 &account.base.owner,
1562 authority_info,
1563 authority_info.data_len(),
1564 account_info_iter.as_slice(),
1565 )?;
1566 } else if let Ok(mint) = PodStateWithExtensions::<PodMint>::unpack(&source_data) {
1567 match &mint.base.mint_authority {
1568 PodCOption {
1569 option: PodCOption::<Pubkey>::SOME,
1570 value: mint_authority,
1571 } => {
1572 Self::validate_owner(
1573 program_id,
1574 mint_authority,
1575 authority_info,
1576 authority_info.data_len(),
1577 account_info_iter.as_slice(),
1578 )?;
1579 }
1580 _ => return Err(TokenError::AuthorityTypeNotSupported.into()),
1581 }
1582 } else if source_data.len() == PodMultisig::SIZE_OF {
1583 Self::validate_owner(
1584 program_id,
1585 source_info.key,
1586 authority_info,
1587 authority_info.data_len(),
1588 account_info_iter.as_slice(),
1589 )?;
1590 } else {
1591 return Err(TokenError::InvalidState.into());
1592 }
1593
1594 let source_rent_exempt_reserve = Rent::get()?.minimum_balance(source_info.data_len());
1595
1596 let transfer_amount = source_info
1597 .lamports()
1598 .checked_sub(source_rent_exempt_reserve)
1599 .ok_or(TokenError::NotRentExempt)?;
1600
1601 let source_starting_lamports = source_info.lamports();
1602 **source_info.lamports.borrow_mut() = source_starting_lamports
1603 .checked_sub(transfer_amount)
1604 .ok_or(TokenError::Overflow)?;
1605
1606 let destination_starting_lamports = destination_info.lamports();
1607 **destination_info.lamports.borrow_mut() = destination_starting_lamports
1608 .checked_add(transfer_amount)
1609 .ok_or(TokenError::Overflow)?;
1610
1611 Ok(())
1612 }
1613
1614 pub fn process(program_id: &Pubkey, accounts: &[AccountInfo], input: &[u8]) -> ProgramResult {
1616 if let Ok(instruction_type) = decode_instruction_type(input) {
1617 match instruction_type {
1618 PodTokenInstruction::InitializeMint => {
1619 msg!("Instruction: InitializeMint");
1620 let (data, freeze_authority) =
1621 decode_instruction_data_with_coption_pubkey::<InitializeMintData>(input)?;
1622 Self::process_initialize_mint(
1623 accounts,
1624 data.decimals,
1625 &data.mint_authority,
1626 freeze_authority,
1627 )
1628 }
1629 PodTokenInstruction::InitializeMint2 => {
1630 msg!("Instruction: InitializeMint2");
1631 let (data, freeze_authority) =
1632 decode_instruction_data_with_coption_pubkey::<InitializeMintData>(input)?;
1633 Self::process_initialize_mint2(
1634 accounts,
1635 data.decimals,
1636 &data.mint_authority,
1637 freeze_authority,
1638 )
1639 }
1640 PodTokenInstruction::InitializeAccount => {
1641 msg!("Instruction: InitializeAccount");
1642 Self::process_initialize_account(accounts)
1643 }
1644 PodTokenInstruction::InitializeAccount2 => {
1645 msg!("Instruction: InitializeAccount2");
1646 let owner = decode_instruction_data::<Pubkey>(input)?;
1647 Self::process_initialize_account2(accounts, owner)
1648 }
1649 PodTokenInstruction::InitializeAccount3 => {
1650 msg!("Instruction: InitializeAccount3");
1651 let owner = decode_instruction_data::<Pubkey>(input)?;
1652 Self::process_initialize_account3(accounts, owner)
1653 }
1654 PodTokenInstruction::InitializeMultisig => {
1655 msg!("Instruction: InitializeMultisig");
1656 let data = decode_instruction_data::<InitializeMultisigData>(input)?;
1657 Self::process_initialize_multisig(accounts, data.m)
1658 }
1659 PodTokenInstruction::InitializeMultisig2 => {
1660 msg!("Instruction: InitializeMultisig2");
1661 let data = decode_instruction_data::<InitializeMultisigData>(input)?;
1662 Self::process_initialize_multisig2(accounts, data.m)
1663 }
1664 #[allow(deprecated)]
1665 PodTokenInstruction::Transfer => {
1666 msg!("Instruction: Transfer");
1667 let data = decode_instruction_data::<AmountData>(input)?;
1668 Self::process_transfer(program_id, accounts, data.amount.into(), None, None)
1669 }
1670 PodTokenInstruction::Approve => {
1671 msg!("Instruction: Approve");
1672 let data = decode_instruction_data::<AmountData>(input)?;
1673 Self::process_approve(program_id, accounts, data.amount.into(), None)
1674 }
1675 PodTokenInstruction::Revoke => {
1676 msg!("Instruction: Revoke");
1677 Self::process_revoke(program_id, accounts)
1678 }
1679 PodTokenInstruction::SetAuthority => {
1680 msg!("Instruction: SetAuthority");
1681 let (data, new_authority) =
1682 decode_instruction_data_with_coption_pubkey::<SetAuthorityData>(input)?;
1683 Self::process_set_authority(
1684 program_id,
1685 accounts,
1686 AuthorityType::from(data.authority_type)?,
1687 new_authority,
1688 )
1689 }
1690 PodTokenInstruction::MintTo => {
1691 msg!("Instruction: MintTo");
1692 let data = decode_instruction_data::<AmountData>(input)?;
1693 Self::process_mint_to(program_id, accounts, data.amount.into(), None)
1694 }
1695 PodTokenInstruction::Burn => {
1696 msg!("Instruction: Burn");
1697 let data = decode_instruction_data::<AmountData>(input)?;
1698 Self::process_burn(program_id, accounts, data.amount.into(), None)
1699 }
1700 PodTokenInstruction::CloseAccount => {
1701 msg!("Instruction: CloseAccount");
1702 Self::process_close_account(program_id, accounts)
1703 }
1704 PodTokenInstruction::FreezeAccount => {
1705 msg!("Instruction: FreezeAccount");
1706 Self::process_toggle_freeze_account(program_id, accounts, true)
1707 }
1708 PodTokenInstruction::ThawAccount => {
1709 msg!("Instruction: ThawAccount");
1710 Self::process_toggle_freeze_account(program_id, accounts, false)
1711 }
1712 PodTokenInstruction::TransferChecked => {
1713 msg!("Instruction: TransferChecked");
1714 let data = decode_instruction_data::<AmountCheckedData>(input)?;
1715 Self::process_transfer(
1716 program_id,
1717 accounts,
1718 data.amount.into(),
1719 Some(data.decimals),
1720 None,
1721 )
1722 }
1723 PodTokenInstruction::ApproveChecked => {
1724 msg!("Instruction: ApproveChecked");
1725 let data = decode_instruction_data::<AmountCheckedData>(input)?;
1726 Self::process_approve(
1727 program_id,
1728 accounts,
1729 data.amount.into(),
1730 Some(data.decimals),
1731 )
1732 }
1733 PodTokenInstruction::MintToChecked => {
1734 msg!("Instruction: MintToChecked");
1735 let data = decode_instruction_data::<AmountCheckedData>(input)?;
1736 Self::process_mint_to(
1737 program_id,
1738 accounts,
1739 data.amount.into(),
1740 Some(data.decimals),
1741 )
1742 }
1743 PodTokenInstruction::BurnChecked => {
1744 msg!("Instruction: BurnChecked");
1745 let data = decode_instruction_data::<AmountCheckedData>(input)?;
1746 Self::process_burn(
1747 program_id,
1748 accounts,
1749 data.amount.into(),
1750 Some(data.decimals),
1751 )
1752 }
1753 PodTokenInstruction::SyncNative => {
1754 msg!("Instruction: SyncNative");
1755 Self::process_sync_native(accounts)
1756 }
1757 PodTokenInstruction::GetAccountDataSize => {
1758 msg!("Instruction: GetAccountDataSize");
1759 let extension_types = input[1..]
1760 .chunks(std::mem::size_of::<ExtensionType>())
1761 .map(ExtensionType::try_from)
1762 .collect::<Result<Vec<_>, _>>()?;
1763 Self::process_get_account_data_size(accounts, &extension_types)
1764 }
1765 PodTokenInstruction::InitializeMintCloseAuthority => {
1766 msg!("Instruction: InitializeMintCloseAuthority");
1767 let (_, close_authority) =
1768 decode_instruction_data_with_coption_pubkey::<()>(input)?;
1769 Self::process_initialize_mint_close_authority(accounts, close_authority)
1770 }
1771 PodTokenInstruction::TransferFeeExtension => {
1772 transfer_fee::processor::process_instruction(program_id, accounts, &input[1..])
1773 }
1774 PodTokenInstruction::ConfidentialTransferExtension => {
1775 confidential_transfer::processor::process_instruction(
1776 program_id,
1777 accounts,
1778 &input[1..],
1779 )
1780 }
1781 PodTokenInstruction::DefaultAccountStateExtension => {
1782 default_account_state::processor::process_instruction(
1783 program_id,
1784 accounts,
1785 &input[1..],
1786 )
1787 }
1788 PodTokenInstruction::InitializeImmutableOwner => {
1789 msg!("Instruction: InitializeImmutableOwner");
1790 Self::process_initialize_immutable_owner(accounts)
1791 }
1792 PodTokenInstruction::AmountToUiAmount => {
1793 msg!("Instruction: AmountToUiAmount");
1794 let data = decode_instruction_data::<AmountData>(input)?;
1795 Self::process_amount_to_ui_amount(accounts, data.amount.into())
1796 }
1797 PodTokenInstruction::UiAmountToAmount => {
1798 msg!("Instruction: UiAmountToAmount");
1799 let ui_amount = std::str::from_utf8(&input[1..])
1800 .map_err(|_| TokenError::InvalidInstruction)?;
1801 Self::process_ui_amount_to_amount(accounts, ui_amount)
1802 }
1803 PodTokenInstruction::Reallocate => {
1804 msg!("Instruction: Reallocate");
1805 let extension_types = input[1..]
1806 .chunks(std::mem::size_of::<ExtensionType>())
1807 .map(ExtensionType::try_from)
1808 .collect::<Result<Vec<_>, _>>()?;
1809 reallocate::process_reallocate(program_id, accounts, extension_types)
1810 }
1811 PodTokenInstruction::MemoTransferExtension => {
1812 memo_transfer::processor::process_instruction(program_id, accounts, &input[1..])
1813 }
1814 PodTokenInstruction::CreateNativeMint => {
1815 msg!("Instruction: CreateNativeMint");
1816 Self::process_create_native_mint(accounts)
1817 }
1818 PodTokenInstruction::InitializeNonTransferableMint => {
1819 msg!("Instruction: InitializeNonTransferableMint");
1820 Self::process_initialize_non_transferable_mint(accounts)
1821 }
1822 PodTokenInstruction::InterestBearingMintExtension => {
1823 interest_bearing_mint::processor::process_instruction(
1824 program_id,
1825 accounts,
1826 &input[1..],
1827 )
1828 }
1829 PodTokenInstruction::CpiGuardExtension => {
1830 cpi_guard::processor::process_instruction(program_id, accounts, &input[1..])
1831 }
1832 PodTokenInstruction::InitializePermanentDelegate => {
1833 msg!("Instruction: InitializePermanentDelegate");
1834 let delegate = decode_instruction_data::<Pubkey>(input)?;
1835 Self::process_initialize_permanent_delegate(accounts, delegate)
1836 }
1837 PodTokenInstruction::TransferHookExtension => {
1838 transfer_hook::processor::process_instruction(program_id, accounts, &input[1..])
1839 }
1840 PodTokenInstruction::ConfidentialTransferFeeExtension => {
1841 confidential_transfer_fee::processor::process_instruction(
1842 program_id,
1843 accounts,
1844 &input[1..],
1845 )
1846 }
1847 PodTokenInstruction::WithdrawExcessLamports => {
1848 msg!("Instruction: WithdrawExcessLamports");
1849 Self::process_withdraw_excess_lamports(program_id, accounts)
1850 }
1851 PodTokenInstruction::MetadataPointerExtension => {
1852 metadata_pointer::processor::process_instruction(
1853 program_id,
1854 accounts,
1855 &input[1..],
1856 )
1857 }
1858 PodTokenInstruction::GroupPointerExtension => {
1859 group_pointer::processor::process_instruction(program_id, accounts, &input[1..])
1860 }
1861 PodTokenInstruction::GroupMemberPointerExtension => {
1862 group_member_pointer::processor::process_instruction(
1863 program_id,
1864 accounts,
1865 &input[1..],
1866 )
1867 }
1868 PodTokenInstruction::ConfidentialMintBurnExtension => {
1869 msg!("Instruction: ConfidentialMintBurnExtension");
1870 confidential_mint_burn::processor::process_instruction(
1871 program_id,
1872 accounts,
1873 &input[1..],
1874 )
1875 }
1876 PodTokenInstruction::ScaledUiAmountExtension => {
1877 msg!("Instruction: ScaledUiAmountExtension");
1878 scaled_ui_amount::processor::process_instruction(
1879 program_id,
1880 accounts,
1881 &input[1..],
1882 )
1883 }
1884 PodTokenInstruction::PausableExtension => {
1885 msg!("Instruction: PausableExtension");
1886 pausable::processor::process_instruction(program_id, accounts, &input[1..])
1887 }
1888 }
1889 } else if let Ok(instruction) = TokenMetadataInstruction::unpack(input) {
1890 token_metadata::processor::process_instruction(program_id, accounts, instruction)
1891 } else if let Ok(instruction) = TokenGroupInstruction::unpack(input) {
1892 token_group::processor::process_instruction(program_id, accounts, instruction)
1893 } else {
1894 Err(TokenError::InvalidInstruction.into())
1895 }
1896 }
1897
1898 pub fn validate_owner(
1900 program_id: &Pubkey,
1901 expected_owner: &Pubkey,
1902 owner_account_info: &AccountInfo,
1903 owner_account_data_len: usize,
1904 signers: &[AccountInfo],
1905 ) -> ProgramResult {
1906 if expected_owner != owner_account_info.key {
1907 return Err(TokenError::OwnerMismatch.into());
1908 }
1909
1910 if program_id == owner_account_info.owner && owner_account_data_len == PodMultisig::SIZE_OF
1911 {
1912 let multisig_data = &owner_account_info.data.borrow();
1913 let multisig = pod_from_bytes::<PodMultisig>(multisig_data)?;
1914 let mut num_signers = 0;
1915 let mut matched = [false; MAX_SIGNERS];
1916 for signer in signers.iter() {
1917 for (position, key) in multisig.signers[0..multisig.n as usize].iter().enumerate() {
1918 if key == signer.key && !matched[position] {
1919 if !signer.is_signer {
1920 return Err(ProgramError::MissingRequiredSignature);
1921 }
1922 matched[position] = true;
1923 num_signers += 1;
1924 }
1925 }
1926 }
1927 if num_signers < multisig.m {
1928 return Err(ProgramError::MissingRequiredSignature);
1929 }
1930 return Ok(());
1931 } else if !owner_account_info.is_signer {
1932 return Err(ProgramError::MissingRequiredSignature);
1933 }
1934 Ok(())
1935 }
1936
1937 fn get_required_account_extensions(
1938 mint_account_info: &AccountInfo,
1939 ) -> Result<Vec<ExtensionType>, ProgramError> {
1940 let mint_data = mint_account_info.data.borrow();
1941 let state = PodStateWithExtensions::<PodMint>::unpack(&mint_data)
1942 .map_err(|_| Into::<ProgramError>::into(TokenError::InvalidMint))?;
1943 Self::get_required_account_extensions_from_unpacked_mint(mint_account_info.owner, &state)
1944 }
1945
1946 fn get_required_account_extensions_from_unpacked_mint(
1947 token_program_id: &Pubkey,
1948 state: &PodStateWithExtensions<PodMint>,
1949 ) -> Result<Vec<ExtensionType>, ProgramError> {
1950 check_program_account(token_program_id)?;
1951 let mint_extensions = state.get_extension_types()?;
1952 Ok(ExtensionType::get_required_init_account_extensions(
1953 &mint_extensions,
1954 ))
1955 }
1956}
1957
1958#[cfg(not(target_os = "solana"))]
1962fn delete_account(account_info: &AccountInfo) -> Result<(), ProgramError> {
1963 account_info.assign(&system_program::id());
1964 let mut account_data = account_info.data.borrow_mut();
1965 let data_len = account_data.len();
1966 solana_program::program_memory::sol_memset(*account_data, 0, data_len);
1967 Ok(())
1968}
1969
1970#[cfg(target_os = "solana")]
1972fn delete_account(account_info: &AccountInfo) -> Result<(), ProgramError> {
1973 account_info.assign(&system_program::id());
1974 account_info.realloc(0, false)
1975}
1976
1977#[cfg(test)]
1978mod tests {
1979 use {
1980 super::*,
1981 crate::{
1982 extension::transfer_fee::instruction::initialize_transfer_fee_config, instruction::*,
1983 state::Multisig,
1984 },
1985 serial_test::serial,
1986 solana_program::{
1987 account_info::IntoAccountInfo,
1988 clock::Epoch,
1989 instruction::Instruction,
1990 program_error::{self, PrintProgramError},
1991 program_option::COption,
1992 sysvar::{clock::Clock, rent},
1993 },
1994 solana_sdk::account::{
1995 create_account_for_test, create_is_signer_account_infos, Account as SolanaAccount,
1996 },
1997 std::sync::{Arc, RwLock},
1998 };
1999
2000 lazy_static::lazy_static! {
2001 static ref EXPECTED_DATA: Arc<RwLock<Vec<u8>>> = Arc::new(RwLock::new(Vec::new()));
2002 }
2003
2004 fn set_expected_data(expected_data: Vec<u8>) {
2005 *EXPECTED_DATA.write().unwrap() = expected_data;
2006 }
2007
2008 struct SyscallStubs {}
2009 impl solana_sdk::program_stubs::SyscallStubs for SyscallStubs {
2010 fn sol_log(&self, _message: &str) {}
2011
2012 fn sol_invoke_signed(
2013 &self,
2014 _instruction: &Instruction,
2015 _account_infos: &[AccountInfo],
2016 _signers_seeds: &[&[&[u8]]],
2017 ) -> ProgramResult {
2018 Err(ProgramError::Custom(42)) }
2020
2021 fn sol_get_clock_sysvar(&self, var_addr: *mut u8) -> u64 {
2022 unsafe {
2023 *(var_addr as *mut _ as *mut Clock) = Clock::default();
2024 }
2025 solana_program::entrypoint::SUCCESS
2026 }
2027
2028 fn sol_get_epoch_schedule_sysvar(&self, _var_addr: *mut u8) -> u64 {
2029 program_error::UNSUPPORTED_SYSVAR
2030 }
2031
2032 #[allow(deprecated)]
2033 fn sol_get_fees_sysvar(&self, _var_addr: *mut u8) -> u64 {
2034 program_error::UNSUPPORTED_SYSVAR
2035 }
2036
2037 fn sol_get_rent_sysvar(&self, var_addr: *mut u8) -> u64 {
2038 unsafe {
2039 *(var_addr as *mut _ as *mut Rent) = Rent::default();
2040 }
2041 solana_program::entrypoint::SUCCESS
2042 }
2043
2044 fn sol_set_return_data(&self, data: &[u8]) {
2045 assert_eq!(&*EXPECTED_DATA.read().unwrap(), data)
2046 }
2047 }
2048
2049 fn do_process_instruction(
2050 instruction: Instruction,
2051 accounts: Vec<&mut SolanaAccount>,
2052 ) -> ProgramResult {
2053 {
2054 use std::sync::Once;
2055 static ONCE: Once = Once::new();
2056
2057 ONCE.call_once(|| {
2058 solana_sdk::program_stubs::set_syscall_stubs(Box::new(SyscallStubs {}));
2059 });
2060 }
2061
2062 let mut meta = instruction
2063 .accounts
2064 .iter()
2065 .zip(accounts)
2066 .map(|(account_meta, account)| (&account_meta.pubkey, account_meta.is_signer, account))
2067 .collect::<Vec<_>>();
2068
2069 let account_infos = create_is_signer_account_infos(&mut meta);
2070 Processor::process(&instruction.program_id, &account_infos, &instruction.data)
2071 }
2072
2073 fn do_process_instruction_dups(
2074 instruction: Instruction,
2075 account_infos: Vec<AccountInfo>,
2076 ) -> ProgramResult {
2077 Processor::process(&instruction.program_id, &account_infos, &instruction.data)
2078 }
2079
2080 fn return_token_error_as_program_error() -> ProgramError {
2081 TokenError::MintMismatch.into()
2082 }
2083
2084 fn rent_sysvar() -> SolanaAccount {
2085 create_account_for_test(&Rent::default())
2086 }
2087
2088 fn mint_minimum_balance() -> u64 {
2089 Rent::default().minimum_balance(Mint::get_packed_len())
2090 }
2091
2092 fn account_minimum_balance() -> u64 {
2093 Rent::default().minimum_balance(Account::get_packed_len())
2094 }
2095
2096 fn multisig_minimum_balance() -> u64 {
2097 Rent::default().minimum_balance(Multisig::get_packed_len())
2098 }
2099
2100 fn native_mint() -> SolanaAccount {
2101 let mut rent_sysvar = rent_sysvar();
2102 let mut mint_account =
2103 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &crate::id());
2104 do_process_instruction(
2105 initialize_mint(
2106 &crate::id(),
2107 &crate::native_mint::id(),
2108 &Pubkey::default(),
2109 None,
2110 crate::native_mint::DECIMALS,
2111 )
2112 .unwrap(),
2113 vec![&mut mint_account, &mut rent_sysvar],
2114 )
2115 .unwrap();
2116 mint_account
2117 }
2118
2119 #[test]
2120 fn test_print_error() {
2121 let error = return_token_error_as_program_error();
2122 error.print::<TokenError>();
2123 }
2124
2125 #[test]
2126 fn test_error_as_custom() {
2127 assert_eq!(
2128 return_token_error_as_program_error(),
2129 ProgramError::Custom(3)
2130 );
2131 }
2132
2133 #[test]
2134 fn test_unique_account_sizes() {
2135 assert_ne!(Mint::get_packed_len(), 0);
2136 assert_ne!(Mint::get_packed_len(), Account::get_packed_len());
2137 assert_ne!(Mint::get_packed_len(), Multisig::get_packed_len());
2138 assert_ne!(Account::get_packed_len(), 0);
2139 assert_ne!(Account::get_packed_len(), Multisig::get_packed_len());
2140 assert_ne!(Multisig::get_packed_len(), 0);
2141 }
2142
2143 #[test]
2144 fn test_initialize_mint() {
2145 let program_id = crate::id();
2146 let owner_key = Pubkey::new_unique();
2147 let mint_key = Pubkey::new_unique();
2148 let mut mint_account = SolanaAccount::new(42, Mint::get_packed_len(), &program_id);
2149 let mint2_key = Pubkey::new_unique();
2150 let mut mint2_account =
2151 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
2152 let mut rent_sysvar = rent_sysvar();
2153
2154 assert_eq!(
2156 Err(TokenError::NotRentExempt.into()),
2157 do_process_instruction(
2158 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
2159 vec![&mut mint_account, &mut rent_sysvar]
2160 )
2161 );
2162
2163 mint_account.lamports = mint_minimum_balance();
2164
2165 do_process_instruction(
2167 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
2168 vec![&mut mint_account, &mut rent_sysvar],
2169 )
2170 .unwrap();
2171
2172 assert_eq!(
2174 Err(TokenError::AlreadyInUse.into()),
2175 do_process_instruction(
2176 initialize_mint(&program_id, &mint_key, &owner_key, None, 2,).unwrap(),
2177 vec![&mut mint_account, &mut rent_sysvar]
2178 )
2179 );
2180
2181 do_process_instruction(
2183 initialize_mint(&program_id, &mint2_key, &owner_key, Some(&owner_key), 2).unwrap(),
2184 vec![&mut mint2_account, &mut rent_sysvar],
2185 )
2186 .unwrap();
2187 let mint = Mint::unpack_unchecked(&mint2_account.data).unwrap();
2188 assert_eq!(mint.freeze_authority, COption::Some(owner_key));
2189 }
2190
2191 #[test]
2192 fn test_initialize_mint2() {
2193 let program_id = crate::id();
2194 let owner_key = Pubkey::new_unique();
2195 let mint_key = Pubkey::new_unique();
2196 let mut mint_account = SolanaAccount::new(42, Mint::get_packed_len(), &program_id);
2197 let mint2_key = Pubkey::new_unique();
2198 let mut mint2_account =
2199 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
2200
2201 assert_eq!(
2203 Err(TokenError::NotRentExempt.into()),
2204 do_process_instruction(
2205 initialize_mint2(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
2206 vec![&mut mint_account]
2207 )
2208 );
2209
2210 mint_account.lamports = mint_minimum_balance();
2211
2212 do_process_instruction(
2214 initialize_mint2(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
2215 vec![&mut mint_account],
2216 )
2217 .unwrap();
2218
2219 assert_eq!(
2221 Err(TokenError::AlreadyInUse.into()),
2222 do_process_instruction(
2223 initialize_mint2(&program_id, &mint_key, &owner_key, None, 2,).unwrap(),
2224 vec![&mut mint_account]
2225 )
2226 );
2227
2228 do_process_instruction(
2230 initialize_mint2(&program_id, &mint2_key, &owner_key, Some(&owner_key), 2).unwrap(),
2231 vec![&mut mint2_account],
2232 )
2233 .unwrap();
2234 let mint = Mint::unpack_unchecked(&mint2_account.data).unwrap();
2235 assert_eq!(mint.freeze_authority, COption::Some(owner_key));
2236 }
2237
2238 #[test]
2239 fn test_initialize_mint_account() {
2240 let program_id = crate::id();
2241 let account_key = Pubkey::new_unique();
2242 let mut account_account = SolanaAccount::new(42, Account::get_packed_len(), &program_id);
2243 let owner_key = Pubkey::new_unique();
2244 let mut owner_account = SolanaAccount::default();
2245 let mint_key = Pubkey::new_unique();
2246 let mut mint_account =
2247 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
2248 let mut rent_sysvar = rent_sysvar();
2249
2250 assert_eq!(
2252 Err(TokenError::NotRentExempt.into()),
2253 do_process_instruction(
2254 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
2255 vec![
2256 &mut account_account,
2257 &mut mint_account,
2258 &mut owner_account,
2259 &mut rent_sysvar
2260 ],
2261 )
2262 );
2263
2264 account_account.lamports = account_minimum_balance();
2265
2266 assert_eq!(
2268 Err(TokenError::InvalidMint.into()),
2269 do_process_instruction(
2270 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
2271 vec![
2272 &mut account_account,
2273 &mut mint_account,
2274 &mut owner_account,
2275 &mut rent_sysvar
2276 ],
2277 )
2278 );
2279
2280 do_process_instruction(
2282 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
2283 vec![&mut mint_account, &mut rent_sysvar],
2284 )
2285 .unwrap();
2286
2287 let not_program_id = Pubkey::new_unique();
2289 mint_account.owner = not_program_id;
2290 assert_eq!(
2291 Err(ProgramError::IncorrectProgramId),
2292 do_process_instruction(
2293 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
2294 vec![
2295 &mut account_account,
2296 &mut mint_account,
2297 &mut owner_account,
2298 &mut rent_sysvar
2299 ],
2300 )
2301 );
2302 mint_account.owner = program_id;
2303
2304 do_process_instruction(
2306 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
2307 vec![
2308 &mut account_account,
2309 &mut mint_account,
2310 &mut owner_account,
2311 &mut rent_sysvar,
2312 ],
2313 )
2314 .unwrap();
2315
2316 assert_eq!(
2318 Err(TokenError::AlreadyInUse.into()),
2319 do_process_instruction(
2320 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
2321 vec![
2322 &mut account_account,
2323 &mut mint_account,
2324 &mut owner_account,
2325 &mut rent_sysvar
2326 ],
2327 )
2328 );
2329 }
2330
2331 #[test]
2332 fn test_transfer_dups() {
2333 let program_id = crate::id();
2334 let account1_key = Pubkey::new_unique();
2335 let mut account1_account = SolanaAccount::new(
2336 account_minimum_balance(),
2337 Account::get_packed_len(),
2338 &program_id,
2339 );
2340 let mut account1_info: AccountInfo = (&account1_key, true, &mut account1_account).into();
2341 let account2_key = Pubkey::new_unique();
2342 let mut account2_account = SolanaAccount::new(
2343 account_minimum_balance(),
2344 Account::get_packed_len(),
2345 &program_id,
2346 );
2347 let mut account2_info: AccountInfo = (&account2_key, false, &mut account2_account).into();
2348 let account3_key = Pubkey::new_unique();
2349 let mut account3_account = SolanaAccount::new(
2350 account_minimum_balance(),
2351 Account::get_packed_len(),
2352 &program_id,
2353 );
2354 let account3_info: AccountInfo = (&account3_key, false, &mut account3_account).into();
2355 let account4_key = Pubkey::new_unique();
2356 let mut account4_account = SolanaAccount::new(
2357 account_minimum_balance(),
2358 Account::get_packed_len(),
2359 &program_id,
2360 );
2361 let account4_info: AccountInfo = (&account4_key, true, &mut account4_account).into();
2362 let multisig_key = Pubkey::new_unique();
2363 let mut multisig_account = SolanaAccount::new(
2364 multisig_minimum_balance(),
2365 Multisig::get_packed_len(),
2366 &program_id,
2367 );
2368 let multisig_info: AccountInfo = (&multisig_key, true, &mut multisig_account).into();
2369 let owner_key = Pubkey::new_unique();
2370 let mut owner_account = SolanaAccount::default();
2371 let owner_info: AccountInfo = (&owner_key, true, &mut owner_account).into();
2372 let mint_key = Pubkey::new_unique();
2373 let mut mint_account =
2374 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
2375 let mint_info: AccountInfo = (&mint_key, false, &mut mint_account).into();
2376 let rent_key = rent::id();
2377 let mut rent_sysvar = rent_sysvar();
2378 let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
2379
2380 do_process_instruction_dups(
2382 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
2383 vec![mint_info.clone(), rent_info.clone()],
2384 )
2385 .unwrap();
2386
2387 do_process_instruction_dups(
2389 initialize_account(&program_id, &account1_key, &mint_key, &account1_key).unwrap(),
2390 vec![
2391 account1_info.clone(),
2392 mint_info.clone(),
2393 account1_info.clone(),
2394 rent_info.clone(),
2395 ],
2396 )
2397 .unwrap();
2398
2399 do_process_instruction_dups(
2401 initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
2402 vec![
2403 account2_info.clone(),
2404 mint_info.clone(),
2405 owner_info.clone(),
2406 rent_info.clone(),
2407 ],
2408 )
2409 .unwrap();
2410
2411 do_process_instruction_dups(
2413 mint_to(&program_id, &mint_key, &account1_key, &owner_key, &[], 1000).unwrap(),
2414 vec![mint_info.clone(), account1_info.clone(), owner_info.clone()],
2415 )
2416 .unwrap();
2417
2418 do_process_instruction_dups(
2420 #[allow(deprecated)]
2421 transfer(
2422 &program_id,
2423 &account1_key,
2424 &account2_key,
2425 &account1_key,
2426 &[],
2427 500,
2428 )
2429 .unwrap(),
2430 vec![
2431 account1_info.clone(),
2432 account2_info.clone(),
2433 account1_info.clone(),
2434 ],
2435 )
2436 .unwrap();
2437
2438 do_process_instruction_dups(
2440 transfer_checked(
2441 &program_id,
2442 &account1_key,
2443 &mint_key,
2444 &account2_key,
2445 &account1_key,
2446 &[],
2447 500,
2448 2,
2449 )
2450 .unwrap(),
2451 vec![
2452 account1_info.clone(),
2453 mint_info.clone(),
2454 account2_info.clone(),
2455 account1_info.clone(),
2456 ],
2457 )
2458 .unwrap();
2459
2460 let mut account = Account::unpack_unchecked(&account1_info.data.borrow()).unwrap();
2462 account.amount = 1000;
2463 account.delegated_amount = 1000;
2464 account.delegate = COption::Some(account1_key);
2465 account.owner = owner_key;
2466 Account::pack(account, &mut account1_info.data.borrow_mut()).unwrap();
2467
2468 do_process_instruction_dups(
2469 #[allow(deprecated)]
2470 transfer(
2471 &program_id,
2472 &account1_key,
2473 &account2_key,
2474 &account1_key,
2475 &[],
2476 500,
2477 )
2478 .unwrap(),
2479 vec![
2480 account1_info.clone(),
2481 account2_info.clone(),
2482 account1_info.clone(),
2483 ],
2484 )
2485 .unwrap();
2486
2487 do_process_instruction_dups(
2489 transfer_checked(
2490 &program_id,
2491 &account1_key,
2492 &mint_key,
2493 &account2_key,
2494 &account1_key,
2495 &[],
2496 500,
2497 2,
2498 )
2499 .unwrap(),
2500 vec![
2501 account1_info.clone(),
2502 mint_info.clone(),
2503 account2_info.clone(),
2504 account1_info.clone(),
2505 ],
2506 )
2507 .unwrap();
2508
2509 do_process_instruction_dups(
2511 initialize_account(&program_id, &account3_key, &mint_key, &account2_key).unwrap(),
2512 vec![
2513 account3_info.clone(),
2514 mint_info.clone(),
2515 account2_info.clone(),
2516 rent_info.clone(),
2517 ],
2518 )
2519 .unwrap();
2520 do_process_instruction_dups(
2521 mint_to(&program_id, &mint_key, &account3_key, &owner_key, &[], 1000).unwrap(),
2522 vec![mint_info.clone(), account3_info.clone(), owner_info.clone()],
2523 )
2524 .unwrap();
2525
2526 account1_info.is_signer = false;
2527 account2_info.is_signer = true;
2528 do_process_instruction_dups(
2529 #[allow(deprecated)]
2530 transfer(
2531 &program_id,
2532 &account3_key,
2533 &account2_key,
2534 &account2_key,
2535 &[],
2536 500,
2537 )
2538 .unwrap(),
2539 vec![
2540 account3_info.clone(),
2541 account2_info.clone(),
2542 account2_info.clone(),
2543 ],
2544 )
2545 .unwrap();
2546
2547 do_process_instruction_dups(
2549 transfer_checked(
2550 &program_id,
2551 &account3_key,
2552 &mint_key,
2553 &account2_key,
2554 &account2_key,
2555 &[],
2556 500,
2557 2,
2558 )
2559 .unwrap(),
2560 vec![
2561 account3_info.clone(),
2562 mint_info.clone(),
2563 account2_info.clone(),
2564 account2_info.clone(),
2565 ],
2566 )
2567 .unwrap();
2568
2569 do_process_instruction_dups(
2571 initialize_multisig(&program_id, &multisig_key, &[&account4_key], 1).unwrap(),
2572 vec![
2573 multisig_info.clone(),
2574 rent_info.clone(),
2575 account4_info.clone(),
2576 ],
2577 )
2578 .unwrap();
2579
2580 do_process_instruction_dups(
2581 initialize_account(&program_id, &account4_key, &mint_key, &multisig_key).unwrap(),
2582 vec![
2583 account4_info.clone(),
2584 mint_info.clone(),
2585 multisig_info.clone(),
2586 rent_info.clone(),
2587 ],
2588 )
2589 .unwrap();
2590
2591 do_process_instruction_dups(
2592 mint_to(&program_id, &mint_key, &account4_key, &owner_key, &[], 1000).unwrap(),
2593 vec![mint_info.clone(), account4_info.clone(), owner_info.clone()],
2594 )
2595 .unwrap();
2596
2597 do_process_instruction_dups(
2599 #[allow(deprecated)]
2600 transfer(
2601 &program_id,
2602 &account4_key,
2603 &account2_key,
2604 &multisig_key,
2605 &[&account4_key],
2606 500,
2607 )
2608 .unwrap(),
2609 vec![
2610 account4_info.clone(),
2611 account2_info.clone(),
2612 multisig_info.clone(),
2613 account4_info.clone(),
2614 ],
2615 )
2616 .unwrap();
2617
2618 do_process_instruction_dups(
2620 transfer_checked(
2621 &program_id,
2622 &account4_key,
2623 &mint_key,
2624 &account2_key,
2625 &multisig_key,
2626 &[&account4_key],
2627 500,
2628 2,
2629 )
2630 .unwrap(),
2631 vec![
2632 account4_info.clone(),
2633 mint_info.clone(),
2634 account2_info.clone(),
2635 multisig_info.clone(),
2636 account4_info.clone(),
2637 ],
2638 )
2639 .unwrap();
2640 }
2641
2642 #[test]
2643 fn test_transfer() {
2644 let program_id = crate::id();
2645 let account_key = Pubkey::new_unique();
2646 let mut account_account = SolanaAccount::new(
2647 account_minimum_balance(),
2648 Account::get_packed_len(),
2649 &program_id,
2650 );
2651 let account2_key = Pubkey::new_unique();
2652 let mut account2_account = SolanaAccount::new(
2653 account_minimum_balance(),
2654 Account::get_packed_len(),
2655 &program_id,
2656 );
2657 let account3_key = Pubkey::new_unique();
2658 let mut account3_account = SolanaAccount::new(
2659 account_minimum_balance(),
2660 Account::get_packed_len(),
2661 &program_id,
2662 );
2663 let delegate_key = Pubkey::new_unique();
2664 let mut delegate_account = SolanaAccount::default();
2665 let mismatch_key = Pubkey::new_unique();
2666 let mut mismatch_account = SolanaAccount::new(
2667 account_minimum_balance(),
2668 Account::get_packed_len(),
2669 &program_id,
2670 );
2671 let owner_key = Pubkey::new_unique();
2672 let mut owner_account = SolanaAccount::default();
2673 let owner2_key = Pubkey::new_unique();
2674 let mut owner2_account = SolanaAccount::default();
2675 let mint_key = Pubkey::new_unique();
2676 let mut mint_account =
2677 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
2678 let mint2_key = Pubkey::new_unique();
2679 let mut rent_sysvar = rent_sysvar();
2680
2681 do_process_instruction(
2683 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
2684 vec![&mut mint_account, &mut rent_sysvar],
2685 )
2686 .unwrap();
2687
2688 do_process_instruction(
2690 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
2691 vec![
2692 &mut account_account,
2693 &mut mint_account,
2694 &mut owner_account,
2695 &mut rent_sysvar,
2696 ],
2697 )
2698 .unwrap();
2699
2700 do_process_instruction(
2702 initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
2703 vec![
2704 &mut account2_account,
2705 &mut mint_account,
2706 &mut owner_account,
2707 &mut rent_sysvar,
2708 ],
2709 )
2710 .unwrap();
2711
2712 do_process_instruction(
2714 initialize_account(&program_id, &account3_key, &mint_key, &owner_key).unwrap(),
2715 vec![
2716 &mut account3_account,
2717 &mut mint_account,
2718 &mut owner_account,
2719 &mut rent_sysvar,
2720 ],
2721 )
2722 .unwrap();
2723
2724 do_process_instruction(
2726 initialize_account(&program_id, &mismatch_key, &mint_key, &owner_key).unwrap(),
2727 vec![
2728 &mut mismatch_account,
2729 &mut mint_account,
2730 &mut owner_account,
2731 &mut rent_sysvar,
2732 ],
2733 )
2734 .unwrap();
2735 let mut account = Account::unpack_unchecked(&mismatch_account.data).unwrap();
2736 account.mint = mint2_key;
2737 Account::pack(account, &mut mismatch_account.data).unwrap();
2738
2739 do_process_instruction(
2741 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
2742 vec![&mut mint_account, &mut account_account, &mut owner_account],
2743 )
2744 .unwrap();
2745
2746 #[allow(deprecated)]
2748 let mut instruction = transfer(
2749 &program_id,
2750 &account_key,
2751 &account2_key,
2752 &owner_key,
2753 &[],
2754 1000,
2755 )
2756 .unwrap();
2757 instruction.accounts[2].is_signer = false;
2758 assert_eq!(
2759 Err(ProgramError::MissingRequiredSignature),
2760 do_process_instruction(
2761 instruction,
2762 vec![
2763 &mut account_account,
2764 &mut account2_account,
2765 &mut owner_account,
2766 ],
2767 )
2768 );
2769
2770 assert_eq!(
2772 Err(TokenError::MintMismatch.into()),
2773 do_process_instruction(
2774 #[allow(deprecated)]
2775 transfer(
2776 &program_id,
2777 &account_key,
2778 &mismatch_key,
2779 &owner_key,
2780 &[],
2781 1000
2782 )
2783 .unwrap(),
2784 vec![
2785 &mut account_account,
2786 &mut mismatch_account,
2787 &mut owner_account,
2788 ],
2789 )
2790 );
2791
2792 assert_eq!(
2794 Err(TokenError::OwnerMismatch.into()),
2795 do_process_instruction(
2796 #[allow(deprecated)]
2797 transfer(
2798 &program_id,
2799 &account_key,
2800 &account2_key,
2801 &owner2_key,
2802 &[],
2803 1000
2804 )
2805 .unwrap(),
2806 vec![
2807 &mut account_account,
2808 &mut account2_account,
2809 &mut owner2_account,
2810 ],
2811 )
2812 );
2813
2814 let not_program_id = Pubkey::new_unique();
2816 account_account.owner = not_program_id;
2817 assert_eq!(
2818 Err(ProgramError::IncorrectProgramId),
2819 do_process_instruction(
2820 #[allow(deprecated)]
2821 transfer(&program_id, &account_key, &account2_key, &owner_key, &[], 0,).unwrap(),
2822 vec![
2823 &mut account_account,
2824 &mut account2_account,
2825 &mut owner2_account,
2826 ],
2827 )
2828 );
2829 account_account.owner = program_id;
2830
2831 let not_program_id = Pubkey::new_unique();
2833 account2_account.owner = not_program_id;
2834 assert_eq!(
2835 Err(ProgramError::IncorrectProgramId),
2836 do_process_instruction(
2837 #[allow(deprecated)]
2838 transfer(&program_id, &account_key, &account2_key, &owner_key, &[], 0,).unwrap(),
2839 vec![
2840 &mut account_account,
2841 &mut account2_account,
2842 &mut owner2_account,
2843 ],
2844 )
2845 );
2846 account2_account.owner = program_id;
2847
2848 do_process_instruction(
2850 #[allow(deprecated)]
2851 transfer(
2852 &program_id,
2853 &account_key,
2854 &account2_key,
2855 &owner_key,
2856 &[],
2857 1000,
2858 )
2859 .unwrap(),
2860 vec![
2861 &mut account_account,
2862 &mut account2_account,
2863 &mut owner_account,
2864 ],
2865 )
2866 .unwrap();
2867
2868 assert_eq!(
2870 Err(TokenError::InsufficientFunds.into()),
2871 do_process_instruction(
2872 #[allow(deprecated)]
2873 transfer(&program_id, &account_key, &account2_key, &owner_key, &[], 1).unwrap(),
2874 vec![
2875 &mut account_account,
2876 &mut account2_account,
2877 &mut owner_account,
2878 ],
2879 )
2880 );
2881
2882 do_process_instruction(
2884 #[allow(deprecated)]
2885 transfer(
2886 &program_id,
2887 &account2_key,
2888 &account_key,
2889 &owner_key,
2890 &[],
2891 500,
2892 )
2893 .unwrap(),
2894 vec![
2895 &mut account2_account,
2896 &mut account_account,
2897 &mut owner_account,
2898 ],
2899 )
2900 .unwrap();
2901
2902 assert_eq!(
2904 Err(TokenError::MintDecimalsMismatch.into()),
2905 do_process_instruction(
2906 transfer_checked(
2907 &program_id,
2908 &account2_key,
2909 &mint_key,
2910 &account_key,
2911 &owner_key,
2912 &[],
2913 1,
2914 10 )
2916 .unwrap(),
2917 vec![
2918 &mut account2_account,
2919 &mut mint_account,
2920 &mut account_account,
2921 &mut owner_account,
2922 ],
2923 )
2924 );
2925
2926 assert_eq!(
2928 Err(TokenError::MintMismatch.into()),
2929 do_process_instruction(
2930 transfer_checked(
2931 &program_id,
2932 &account2_key,
2933 &account3_key, &account_key,
2935 &owner_key,
2936 &[],
2937 1,
2938 2
2939 )
2940 .unwrap(),
2941 vec![
2942 &mut account2_account,
2943 &mut account3_account, &mut account_account,
2945 &mut owner_account,
2946 ],
2947 )
2948 );
2949 do_process_instruction(
2951 transfer_checked(
2952 &program_id,
2953 &account2_key,
2954 &mint_key,
2955 &account_key,
2956 &owner_key,
2957 &[],
2958 500,
2959 2,
2960 )
2961 .unwrap(),
2962 vec![
2963 &mut account2_account,
2964 &mut mint_account,
2965 &mut account_account,
2966 &mut owner_account,
2967 ],
2968 )
2969 .unwrap();
2970
2971 assert_eq!(
2973 Err(TokenError::InsufficientFunds.into()),
2974 do_process_instruction(
2975 #[allow(deprecated)]
2976 transfer(&program_id, &account2_key, &account_key, &owner_key, &[], 1).unwrap(),
2977 vec![
2978 &mut account2_account,
2979 &mut account_account,
2980 &mut owner_account,
2981 ],
2982 )
2983 );
2984
2985 do_process_instruction(
2987 approve(
2988 &program_id,
2989 &account_key,
2990 &delegate_key,
2991 &owner_key,
2992 &[],
2993 100,
2994 )
2995 .unwrap(),
2996 vec![
2997 &mut account_account,
2998 &mut delegate_account,
2999 &mut owner_account,
3000 ],
3001 )
3002 .unwrap();
3003
3004 assert_eq!(
3006 Err(TokenError::OwnerMismatch.into()),
3007 do_process_instruction(
3008 #[allow(deprecated)]
3009 transfer(
3010 &program_id,
3011 &account_key,
3012 &account2_key,
3013 &owner2_key, &[],
3015 1,
3016 )
3017 .unwrap(),
3018 vec![
3019 &mut account_account,
3020 &mut account2_account,
3021 &mut owner2_account,
3022 ],
3023 )
3024 );
3025
3026 assert_eq!(
3028 Err(TokenError::InsufficientFunds.into()),
3029 do_process_instruction(
3030 #[allow(deprecated)]
3031 transfer(
3032 &program_id,
3033 &account_key,
3034 &account2_key,
3035 &delegate_key,
3036 &[],
3037 101
3038 )
3039 .unwrap(),
3040 vec![
3041 &mut account_account,
3042 &mut account2_account,
3043 &mut delegate_account,
3044 ],
3045 )
3046 );
3047
3048 do_process_instruction(
3050 #[allow(deprecated)]
3051 transfer(
3052 &program_id,
3053 &account_key,
3054 &account2_key,
3055 &delegate_key,
3056 &[],
3057 100,
3058 )
3059 .unwrap(),
3060 vec![
3061 &mut account_account,
3062 &mut account2_account,
3063 &mut delegate_account,
3064 ],
3065 )
3066 .unwrap();
3067
3068 assert_eq!(
3070 Err(TokenError::OwnerMismatch.into()),
3071 do_process_instruction(
3072 #[allow(deprecated)]
3073 transfer(
3074 &program_id,
3075 &account_key,
3076 &account2_key,
3077 &delegate_key,
3078 &[],
3079 1
3080 )
3081 .unwrap(),
3082 vec![
3083 &mut account_account,
3084 &mut account2_account,
3085 &mut delegate_account,
3086 ],
3087 )
3088 );
3089
3090 do_process_instruction(
3092 #[allow(deprecated)]
3093 transfer(
3094 &program_id,
3095 &account_key,
3096 &account2_key,
3097 &owner_key,
3098 &[],
3099 900,
3100 )
3101 .unwrap(),
3102 vec![
3103 &mut account_account,
3104 &mut account2_account,
3105 &mut owner_account,
3106 ],
3107 )
3108 .unwrap();
3109
3110 do_process_instruction(
3112 approve(
3113 &program_id,
3114 &account_key,
3115 &delegate_key,
3116 &owner_key,
3117 &[],
3118 100,
3119 )
3120 .unwrap(),
3121 vec![
3122 &mut account_account,
3123 &mut delegate_account,
3124 &mut owner_account,
3125 ],
3126 )
3127 .unwrap();
3128
3129 assert_eq!(
3131 Err(TokenError::InsufficientFunds.into()),
3132 do_process_instruction(
3133 #[allow(deprecated)]
3134 transfer(
3135 &program_id,
3136 &account_key,
3137 &account2_key,
3138 &delegate_key,
3139 &[],
3140 100
3141 )
3142 .unwrap(),
3143 vec![
3144 &mut account_account,
3145 &mut account2_account,
3146 &mut delegate_account,
3147 ],
3148 )
3149 );
3150 }
3151
3152 #[test]
3153 fn test_self_transfer() {
3154 let program_id = crate::id();
3155 let account_key = Pubkey::new_unique();
3156 let mut account_account = SolanaAccount::new(
3157 account_minimum_balance(),
3158 Account::get_packed_len(),
3159 &program_id,
3160 );
3161 let account2_key = Pubkey::new_unique();
3162 let mut account2_account = SolanaAccount::new(
3163 account_minimum_balance(),
3164 Account::get_packed_len(),
3165 &program_id,
3166 );
3167 let account3_key = Pubkey::new_unique();
3168 let mut account3_account = SolanaAccount::new(
3169 account_minimum_balance(),
3170 Account::get_packed_len(),
3171 &program_id,
3172 );
3173 let delegate_key = Pubkey::new_unique();
3174 let mut delegate_account = SolanaAccount::default();
3175 let owner_key = Pubkey::new_unique();
3176 let mut owner_account = SolanaAccount::default();
3177 let owner2_key = Pubkey::new_unique();
3178 let mut owner2_account = SolanaAccount::default();
3179 let mint_key = Pubkey::new_unique();
3180 let mut mint_account =
3181 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
3182 let mut rent_sysvar = rent_sysvar();
3183
3184 do_process_instruction(
3186 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
3187 vec![&mut mint_account, &mut rent_sysvar],
3188 )
3189 .unwrap();
3190
3191 do_process_instruction(
3193 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
3194 vec![
3195 &mut account_account,
3196 &mut mint_account,
3197 &mut owner_account,
3198 &mut rent_sysvar,
3199 ],
3200 )
3201 .unwrap();
3202
3203 do_process_instruction(
3205 initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
3206 vec![
3207 &mut account2_account,
3208 &mut mint_account,
3209 &mut owner_account,
3210 &mut rent_sysvar,
3211 ],
3212 )
3213 .unwrap();
3214
3215 do_process_instruction(
3217 initialize_account(&program_id, &account3_key, &mint_key, &owner_key).unwrap(),
3218 vec![
3219 &mut account3_account,
3220 &mut mint_account,
3221 &mut owner_account,
3222 &mut rent_sysvar,
3223 ],
3224 )
3225 .unwrap();
3226
3227 do_process_instruction(
3229 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
3230 vec![&mut mint_account, &mut account_account, &mut owner_account],
3231 )
3232 .unwrap();
3233
3234 let account_info = (&account_key, false, &mut account_account).into_account_info();
3235 let account3_info = (&account3_key, false, &mut account3_account).into_account_info();
3236 let delegate_info = (&delegate_key, true, &mut delegate_account).into_account_info();
3237 let owner_info = (&owner_key, true, &mut owner_account).into_account_info();
3238 let owner2_info = (&owner2_key, true, &mut owner2_account).into_account_info();
3239 let mint_info = (&mint_key, false, &mut mint_account).into_account_info();
3240
3241 #[allow(deprecated)]
3243 let instruction = transfer(
3244 &program_id,
3245 account_info.key,
3246 account_info.key,
3247 owner_info.key,
3248 &[],
3249 1000,
3250 )
3251 .unwrap();
3252 assert_eq!(
3253 Ok(()),
3254 Processor::process(
3255 &instruction.program_id,
3256 &[
3257 account_info.clone(),
3258 account_info.clone(),
3259 owner_info.clone(),
3260 ],
3261 &instruction.data,
3262 )
3263 );
3264 let account = Account::unpack_unchecked(&account_info.try_borrow_data().unwrap()).unwrap();
3266 assert_eq!(account.amount, 1000);
3267
3268 let instruction = transfer_checked(
3270 &program_id,
3271 account_info.key,
3272 mint_info.key,
3273 account_info.key,
3274 owner_info.key,
3275 &[],
3276 1000,
3277 2,
3278 )
3279 .unwrap();
3280 assert_eq!(
3281 Ok(()),
3282 Processor::process(
3283 &instruction.program_id,
3284 &[
3285 account_info.clone(),
3286 mint_info.clone(),
3287 account_info.clone(),
3288 owner_info.clone(),
3289 ],
3290 &instruction.data,
3291 )
3292 );
3293 let account = Account::unpack_unchecked(&account_info.try_borrow_data().unwrap()).unwrap();
3295 assert_eq!(account.amount, 1000);
3296
3297 let mut owner_no_sign_info = owner_info.clone();
3299 #[allow(deprecated)]
3300 let mut instruction = transfer(
3301 &program_id,
3302 account_info.key,
3303 account_info.key,
3304 owner_no_sign_info.key,
3305 &[],
3306 1000,
3307 )
3308 .unwrap();
3309 instruction.accounts[2].is_signer = false;
3310 owner_no_sign_info.is_signer = false;
3311 assert_eq!(
3312 Err(ProgramError::MissingRequiredSignature),
3313 Processor::process(
3314 &instruction.program_id,
3315 &[
3316 account_info.clone(),
3317 account_info.clone(),
3318 owner_no_sign_info.clone(),
3319 ],
3320 &instruction.data,
3321 )
3322 );
3323
3324 let mut instruction = transfer_checked(
3326 &program_id,
3327 account_info.key,
3328 mint_info.key,
3329 account_info.key,
3330 owner_no_sign_info.key,
3331 &[],
3332 1000,
3333 2,
3334 )
3335 .unwrap();
3336 instruction.accounts[3].is_signer = false;
3337 assert_eq!(
3338 Err(ProgramError::MissingRequiredSignature),
3339 Processor::process(
3340 &instruction.program_id,
3341 &[
3342 account_info.clone(),
3343 mint_info.clone(),
3344 account_info.clone(),
3345 owner_no_sign_info,
3346 ],
3347 &instruction.data,
3348 )
3349 );
3350
3351 #[allow(deprecated)]
3353 let instruction = transfer(
3354 &program_id,
3355 account_info.key,
3356 account_info.key,
3357 owner2_info.key,
3358 &[],
3359 1000,
3360 )
3361 .unwrap();
3362 assert_eq!(
3363 Err(TokenError::OwnerMismatch.into()),
3364 Processor::process(
3365 &instruction.program_id,
3366 &[
3367 account_info.clone(),
3368 account_info.clone(),
3369 owner2_info.clone(),
3370 ],
3371 &instruction.data,
3372 )
3373 );
3374
3375 let instruction = transfer_checked(
3377 &program_id,
3378 account_info.key,
3379 mint_info.key,
3380 account_info.key,
3381 owner2_info.key,
3382 &[],
3383 1000,
3384 2,
3385 )
3386 .unwrap();
3387 assert_eq!(
3388 Err(TokenError::OwnerMismatch.into()),
3389 Processor::process(
3390 &instruction.program_id,
3391 &[
3392 account_info.clone(),
3393 mint_info.clone(),
3394 account_info.clone(),
3395 owner2_info.clone(),
3396 ],
3397 &instruction.data,
3398 )
3399 );
3400
3401 #[allow(deprecated)]
3403 let instruction = transfer(
3404 &program_id,
3405 account_info.key,
3406 account_info.key,
3407 owner_info.key,
3408 &[],
3409 1001,
3410 )
3411 .unwrap();
3412 assert_eq!(
3413 Err(TokenError::InsufficientFunds.into()),
3414 Processor::process(
3415 &instruction.program_id,
3416 &[
3417 account_info.clone(),
3418 account_info.clone(),
3419 owner_info.clone(),
3420 ],
3421 &instruction.data,
3422 )
3423 );
3424
3425 let instruction = transfer_checked(
3427 &program_id,
3428 account_info.key,
3429 mint_info.key,
3430 account_info.key,
3431 owner_info.key,
3432 &[],
3433 1001,
3434 2,
3435 )
3436 .unwrap();
3437 assert_eq!(
3438 Err(TokenError::InsufficientFunds.into()),
3439 Processor::process(
3440 &instruction.program_id,
3441 &[
3442 account_info.clone(),
3443 mint_info.clone(),
3444 account_info.clone(),
3445 owner_info.clone(),
3446 ],
3447 &instruction.data,
3448 )
3449 );
3450
3451 let instruction = transfer_checked(
3453 &program_id,
3454 account_info.key,
3455 mint_info.key,
3456 account_info.key,
3457 owner_info.key,
3458 &[],
3459 1,
3460 10, )
3462 .unwrap();
3463 assert_eq!(
3464 Err(TokenError::MintDecimalsMismatch.into()),
3465 Processor::process(
3466 &instruction.program_id,
3467 &[
3468 account_info.clone(),
3469 mint_info.clone(),
3470 account_info.clone(),
3471 owner_info.clone(),
3472 ],
3473 &instruction.data,
3474 )
3475 );
3476
3477 let instruction = transfer_checked(
3479 &program_id,
3480 account_info.key,
3481 account3_info.key, account_info.key,
3483 owner_info.key,
3484 &[],
3485 1,
3486 2,
3487 )
3488 .unwrap();
3489 assert_eq!(
3490 Err(TokenError::MintMismatch.into()),
3491 Processor::process(
3492 &instruction.program_id,
3493 &[
3494 account_info.clone(),
3495 account3_info.clone(), account_info.clone(),
3497 owner_info.clone(),
3498 ],
3499 &instruction.data,
3500 )
3501 );
3502
3503 let instruction = approve(
3505 &program_id,
3506 account_info.key,
3507 delegate_info.key,
3508 owner_info.key,
3509 &[],
3510 100,
3511 )
3512 .unwrap();
3513 Processor::process(
3514 &instruction.program_id,
3515 &[
3516 account_info.clone(),
3517 delegate_info.clone(),
3518 owner_info.clone(),
3519 ],
3520 &instruction.data,
3521 )
3522 .unwrap();
3523
3524 #[allow(deprecated)]
3526 let instruction = transfer(
3527 &program_id,
3528 account_info.key,
3529 account_info.key,
3530 delegate_info.key,
3531 &[],
3532 100,
3533 )
3534 .unwrap();
3535 assert_eq!(
3536 Ok(()),
3537 Processor::process(
3538 &instruction.program_id,
3539 &[
3540 account_info.clone(),
3541 account_info.clone(),
3542 delegate_info.clone(),
3543 ],
3544 &instruction.data,
3545 )
3546 );
3547 let account = Account::unpack_unchecked(&account_info.try_borrow_data().unwrap()).unwrap();
3549 assert_eq!(account.amount, 1000);
3550 assert_eq!(account.delegated_amount, 100);
3551
3552 let instruction = transfer_checked(
3554 &program_id,
3555 account_info.key,
3556 mint_info.key,
3557 account_info.key,
3558 delegate_info.key,
3559 &[],
3560 100,
3561 2,
3562 )
3563 .unwrap();
3564 assert_eq!(
3565 Ok(()),
3566 Processor::process(
3567 &instruction.program_id,
3568 &[
3569 account_info.clone(),
3570 mint_info.clone(),
3571 account_info.clone(),
3572 delegate_info.clone(),
3573 ],
3574 &instruction.data,
3575 )
3576 );
3577 let account = Account::unpack_unchecked(&account_info.try_borrow_data().unwrap()).unwrap();
3579 assert_eq!(account.amount, 1000);
3580 assert_eq!(account.delegated_amount, 100);
3581
3582 #[allow(deprecated)]
3584 let instruction = transfer(
3585 &program_id,
3586 account_info.key,
3587 account_info.key,
3588 delegate_info.key,
3589 &[],
3590 101,
3591 )
3592 .unwrap();
3593 assert_eq!(
3594 Err(TokenError::InsufficientFunds.into()),
3595 Processor::process(
3596 &instruction.program_id,
3597 &[
3598 account_info.clone(),
3599 account_info.clone(),
3600 delegate_info.clone(),
3601 ],
3602 &instruction.data,
3603 )
3604 );
3605
3606 let instruction = transfer_checked(
3608 &program_id,
3609 account_info.key,
3610 mint_info.key,
3611 account_info.key,
3612 delegate_info.key,
3613 &[],
3614 101,
3615 2,
3616 )
3617 .unwrap();
3618 assert_eq!(
3619 Err(TokenError::InsufficientFunds.into()),
3620 Processor::process(
3621 &instruction.program_id,
3622 &[
3623 account_info.clone(),
3624 mint_info.clone(),
3625 account_info.clone(),
3626 delegate_info.clone(),
3627 ],
3628 &instruction.data,
3629 )
3630 );
3631
3632 #[allow(deprecated)]
3634 let instruction = transfer(
3635 &program_id,
3636 account_info.key,
3637 account_info.key,
3638 owner_info.key,
3639 &[],
3640 1000,
3641 )
3642 .unwrap();
3643 assert_eq!(
3644 Ok(()),
3645 Processor::process(
3646 &instruction.program_id,
3647 &[
3648 account_info.clone(),
3649 account_info.clone(),
3650 owner_info.clone(),
3651 ],
3652 &instruction.data,
3653 )
3654 );
3655 let account = Account::unpack_unchecked(&account_info.try_borrow_data().unwrap()).unwrap();
3657 assert_eq!(account.amount, 1000);
3658
3659 let instruction = transfer_checked(
3661 &program_id,
3662 account_info.key,
3663 mint_info.key,
3664 account_info.key,
3665 owner_info.key,
3666 &[],
3667 1000,
3668 2,
3669 )
3670 .unwrap();
3671 assert_eq!(
3672 Ok(()),
3673 Processor::process(
3674 &instruction.program_id,
3675 &[
3676 account_info.clone(),
3677 mint_info.clone(),
3678 account_info.clone(),
3679 owner_info.clone(),
3680 ],
3681 &instruction.data,
3682 )
3683 );
3684 let account = Account::unpack_unchecked(&account_info.try_borrow_data().unwrap()).unwrap();
3686 assert_eq!(account.amount, 1000);
3687 }
3688
3689 #[test]
3690 fn test_mintable_token_with_zero_supply() {
3691 let program_id = crate::id();
3692 let account_key = Pubkey::new_unique();
3693 let mut account_account = SolanaAccount::new(
3694 account_minimum_balance(),
3695 Account::get_packed_len(),
3696 &program_id,
3697 );
3698 let owner_key = Pubkey::new_unique();
3699 let mut owner_account = SolanaAccount::default();
3700 let mint_key = Pubkey::new_unique();
3701 let mut mint_account =
3702 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
3703 let mut rent_sysvar = rent_sysvar();
3704
3705 let decimals = 2;
3707 do_process_instruction(
3708 initialize_mint(&program_id, &mint_key, &owner_key, None, decimals).unwrap(),
3709 vec![&mut mint_account, &mut rent_sysvar],
3710 )
3711 .unwrap();
3712 let mint = Mint::unpack_unchecked(&mint_account.data).unwrap();
3713 assert_eq!(
3714 mint,
3715 Mint {
3716 mint_authority: COption::Some(owner_key),
3717 supply: 0,
3718 decimals,
3719 is_initialized: true,
3720 freeze_authority: COption::None,
3721 }
3722 );
3723
3724 do_process_instruction(
3726 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
3727 vec![
3728 &mut account_account,
3729 &mut mint_account,
3730 &mut owner_account,
3731 &mut rent_sysvar,
3732 ],
3733 )
3734 .unwrap();
3735
3736 do_process_instruction(
3738 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 42).unwrap(),
3739 vec![&mut mint_account, &mut account_account, &mut owner_account],
3740 )
3741 .unwrap();
3742 let _ = Mint::unpack(&mint_account.data).unwrap();
3743 let account = Account::unpack_unchecked(&account_account.data).unwrap();
3744 assert_eq!(account.amount, 42);
3745
3746 assert_eq!(
3748 Err(TokenError::MintDecimalsMismatch.into()),
3749 do_process_instruction(
3750 mint_to_checked(
3751 &program_id,
3752 &mint_key,
3753 &account_key,
3754 &owner_key,
3755 &[],
3756 42,
3757 decimals + 1
3758 )
3759 .unwrap(),
3760 vec![&mut mint_account, &mut account_account, &mut owner_account],
3761 )
3762 );
3763
3764 let _ = Mint::unpack(&mint_account.data).unwrap();
3765 let account = Account::unpack_unchecked(&account_account.data).unwrap();
3766 assert_eq!(account.amount, 42);
3767
3768 do_process_instruction(
3770 mint_to_checked(
3771 &program_id,
3772 &mint_key,
3773 &account_key,
3774 &owner_key,
3775 &[],
3776 42,
3777 decimals,
3778 )
3779 .unwrap(),
3780 vec![&mut mint_account, &mut account_account, &mut owner_account],
3781 )
3782 .unwrap();
3783 let _ = Mint::unpack(&mint_account.data).unwrap();
3784 let account = Account::unpack_unchecked(&account_account.data).unwrap();
3785 assert_eq!(account.amount, 84);
3786 }
3787
3788 #[test]
3789 fn test_approve_dups() {
3790 let program_id = crate::id();
3791 let account1_key = Pubkey::new_unique();
3792 let mut account1_account = SolanaAccount::new(
3793 account_minimum_balance(),
3794 Account::get_packed_len(),
3795 &program_id,
3796 );
3797 let account1_info: AccountInfo = (&account1_key, true, &mut account1_account).into();
3798 let account2_key = Pubkey::new_unique();
3799 let mut account2_account = SolanaAccount::new(
3800 account_minimum_balance(),
3801 Account::get_packed_len(),
3802 &program_id,
3803 );
3804 let account2_info: AccountInfo = (&account2_key, false, &mut account2_account).into();
3805 let account3_key = Pubkey::new_unique();
3806 let mut account3_account = SolanaAccount::new(
3807 account_minimum_balance(),
3808 Account::get_packed_len(),
3809 &program_id,
3810 );
3811 let account3_info: AccountInfo = (&account3_key, true, &mut account3_account).into();
3812 let multisig_key = Pubkey::new_unique();
3813 let mut multisig_account = SolanaAccount::new(
3814 multisig_minimum_balance(),
3815 Multisig::get_packed_len(),
3816 &program_id,
3817 );
3818 let multisig_info: AccountInfo = (&multisig_key, true, &mut multisig_account).into();
3819 let owner_key = Pubkey::new_unique();
3820 let mut owner_account = SolanaAccount::default();
3821 let owner_info: AccountInfo = (&owner_key, true, &mut owner_account).into();
3822 let mint_key = Pubkey::new_unique();
3823 let mut mint_account =
3824 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
3825 let mint_info: AccountInfo = (&mint_key, false, &mut mint_account).into();
3826 let rent_key = rent::id();
3827 let mut rent_sysvar = rent_sysvar();
3828 let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
3829
3830 do_process_instruction_dups(
3832 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
3833 vec![mint_info.clone(), rent_info.clone()],
3834 )
3835 .unwrap();
3836
3837 do_process_instruction_dups(
3839 initialize_account(&program_id, &account1_key, &mint_key, &account1_key).unwrap(),
3840 vec![
3841 account1_info.clone(),
3842 mint_info.clone(),
3843 account1_info.clone(),
3844 rent_info.clone(),
3845 ],
3846 )
3847 .unwrap();
3848
3849 do_process_instruction_dups(
3851 initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
3852 vec![
3853 account2_info.clone(),
3854 mint_info.clone(),
3855 owner_info.clone(),
3856 rent_info.clone(),
3857 ],
3858 )
3859 .unwrap();
3860
3861 do_process_instruction_dups(
3863 mint_to(&program_id, &mint_key, &account1_key, &owner_key, &[], 1000).unwrap(),
3864 vec![mint_info.clone(), account1_info.clone(), owner_info.clone()],
3865 )
3866 .unwrap();
3867
3868 do_process_instruction_dups(
3870 approve(
3871 &program_id,
3872 &account1_key,
3873 &account2_key,
3874 &account1_key,
3875 &[],
3876 500,
3877 )
3878 .unwrap(),
3879 vec![
3880 account1_info.clone(),
3881 account2_info.clone(),
3882 account1_info.clone(),
3883 ],
3884 )
3885 .unwrap();
3886
3887 do_process_instruction_dups(
3889 approve_checked(
3890 &program_id,
3891 &account1_key,
3892 &mint_key,
3893 &account2_key,
3894 &account1_key,
3895 &[],
3896 500,
3897 2,
3898 )
3899 .unwrap(),
3900 vec![
3901 account1_info.clone(),
3902 mint_info.clone(),
3903 account2_info.clone(),
3904 account1_info.clone(),
3905 ],
3906 )
3907 .unwrap();
3908
3909 do_process_instruction_dups(
3911 revoke(&program_id, &account1_key, &account1_key, &[]).unwrap(),
3912 vec![account1_info.clone(), account1_info.clone()],
3913 )
3914 .unwrap();
3915
3916 do_process_instruction_dups(
3918 initialize_multisig(&program_id, &multisig_key, &[&account3_key], 1).unwrap(),
3919 vec![
3920 multisig_info.clone(),
3921 rent_info.clone(),
3922 account3_info.clone(),
3923 ],
3924 )
3925 .unwrap();
3926
3927 do_process_instruction_dups(
3928 initialize_account(&program_id, &account3_key, &mint_key, &multisig_key).unwrap(),
3929 vec![
3930 account3_info.clone(),
3931 mint_info.clone(),
3932 multisig_info.clone(),
3933 rent_info.clone(),
3934 ],
3935 )
3936 .unwrap();
3937
3938 do_process_instruction_dups(
3939 mint_to(&program_id, &mint_key, &account3_key, &owner_key, &[], 1000).unwrap(),
3940 vec![mint_info.clone(), account3_info.clone(), owner_info.clone()],
3941 )
3942 .unwrap();
3943
3944 do_process_instruction_dups(
3946 approve(
3947 &program_id,
3948 &account3_key,
3949 &account2_key,
3950 &multisig_key,
3951 &[&account3_key],
3952 500,
3953 )
3954 .unwrap(),
3955 vec![
3956 account3_info.clone(),
3957 account2_info.clone(),
3958 multisig_info.clone(),
3959 account3_info.clone(),
3960 ],
3961 )
3962 .unwrap();
3963
3964 do_process_instruction_dups(
3966 approve_checked(
3967 &program_id,
3968 &account3_key,
3969 &mint_key,
3970 &account2_key,
3971 &multisig_key,
3972 &[&account3_key],
3973 500,
3974 2,
3975 )
3976 .unwrap(),
3977 vec![
3978 account3_info.clone(),
3979 mint_info.clone(),
3980 account2_info.clone(),
3981 multisig_info.clone(),
3982 account3_info.clone(),
3983 ],
3984 )
3985 .unwrap();
3986
3987 do_process_instruction_dups(
3989 revoke(&program_id, &account3_key, &multisig_key, &[&account3_key]).unwrap(),
3990 vec![
3991 account3_info.clone(),
3992 multisig_info.clone(),
3993 account3_info.clone(),
3994 ],
3995 )
3996 .unwrap();
3997
3998 do_process_instruction_dups(
4000 approve_checked(
4001 &program_id,
4002 &account2_key,
4003 &mint_key,
4004 &account2_key,
4005 &owner_key,
4006 &[],
4007 500,
4008 2,
4009 )
4010 .unwrap(),
4011 vec![
4012 account2_info.clone(),
4013 mint_info.clone(),
4014 account2_info.clone(),
4015 owner_info.clone(),
4016 ],
4017 )
4018 .unwrap();
4019
4020 let account2_info: AccountInfo = (&account2_key, true, &mut account2_account).into();
4022 do_process_instruction_dups(
4023 revoke(&program_id, &account2_key, &account2_key, &[]).unwrap(),
4024 vec![account2_info.clone(), account2_info.clone()],
4025 )
4026 .unwrap();
4027 }
4028
4029 #[test]
4030 fn test_approve() {
4031 let program_id = crate::id();
4032 let account_key = Pubkey::new_unique();
4033 let mut account_account = SolanaAccount::new(
4034 account_minimum_balance(),
4035 Account::get_packed_len(),
4036 &program_id,
4037 );
4038 let account2_key = Pubkey::new_unique();
4039 let mut account2_account = SolanaAccount::new(
4040 account_minimum_balance(),
4041 Account::get_packed_len(),
4042 &program_id,
4043 );
4044 let delegate_key = Pubkey::new_unique();
4045 let mut delegate_account = SolanaAccount::default();
4046 let owner_key = Pubkey::new_unique();
4047 let mut owner_account = SolanaAccount::default();
4048 let owner2_key = Pubkey::new_unique();
4049 let mut owner2_account = SolanaAccount::default();
4050 let mint_key = Pubkey::new_unique();
4051 let mut mint_account =
4052 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
4053 let mut rent_sysvar = rent_sysvar();
4054
4055 do_process_instruction(
4057 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
4058 vec![&mut mint_account, &mut rent_sysvar],
4059 )
4060 .unwrap();
4061
4062 do_process_instruction(
4064 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
4065 vec![
4066 &mut account_account,
4067 &mut mint_account,
4068 &mut owner_account,
4069 &mut rent_sysvar,
4070 ],
4071 )
4072 .unwrap();
4073
4074 do_process_instruction(
4076 initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
4077 vec![
4078 &mut account2_account,
4079 &mut mint_account,
4080 &mut owner_account,
4081 &mut rent_sysvar,
4082 ],
4083 )
4084 .unwrap();
4085
4086 do_process_instruction(
4088 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
4089 vec![&mut mint_account, &mut account_account, &mut owner_account],
4090 )
4091 .unwrap();
4092
4093 let mut instruction = approve(
4095 &program_id,
4096 &account_key,
4097 &delegate_key,
4098 &owner_key,
4099 &[],
4100 100,
4101 )
4102 .unwrap();
4103 instruction.accounts[2].is_signer = false;
4104 assert_eq!(
4105 Err(ProgramError::MissingRequiredSignature),
4106 do_process_instruction(
4107 instruction,
4108 vec![
4109 &mut account_account,
4110 &mut delegate_account,
4111 &mut owner_account,
4112 ],
4113 )
4114 );
4115
4116 assert_eq!(
4118 Err(TokenError::OwnerMismatch.into()),
4119 do_process_instruction(
4120 approve(
4121 &program_id,
4122 &account_key,
4123 &delegate_key,
4124 &owner2_key,
4125 &[],
4126 100
4127 )
4128 .unwrap(),
4129 vec![
4130 &mut account_account,
4131 &mut delegate_account,
4132 &mut owner2_account,
4133 ],
4134 )
4135 );
4136
4137 do_process_instruction(
4139 approve(
4140 &program_id,
4141 &account_key,
4142 &delegate_key,
4143 &owner_key,
4144 &[],
4145 100,
4146 )
4147 .unwrap(),
4148 vec![
4149 &mut account_account,
4150 &mut delegate_account,
4151 &mut owner_account,
4152 ],
4153 )
4154 .unwrap();
4155
4156 assert_eq!(
4158 Err(TokenError::MintDecimalsMismatch.into()),
4159 do_process_instruction(
4160 approve_checked(
4161 &program_id,
4162 &account_key,
4163 &mint_key,
4164 &delegate_key,
4165 &owner_key,
4166 &[],
4167 100,
4168 0 )
4170 .unwrap(),
4171 vec![
4172 &mut account_account,
4173 &mut mint_account,
4174 &mut delegate_account,
4175 &mut owner_account,
4176 ],
4177 )
4178 );
4179
4180 assert_eq!(
4182 Err(TokenError::MintMismatch.into()),
4183 do_process_instruction(
4184 approve_checked(
4185 &program_id,
4186 &account_key,
4187 &account2_key, &delegate_key,
4189 &owner_key,
4190 &[],
4191 100,
4192 0
4193 )
4194 .unwrap(),
4195 vec![
4196 &mut account_account,
4197 &mut account2_account, &mut delegate_account,
4199 &mut owner_account,
4200 ],
4201 )
4202 );
4203
4204 do_process_instruction(
4206 approve_checked(
4207 &program_id,
4208 &account_key,
4209 &mint_key,
4210 &delegate_key,
4211 &owner_key,
4212 &[],
4213 100,
4214 2,
4215 )
4216 .unwrap(),
4217 vec![
4218 &mut account_account,
4219 &mut mint_account,
4220 &mut delegate_account,
4221 &mut owner_account,
4222 ],
4223 )
4224 .unwrap();
4225
4226 do_process_instruction(
4228 revoke(&program_id, &account_key, &owner_key, &[]).unwrap(),
4229 vec![&mut account_account, &mut owner_account],
4230 )
4231 .unwrap();
4232
4233 do_process_instruction(
4235 approve_checked(
4236 &program_id,
4237 &account_key,
4238 &mint_key,
4239 &delegate_key,
4240 &owner_key,
4241 &[],
4242 100,
4243 2,
4244 )
4245 .unwrap(),
4246 vec![
4247 &mut account_account,
4248 &mut mint_account,
4249 &mut delegate_account,
4250 &mut owner_account,
4251 ],
4252 )
4253 .unwrap();
4254
4255 do_process_instruction(
4257 revoke(&program_id, &account_key, &delegate_key, &[]).unwrap(),
4258 vec![&mut account_account, &mut delegate_account],
4259 )
4260 .unwrap();
4261
4262 assert_eq!(
4264 Err(TokenError::OwnerMismatch.into()),
4265 do_process_instruction(
4266 revoke(&program_id, &account_key, &delegate_key, &[]).unwrap(),
4267 vec![&mut account_account, &mut delegate_account],
4268 )
4269 );
4270 }
4271
4272 #[test]
4273 fn test_set_authority_dups() {
4274 let program_id = crate::id();
4275 let account1_key = Pubkey::new_unique();
4276 let mut account1_account = SolanaAccount::new(
4277 account_minimum_balance(),
4278 Account::get_packed_len(),
4279 &program_id,
4280 );
4281 let account1_info: AccountInfo = (&account1_key, true, &mut account1_account).into();
4282 let owner_key = Pubkey::new_unique();
4283 let mint_key = Pubkey::new_unique();
4284 let mut mint_account =
4285 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
4286 let mint_info: AccountInfo = (&mint_key, true, &mut mint_account).into();
4287 let rent_key = rent::id();
4288 let mut rent_sysvar = rent_sysvar();
4289 let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
4290
4291 do_process_instruction_dups(
4293 initialize_mint(&program_id, &mint_key, &mint_key, Some(&mint_key), 2).unwrap(),
4294 vec![mint_info.clone(), rent_info.clone()],
4295 )
4296 .unwrap();
4297
4298 do_process_instruction_dups(
4300 initialize_account(&program_id, &account1_key, &mint_key, &account1_key).unwrap(),
4301 vec![
4302 account1_info.clone(),
4303 mint_info.clone(),
4304 account1_info.clone(),
4305 rent_info.clone(),
4306 ],
4307 )
4308 .unwrap();
4309
4310 do_process_instruction_dups(
4312 set_authority(
4313 &program_id,
4314 &mint_key,
4315 Some(&owner_key),
4316 AuthorityType::MintTokens,
4317 &mint_key,
4318 &[],
4319 )
4320 .unwrap(),
4321 vec![mint_info.clone(), mint_info.clone()],
4322 )
4323 .unwrap();
4324
4325 do_process_instruction_dups(
4327 set_authority(
4328 &program_id,
4329 &mint_key,
4330 Some(&owner_key),
4331 AuthorityType::FreezeAccount,
4332 &mint_key,
4333 &[],
4334 )
4335 .unwrap(),
4336 vec![mint_info.clone(), mint_info.clone()],
4337 )
4338 .unwrap();
4339
4340 do_process_instruction_dups(
4342 set_authority(
4343 &program_id,
4344 &account1_key,
4345 Some(&owner_key),
4346 AuthorityType::AccountOwner,
4347 &account1_key,
4348 &[],
4349 )
4350 .unwrap(),
4351 vec![account1_info.clone(), account1_info.clone()],
4352 )
4353 .unwrap();
4354
4355 let mut account = Account::unpack_unchecked(&account1_info.data.borrow()).unwrap();
4357 account.close_authority = COption::Some(account1_key);
4358 Account::pack(account, &mut account1_info.data.borrow_mut()).unwrap();
4359
4360 do_process_instruction_dups(
4361 set_authority(
4362 &program_id,
4363 &account1_key,
4364 Some(&owner_key),
4365 AuthorityType::CloseAccount,
4366 &account1_key,
4367 &[],
4368 )
4369 .unwrap(),
4370 vec![account1_info.clone(), account1_info.clone()],
4371 )
4372 .unwrap();
4373 }
4374
4375 #[test]
4376 fn test_set_authority() {
4377 let program_id = crate::id();
4378 let account_key = Pubkey::new_unique();
4379 let mut account_account = SolanaAccount::new(
4380 account_minimum_balance(),
4381 Account::get_packed_len(),
4382 &program_id,
4383 );
4384 let account2_key = Pubkey::new_unique();
4385 let mut account2_account = SolanaAccount::new(
4386 account_minimum_balance(),
4387 Account::get_packed_len(),
4388 &program_id,
4389 );
4390 let owner_key = Pubkey::new_unique();
4391 let mut owner_account = SolanaAccount::default();
4392 let owner2_key = Pubkey::new_unique();
4393 let mut owner2_account = SolanaAccount::default();
4394 let owner3_key = Pubkey::new_unique();
4395 let mut owner3_account = SolanaAccount::default();
4396 let mint_key = Pubkey::new_unique();
4397 let mut mint_account =
4398 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
4399 let mint2_key = Pubkey::new_unique();
4400 let mut mint2_account =
4401 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
4402 let mut rent_sysvar = rent_sysvar();
4403
4404 do_process_instruction(
4406 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
4407 vec![&mut mint_account, &mut rent_sysvar],
4408 )
4409 .unwrap();
4410
4411 do_process_instruction(
4413 initialize_mint(&program_id, &mint2_key, &owner_key, Some(&owner_key), 2).unwrap(),
4414 vec![&mut mint2_account, &mut rent_sysvar],
4415 )
4416 .unwrap();
4417
4418 assert_eq!(
4420 Err(ProgramError::InvalidAccountData),
4421 do_process_instruction(
4422 set_authority(
4423 &program_id,
4424 &account_key,
4425 Some(&owner2_key),
4426 AuthorityType::AccountOwner,
4427 &owner_key,
4428 &[]
4429 )
4430 .unwrap(),
4431 vec![&mut account_account, &mut owner_account],
4432 )
4433 );
4434
4435 do_process_instruction(
4437 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
4438 vec![
4439 &mut account_account,
4440 &mut mint_account,
4441 &mut owner_account,
4442 &mut rent_sysvar,
4443 ],
4444 )
4445 .unwrap();
4446
4447 do_process_instruction(
4449 initialize_account(&program_id, &account2_key, &mint2_key, &owner_key).unwrap(),
4450 vec![
4451 &mut account2_account,
4452 &mut mint2_account,
4453 &mut owner_account,
4454 &mut rent_sysvar,
4455 ],
4456 )
4457 .unwrap();
4458
4459 assert_eq!(
4461 Err(TokenError::OwnerMismatch.into()),
4462 do_process_instruction(
4463 set_authority(
4464 &program_id,
4465 &account_key,
4466 Some(&owner_key),
4467 AuthorityType::AccountOwner,
4468 &owner2_key,
4469 &[]
4470 )
4471 .unwrap(),
4472 vec![&mut account_account, &mut owner2_account],
4473 )
4474 );
4475
4476 let mut instruction = set_authority(
4478 &program_id,
4479 &account_key,
4480 Some(&owner2_key),
4481 AuthorityType::AccountOwner,
4482 &owner_key,
4483 &[],
4484 )
4485 .unwrap();
4486 instruction.accounts[1].is_signer = false;
4487 assert_eq!(
4488 Err(ProgramError::MissingRequiredSignature),
4489 do_process_instruction(instruction, vec![&mut account_account, &mut owner_account,],)
4490 );
4491
4492 assert_eq!(
4494 Err(TokenError::AuthorityTypeNotSupported.into()),
4495 do_process_instruction(
4496 set_authority(
4497 &program_id,
4498 &account_key,
4499 Some(&owner2_key),
4500 AuthorityType::FreezeAccount,
4501 &owner_key,
4502 &[],
4503 )
4504 .unwrap(),
4505 vec![&mut account_account, &mut owner_account],
4506 )
4507 );
4508
4509 assert_eq!(
4511 Err(TokenError::InvalidInstruction.into()),
4512 do_process_instruction(
4513 set_authority(
4514 &program_id,
4515 &account_key,
4516 None,
4517 AuthorityType::AccountOwner,
4518 &owner_key,
4519 &[],
4520 )
4521 .unwrap(),
4522 vec![&mut account_account, &mut owner_account],
4523 )
4524 );
4525
4526 do_process_instruction(
4528 approve(
4529 &program_id,
4530 &account_key,
4531 &owner2_key,
4532 &owner_key,
4533 &[],
4534 u64::MAX,
4535 )
4536 .unwrap(),
4537 vec![
4538 &mut account_account,
4539 &mut owner2_account,
4540 &mut owner_account,
4541 ],
4542 )
4543 .unwrap();
4544 let account = Account::unpack_unchecked(&account_account.data).unwrap();
4545 assert_eq!(account.delegate, COption::Some(owner2_key));
4546 assert_eq!(account.delegated_amount, u64::MAX);
4547
4548 do_process_instruction(
4550 set_authority(
4551 &program_id,
4552 &account_key,
4553 Some(&owner3_key),
4554 AuthorityType::AccountOwner,
4555 &owner_key,
4556 &[],
4557 )
4558 .unwrap(),
4559 vec![&mut account_account, &mut owner_account],
4560 )
4561 .unwrap();
4562
4563 let account = Account::unpack_unchecked(&account_account.data).unwrap();
4565 assert_eq!(account.delegate, COption::None);
4566 assert_eq!(account.delegated_amount, 0);
4567
4568 do_process_instruction(
4570 set_authority(
4571 &program_id,
4572 &account_key,
4573 Some(&owner2_key),
4574 AuthorityType::AccountOwner,
4575 &owner3_key,
4576 &[],
4577 )
4578 .unwrap(),
4579 vec![&mut account_account, &mut owner3_account],
4580 )
4581 .unwrap();
4582
4583 do_process_instruction(
4585 set_authority(
4586 &program_id,
4587 &account_key,
4588 Some(&owner2_key),
4589 AuthorityType::CloseAccount,
4590 &owner2_key,
4591 &[],
4592 )
4593 .unwrap(),
4594 vec![&mut account_account, &mut owner2_account],
4595 )
4596 .unwrap();
4597
4598 do_process_instruction(
4600 set_authority(
4601 &program_id,
4602 &account_key,
4603 None,
4604 AuthorityType::CloseAccount,
4605 &owner2_key,
4606 &[],
4607 )
4608 .unwrap(),
4609 vec![&mut account_account, &mut owner2_account],
4610 )
4611 .unwrap();
4612
4613 assert_eq!(
4615 Err(TokenError::OwnerMismatch.into()),
4616 do_process_instruction(
4617 set_authority(
4618 &program_id,
4619 &mint_key,
4620 Some(&owner3_key),
4621 AuthorityType::MintTokens,
4622 &owner2_key,
4623 &[]
4624 )
4625 .unwrap(),
4626 vec![&mut mint_account, &mut owner2_account],
4627 )
4628 );
4629
4630 let mut instruction = set_authority(
4632 &program_id,
4633 &mint_key,
4634 Some(&owner2_key),
4635 AuthorityType::MintTokens,
4636 &owner_key,
4637 &[],
4638 )
4639 .unwrap();
4640 instruction.accounts[1].is_signer = false;
4641 assert_eq!(
4642 Err(ProgramError::MissingRequiredSignature),
4643 do_process_instruction(instruction, vec![&mut mint_account, &mut owner_account],)
4644 );
4645
4646 assert_eq!(
4648 Err(TokenError::MintCannotFreeze.into()),
4649 do_process_instruction(
4650 set_authority(
4651 &program_id,
4652 &mint_key,
4653 Some(&owner2_key),
4654 AuthorityType::FreezeAccount,
4655 &owner_key,
4656 &[],
4657 )
4658 .unwrap(),
4659 vec![&mut mint_account, &mut owner_account],
4660 )
4661 );
4662
4663 do_process_instruction(
4665 set_authority(
4666 &program_id,
4667 &mint_key,
4668 Some(&owner2_key),
4669 AuthorityType::MintTokens,
4670 &owner_key,
4671 &[],
4672 )
4673 .unwrap(),
4674 vec![&mut mint_account, &mut owner_account],
4675 )
4676 .unwrap();
4677
4678 do_process_instruction(
4680 set_authority(
4681 &program_id,
4682 &mint_key,
4683 None,
4684 AuthorityType::MintTokens,
4685 &owner2_key,
4686 &[],
4687 )
4688 .unwrap(),
4689 vec![&mut mint_account, &mut owner2_account],
4690 )
4691 .unwrap();
4692
4693 assert_eq!(
4695 Err(TokenError::FixedSupply.into()),
4696 do_process_instruction(
4697 set_authority(
4698 &program_id,
4699 &mint2_key,
4700 Some(&owner2_key),
4701 AuthorityType::MintTokens,
4702 &owner_key,
4703 &[]
4704 )
4705 .unwrap(),
4706 vec![&mut mint_account, &mut owner_account],
4707 )
4708 );
4709
4710 do_process_instruction(
4712 set_authority(
4713 &program_id,
4714 &mint2_key,
4715 Some(&owner2_key),
4716 AuthorityType::FreezeAccount,
4717 &owner_key,
4718 &[],
4719 )
4720 .unwrap(),
4721 vec![&mut mint2_account, &mut owner_account],
4722 )
4723 .unwrap();
4724
4725 do_process_instruction(
4727 set_authority(
4728 &program_id,
4729 &mint2_key,
4730 None,
4731 AuthorityType::FreezeAccount,
4732 &owner2_key,
4733 &[],
4734 )
4735 .unwrap(),
4736 vec![&mut mint2_account, &mut owner2_account],
4737 )
4738 .unwrap();
4739
4740 assert_eq!(
4741 Err(TokenError::MintCannotFreeze.into()),
4742 do_process_instruction(
4743 set_authority(
4744 &program_id,
4745 &mint2_key,
4746 Some(&owner2_key),
4747 AuthorityType::FreezeAccount,
4748 &owner_key,
4749 &[],
4750 )
4751 .unwrap(),
4752 vec![&mut mint2_account, &mut owner2_account],
4753 )
4754 );
4755 }
4756
4757 #[test]
4758 fn test_set_authority_with_immutable_owner_extension() {
4759 let program_id = crate::id();
4760 let account_key = Pubkey::new_unique();
4761
4762 let account_len =
4763 ExtensionType::try_calculate_account_len::<Account>(&[ExtensionType::ImmutableOwner])
4764 .unwrap();
4765 let mut account_account = SolanaAccount::new(
4766 Rent::default().minimum_balance(account_len),
4767 account_len,
4768 &program_id,
4769 );
4770 let owner_key = Pubkey::new_unique();
4771 let mut owner_account = SolanaAccount::default();
4772 let owner2_key = Pubkey::new_unique();
4773
4774 let mint_key = Pubkey::new_unique();
4775 let mut mint_account =
4776 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
4777 let mut rent_sysvar = rent_sysvar();
4778
4779 assert_eq!(
4781 Ok(()),
4782 do_process_instruction(
4783 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
4784 vec![&mut mint_account, &mut rent_sysvar],
4785 )
4786 );
4787
4788 assert_eq!(
4790 Ok(()),
4791 do_process_instruction(
4792 initialize_immutable_owner(&program_id, &account_key).unwrap(),
4793 vec![&mut account_account],
4794 )
4795 );
4796 assert_eq!(
4797 Ok(()),
4798 do_process_instruction(
4799 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
4800 vec![
4801 &mut account_account,
4802 &mut mint_account,
4803 &mut owner_account,
4804 &mut rent_sysvar,
4805 ],
4806 )
4807 );
4808
4809 assert_eq!(
4811 Err(TokenError::ImmutableOwner.into()),
4812 do_process_instruction(
4813 set_authority(
4814 &program_id,
4815 &account_key,
4816 Some(&owner2_key),
4817 AuthorityType::AccountOwner,
4818 &owner_key,
4819 &[],
4820 )
4821 .unwrap(),
4822 vec![&mut account_account, &mut owner_account],
4823 )
4824 );
4825 }
4826
4827 #[test]
4828 fn test_mint_to_dups() {
4829 let program_id = crate::id();
4830 let account1_key = Pubkey::new_unique();
4831 let mut account1_account = SolanaAccount::new(
4832 account_minimum_balance(),
4833 Account::get_packed_len(),
4834 &program_id,
4835 );
4836 let account1_info: AccountInfo = (&account1_key, true, &mut account1_account).into();
4837 let owner_key = Pubkey::new_unique();
4838 let mut owner_account = SolanaAccount::default();
4839 let owner_info: AccountInfo = (&owner_key, true, &mut owner_account).into();
4840 let mint_key = Pubkey::new_unique();
4841 let mut mint_account =
4842 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
4843 let mint_info: AccountInfo = (&mint_key, true, &mut mint_account).into();
4844 let rent_key = rent::id();
4845 let mut rent_sysvar = rent_sysvar();
4846 let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
4847
4848 do_process_instruction_dups(
4850 initialize_mint(&program_id, &mint_key, &mint_key, None, 2).unwrap(),
4851 vec![mint_info.clone(), rent_info.clone()],
4852 )
4853 .unwrap();
4854
4855 do_process_instruction_dups(
4857 initialize_account(&program_id, &account1_key, &mint_key, &owner_key).unwrap(),
4858 vec![
4859 account1_info.clone(),
4860 mint_info.clone(),
4861 owner_info.clone(),
4862 rent_info.clone(),
4863 ],
4864 )
4865 .unwrap();
4866
4867 do_process_instruction_dups(
4869 mint_to(&program_id, &mint_key, &account1_key, &mint_key, &[], 42).unwrap(),
4870 vec![mint_info.clone(), account1_info.clone(), mint_info.clone()],
4871 )
4872 .unwrap();
4873
4874 do_process_instruction_dups(
4876 mint_to_checked(&program_id, &mint_key, &account1_key, &mint_key, &[], 42, 2).unwrap(),
4877 vec![mint_info.clone(), account1_info.clone(), mint_info.clone()],
4878 )
4879 .unwrap();
4880
4881 let mut mint = Mint::unpack_unchecked(&mint_info.data.borrow()).unwrap();
4883 mint.mint_authority = COption::Some(account1_key);
4884 Mint::pack(mint, &mut mint_info.data.borrow_mut()).unwrap();
4885 do_process_instruction_dups(
4886 mint_to(
4887 &program_id,
4888 &mint_key,
4889 &account1_key,
4890 &account1_key,
4891 &[],
4892 42,
4893 )
4894 .unwrap(),
4895 vec![
4896 mint_info.clone(),
4897 account1_info.clone(),
4898 account1_info.clone(),
4899 ],
4900 )
4901 .unwrap();
4902
4903 do_process_instruction_dups(
4905 mint_to(
4906 &program_id,
4907 &mint_key,
4908 &account1_key,
4909 &account1_key,
4910 &[],
4911 42,
4912 )
4913 .unwrap(),
4914 vec![
4915 mint_info.clone(),
4916 account1_info.clone(),
4917 account1_info.clone(),
4918 ],
4919 )
4920 .unwrap();
4921 }
4922
4923 #[test]
4924 fn test_mint_to() {
4925 let program_id = crate::id();
4926 let account_key = Pubkey::new_unique();
4927 let mut account_account = SolanaAccount::new(
4928 account_minimum_balance(),
4929 Account::get_packed_len(),
4930 &program_id,
4931 );
4932 let account2_key = Pubkey::new_unique();
4933 let mut account2_account = SolanaAccount::new(
4934 account_minimum_balance(),
4935 Account::get_packed_len(),
4936 &program_id,
4937 );
4938 let account3_key = Pubkey::new_unique();
4939 let mut account3_account = SolanaAccount::new(
4940 account_minimum_balance(),
4941 Account::get_packed_len(),
4942 &program_id,
4943 );
4944 let mismatch_key = Pubkey::new_unique();
4945 let mut mismatch_account = SolanaAccount::new(
4946 account_minimum_balance(),
4947 Account::get_packed_len(),
4948 &program_id,
4949 );
4950 let owner_key = Pubkey::new_unique();
4951 let mut owner_account = SolanaAccount::default();
4952 let owner2_key = Pubkey::new_unique();
4953 let mut owner2_account = SolanaAccount::default();
4954 let mint_key = Pubkey::new_unique();
4955 let mut mint_account =
4956 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
4957 let mint2_key = Pubkey::new_unique();
4958 let uninitialized_key = Pubkey::new_unique();
4959 let mut uninitialized_account = SolanaAccount::new(
4960 account_minimum_balance(),
4961 Account::get_packed_len(),
4962 &program_id,
4963 );
4964 let mut rent_sysvar = rent_sysvar();
4965
4966 do_process_instruction(
4968 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
4969 vec![&mut mint_account, &mut rent_sysvar],
4970 )
4971 .unwrap();
4972
4973 do_process_instruction(
4975 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
4976 vec![
4977 &mut account_account,
4978 &mut mint_account,
4979 &mut owner_account,
4980 &mut rent_sysvar,
4981 ],
4982 )
4983 .unwrap();
4984
4985 do_process_instruction(
4987 initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
4988 vec![
4989 &mut account2_account,
4990 &mut mint_account,
4991 &mut owner_account,
4992 &mut rent_sysvar,
4993 ],
4994 )
4995 .unwrap();
4996
4997 do_process_instruction(
4999 initialize_account(&program_id, &account3_key, &mint_key, &owner_key).unwrap(),
5000 vec![
5001 &mut account3_account,
5002 &mut mint_account,
5003 &mut owner_account,
5004 &mut rent_sysvar,
5005 ],
5006 )
5007 .unwrap();
5008
5009 do_process_instruction(
5011 initialize_account(&program_id, &mismatch_key, &mint_key, &owner_key).unwrap(),
5012 vec![
5013 &mut mismatch_account,
5014 &mut mint_account,
5015 &mut owner_account,
5016 &mut rent_sysvar,
5017 ],
5018 )
5019 .unwrap();
5020 let mut account = Account::unpack_unchecked(&mismatch_account.data).unwrap();
5021 account.mint = mint2_key;
5022 Account::pack(account, &mut mismatch_account.data).unwrap();
5023
5024 do_process_instruction(
5026 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 42).unwrap(),
5027 vec![&mut mint_account, &mut account_account, &mut owner_account],
5028 )
5029 .unwrap();
5030
5031 let mint = Mint::unpack_unchecked(&mint_account.data).unwrap();
5032 assert_eq!(mint.supply, 42);
5033 let account = Account::unpack_unchecked(&account_account.data).unwrap();
5034 assert_eq!(account.amount, 42);
5035
5036 do_process_instruction(
5038 mint_to(&program_id, &mint_key, &account2_key, &owner_key, &[], 42).unwrap(),
5039 vec![&mut mint_account, &mut account2_account, &mut owner_account],
5040 )
5041 .unwrap();
5042
5043 let mint = Mint::unpack_unchecked(&mint_account.data).unwrap();
5044 assert_eq!(mint.supply, 84);
5045 let account = Account::unpack_unchecked(&account2_account.data).unwrap();
5046 assert_eq!(account.amount, 42);
5047
5048 let mut instruction =
5050 mint_to(&program_id, &mint_key, &account2_key, &owner_key, &[], 42).unwrap();
5051 instruction.accounts[2].is_signer = false;
5052 assert_eq!(
5053 Err(ProgramError::MissingRequiredSignature),
5054 do_process_instruction(
5055 instruction,
5056 vec![&mut mint_account, &mut account2_account, &mut owner_account],
5057 )
5058 );
5059
5060 assert_eq!(
5062 Err(TokenError::MintMismatch.into()),
5063 do_process_instruction(
5064 mint_to(&program_id, &mint_key, &mismatch_key, &owner_key, &[], 42).unwrap(),
5065 vec![&mut mint_account, &mut mismatch_account, &mut owner_account],
5066 )
5067 );
5068
5069 assert_eq!(
5071 Err(TokenError::OwnerMismatch.into()),
5072 do_process_instruction(
5073 mint_to(&program_id, &mint_key, &account2_key, &owner2_key, &[], 42).unwrap(),
5074 vec![
5075 &mut mint_account,
5076 &mut account2_account,
5077 &mut owner2_account,
5078 ],
5079 )
5080 );
5081
5082 let not_program_id = Pubkey::new_unique();
5084 mint_account.owner = not_program_id;
5085 assert_eq!(
5086 Err(ProgramError::IncorrectProgramId),
5087 do_process_instruction(
5088 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 0).unwrap(),
5089 vec![&mut mint_account, &mut account_account, &mut owner_account],
5090 )
5091 );
5092 mint_account.owner = program_id;
5093
5094 let not_program_id = Pubkey::new_unique();
5096 account_account.owner = not_program_id;
5097 assert_eq!(
5098 Err(ProgramError::IncorrectProgramId),
5099 do_process_instruction(
5100 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 0).unwrap(),
5101 vec![&mut mint_account, &mut account_account, &mut owner_account],
5102 )
5103 );
5104 account_account.owner = program_id;
5105
5106 assert_eq!(
5108 Err(ProgramError::UninitializedAccount),
5109 do_process_instruction(
5110 mint_to(
5111 &program_id,
5112 &mint_key,
5113 &uninitialized_key,
5114 &owner_key,
5115 &[],
5116 42
5117 )
5118 .unwrap(),
5119 vec![
5120 &mut mint_account,
5121 &mut uninitialized_account,
5122 &mut owner_account,
5123 ],
5124 )
5125 );
5126
5127 do_process_instruction(
5129 set_authority(
5130 &program_id,
5131 &mint_key,
5132 None,
5133 AuthorityType::MintTokens,
5134 &owner_key,
5135 &[],
5136 )
5137 .unwrap(),
5138 vec![&mut mint_account, &mut owner_account],
5139 )
5140 .unwrap();
5141 assert_eq!(
5142 Err(TokenError::FixedSupply.into()),
5143 do_process_instruction(
5144 mint_to(&program_id, &mint_key, &account2_key, &owner_key, &[], 42).unwrap(),
5145 vec![&mut mint_account, &mut account2_account, &mut owner_account],
5146 )
5147 );
5148 }
5149
5150 #[test]
5151 fn test_burn_dups() {
5152 let program_id = crate::id();
5153 let account1_key = Pubkey::new_unique();
5154 let mut account1_account = SolanaAccount::new(
5155 account_minimum_balance(),
5156 Account::get_packed_len(),
5157 &program_id,
5158 );
5159 let account1_info: AccountInfo = (&account1_key, true, &mut account1_account).into();
5160 let owner_key = Pubkey::new_unique();
5161 let mut owner_account = SolanaAccount::default();
5162 let owner_info: AccountInfo = (&owner_key, true, &mut owner_account).into();
5163 let mint_key = Pubkey::new_unique();
5164 let mut mint_account =
5165 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
5166 let mint_info: AccountInfo = (&mint_key, true, &mut mint_account).into();
5167 let rent_key = rent::id();
5168 let mut rent_sysvar = rent_sysvar();
5169 let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
5170
5171 do_process_instruction_dups(
5173 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
5174 vec![mint_info.clone(), rent_info.clone()],
5175 )
5176 .unwrap();
5177
5178 do_process_instruction_dups(
5180 initialize_account(&program_id, &account1_key, &mint_key, &account1_key).unwrap(),
5181 vec![
5182 account1_info.clone(),
5183 mint_info.clone(),
5184 account1_info.clone(),
5185 rent_info.clone(),
5186 ],
5187 )
5188 .unwrap();
5189
5190 do_process_instruction_dups(
5192 mint_to(&program_id, &mint_key, &account1_key, &owner_key, &[], 1000).unwrap(),
5193 vec![mint_info.clone(), account1_info.clone(), owner_info.clone()],
5194 )
5195 .unwrap();
5196
5197 do_process_instruction_dups(
5199 burn(
5200 &program_id,
5201 &mint_key,
5202 &account1_key,
5203 &account1_key,
5204 &[],
5205 500,
5206 )
5207 .unwrap(),
5208 vec![
5209 account1_info.clone(),
5210 mint_info.clone(),
5211 account1_info.clone(),
5212 ],
5213 )
5214 .unwrap();
5215
5216 do_process_instruction_dups(
5218 burn_checked(
5219 &program_id,
5220 &account1_key,
5221 &mint_key,
5222 &account1_key,
5223 &[],
5224 500,
5225 2,
5226 )
5227 .unwrap(),
5228 vec![
5229 account1_info.clone(),
5230 mint_info.clone(),
5231 account1_info.clone(),
5232 ],
5233 )
5234 .unwrap();
5235
5236 do_process_instruction_dups(
5238 mint_to(&program_id, &mint_key, &account1_key, &owner_key, &[], 1000).unwrap(),
5239 vec![mint_info.clone(), account1_info.clone(), owner_info.clone()],
5240 )
5241 .unwrap();
5242 let mut account = Account::unpack_unchecked(&account1_info.data.borrow()).unwrap();
5243 account.owner = mint_key;
5244 Account::pack(account, &mut account1_info.data.borrow_mut()).unwrap();
5245 do_process_instruction_dups(
5246 burn(&program_id, &account1_key, &mint_key, &mint_key, &[], 500).unwrap(),
5247 vec![account1_info.clone(), mint_info.clone(), mint_info.clone()],
5248 )
5249 .unwrap();
5250
5251 do_process_instruction_dups(
5253 burn_checked(
5254 &program_id,
5255 &account1_key,
5256 &mint_key,
5257 &mint_key,
5258 &[],
5259 500,
5260 2,
5261 )
5262 .unwrap(),
5263 vec![account1_info.clone(), mint_info.clone(), mint_info.clone()],
5264 )
5265 .unwrap();
5266
5267 do_process_instruction_dups(
5269 mint_to(&program_id, &mint_key, &account1_key, &owner_key, &[], 1000).unwrap(),
5270 vec![mint_info.clone(), account1_info.clone(), owner_info.clone()],
5271 )
5272 .unwrap();
5273 let mut account = Account::unpack_unchecked(&account1_info.data.borrow()).unwrap();
5274 account.delegated_amount = 1000;
5275 account.delegate = COption::Some(account1_key);
5276 account.owner = owner_key;
5277 Account::pack(account, &mut account1_info.data.borrow_mut()).unwrap();
5278 do_process_instruction_dups(
5279 burn(
5280 &program_id,
5281 &account1_key,
5282 &mint_key,
5283 &account1_key,
5284 &[],
5285 500,
5286 )
5287 .unwrap(),
5288 vec![
5289 account1_info.clone(),
5290 mint_info.clone(),
5291 account1_info.clone(),
5292 ],
5293 )
5294 .unwrap();
5295
5296 do_process_instruction_dups(
5298 burn_checked(
5299 &program_id,
5300 &account1_key,
5301 &mint_key,
5302 &account1_key,
5303 &[],
5304 500,
5305 2,
5306 )
5307 .unwrap(),
5308 vec![
5309 account1_info.clone(),
5310 mint_info.clone(),
5311 account1_info.clone(),
5312 ],
5313 )
5314 .unwrap();
5315
5316 do_process_instruction_dups(
5318 mint_to(&program_id, &mint_key, &account1_key, &owner_key, &[], 1000).unwrap(),
5319 vec![mint_info.clone(), account1_info.clone(), owner_info.clone()],
5320 )
5321 .unwrap();
5322 let mut account = Account::unpack_unchecked(&account1_info.data.borrow()).unwrap();
5323 account.delegated_amount = 1000;
5324 account.delegate = COption::Some(mint_key);
5325 account.owner = owner_key;
5326 Account::pack(account, &mut account1_info.data.borrow_mut()).unwrap();
5327 do_process_instruction_dups(
5328 burn(&program_id, &account1_key, &mint_key, &mint_key, &[], 500).unwrap(),
5329 vec![account1_info.clone(), mint_info.clone(), mint_info.clone()],
5330 )
5331 .unwrap();
5332
5333 do_process_instruction_dups(
5335 burn_checked(
5336 &program_id,
5337 &account1_key,
5338 &mint_key,
5339 &mint_key,
5340 &[],
5341 500,
5342 2,
5343 )
5344 .unwrap(),
5345 vec![account1_info.clone(), mint_info.clone(), mint_info.clone()],
5346 )
5347 .unwrap();
5348 }
5349
5350 #[test]
5351 fn test_burn() {
5352 let program_id = crate::id();
5353 let account_key = Pubkey::new_unique();
5354 let mut account_account = SolanaAccount::new(
5355 account_minimum_balance(),
5356 Account::get_packed_len(),
5357 &program_id,
5358 );
5359 let account2_key = Pubkey::new_unique();
5360 let mut account2_account = SolanaAccount::new(
5361 account_minimum_balance(),
5362 Account::get_packed_len(),
5363 &program_id,
5364 );
5365 let account3_key = Pubkey::new_unique();
5366 let mut account3_account = SolanaAccount::new(
5367 account_minimum_balance(),
5368 Account::get_packed_len(),
5369 &program_id,
5370 );
5371 let delegate_key = Pubkey::new_unique();
5372 let mut delegate_account = SolanaAccount::default();
5373 let mismatch_key = Pubkey::new_unique();
5374 let mut mismatch_account = SolanaAccount::new(
5375 account_minimum_balance(),
5376 Account::get_packed_len(),
5377 &program_id,
5378 );
5379 let owner_key = Pubkey::new_unique();
5380 let mut owner_account = SolanaAccount::default();
5381 let owner2_key = Pubkey::new_unique();
5382 let mut owner2_account = SolanaAccount::default();
5383 let mint_key = Pubkey::new_unique();
5384 let mut mint_account =
5385 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
5386 let mint2_key = Pubkey::new_unique();
5387 let mut rent_sysvar = rent_sysvar();
5388
5389 do_process_instruction(
5391 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
5392 vec![&mut mint_account, &mut rent_sysvar],
5393 )
5394 .unwrap();
5395
5396 do_process_instruction(
5398 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
5399 vec![
5400 &mut account_account,
5401 &mut mint_account,
5402 &mut owner_account,
5403 &mut rent_sysvar,
5404 ],
5405 )
5406 .unwrap();
5407
5408 do_process_instruction(
5410 initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
5411 vec![
5412 &mut account2_account,
5413 &mut mint_account,
5414 &mut owner_account,
5415 &mut rent_sysvar,
5416 ],
5417 )
5418 .unwrap();
5419
5420 do_process_instruction(
5422 initialize_account(&program_id, &account3_key, &mint_key, &owner_key).unwrap(),
5423 vec![
5424 &mut account3_account,
5425 &mut mint_account,
5426 &mut owner_account,
5427 &mut rent_sysvar,
5428 ],
5429 )
5430 .unwrap();
5431
5432 do_process_instruction(
5434 initialize_account(&program_id, &mismatch_key, &mint_key, &owner_key).unwrap(),
5435 vec![
5436 &mut mismatch_account,
5437 &mut mint_account,
5438 &mut owner_account,
5439 &mut rent_sysvar,
5440 ],
5441 )
5442 .unwrap();
5443
5444 do_process_instruction(
5446 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
5447 vec![&mut mint_account, &mut account_account, &mut owner_account],
5448 )
5449 .unwrap();
5450
5451 do_process_instruction(
5453 mint_to(&program_id, &mint_key, &mismatch_key, &owner_key, &[], 1000).unwrap(),
5454 vec![&mut mint_account, &mut mismatch_account, &mut owner_account],
5455 )
5456 .unwrap();
5457 let mut account = Account::unpack_unchecked(&mismatch_account.data).unwrap();
5458 account.mint = mint2_key;
5459 Account::pack(account, &mut mismatch_account.data).unwrap();
5460
5461 let mut instruction =
5463 burn(&program_id, &account_key, &mint_key, &delegate_key, &[], 42).unwrap();
5464 instruction.accounts[1].is_signer = false;
5465 assert_eq!(
5466 Err(TokenError::OwnerMismatch.into()),
5467 do_process_instruction(
5468 instruction,
5469 vec![
5470 &mut account_account,
5471 &mut mint_account,
5472 &mut delegate_account
5473 ],
5474 )
5475 );
5476
5477 assert_eq!(
5479 Err(TokenError::OwnerMismatch.into()),
5480 do_process_instruction(
5481 burn(&program_id, &account_key, &mint_key, &owner2_key, &[], 42).unwrap(),
5482 vec![&mut account_account, &mut mint_account, &mut owner2_account],
5483 )
5484 );
5485
5486 let not_program_id = Pubkey::new_unique();
5488 account_account.owner = not_program_id;
5489 assert_eq!(
5490 Err(ProgramError::IncorrectProgramId),
5491 do_process_instruction(
5492 burn(&program_id, &account_key, &mint_key, &owner_key, &[], 0).unwrap(),
5493 vec![&mut account_account, &mut mint_account, &mut owner_account],
5494 )
5495 );
5496 account_account.owner = program_id;
5497
5498 let not_program_id = Pubkey::new_unique();
5500 mint_account.owner = not_program_id;
5501 assert_eq!(
5502 Err(ProgramError::IncorrectProgramId),
5503 do_process_instruction(
5504 burn(&program_id, &account_key, &mint_key, &owner_key, &[], 0).unwrap(),
5505 vec![&mut account_account, &mut mint_account, &mut owner_account],
5506 )
5507 );
5508 mint_account.owner = program_id;
5509
5510 assert_eq!(
5512 Err(TokenError::MintMismatch.into()),
5513 do_process_instruction(
5514 burn(&program_id, &mismatch_key, &mint_key, &owner_key, &[], 42).unwrap(),
5515 vec![&mut mismatch_account, &mut mint_account, &mut owner_account],
5516 )
5517 );
5518
5519 do_process_instruction(
5521 burn(&program_id, &account_key, &mint_key, &owner_key, &[], 21).unwrap(),
5522 vec![&mut account_account, &mut mint_account, &mut owner_account],
5523 )
5524 .unwrap();
5525
5526 assert_eq!(
5528 Err(TokenError::MintDecimalsMismatch.into()),
5529 do_process_instruction(
5530 burn_checked(&program_id, &account_key, &mint_key, &owner_key, &[], 21, 3).unwrap(),
5531 vec![&mut account_account, &mut mint_account, &mut owner_account],
5532 )
5533 );
5534
5535 do_process_instruction(
5537 burn_checked(&program_id, &account_key, &mint_key, &owner_key, &[], 21, 2).unwrap(),
5538 vec![&mut account_account, &mut mint_account, &mut owner_account],
5539 )
5540 .unwrap();
5541
5542 let mint = Mint::unpack_unchecked(&mint_account.data).unwrap();
5543 assert_eq!(mint.supply, 2000 - 42);
5544 let account = Account::unpack_unchecked(&account_account.data).unwrap();
5545 assert_eq!(account.amount, 1000 - 42);
5546
5547 assert_eq!(
5549 Err(TokenError::InsufficientFunds.into()),
5550 do_process_instruction(
5551 burn(
5552 &program_id,
5553 &account_key,
5554 &mint_key,
5555 &owner_key,
5556 &[],
5557 100_000_000
5558 )
5559 .unwrap(),
5560 vec![&mut account_account, &mut mint_account, &mut owner_account],
5561 )
5562 );
5563
5564 do_process_instruction(
5566 approve(
5567 &program_id,
5568 &account_key,
5569 &delegate_key,
5570 &owner_key,
5571 &[],
5572 84,
5573 )
5574 .unwrap(),
5575 vec![
5576 &mut account_account,
5577 &mut delegate_account,
5578 &mut owner_account,
5579 ],
5580 )
5581 .unwrap();
5582
5583 assert_eq!(
5585 Err(TokenError::OwnerMismatch.into()),
5586 do_process_instruction(
5587 burn(
5588 &program_id,
5589 &account_key,
5590 &mint_key,
5591 &owner2_key, &[],
5593 1,
5594 )
5595 .unwrap(),
5596 vec![&mut account_account, &mut mint_account, &mut owner2_account],
5597 )
5598 );
5599
5600 assert_eq!(
5602 Err(TokenError::InsufficientFunds.into()),
5603 do_process_instruction(
5604 burn(&program_id, &account_key, &mint_key, &delegate_key, &[], 85).unwrap(),
5605 vec![
5606 &mut account_account,
5607 &mut mint_account,
5608 &mut delegate_account
5609 ],
5610 )
5611 );
5612
5613 do_process_instruction(
5615 burn(&program_id, &account_key, &mint_key, &delegate_key, &[], 84).unwrap(),
5616 vec![
5617 &mut account_account,
5618 &mut mint_account,
5619 &mut delegate_account,
5620 ],
5621 )
5622 .unwrap();
5623
5624 let mint = Mint::unpack_unchecked(&mint_account.data).unwrap();
5626 assert_eq!(mint.supply, 2000 - 42 - 84);
5627 let account = Account::unpack_unchecked(&account_account.data).unwrap();
5628 assert_eq!(account.amount, 1000 - 42 - 84);
5629
5630 assert_eq!(
5632 Err(TokenError::OwnerMismatch.into()),
5633 do_process_instruction(
5634 burn(&program_id, &account_key, &mint_key, &delegate_key, &[], 1).unwrap(),
5635 vec![
5636 &mut account_account,
5637 &mut mint_account,
5638 &mut delegate_account
5639 ],
5640 )
5641 );
5642 }
5643
5644 #[test]
5645 fn test_multisig() {
5646 let program_id = crate::id();
5647 let mint_key = Pubkey::new_unique();
5648 let mut mint_account =
5649 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
5650 let account_key = Pubkey::new_unique();
5651 let mut account = SolanaAccount::new(
5652 account_minimum_balance(),
5653 Account::get_packed_len(),
5654 &program_id,
5655 );
5656 let account2_key = Pubkey::new_unique();
5657 let mut account2_account = SolanaAccount::new(
5658 account_minimum_balance(),
5659 Account::get_packed_len(),
5660 &program_id,
5661 );
5662 let owner_key = Pubkey::new_unique();
5663 let mut owner_account = SolanaAccount::default();
5664 let multisig_key = Pubkey::new_unique();
5665 let mut multisig_account = SolanaAccount::new(42, Multisig::get_packed_len(), &program_id);
5666 let multisig_delegate_key = Pubkey::new_unique();
5667 let mut multisig_delegate_account = SolanaAccount::new(
5668 multisig_minimum_balance(),
5669 Multisig::get_packed_len(),
5670 &program_id,
5671 );
5672 let signer_keys = vec![Pubkey::new_unique(); MAX_SIGNERS];
5673 let signer_key_refs: Vec<&Pubkey> = signer_keys.iter().collect();
5674 let mut signer_accounts = vec![SolanaAccount::new(0, 0, &program_id); MAX_SIGNERS];
5675 let mut rent_sysvar = rent_sysvar();
5676
5677 let account_info_iter = &mut signer_accounts.iter_mut();
5679 assert_eq!(
5680 Err(TokenError::NotRentExempt.into()),
5681 do_process_instruction(
5682 initialize_multisig(&program_id, &multisig_key, &[&signer_keys[0]], 1).unwrap(),
5683 vec![
5684 &mut multisig_account,
5685 &mut rent_sysvar,
5686 account_info_iter.next().unwrap(),
5687 ],
5688 )
5689 );
5690
5691 multisig_account.lamports = multisig_minimum_balance();
5692 let mut multisig_account2 = multisig_account.clone();
5693
5694 let account_info_iter = &mut signer_accounts.iter_mut();
5696 do_process_instruction(
5697 initialize_multisig(&program_id, &multisig_key, &[&signer_keys[0]], 1).unwrap(),
5698 vec![
5699 &mut multisig_account,
5700 &mut rent_sysvar,
5701 account_info_iter.next().unwrap(),
5702 ],
5703 )
5704 .unwrap();
5705
5706 let account_info_iter = &mut signer_accounts.iter_mut();
5708 do_process_instruction(
5709 initialize_multisig2(&program_id, &multisig_key, &[&signer_keys[0]], 1).unwrap(),
5710 vec![&mut multisig_account2, account_info_iter.next().unwrap()],
5711 )
5712 .unwrap();
5713
5714 let account_info_iter = &mut signer_accounts.iter_mut();
5716 do_process_instruction(
5717 initialize_multisig(
5718 &program_id,
5719 &multisig_delegate_key,
5720 &signer_key_refs,
5721 MAX_SIGNERS as u8,
5722 )
5723 .unwrap(),
5724 vec![
5725 &mut multisig_delegate_account,
5726 &mut rent_sysvar,
5727 account_info_iter.next().unwrap(),
5728 account_info_iter.next().unwrap(),
5729 account_info_iter.next().unwrap(),
5730 account_info_iter.next().unwrap(),
5731 account_info_iter.next().unwrap(),
5732 account_info_iter.next().unwrap(),
5733 account_info_iter.next().unwrap(),
5734 account_info_iter.next().unwrap(),
5735 account_info_iter.next().unwrap(),
5736 account_info_iter.next().unwrap(),
5737 account_info_iter.next().unwrap(),
5738 ],
5739 )
5740 .unwrap();
5741
5742 do_process_instruction(
5744 initialize_mint(&program_id, &mint_key, &multisig_key, None, 2).unwrap(),
5745 vec![&mut mint_account, &mut rent_sysvar],
5746 )
5747 .unwrap();
5748
5749 do_process_instruction(
5751 initialize_account(&program_id, &account_key, &mint_key, &multisig_key).unwrap(),
5752 vec![
5753 &mut account,
5754 &mut mint_account,
5755 &mut multisig_account,
5756 &mut rent_sysvar,
5757 ],
5758 )
5759 .unwrap();
5760
5761 do_process_instruction(
5763 initialize_account(
5764 &program_id,
5765 &account2_key,
5766 &mint_key,
5767 &multisig_delegate_key,
5768 )
5769 .unwrap(),
5770 vec![
5771 &mut account2_account,
5772 &mut mint_account,
5773 &mut multisig_account,
5774 &mut rent_sysvar,
5775 ],
5776 )
5777 .unwrap();
5778
5779 let account_info_iter = &mut signer_accounts.iter_mut();
5781 do_process_instruction(
5782 mint_to(
5783 &program_id,
5784 &mint_key,
5785 &account_key,
5786 &multisig_key,
5787 &[&signer_keys[0]],
5788 1000,
5789 )
5790 .unwrap(),
5791 vec![
5792 &mut mint_account,
5793 &mut account,
5794 &mut multisig_account,
5795 account_info_iter.next().unwrap(),
5796 ],
5797 )
5798 .unwrap();
5799
5800 let account_info_iter = &mut signer_accounts.iter_mut();
5802 do_process_instruction(
5803 approve(
5804 &program_id,
5805 &account_key,
5806 &multisig_delegate_key,
5807 &multisig_key,
5808 &[&signer_keys[0]],
5809 100,
5810 )
5811 .unwrap(),
5812 vec![
5813 &mut account,
5814 &mut multisig_delegate_account,
5815 &mut multisig_account,
5816 account_info_iter.next().unwrap(),
5817 ],
5818 )
5819 .unwrap();
5820
5821 let account_info_iter = &mut signer_accounts.iter_mut();
5823 do_process_instruction(
5824 #[allow(deprecated)]
5825 transfer(
5826 &program_id,
5827 &account_key,
5828 &account2_key,
5829 &multisig_key,
5830 &[&signer_keys[0]],
5831 42,
5832 )
5833 .unwrap(),
5834 vec![
5835 &mut account,
5836 &mut account2_account,
5837 &mut multisig_account,
5838 account_info_iter.next().unwrap(),
5839 ],
5840 )
5841 .unwrap();
5842
5843 let account_info_iter = &mut signer_accounts.iter_mut();
5845 do_process_instruction(
5846 #[allow(deprecated)]
5847 transfer(
5848 &program_id,
5849 &account_key,
5850 &account2_key,
5851 &multisig_delegate_key,
5852 &signer_key_refs,
5853 42,
5854 )
5855 .unwrap(),
5856 vec![
5857 &mut account,
5858 &mut account2_account,
5859 &mut multisig_delegate_account,
5860 account_info_iter.next().unwrap(),
5861 account_info_iter.next().unwrap(),
5862 account_info_iter.next().unwrap(),
5863 account_info_iter.next().unwrap(),
5864 account_info_iter.next().unwrap(),
5865 account_info_iter.next().unwrap(),
5866 account_info_iter.next().unwrap(),
5867 account_info_iter.next().unwrap(),
5868 account_info_iter.next().unwrap(),
5869 account_info_iter.next().unwrap(),
5870 account_info_iter.next().unwrap(),
5871 ],
5872 )
5873 .unwrap();
5874
5875 let account_info_iter = &mut signer_accounts.iter_mut();
5877 do_process_instruction(
5878 mint_to(
5879 &program_id,
5880 &mint_key,
5881 &account2_key,
5882 &multisig_key,
5883 &[&signer_keys[0]],
5884 42,
5885 )
5886 .unwrap(),
5887 vec![
5888 &mut mint_account,
5889 &mut account2_account,
5890 &mut multisig_account,
5891 account_info_iter.next().unwrap(),
5892 ],
5893 )
5894 .unwrap();
5895
5896 let account_info_iter = &mut signer_accounts.iter_mut();
5898 do_process_instruction(
5899 burn(
5900 &program_id,
5901 &account_key,
5902 &mint_key,
5903 &multisig_key,
5904 &[&signer_keys[0]],
5905 42,
5906 )
5907 .unwrap(),
5908 vec![
5909 &mut account,
5910 &mut mint_account,
5911 &mut multisig_account,
5912 account_info_iter.next().unwrap(),
5913 ],
5914 )
5915 .unwrap();
5916
5917 let account_info_iter = &mut signer_accounts.iter_mut();
5919 do_process_instruction(
5920 burn(
5921 &program_id,
5922 &account_key,
5923 &mint_key,
5924 &multisig_delegate_key,
5925 &signer_key_refs,
5926 42,
5927 )
5928 .unwrap(),
5929 vec![
5930 &mut account,
5931 &mut mint_account,
5932 &mut multisig_delegate_account,
5933 account_info_iter.next().unwrap(),
5934 account_info_iter.next().unwrap(),
5935 account_info_iter.next().unwrap(),
5936 account_info_iter.next().unwrap(),
5937 account_info_iter.next().unwrap(),
5938 account_info_iter.next().unwrap(),
5939 account_info_iter.next().unwrap(),
5940 account_info_iter.next().unwrap(),
5941 account_info_iter.next().unwrap(),
5942 account_info_iter.next().unwrap(),
5943 account_info_iter.next().unwrap(),
5944 ],
5945 )
5946 .unwrap();
5947
5948 let account3_key = Pubkey::new_unique();
5950 let mut account3_account = SolanaAccount::new(
5951 account_minimum_balance(),
5952 Account::get_packed_len(),
5953 &program_id,
5954 );
5955 let mint2_key = Pubkey::new_unique();
5956 let mut mint2_account =
5957 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
5958 do_process_instruction(
5959 initialize_mint(
5960 &program_id,
5961 &mint2_key,
5962 &multisig_key,
5963 Some(&multisig_key),
5964 2,
5965 )
5966 .unwrap(),
5967 vec![&mut mint2_account, &mut rent_sysvar],
5968 )
5969 .unwrap();
5970 do_process_instruction(
5971 initialize_account(&program_id, &account3_key, &mint2_key, &owner_key).unwrap(),
5972 vec![
5973 &mut account3_account,
5974 &mut mint2_account,
5975 &mut owner_account,
5976 &mut rent_sysvar,
5977 ],
5978 )
5979 .unwrap();
5980 let account_info_iter = &mut signer_accounts.iter_mut();
5981 do_process_instruction(
5982 mint_to(
5983 &program_id,
5984 &mint2_key,
5985 &account3_key,
5986 &multisig_key,
5987 &[&signer_keys[0]],
5988 1000,
5989 )
5990 .unwrap(),
5991 vec![
5992 &mut mint2_account,
5993 &mut account3_account,
5994 &mut multisig_account,
5995 account_info_iter.next().unwrap(),
5996 ],
5997 )
5998 .unwrap();
5999 let account_info_iter = &mut signer_accounts.iter_mut();
6000 do_process_instruction(
6001 freeze_account(
6002 &program_id,
6003 &account3_key,
6004 &mint2_key,
6005 &multisig_key,
6006 &[&signer_keys[0]],
6007 )
6008 .unwrap(),
6009 vec![
6010 &mut account3_account,
6011 &mut mint2_account,
6012 &mut multisig_account,
6013 account_info_iter.next().unwrap(),
6014 ],
6015 )
6016 .unwrap();
6017
6018 let account_info_iter = &mut signer_accounts.iter_mut();
6020 do_process_instruction(
6021 set_authority(
6022 &program_id,
6023 &mint_key,
6024 Some(&owner_key),
6025 AuthorityType::MintTokens,
6026 &multisig_key,
6027 &[&signer_keys[0]],
6028 )
6029 .unwrap(),
6030 vec![
6031 &mut mint_account,
6032 &mut multisig_account,
6033 account_info_iter.next().unwrap(),
6034 ],
6035 )
6036 .unwrap();
6037
6038 let account_info_iter = &mut signer_accounts.iter_mut();
6040 do_process_instruction(
6041 set_authority(
6042 &program_id,
6043 &account_key,
6044 Some(&owner_key),
6045 AuthorityType::AccountOwner,
6046 &multisig_key,
6047 &[&signer_keys[0]],
6048 )
6049 .unwrap(),
6050 vec![
6051 &mut account,
6052 &mut multisig_account,
6053 account_info_iter.next().unwrap(),
6054 ],
6055 )
6056 .unwrap();
6057 }
6058
6059 #[test]
6060 fn test_validate_owner() {
6061 let program_id = crate::id();
6062 let owner_key = Pubkey::new_unique();
6063 let account_to_validate = Pubkey::new_unique();
6064 let mut signer_keys = [Pubkey::default(); MAX_SIGNERS];
6065 for signer_key in signer_keys.iter_mut().take(MAX_SIGNERS) {
6066 *signer_key = Pubkey::new_unique();
6067 }
6068 let mut signer_lamports = 0;
6069 let mut signer_data = vec![];
6070 let mut signers = vec![
6071 AccountInfo::new(
6072 &owner_key,
6073 true,
6074 false,
6075 &mut signer_lamports,
6076 &mut signer_data,
6077 &program_id,
6078 false,
6079 Epoch::default(),
6080 );
6081 MAX_SIGNERS + 1
6082 ];
6083 for (signer, key) in signers.iter_mut().zip(&signer_keys) {
6084 signer.key = key;
6085 }
6086 let mut lamports = 0;
6087 let mut data = vec![0; Multisig::get_packed_len()];
6088 let mut multisig = Multisig::unpack_unchecked(&data).unwrap();
6089 multisig.m = MAX_SIGNERS as u8;
6090 multisig.n = MAX_SIGNERS as u8;
6091 multisig.signers = signer_keys;
6092 multisig.is_initialized = true;
6093 Multisig::pack(multisig, &mut data).unwrap();
6094 let owner_account_info = AccountInfo::new(
6095 &owner_key,
6096 false,
6097 false,
6098 &mut lamports,
6099 &mut data,
6100 &program_id,
6101 false,
6102 Epoch::default(),
6103 );
6104
6105 {
6108 let mut lamports = 0;
6109 let mut data = vec![0; Account::get_packed_len()];
6110 let mut account = Account::unpack_unchecked(&data).unwrap();
6111 account.owner = account_to_validate;
6112 Account::pack(account, &mut data).unwrap();
6113 let account_info = AccountInfo::new(
6114 &account_to_validate,
6115 true,
6116 false,
6117 &mut lamports,
6118 &mut data,
6119 &program_id,
6120 false,
6121 Epoch::default(),
6122 );
6123 let account_info_data_len = account_info.data_len();
6124 let mut borrowed_data = account_info.try_borrow_mut_data().unwrap();
6125 Processor::validate_owner(
6126 &program_id,
6127 &account_to_validate,
6128 &account_info,
6129 account_info_data_len,
6130 &[],
6131 )
6132 .unwrap();
6133 borrowed_data[0] = 1;
6135 }
6136
6137 Processor::validate_owner(
6139 &program_id,
6140 &owner_key,
6141 &owner_account_info,
6142 owner_account_info.data_len(),
6143 &signers,
6144 )
6145 .unwrap();
6146
6147 {
6149 let mut multisig =
6150 Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
6151 multisig.m = 1;
6152 Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
6153 }
6154 Processor::validate_owner(
6155 &program_id,
6156 &owner_key,
6157 &owner_account_info,
6158 owner_account_info.data_len(),
6159 &signers,
6160 )
6161 .unwrap();
6162
6163 {
6165 let mut multisig =
6166 Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
6167 multisig.m = 2;
6168 multisig.n = 1;
6169 Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
6170 }
6171 assert_eq!(
6172 Err(ProgramError::MissingRequiredSignature),
6173 Processor::validate_owner(
6174 &program_id,
6175 &owner_key,
6176 &owner_account_info,
6177 owner_account_info.data_len(),
6178 &signers
6179 )
6180 );
6181
6182 {
6184 let mut multisig =
6185 Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
6186 multisig.m = 0;
6187 multisig.n = 11;
6188 Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
6189 }
6190 Processor::validate_owner(
6191 &program_id,
6192 &owner_key,
6193 &owner_account_info,
6194 owner_account_info.data_len(),
6195 &signers,
6196 )
6197 .unwrap();
6198
6199 {
6201 let mut multisig =
6202 Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
6203 multisig.m = 2;
6204 multisig.n = 11;
6205 Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
6206 }
6207 assert_eq!(
6208 Err(ProgramError::MissingRequiredSignature),
6209 Processor::validate_owner(
6210 &program_id,
6211 &owner_key,
6212 &owner_account_info,
6213 owner_account_info.data_len(),
6214 &[]
6215 )
6216 );
6217 {
6219 let mut multisig =
6220 Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
6221 multisig.m = 2;
6222 multisig.n = 11;
6223 Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
6224 }
6225 assert_eq!(
6226 Err(ProgramError::MissingRequiredSignature),
6227 Processor::validate_owner(
6228 &program_id,
6229 &owner_key,
6230 &owner_account_info,
6231 owner_account_info.data_len(),
6232 &signers[0..1]
6233 )
6234 );
6235
6236 {
6238 let mut multisig =
6239 Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
6240 multisig.m = 2;
6241 multisig.n = 11;
6242 Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
6243 }
6244 Processor::validate_owner(
6245 &program_id,
6246 &owner_key,
6247 &owner_account_info,
6248 owner_account_info.data_len(),
6249 &signers[5..7],
6250 )
6251 .unwrap();
6252
6253 {
6255 let mut multisig =
6256 Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
6257 multisig.m = 11;
6258 multisig.n = 11;
6259 Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
6260 }
6261 signers[5].is_signer = false;
6262 assert_eq!(
6263 Err(ProgramError::MissingRequiredSignature),
6264 Processor::validate_owner(
6265 &program_id,
6266 &owner_key,
6267 &owner_account_info,
6268 owner_account_info.data_len(),
6269 &signers
6270 )
6271 );
6272 signers[5].is_signer = true;
6273
6274 {
6276 let mut signer_lamports = 0;
6277 let mut signer_data = vec![];
6278 let signers = vec![
6279 AccountInfo::new(
6280 &signer_keys[5],
6281 true,
6282 false,
6283 &mut signer_lamports,
6284 &mut signer_data,
6285 &program_id,
6286 false,
6287 Epoch::default(),
6288 );
6289 MAX_SIGNERS + 1
6290 ];
6291 let mut multisig =
6292 Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
6293 multisig.m = 11;
6294 multisig.n = 11;
6295 Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
6296 assert_eq!(
6297 Err(ProgramError::MissingRequiredSignature),
6298 Processor::validate_owner(
6299 &program_id,
6300 &owner_key,
6301 &owner_account_info,
6302 owner_account_info.data_len(),
6303 &signers
6304 )
6305 );
6306 }
6307 }
6308
6309 #[test]
6310 fn test_owner_close_account_dups() {
6311 let program_id = crate::id();
6312 let owner_key = Pubkey::new_unique();
6313 let mint_key = Pubkey::new_unique();
6314 let mut mint_account =
6315 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
6316 let mint_info: AccountInfo = (&mint_key, false, &mut mint_account).into();
6317 let rent_key = rent::id();
6318 let mut rent_sysvar = rent_sysvar();
6319 let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
6320
6321 do_process_instruction_dups(
6323 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
6324 vec![mint_info.clone(), rent_info.clone()],
6325 )
6326 .unwrap();
6327
6328 let to_close_key = Pubkey::new_unique();
6329 let mut to_close_account = SolanaAccount::new(
6330 account_minimum_balance(),
6331 Account::get_packed_len(),
6332 &program_id,
6333 );
6334 let to_close_account_info: AccountInfo =
6335 (&to_close_key, true, &mut to_close_account).into();
6336 let destination_account_key = Pubkey::new_unique();
6337 let mut destination_account = SolanaAccount::new(
6338 account_minimum_balance(),
6339 Account::get_packed_len(),
6340 &program_id,
6341 );
6342 let destination_account_info: AccountInfo =
6343 (&destination_account_key, true, &mut destination_account).into();
6344 do_process_instruction_dups(
6346 initialize_account(&program_id, &to_close_key, &mint_key, &to_close_key).unwrap(),
6347 vec![
6348 to_close_account_info.clone(),
6349 mint_info.clone(),
6350 to_close_account_info.clone(),
6351 rent_info.clone(),
6352 ],
6353 )
6354 .unwrap();
6355
6356 do_process_instruction_dups(
6358 close_account(
6359 &program_id,
6360 &to_close_key,
6361 &destination_account_key,
6362 &to_close_key,
6363 &[],
6364 )
6365 .unwrap(),
6366 vec![
6367 to_close_account_info.clone(),
6368 destination_account_info.clone(),
6369 to_close_account_info.clone(),
6370 ],
6371 )
6372 .unwrap();
6373 assert_eq!(*to_close_account_info.data.borrow(), &[0u8; Account::LEN]);
6374 }
6375
6376 #[test]
6377 fn test_close_authority_close_account_dups() {
6378 let program_id = crate::id();
6379 let owner_key = Pubkey::new_unique();
6380 let mint_key = Pubkey::new_unique();
6381 let mut mint_account =
6382 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
6383 let mint_info: AccountInfo = (&mint_key, false, &mut mint_account).into();
6384 let rent_key = rent::id();
6385 let mut rent_sysvar = rent_sysvar();
6386 let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
6387
6388 do_process_instruction_dups(
6390 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
6391 vec![mint_info.clone(), rent_info.clone()],
6392 )
6393 .unwrap();
6394
6395 let to_close_key = Pubkey::new_unique();
6396 let mut to_close_account = SolanaAccount::new(
6397 account_minimum_balance(),
6398 Account::get_packed_len(),
6399 &program_id,
6400 );
6401 let to_close_account_info: AccountInfo =
6402 (&to_close_key, true, &mut to_close_account).into();
6403 let destination_account_key = Pubkey::new_unique();
6404 let mut destination_account = SolanaAccount::new(
6405 account_minimum_balance(),
6406 Account::get_packed_len(),
6407 &program_id,
6408 );
6409 let destination_account_info: AccountInfo =
6410 (&destination_account_key, true, &mut destination_account).into();
6411 do_process_instruction_dups(
6413 initialize_account(&program_id, &to_close_key, &mint_key, &to_close_key).unwrap(),
6414 vec![
6415 to_close_account_info.clone(),
6416 mint_info.clone(),
6417 to_close_account_info.clone(),
6418 rent_info.clone(),
6419 ],
6420 )
6421 .unwrap();
6422 let mut account = Account::unpack_unchecked(&to_close_account_info.data.borrow()).unwrap();
6423 account.close_authority = COption::Some(to_close_key);
6424 account.owner = owner_key;
6425 Account::pack(account, &mut to_close_account_info.data.borrow_mut()).unwrap();
6426 do_process_instruction_dups(
6427 close_account(
6428 &program_id,
6429 &to_close_key,
6430 &destination_account_key,
6431 &to_close_key,
6432 &[],
6433 )
6434 .unwrap(),
6435 vec![
6436 to_close_account_info.clone(),
6437 destination_account_info.clone(),
6438 to_close_account_info.clone(),
6439 ],
6440 )
6441 .unwrap();
6442 assert_eq!(*to_close_account_info.data.borrow(), &[0u8; Account::LEN]);
6443 }
6444
6445 #[test]
6446 fn test_close_account() {
6447 let program_id = crate::id();
6448 let mint_key = Pubkey::new_unique();
6449 let mut mint_account =
6450 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
6451 let account_key = Pubkey::new_unique();
6452 let mut account_account = SolanaAccount::new(
6453 account_minimum_balance(),
6454 Account::get_packed_len(),
6455 &program_id,
6456 );
6457 let account2_key = Pubkey::new_unique();
6458 let mut account2_account = SolanaAccount::new(
6459 account_minimum_balance() + 42,
6460 Account::get_packed_len(),
6461 &program_id,
6462 );
6463 let account3_key = Pubkey::new_unique();
6464 let mut account3_account = SolanaAccount::new(
6465 account_minimum_balance(),
6466 Account::get_packed_len(),
6467 &program_id,
6468 );
6469 let owner_key = Pubkey::new_unique();
6470 let mut owner_account = SolanaAccount::default();
6471 let owner2_key = Pubkey::new_unique();
6472 let mut owner2_account = SolanaAccount::default();
6473 let mut rent_sysvar = rent_sysvar();
6474
6475 assert_eq!(
6477 Err(ProgramError::UninitializedAccount),
6478 do_process_instruction(
6479 close_account(&program_id, &account_key, &account3_key, &owner2_key, &[]).unwrap(),
6480 vec![
6481 &mut account_account,
6482 &mut account3_account,
6483 &mut owner2_account,
6484 ],
6485 )
6486 );
6487
6488 do_process_instruction(
6490 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
6491 vec![&mut mint_account, &mut rent_sysvar],
6492 )
6493 .unwrap();
6494 do_process_instruction(
6495 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
6496 vec![
6497 &mut account_account,
6498 &mut mint_account,
6499 &mut owner_account,
6500 &mut rent_sysvar,
6501 ],
6502 )
6503 .unwrap();
6504 do_process_instruction(
6505 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 42).unwrap(),
6506 vec![
6507 &mut mint_account,
6508 &mut account_account,
6509 &mut owner_account,
6510 &mut rent_sysvar,
6511 ],
6512 )
6513 .unwrap();
6514 let account = Account::unpack_unchecked(&account_account.data).unwrap();
6515 assert_eq!(account.amount, 42);
6516
6517 do_process_instruction(
6519 initialize_account(
6520 &program_id,
6521 &account2_key,
6522 &crate::native_mint::id(),
6523 &owner_key,
6524 )
6525 .unwrap(),
6526 vec![
6527 &mut account2_account,
6528 &mut mint_account,
6529 &mut owner_account,
6530 &mut rent_sysvar,
6531 ],
6532 )
6533 .unwrap();
6534 let account = Account::unpack_unchecked(&account2_account.data).unwrap();
6535 assert!(account.is_native());
6536 assert_eq!(account.amount, 42);
6537
6538 assert_eq!(
6540 Err(TokenError::NonNativeHasBalance.into()),
6541 do_process_instruction(
6542 close_account(&program_id, &account_key, &account3_key, &owner_key, &[]).unwrap(),
6543 vec![
6544 &mut account_account,
6545 &mut account3_account,
6546 &mut owner_account,
6547 ],
6548 )
6549 );
6550 assert_eq!(account_account.lamports, account_minimum_balance());
6551
6552 do_process_instruction(
6554 burn(&program_id, &account_key, &mint_key, &owner_key, &[], 42).unwrap(),
6555 vec![&mut account_account, &mut mint_account, &mut owner_account],
6556 )
6557 .unwrap();
6558
6559 assert_eq!(
6561 Err(TokenError::OwnerMismatch.into()),
6562 do_process_instruction(
6563 close_account(&program_id, &account_key, &account3_key, &owner2_key, &[]).unwrap(),
6564 vec![
6565 &mut account_account,
6566 &mut account3_account,
6567 &mut owner2_account,
6568 ],
6569 )
6570 );
6571
6572 do_process_instruction(
6574 close_account(&program_id, &account_key, &account3_key, &owner_key, &[]).unwrap(),
6575 vec![
6576 &mut account_account,
6577 &mut account3_account,
6578 &mut owner_account,
6579 ],
6580 )
6581 .unwrap();
6582 assert_eq!(account_account.lamports, 0);
6583 assert_eq!(account3_account.lamports, 2 * account_minimum_balance());
6584 let account = Account::unpack_unchecked(&account_account.data).unwrap();
6585 assert_eq!(account.amount, 0);
6586
6587 let account_key = Pubkey::new_unique();
6589 let mut account_account = SolanaAccount::new(
6590 account_minimum_balance(),
6591 Account::get_packed_len(),
6592 &program_id,
6593 );
6594 let owner2_key = Pubkey::new_unique();
6595 let mut owner2_account = SolanaAccount::new(
6596 account_minimum_balance(),
6597 Account::get_packed_len(),
6598 &program_id,
6599 );
6600 do_process_instruction(
6601 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
6602 vec![
6603 &mut account_account,
6604 &mut mint_account,
6605 &mut owner_account,
6606 &mut rent_sysvar,
6607 ],
6608 )
6609 .unwrap();
6610 account_account.lamports = 2;
6611
6612 do_process_instruction(
6613 set_authority(
6614 &program_id,
6615 &account_key,
6616 Some(&owner2_key),
6617 AuthorityType::CloseAccount,
6618 &owner_key,
6619 &[],
6620 )
6621 .unwrap(),
6622 vec![&mut account_account, &mut owner_account],
6623 )
6624 .unwrap();
6625
6626 assert_eq!(
6628 Err(TokenError::OwnerMismatch.into()),
6629 do_process_instruction(
6630 close_account(&program_id, &account_key, &account3_key, &owner_key, &[]).unwrap(),
6631 vec![
6632 &mut account_account,
6633 &mut account3_account,
6634 &mut owner_account,
6635 ],
6636 )
6637 );
6638
6639 do_process_instruction(
6641 close_account(&program_id, &account_key, &account3_key, &owner2_key, &[]).unwrap(),
6642 vec![
6643 &mut account_account,
6644 &mut account3_account,
6645 &mut owner2_account,
6646 ],
6647 )
6648 .unwrap();
6649 assert_eq!(account_account.lamports, 0);
6650 assert_eq!(account3_account.lamports, 2 * account_minimum_balance() + 2);
6651 let account = Account::unpack_unchecked(&account_account.data).unwrap();
6652 assert_eq!(account.amount, 0);
6653
6654 do_process_instruction(
6656 close_account(&program_id, &account2_key, &account3_key, &owner_key, &[]).unwrap(),
6657 vec![
6658 &mut account2_account,
6659 &mut account3_account,
6660 &mut owner_account,
6661 ],
6662 )
6663 .unwrap();
6664 assert_eq!(account2_account.data, [0u8; Account::LEN]);
6665 assert_eq!(
6666 account3_account.lamports,
6667 3 * account_minimum_balance() + 2 + 42
6668 );
6669 }
6670
6671 #[test]
6672 fn test_native_token() {
6673 let program_id = crate::id();
6674 let mut mint_account = native_mint();
6675 let account_key = Pubkey::new_unique();
6676 let mut account_account = SolanaAccount::new(
6677 account_minimum_balance() + 40,
6678 Account::get_packed_len(),
6679 &program_id,
6680 );
6681 let account2_key = Pubkey::new_unique();
6682 let mut account2_account = SolanaAccount::new(
6683 account_minimum_balance(),
6684 Account::get_packed_len(),
6685 &program_id,
6686 );
6687 let account3_key = Pubkey::new_unique();
6688 let mut account3_account = SolanaAccount::new(account_minimum_balance(), 0, &program_id);
6689 let owner_key = Pubkey::new_unique();
6690 let mut owner_account = SolanaAccount::default();
6691 let owner2_key = Pubkey::new_unique();
6692 let mut owner2_account = SolanaAccount::default();
6693 let owner3_key = Pubkey::new_unique();
6694 let mut rent_sysvar = rent_sysvar();
6695
6696 do_process_instruction(
6698 initialize_account(
6699 &program_id,
6700 &account_key,
6701 &crate::native_mint::id(),
6702 &owner_key,
6703 )
6704 .unwrap(),
6705 vec![
6706 &mut account_account,
6707 &mut mint_account,
6708 &mut owner_account,
6709 &mut rent_sysvar,
6710 ],
6711 )
6712 .unwrap();
6713 let account = Account::unpack_unchecked(&account_account.data).unwrap();
6714 assert!(account.is_native());
6715 assert_eq!(account.amount, 40);
6716
6717 do_process_instruction(
6719 initialize_account(
6720 &program_id,
6721 &account2_key,
6722 &crate::native_mint::id(),
6723 &owner_key,
6724 )
6725 .unwrap(),
6726 vec![
6727 &mut account2_account,
6728 &mut mint_account,
6729 &mut owner_account,
6730 &mut rent_sysvar,
6731 ],
6732 )
6733 .unwrap();
6734 let account = Account::unpack_unchecked(&account2_account.data).unwrap();
6735 assert!(account.is_native());
6736 assert_eq!(account.amount, 0);
6737
6738 assert_eq!(
6740 Err(TokenError::NativeNotSupported.into()),
6741 do_process_instruction(
6742 mint_to(
6743 &program_id,
6744 &crate::native_mint::id(),
6745 &account_key,
6746 &owner_key,
6747 &[],
6748 42
6749 )
6750 .unwrap(),
6751 vec![&mut mint_account, &mut account_account, &mut owner_account],
6752 )
6753 );
6754
6755 let bogus_mint_key = Pubkey::new_unique();
6757 let mut bogus_mint_account =
6758 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
6759 do_process_instruction(
6760 initialize_mint(&program_id, &bogus_mint_key, &owner_key, None, 2).unwrap(),
6761 vec![&mut bogus_mint_account, &mut rent_sysvar],
6762 )
6763 .unwrap();
6764
6765 assert_eq!(
6766 Err(TokenError::NativeNotSupported.into()),
6767 do_process_instruction(
6768 burn(
6769 &program_id,
6770 &account_key,
6771 &bogus_mint_key,
6772 &owner_key,
6773 &[],
6774 42
6775 )
6776 .unwrap(),
6777 vec![
6778 &mut account_account,
6779 &mut bogus_mint_account,
6780 &mut owner_account
6781 ],
6782 )
6783 );
6784
6785 assert_eq!(
6787 Err(TokenError::InsufficientFunds.into()),
6788 do_process_instruction(
6789 #[allow(deprecated)]
6790 transfer(
6791 &program_id,
6792 &account_key,
6793 &account2_key,
6794 &owner_key,
6795 &[],
6796 50,
6797 )
6798 .unwrap(),
6799 vec![
6800 &mut account_account,
6801 &mut account2_account,
6802 &mut owner_account,
6803 ],
6804 )
6805 );
6806
6807 do_process_instruction(
6809 #[allow(deprecated)]
6810 transfer(
6811 &program_id,
6812 &account_key,
6813 &account2_key,
6814 &owner_key,
6815 &[],
6816 40,
6817 )
6818 .unwrap(),
6819 vec![
6820 &mut account_account,
6821 &mut account2_account,
6822 &mut owner_account,
6823 ],
6824 )
6825 .unwrap();
6826 assert_eq!(account_account.lamports, account_minimum_balance());
6827 let account = Account::unpack_unchecked(&account_account.data).unwrap();
6828 assert!(account.is_native());
6829 assert_eq!(account.amount, 0);
6830 assert_eq!(account2_account.lamports, account_minimum_balance() + 40);
6831 let account = Account::unpack_unchecked(&account2_account.data).unwrap();
6832 assert!(account.is_native());
6833 assert_eq!(account.amount, 40);
6834
6835 do_process_instruction(
6837 set_authority(
6838 &program_id,
6839 &account_key,
6840 Some(&owner3_key),
6841 AuthorityType::CloseAccount,
6842 &owner_key,
6843 &[],
6844 )
6845 .unwrap(),
6846 vec![&mut account_account, &mut owner_account],
6847 )
6848 .unwrap();
6849 let account = Account::unpack_unchecked(&account_account.data).unwrap();
6850 assert_eq!(account.close_authority, COption::Some(owner3_key));
6851
6852 do_process_instruction(
6854 set_authority(
6855 &program_id,
6856 &account_key,
6857 Some(&owner2_key),
6858 AuthorityType::AccountOwner,
6859 &owner_key,
6860 &[],
6861 )
6862 .unwrap(),
6863 vec![&mut account_account, &mut owner_account],
6864 )
6865 .unwrap();
6866
6867 let account = Account::unpack_unchecked(&account_account.data).unwrap();
6869 assert_eq!(account.close_authority, COption::None);
6870
6871 do_process_instruction(
6873 close_account(&program_id, &account_key, &account3_key, &owner2_key, &[]).unwrap(),
6874 vec![
6875 &mut account_account,
6876 &mut account3_account,
6877 &mut owner2_account,
6878 ],
6879 )
6880 .unwrap();
6881 assert_eq!(account_account.lamports, 0);
6882 assert_eq!(account3_account.lamports, 2 * account_minimum_balance());
6883 assert_eq!(account_account.data, [0u8; Account::LEN]);
6884 }
6885
6886 #[test]
6887 fn test_overflow() {
6888 let program_id = crate::id();
6889 let account_key = Pubkey::new_unique();
6890 let mut account_account = SolanaAccount::new(
6891 account_minimum_balance(),
6892 Account::get_packed_len(),
6893 &program_id,
6894 );
6895 let account2_key = Pubkey::new_unique();
6896 let mut account2_account = SolanaAccount::new(
6897 account_minimum_balance(),
6898 Account::get_packed_len(),
6899 &program_id,
6900 );
6901 let owner_key = Pubkey::new_unique();
6902 let mut owner_account = SolanaAccount::default();
6903 let owner2_key = Pubkey::new_unique();
6904 let mut owner2_account = SolanaAccount::default();
6905 let mint_owner_key = Pubkey::new_unique();
6906 let mut mint_owner_account = SolanaAccount::default();
6907 let mint_key = Pubkey::new_unique();
6908 let mut mint_account =
6909 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
6910 let mut rent_sysvar = rent_sysvar();
6911
6912 do_process_instruction(
6914 initialize_mint(&program_id, &mint_key, &mint_owner_key, None, 2).unwrap(),
6915 vec![&mut mint_account, &mut rent_sysvar],
6916 )
6917 .unwrap();
6918
6919 do_process_instruction(
6921 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
6922 vec![
6923 &mut account_account,
6924 &mut mint_account,
6925 &mut owner_account,
6926 &mut rent_sysvar,
6927 ],
6928 )
6929 .unwrap();
6930
6931 do_process_instruction(
6933 initialize_account(&program_id, &account2_key, &mint_key, &owner2_key).unwrap(),
6934 vec![
6935 &mut account2_account,
6936 &mut mint_account,
6937 &mut owner2_account,
6938 &mut rent_sysvar,
6939 ],
6940 )
6941 .unwrap();
6942
6943 do_process_instruction(
6945 mint_to(
6946 &program_id,
6947 &mint_key,
6948 &account_key,
6949 &mint_owner_key,
6950 &[],
6951 u64::MAX,
6952 )
6953 .unwrap(),
6954 vec![
6955 &mut mint_account,
6956 &mut account_account,
6957 &mut mint_owner_account,
6958 ],
6959 )
6960 .unwrap();
6961 let account = Account::unpack_unchecked(&account_account.data).unwrap();
6962 assert_eq!(account.amount, u64::MAX);
6963
6964 assert_eq!(
6966 Err(TokenError::Overflow.into()),
6967 do_process_instruction(
6968 mint_to(
6969 &program_id,
6970 &mint_key,
6971 &account_key,
6972 &mint_owner_key,
6973 &[],
6974 1,
6975 )
6976 .unwrap(),
6977 vec![
6978 &mut mint_account,
6979 &mut account_account,
6980 &mut mint_owner_account,
6981 ],
6982 )
6983 );
6984 let account = Account::unpack_unchecked(&account_account.data).unwrap();
6985 assert_eq!(account.amount, u64::MAX);
6986
6987 assert_eq!(
6989 Err(TokenError::Overflow.into()),
6990 do_process_instruction(
6991 mint_to(
6992 &program_id,
6993 &mint_key,
6994 &account2_key,
6995 &mint_owner_key,
6996 &[],
6997 1,
6998 )
6999 .unwrap(),
7000 vec![
7001 &mut mint_account,
7002 &mut account2_account,
7003 &mut mint_owner_account,
7004 ],
7005 )
7006 );
7007
7008 do_process_instruction(
7010 burn(&program_id, &account_key, &mint_key, &owner_key, &[], 100).unwrap(),
7011 vec![&mut account_account, &mut mint_account, &mut owner_account],
7012 )
7013 .unwrap();
7014 let account = Account::unpack_unchecked(&account_account.data).unwrap();
7015 assert_eq!(account.amount, u64::MAX - 100);
7016
7017 do_process_instruction(
7018 mint_to(
7019 &program_id,
7020 &mint_key,
7021 &account_key,
7022 &mint_owner_key,
7023 &[],
7024 100,
7025 )
7026 .unwrap(),
7027 vec![
7028 &mut mint_account,
7029 &mut account_account,
7030 &mut mint_owner_account,
7031 ],
7032 )
7033 .unwrap();
7034 let account = Account::unpack_unchecked(&account_account.data).unwrap();
7035 assert_eq!(account.amount, u64::MAX);
7036
7037 let mut account = Account::unpack_unchecked(&account2_account.data).unwrap();
7039 account.amount = 1;
7040 Account::pack(account, &mut account2_account.data).unwrap();
7041
7042 assert_eq!(
7043 Err(TokenError::Overflow.into()),
7044 do_process_instruction(
7045 #[allow(deprecated)]
7046 transfer(
7047 &program_id,
7048 &account2_key,
7049 &account_key,
7050 &owner2_key,
7051 &[],
7052 1,
7053 )
7054 .unwrap(),
7055 vec![
7056 &mut account2_account,
7057 &mut account_account,
7058 &mut owner2_account,
7059 ],
7060 )
7061 );
7062 }
7063
7064 #[test]
7065 fn test_frozen() {
7066 let program_id = crate::id();
7067 let account_key = Pubkey::new_unique();
7068 let mut account_account = SolanaAccount::new(
7069 account_minimum_balance(),
7070 Account::get_packed_len(),
7071 &program_id,
7072 );
7073 let account2_key = Pubkey::new_unique();
7074 let mut account2_account = SolanaAccount::new(
7075 account_minimum_balance(),
7076 Account::get_packed_len(),
7077 &program_id,
7078 );
7079 let owner_key = Pubkey::new_unique();
7080 let mut owner_account = SolanaAccount::default();
7081 let mint_key = Pubkey::new_unique();
7082 let mut mint_account =
7083 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
7084 let mut rent_sysvar = rent_sysvar();
7085
7086 do_process_instruction(
7088 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
7089 vec![&mut mint_account, &mut rent_sysvar],
7090 )
7091 .unwrap();
7092
7093 do_process_instruction(
7095 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
7096 vec![
7097 &mut account_account,
7098 &mut mint_account,
7099 &mut owner_account,
7100 &mut rent_sysvar,
7101 ],
7102 )
7103 .unwrap();
7104
7105 do_process_instruction(
7107 initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
7108 vec![
7109 &mut account2_account,
7110 &mut mint_account,
7111 &mut owner_account,
7112 &mut rent_sysvar,
7113 ],
7114 )
7115 .unwrap();
7116
7117 do_process_instruction(
7119 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
7120 vec![&mut mint_account, &mut account_account, &mut owner_account],
7121 )
7122 .unwrap();
7123
7124 let mut account = Account::unpack_unchecked(&account2_account.data).unwrap();
7126 account.state = AccountState::Frozen;
7127 Account::pack(account, &mut account2_account.data).unwrap();
7128 assert_eq!(
7129 Err(TokenError::AccountFrozen.into()),
7130 do_process_instruction(
7131 #[allow(deprecated)]
7132 transfer(
7133 &program_id,
7134 &account_key,
7135 &account2_key,
7136 &owner_key,
7137 &[],
7138 500,
7139 )
7140 .unwrap(),
7141 vec![
7142 &mut account_account,
7143 &mut account2_account,
7144 &mut owner_account,
7145 ],
7146 )
7147 );
7148
7149 let mut account = Account::unpack_unchecked(&account_account.data).unwrap();
7150 account.state = AccountState::Initialized;
7151 Account::pack(account, &mut account_account.data).unwrap();
7152 let mut account = Account::unpack_unchecked(&account2_account.data).unwrap();
7153 account.state = AccountState::Frozen;
7154 Account::pack(account, &mut account2_account.data).unwrap();
7155 assert_eq!(
7156 Err(TokenError::AccountFrozen.into()),
7157 do_process_instruction(
7158 #[allow(deprecated)]
7159 transfer(
7160 &program_id,
7161 &account_key,
7162 &account2_key,
7163 &owner_key,
7164 &[],
7165 500,
7166 )
7167 .unwrap(),
7168 vec![
7169 &mut account_account,
7170 &mut account2_account,
7171 &mut owner_account,
7172 ],
7173 )
7174 );
7175
7176 let mut account = Account::unpack_unchecked(&account_account.data).unwrap();
7178 account.state = AccountState::Frozen;
7179 Account::pack(account, &mut account_account.data).unwrap();
7180 let delegate_key = Pubkey::new_unique();
7181 let mut delegate_account = SolanaAccount::default();
7182 assert_eq!(
7183 Err(TokenError::AccountFrozen.into()),
7184 do_process_instruction(
7185 approve(
7186 &program_id,
7187 &account_key,
7188 &delegate_key,
7189 &owner_key,
7190 &[],
7191 100
7192 )
7193 .unwrap(),
7194 vec![
7195 &mut account_account,
7196 &mut delegate_account,
7197 &mut owner_account,
7198 ],
7199 )
7200 );
7201
7202 let mut account = Account::unpack_unchecked(&account_account.data).unwrap();
7204 account.delegate = COption::Some(delegate_key);
7205 account.delegated_amount = 100;
7206 Account::pack(account, &mut account_account.data).unwrap();
7207 assert_eq!(
7208 Err(TokenError::AccountFrozen.into()),
7209 do_process_instruction(
7210 revoke(&program_id, &account_key, &owner_key, &[]).unwrap(),
7211 vec![&mut account_account, &mut owner_account],
7212 )
7213 );
7214
7215 let new_owner_key = Pubkey::new_unique();
7217 assert_eq!(
7218 Err(TokenError::AccountFrozen.into()),
7219 do_process_instruction(
7220 set_authority(
7221 &program_id,
7222 &account_key,
7223 Some(&new_owner_key),
7224 AuthorityType::AccountOwner,
7225 &owner_key,
7226 &[]
7227 )
7228 .unwrap(),
7229 vec![&mut account_account, &mut owner_account,],
7230 )
7231 );
7232
7233 assert_eq!(
7235 Err(TokenError::AccountFrozen.into()),
7236 do_process_instruction(
7237 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 100).unwrap(),
7238 vec![&mut mint_account, &mut account_account, &mut owner_account,],
7239 )
7240 );
7241
7242 assert_eq!(
7244 Err(TokenError::AccountFrozen.into()),
7245 do_process_instruction(
7246 burn(&program_id, &account_key, &mint_key, &owner_key, &[], 100).unwrap(),
7247 vec![&mut account_account, &mut mint_account, &mut owner_account],
7248 )
7249 );
7250 }
7251
7252 #[test]
7253 fn test_freeze_thaw_dups() {
7254 let program_id = crate::id();
7255 let account1_key = Pubkey::new_unique();
7256 let mut account1_account = SolanaAccount::new(
7257 account_minimum_balance(),
7258 Account::get_packed_len(),
7259 &program_id,
7260 );
7261 let account1_info: AccountInfo = (&account1_key, true, &mut account1_account).into();
7262 let owner_key = Pubkey::new_unique();
7263 let mint_key = Pubkey::new_unique();
7264 let mut mint_account =
7265 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
7266 let mint_info: AccountInfo = (&mint_key, true, &mut mint_account).into();
7267 let rent_key = rent::id();
7268 let mut rent_sysvar = rent_sysvar();
7269 let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
7270
7271 do_process_instruction_dups(
7273 initialize_mint(&program_id, &mint_key, &owner_key, Some(&account1_key), 2).unwrap(),
7274 vec![mint_info.clone(), rent_info.clone()],
7275 )
7276 .unwrap();
7277
7278 do_process_instruction_dups(
7280 initialize_account(&program_id, &account1_key, &mint_key, &account1_key).unwrap(),
7281 vec![
7282 account1_info.clone(),
7283 mint_info.clone(),
7284 account1_info.clone(),
7285 rent_info.clone(),
7286 ],
7287 )
7288 .unwrap();
7289
7290 do_process_instruction_dups(
7292 freeze_account(&program_id, &account1_key, &mint_key, &account1_key, &[]).unwrap(),
7293 vec![
7294 account1_info.clone(),
7295 mint_info.clone(),
7296 account1_info.clone(),
7297 ],
7298 )
7299 .unwrap();
7300
7301 let mut account = Account::unpack_unchecked(&account1_info.data.borrow()).unwrap();
7303 account.state = AccountState::Frozen;
7304 Account::pack(account, &mut account1_info.data.borrow_mut()).unwrap();
7305 do_process_instruction_dups(
7306 thaw_account(&program_id, &account1_key, &mint_key, &account1_key, &[]).unwrap(),
7307 vec![
7308 account1_info.clone(),
7309 mint_info.clone(),
7310 account1_info.clone(),
7311 ],
7312 )
7313 .unwrap();
7314 }
7315
7316 #[test]
7317 fn test_freeze_account() {
7318 let program_id = crate::id();
7319 let account_key = Pubkey::new_unique();
7320 let mut account_account = SolanaAccount::new(
7321 account_minimum_balance(),
7322 Account::get_packed_len(),
7323 &program_id,
7324 );
7325 let account_owner_key = Pubkey::new_unique();
7326 let mut account_owner_account = SolanaAccount::default();
7327 let owner_key = Pubkey::new_unique();
7328 let mut owner_account = SolanaAccount::default();
7329 let owner2_key = Pubkey::new_unique();
7330 let mut owner2_account = SolanaAccount::default();
7331 let mint_key = Pubkey::new_unique();
7332 let mut mint_account =
7333 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
7334 let mut rent_sysvar = rent_sysvar();
7335
7336 do_process_instruction(
7338 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
7339 vec![&mut mint_account, &mut rent_sysvar],
7340 )
7341 .unwrap();
7342
7343 do_process_instruction(
7345 initialize_account(&program_id, &account_key, &mint_key, &account_owner_key).unwrap(),
7346 vec![
7347 &mut account_account,
7348 &mut mint_account,
7349 &mut account_owner_account,
7350 &mut rent_sysvar,
7351 ],
7352 )
7353 .unwrap();
7354
7355 do_process_instruction(
7357 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
7358 vec![&mut mint_account, &mut account_account, &mut owner_account],
7359 )
7360 .unwrap();
7361
7362 assert_eq!(
7364 Err(TokenError::MintCannotFreeze.into()),
7365 do_process_instruction(
7366 freeze_account(&program_id, &account_key, &mint_key, &owner_key, &[]).unwrap(),
7367 vec![&mut account_account, &mut mint_account, &mut owner_account],
7368 )
7369 );
7370
7371 let mut mint = Mint::unpack_unchecked(&mint_account.data).unwrap();
7373 mint.freeze_authority = COption::Some(owner_key);
7374 Mint::pack(mint, &mut mint_account.data).unwrap();
7375 assert_eq!(
7376 Err(TokenError::OwnerMismatch.into()),
7377 do_process_instruction(
7378 freeze_account(&program_id, &account_key, &mint_key, &owner2_key, &[]).unwrap(),
7379 vec![&mut account_account, &mut mint_account, &mut owner2_account],
7380 )
7381 );
7382
7383 assert_eq!(
7385 Err(TokenError::InvalidState.into()),
7386 do_process_instruction(
7387 thaw_account(&program_id, &account_key, &mint_key, &owner2_key, &[]).unwrap(),
7388 vec![&mut account_account, &mut mint_account, &mut owner2_account],
7389 )
7390 );
7391
7392 do_process_instruction(
7394 freeze_account(&program_id, &account_key, &mint_key, &owner_key, &[]).unwrap(),
7395 vec![&mut account_account, &mut mint_account, &mut owner_account],
7396 )
7397 .unwrap();
7398 let account = Account::unpack_unchecked(&account_account.data).unwrap();
7399 assert_eq!(account.state, AccountState::Frozen);
7400
7401 assert_eq!(
7403 Err(TokenError::InvalidState.into()),
7404 do_process_instruction(
7405 freeze_account(&program_id, &account_key, &mint_key, &owner_key, &[]).unwrap(),
7406 vec![&mut account_account, &mut mint_account, &mut owner_account],
7407 )
7408 );
7409
7410 assert_eq!(
7412 Err(TokenError::OwnerMismatch.into()),
7413 do_process_instruction(
7414 thaw_account(&program_id, &account_key, &mint_key, &owner2_key, &[]).unwrap(),
7415 vec![&mut account_account, &mut mint_account, &mut owner2_account],
7416 )
7417 );
7418
7419 do_process_instruction(
7421 thaw_account(&program_id, &account_key, &mint_key, &owner_key, &[]).unwrap(),
7422 vec![&mut account_account, &mut mint_account, &mut owner_account],
7423 )
7424 .unwrap();
7425 let account = Account::unpack_unchecked(&account_account.data).unwrap();
7426 assert_eq!(account.state, AccountState::Initialized);
7427 }
7428
7429 #[test]
7430 fn test_initialize_account2_and_3() {
7431 let program_id = crate::id();
7432 let account_key = Pubkey::new_unique();
7433 let mut account_account = SolanaAccount::new(
7434 account_minimum_balance(),
7435 Account::get_packed_len(),
7436 &program_id,
7437 );
7438 let mut account2_account = SolanaAccount::new(
7439 account_minimum_balance(),
7440 Account::get_packed_len(),
7441 &program_id,
7442 );
7443 let mut account3_account = SolanaAccount::new(
7444 account_minimum_balance(),
7445 Account::get_packed_len(),
7446 &program_id,
7447 );
7448 let owner_key = Pubkey::new_unique();
7449 let mut owner_account = SolanaAccount::default();
7450 let mint_key = Pubkey::new_unique();
7451 let mut mint_account =
7452 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
7453 let mut rent_sysvar = rent_sysvar();
7454
7455 do_process_instruction(
7457 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
7458 vec![&mut mint_account, &mut rent_sysvar],
7459 )
7460 .unwrap();
7461
7462 do_process_instruction(
7463 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
7464 vec![
7465 &mut account_account,
7466 &mut mint_account,
7467 &mut owner_account,
7468 &mut rent_sysvar,
7469 ],
7470 )
7471 .unwrap();
7472
7473 do_process_instruction(
7474 initialize_account2(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
7475 vec![&mut account2_account, &mut mint_account, &mut rent_sysvar],
7476 )
7477 .unwrap();
7478
7479 assert_eq!(account_account, account2_account);
7480
7481 do_process_instruction(
7482 initialize_account3(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
7483 vec![&mut account3_account, &mut mint_account],
7484 )
7485 .unwrap();
7486
7487 assert_eq!(account_account, account3_account);
7488 }
7489
7490 #[test]
7491 fn initialize_account_on_non_transferable_mint() {
7492 let program_id = crate::id();
7493 let account = Pubkey::new_unique();
7494 let account_len = ExtensionType::try_calculate_account_len::<Mint>(&[
7495 ExtensionType::NonTransferableAccount,
7496 ])
7497 .unwrap();
7498 let mut account_without_enough_length = SolanaAccount::new(
7499 Rent::default().minimum_balance(account_len),
7500 account_len,
7501 &program_id,
7502 );
7503
7504 let account2 = Pubkey::new_unique();
7505 let account2_len = ExtensionType::try_calculate_account_len::<Mint>(&[
7506 ExtensionType::NonTransferableAccount,
7507 ExtensionType::ImmutableOwner,
7508 ])
7509 .unwrap();
7510 let mut account_with_enough_length = SolanaAccount::new(
7511 Rent::default().minimum_balance(account2_len),
7512 account2_len,
7513 &program_id,
7514 );
7515
7516 let owner_key = Pubkey::new_unique();
7517 let mut owner_account = SolanaAccount::default();
7518 let mint_key = Pubkey::new_unique();
7519 let mint_len =
7520 ExtensionType::try_calculate_account_len::<Mint>(&[ExtensionType::NonTransferable])
7521 .unwrap();
7522 let mut mint_account = SolanaAccount::new(
7523 Rent::default().minimum_balance(mint_len),
7524 mint_len,
7525 &program_id,
7526 );
7527 let mut rent_sysvar = rent_sysvar();
7528
7529 assert_eq!(
7531 Ok(()),
7532 do_process_instruction(
7533 initialize_non_transferable_mint(&program_id, &mint_key).unwrap(),
7534 vec![&mut mint_account],
7535 )
7536 );
7537 assert_eq!(
7538 Ok(()),
7539 do_process_instruction(
7540 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
7541 vec![&mut mint_account, &mut rent_sysvar]
7542 )
7543 );
7544
7545 assert_eq!(
7548 Err(ProgramError::InvalidAccountData),
7549 do_process_instruction(
7550 initialize_account(&program_id, &account, &mint_key, &owner_key).unwrap(),
7551 vec![
7552 &mut account_without_enough_length,
7553 &mut mint_account,
7554 &mut owner_account,
7555 &mut rent_sysvar,
7556 ]
7557 )
7558 );
7559
7560 assert_eq!(
7562 Ok(()),
7563 do_process_instruction(
7564 initialize_account(&program_id, &account2, &mint_key, &owner_key).unwrap(),
7565 vec![
7566 &mut account_with_enough_length,
7567 &mut mint_account,
7568 &mut owner_account,
7569 &mut rent_sysvar,
7570 ]
7571 )
7572 );
7573 }
7574
7575 #[test]
7576 fn test_sync_native() {
7577 let program_id = crate::id();
7578 let mint_key = Pubkey::new_unique();
7579 let mut mint_account =
7580 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
7581 let native_account_key = Pubkey::new_unique();
7582 let lamports = 40;
7583 let mut native_account = SolanaAccount::new(
7584 account_minimum_balance() + lamports,
7585 Account::get_packed_len(),
7586 &program_id,
7587 );
7588 let non_native_account_key = Pubkey::new_unique();
7589 let mut non_native_account = SolanaAccount::new(
7590 account_minimum_balance() + 50,
7591 Account::get_packed_len(),
7592 &program_id,
7593 );
7594
7595 let owner_key = Pubkey::new_unique();
7596 let mut owner_account = SolanaAccount::default();
7597 let mut rent_sysvar = rent_sysvar();
7598
7599 do_process_instruction(
7601 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
7602 vec![&mut mint_account, &mut rent_sysvar],
7603 )
7604 .unwrap();
7605
7606 do_process_instruction(
7608 initialize_account(&program_id, &non_native_account_key, &mint_key, &owner_key)
7609 .unwrap(),
7610 vec![
7611 &mut non_native_account,
7612 &mut mint_account,
7613 &mut owner_account,
7614 &mut rent_sysvar,
7615 ],
7616 )
7617 .unwrap();
7618
7619 let account = Account::unpack_unchecked(&non_native_account.data).unwrap();
7620 assert!(!account.is_native());
7621 assert_eq!(account.amount, 0);
7622
7623 assert_eq!(
7625 Err(TokenError::NonNativeNotSupported.into()),
7626 do_process_instruction(
7627 sync_native(&program_id, &non_native_account_key,).unwrap(),
7628 vec![&mut non_native_account],
7629 )
7630 );
7631
7632 assert_eq!(
7634 Err(ProgramError::UninitializedAccount),
7635 do_process_instruction(
7636 sync_native(&program_id, &native_account_key,).unwrap(),
7637 vec![&mut native_account],
7638 )
7639 );
7640
7641 do_process_instruction(
7643 initialize_account(
7644 &program_id,
7645 &native_account_key,
7646 &crate::native_mint::id(),
7647 &owner_key,
7648 )
7649 .unwrap(),
7650 vec![
7651 &mut native_account,
7652 &mut mint_account,
7653 &mut owner_account,
7654 &mut rent_sysvar,
7655 ],
7656 )
7657 .unwrap();
7658
7659 let not_program_id = Pubkey::new_unique();
7661 native_account.owner = not_program_id;
7662 assert_eq!(
7663 Err(ProgramError::IncorrectProgramId),
7664 do_process_instruction(
7665 sync_native(&program_id, &native_account_key,).unwrap(),
7666 vec![&mut native_account],
7667 )
7668 );
7669 native_account.owner = program_id;
7670
7671 let account = Account::unpack_unchecked(&native_account.data).unwrap();
7672 assert!(account.is_native());
7673 assert_eq!(account.amount, lamports);
7674
7675 do_process_instruction(
7677 sync_native(&program_id, &native_account_key).unwrap(),
7678 vec![&mut native_account],
7679 )
7680 .unwrap();
7681 let account = Account::unpack_unchecked(&native_account.data).unwrap();
7682 assert_eq!(account.amount, lamports);
7683
7684 let new_lamports = lamports + 50;
7686 native_account.lamports = account_minimum_balance() + new_lamports;
7687
7688 do_process_instruction(
7690 sync_native(&program_id, &native_account_key).unwrap(),
7691 vec![&mut native_account],
7692 )
7693 .unwrap();
7694 let account = Account::unpack_unchecked(&native_account.data).unwrap();
7695 assert_eq!(account.amount, new_lamports);
7696
7697 native_account.lamports -= 1;
7699
7700 assert_eq!(
7702 Err(TokenError::InvalidState.into()),
7703 do_process_instruction(
7704 sync_native(&program_id, &native_account_key,).unwrap(),
7705 vec![&mut native_account],
7706 )
7707 );
7708 }
7709
7710 #[test]
7711 #[serial]
7712 fn test_get_account_data_size() {
7713 let program_id = crate::id();
7715 let owner_key = Pubkey::new_unique();
7716 let mut owner_account = SolanaAccount::default();
7717 let mut rent_sysvar = rent_sysvar();
7718
7719 let mut mint_account =
7721 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
7722 let mint_key = Pubkey::new_unique();
7723 do_process_instruction(
7724 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
7725 vec![&mut mint_account, &mut rent_sysvar],
7726 )
7727 .unwrap();
7728
7729 set_expected_data(
7730 ExtensionType::try_calculate_account_len::<Account>(&[])
7731 .unwrap()
7732 .to_le_bytes()
7733 .to_vec(),
7734 );
7735 do_process_instruction(
7736 get_account_data_size(&program_id, &mint_key, &[]).unwrap(),
7737 vec![&mut mint_account],
7738 )
7739 .unwrap();
7740
7741 set_expected_data(
7742 ExtensionType::try_calculate_account_len::<Account>(&[
7743 ExtensionType::TransferFeeAmount,
7744 ])
7745 .unwrap()
7746 .to_le_bytes()
7747 .to_vec(),
7748 );
7749 do_process_instruction(
7750 get_account_data_size(
7751 &program_id,
7752 &mint_key,
7753 &[
7754 ExtensionType::TransferFeeAmount,
7755 ExtensionType::TransferFeeAmount, ],
7757 )
7758 .unwrap(),
7759 vec![&mut mint_account],
7760 )
7761 .unwrap();
7762
7763 let mut mint_account = native_mint();
7765 set_expected_data(
7766 ExtensionType::try_calculate_account_len::<Account>(&[])
7767 .unwrap()
7768 .to_le_bytes()
7769 .to_vec(),
7770 );
7771 do_process_instruction(
7772 get_account_data_size(&program_id, &mint_key, &[]).unwrap(),
7773 vec![&mut mint_account],
7774 )
7775 .unwrap();
7776
7777 let mint_len =
7779 ExtensionType::try_calculate_account_len::<Mint>(&[ExtensionType::TransferFeeConfig])
7780 .unwrap();
7781 let mut extended_mint_account = SolanaAccount::new(
7782 Rent::default().minimum_balance(mint_len),
7783 mint_len,
7784 &program_id,
7785 );
7786 let extended_mint_key = Pubkey::new_unique();
7787 do_process_instruction(
7788 initialize_transfer_fee_config(&program_id, &extended_mint_key, None, None, 10, 4242)
7789 .unwrap(),
7790 vec![&mut extended_mint_account],
7791 )
7792 .unwrap();
7793 do_process_instruction(
7794 initialize_mint(&program_id, &extended_mint_key, &owner_key, None, 2).unwrap(),
7795 vec![&mut extended_mint_account, &mut rent_sysvar],
7796 )
7797 .unwrap();
7798
7799 set_expected_data(
7800 ExtensionType::try_calculate_account_len::<Account>(&[
7801 ExtensionType::TransferFeeAmount,
7802 ])
7803 .unwrap()
7804 .to_le_bytes()
7805 .to_vec(),
7806 );
7807 do_process_instruction(
7808 get_account_data_size(&program_id, &mint_key, &[]).unwrap(),
7809 vec![&mut extended_mint_account],
7810 )
7811 .unwrap();
7812
7813 do_process_instruction(
7814 get_account_data_size(
7815 &program_id,
7816 &mint_key,
7817 &[ExtensionType::TransferFeeAmount],
7819 )
7820 .unwrap(),
7821 vec![&mut extended_mint_account],
7822 )
7823 .unwrap();
7824
7825 let mut invalid_mint_account = SolanaAccount::new(
7827 account_minimum_balance(),
7828 Account::get_packed_len(),
7829 &program_id,
7830 );
7831 let invalid_mint_key = Pubkey::new_unique();
7832 do_process_instruction(
7833 initialize_account(&program_id, &invalid_mint_key, &mint_key, &owner_key).unwrap(),
7834 vec![
7835 &mut invalid_mint_account,
7836 &mut mint_account,
7837 &mut owner_account,
7838 &mut rent_sysvar,
7839 ],
7840 )
7841 .unwrap();
7842
7843 assert_eq!(
7844 do_process_instruction(
7845 get_account_data_size(&program_id, &invalid_mint_key, &[]).unwrap(),
7846 vec![&mut invalid_mint_account],
7847 ),
7848 Err(TokenError::InvalidMint.into())
7849 );
7850
7851 let invalid_program_id = Pubkey::new_unique();
7853 let mut invalid_mint_account = SolanaAccount::new(
7854 mint_minimum_balance(),
7855 Mint::get_packed_len(),
7856 &invalid_program_id,
7857 );
7858 let invalid_mint_key = Pubkey::new_unique();
7859 let mut instruction =
7860 initialize_mint(&program_id, &invalid_mint_key, &owner_key, None, 2).unwrap();
7861 instruction.program_id = invalid_program_id;
7862 do_process_instruction(
7863 instruction,
7864 vec![&mut invalid_mint_account, &mut rent_sysvar],
7865 )
7866 .unwrap();
7867
7868 assert_eq!(
7869 do_process_instruction(
7870 get_account_data_size(&program_id, &invalid_mint_key, &[]).unwrap(),
7871 vec![&mut invalid_mint_account],
7872 ),
7873 Err(ProgramError::IncorrectProgramId)
7874 );
7875
7876 assert_eq!(
7878 do_process_instruction(
7879 get_account_data_size(&program_id, &mint_key, &[ExtensionType::Uninitialized])
7880 .unwrap(),
7881 vec![&mut mint_account],
7882 ),
7883 Err(TokenError::ExtensionTypeMismatch.into())
7884 );
7885 assert_eq!(
7886 do_process_instruction(
7887 get_account_data_size(
7888 &program_id,
7889 &mint_key,
7890 &[
7891 ExtensionType::MemoTransfer,
7892 ExtensionType::MintCloseAuthority
7893 ]
7894 )
7895 .unwrap(),
7896 vec![&mut mint_account],
7897 ),
7898 Err(TokenError::ExtensionTypeMismatch.into())
7899 );
7900 }
7901
7902 #[test]
7903 #[serial]
7904 fn test_amount_to_ui_amount() {
7905 let program_id = crate::id();
7906 let owner_key = Pubkey::new_unique();
7907 let mint_key = Pubkey::new_unique();
7908 let mut mint_account =
7909 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
7910 let mut rent_sysvar = rent_sysvar();
7911
7912 assert_eq!(
7914 Err(TokenError::InvalidMint.into()),
7915 do_process_instruction(
7916 amount_to_ui_amount(&program_id, &mint_key, 110).unwrap(),
7917 vec![&mut mint_account],
7918 )
7919 );
7920
7921 do_process_instruction(
7923 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
7924 vec![&mut mint_account, &mut rent_sysvar],
7925 )
7926 .unwrap();
7927
7928 set_expected_data("0.23".as_bytes().to_vec());
7929 do_process_instruction(
7930 amount_to_ui_amount(&program_id, &mint_key, 23).unwrap(),
7931 vec![&mut mint_account],
7932 )
7933 .unwrap();
7934
7935 set_expected_data("1.1".as_bytes().to_vec());
7936 do_process_instruction(
7937 amount_to_ui_amount(&program_id, &mint_key, 110).unwrap(),
7938 vec![&mut mint_account],
7939 )
7940 .unwrap();
7941
7942 set_expected_data("42".as_bytes().to_vec());
7943 do_process_instruction(
7944 amount_to_ui_amount(&program_id, &mint_key, 4200).unwrap(),
7945 vec![&mut mint_account],
7946 )
7947 .unwrap();
7948
7949 set_expected_data("0".as_bytes().to_vec());
7950 do_process_instruction(
7951 amount_to_ui_amount(&program_id, &mint_key, 0).unwrap(),
7952 vec![&mut mint_account],
7953 )
7954 .unwrap();
7955 }
7956
7957 #[test]
7958 #[serial]
7959 fn test_ui_amount_to_amount() {
7960 let program_id = crate::id();
7961 let owner_key = Pubkey::new_unique();
7962 let mint_key = Pubkey::new_unique();
7963 let mut mint_account =
7964 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
7965 let mut rent_sysvar = rent_sysvar();
7966
7967 assert_eq!(
7969 Err(TokenError::InvalidMint.into()),
7970 do_process_instruction(
7971 ui_amount_to_amount(&program_id, &mint_key, "1.1").unwrap(),
7972 vec![&mut mint_account],
7973 )
7974 );
7975
7976 do_process_instruction(
7978 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
7979 vec![&mut mint_account, &mut rent_sysvar],
7980 )
7981 .unwrap();
7982
7983 set_expected_data(23u64.to_le_bytes().to_vec());
7984 do_process_instruction(
7985 ui_amount_to_amount(&program_id, &mint_key, "0.23").unwrap(),
7986 vec![&mut mint_account],
7987 )
7988 .unwrap();
7989
7990 set_expected_data(20u64.to_le_bytes().to_vec());
7991 do_process_instruction(
7992 ui_amount_to_amount(&program_id, &mint_key, "0.20").unwrap(),
7993 vec![&mut mint_account],
7994 )
7995 .unwrap();
7996
7997 set_expected_data(20u64.to_le_bytes().to_vec());
7998 do_process_instruction(
7999 ui_amount_to_amount(&program_id, &mint_key, "0.2000").unwrap(),
8000 vec![&mut mint_account],
8001 )
8002 .unwrap();
8003
8004 set_expected_data(20u64.to_le_bytes().to_vec());
8005 do_process_instruction(
8006 ui_amount_to_amount(&program_id, &mint_key, ".20").unwrap(),
8007 vec![&mut mint_account],
8008 )
8009 .unwrap();
8010
8011 set_expected_data(110u64.to_le_bytes().to_vec());
8012 do_process_instruction(
8013 ui_amount_to_amount(&program_id, &mint_key, "1.1").unwrap(),
8014 vec![&mut mint_account],
8015 )
8016 .unwrap();
8017
8018 set_expected_data(110u64.to_le_bytes().to_vec());
8019 do_process_instruction(
8020 ui_amount_to_amount(&program_id, &mint_key, "1.10").unwrap(),
8021 vec![&mut mint_account],
8022 )
8023 .unwrap();
8024
8025 set_expected_data(4200u64.to_le_bytes().to_vec());
8026 do_process_instruction(
8027 ui_amount_to_amount(&program_id, &mint_key, "42").unwrap(),
8028 vec![&mut mint_account],
8029 )
8030 .unwrap();
8031
8032 set_expected_data(4200u64.to_le_bytes().to_vec());
8033 do_process_instruction(
8034 ui_amount_to_amount(&program_id, &mint_key, "42.").unwrap(),
8035 vec![&mut mint_account],
8036 )
8037 .unwrap();
8038
8039 set_expected_data(0u64.to_le_bytes().to_vec());
8040 do_process_instruction(
8041 ui_amount_to_amount(&program_id, &mint_key, "0").unwrap(),
8042 vec![&mut mint_account],
8043 )
8044 .unwrap();
8045
8046 assert_eq!(
8048 Err(ProgramError::InvalidArgument),
8049 do_process_instruction(
8050 ui_amount_to_amount(&program_id, &mint_key, "").unwrap(),
8051 vec![&mut mint_account],
8052 )
8053 );
8054 assert_eq!(
8055 Err(ProgramError::InvalidArgument),
8056 do_process_instruction(
8057 ui_amount_to_amount(&program_id, &mint_key, ".").unwrap(),
8058 vec![&mut mint_account],
8059 )
8060 );
8061 assert_eq!(
8062 Err(ProgramError::InvalidArgument),
8063 do_process_instruction(
8064 ui_amount_to_amount(&program_id, &mint_key, "0.111").unwrap(),
8065 vec![&mut mint_account],
8066 )
8067 );
8068 assert_eq!(
8069 Err(ProgramError::InvalidArgument),
8070 do_process_instruction(
8071 ui_amount_to_amount(&program_id, &mint_key, "0.t").unwrap(),
8072 vec![&mut mint_account],
8073 )
8074 );
8075 }
8076
8077 #[test]
8078 #[serial]
8079 fn test_withdraw_excess_lamports_from_multisig() {
8080 {
8081 use std::sync::Once;
8082 static ONCE: Once = Once::new();
8083
8084 ONCE.call_once(|| {
8085 solana_sdk::program_stubs::set_syscall_stubs(Box::new(SyscallStubs {}));
8086 });
8087 }
8088 let program_id = crate::id();
8089
8090 let mut lamports = 0;
8091 let mut destination_data = vec![];
8092 let system_program_id = system_program::id();
8093 let destination_key = Pubkey::new_unique();
8094 let destination_info = AccountInfo::new(
8095 &destination_key,
8096 true,
8097 false,
8098 &mut lamports,
8099 &mut destination_data,
8100 &system_program_id,
8101 false,
8102 Epoch::default(),
8103 );
8104
8105 let multisig_key = Pubkey::new_unique();
8106 let mut multisig_account = SolanaAccount::new(0, Multisig::get_packed_len(), &program_id);
8107 let excess_lamports = 4_000_000_000_000;
8108 multisig_account.lamports = excess_lamports + multisig_minimum_balance();
8109 let mut signer_keys = [Pubkey::default(); MAX_SIGNERS];
8110
8111 for signer_key in signer_keys.iter_mut().take(MAX_SIGNERS) {
8112 *signer_key = Pubkey::new_unique();
8113 }
8114 let signer_refs: Vec<&Pubkey> = signer_keys.iter().collect();
8115 let mut signer_lamports = 0;
8116 let mut signer_data = vec![];
8117 let mut signers: Vec<AccountInfo<'_>> = vec![
8118 AccountInfo::new(
8119 &destination_key,
8120 true,
8121 false,
8122 &mut signer_lamports,
8123 &mut signer_data,
8124 &program_id,
8125 false,
8126 Epoch::default(),
8127 );
8128 MAX_SIGNERS + 1
8129 ];
8130 for (signer, key) in signers.iter_mut().zip(&signer_keys) {
8131 signer.key = key;
8132 }
8133
8134 let mut multisig =
8135 Multisig::unpack_unchecked(&vec![0; Multisig::get_packed_len()]).unwrap();
8136 multisig.m = MAX_SIGNERS as u8;
8137 multisig.n = MAX_SIGNERS as u8;
8138 multisig.signers = signer_keys;
8139 multisig.is_initialized = true;
8140 Multisig::pack(multisig, &mut multisig_account.data).unwrap();
8141
8142 let multisig_info: AccountInfo = (&multisig_key, true, &mut multisig_account).into();
8143
8144 let mut signers_infos = vec![
8145 multisig_info.clone(),
8146 destination_info.clone(),
8147 multisig_info.clone(),
8148 ];
8149 signers_infos.extend(signers);
8150 do_process_instruction_dups(
8151 withdraw_excess_lamports(
8152 &program_id,
8153 &multisig_key,
8154 &destination_key,
8155 &multisig_key,
8156 &signer_refs,
8157 )
8158 .unwrap(),
8159 signers_infos,
8160 )
8161 .unwrap();
8162
8163 assert_eq!(destination_info.lamports(), excess_lamports);
8164 }
8165
8166 #[test]
8167 #[serial]
8168 fn test_withdraw_excess_lamports_from_account() {
8169 let excess_lamports = 4_000_000_000_000;
8170
8171 let program_id = crate::id();
8172 let account_key = Pubkey::new_unique();
8173 let mut account_account = SolanaAccount::new(
8174 excess_lamports + account_minimum_balance(),
8175 Account::get_packed_len(),
8176 &program_id,
8177 );
8178
8179 let system_program_id = system_program::id();
8180 let owner_key = Pubkey::new_unique();
8181
8182 let mut destination_lamports = 0;
8183 let mut destination_data = vec![];
8184 let destination_key = Pubkey::new_unique();
8185 let destination_info = AccountInfo::new(
8186 &destination_key,
8187 true,
8188 false,
8189 &mut destination_lamports,
8190 &mut destination_data,
8191 &system_program_id,
8192 false,
8193 Epoch::default(),
8194 );
8195 let mint_key = Pubkey::new_unique();
8196 let mut mint_account =
8197 SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
8198
8199 let mut rent_sysvar = rent_sysvar();
8200 do_process_instruction(
8201 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
8202 vec![&mut mint_account, &mut rent_sysvar],
8203 )
8204 .unwrap();
8205
8206 let mint_info = AccountInfo::new(
8207 &mint_key,
8208 true,
8209 false,
8210 &mut mint_account.lamports,
8211 &mut mint_account.data,
8212 &program_id,
8213 false,
8214 Epoch::default(),
8215 );
8216
8217 let account_info: AccountInfo = (&account_key, true, &mut account_account).into();
8218
8219 do_process_instruction_dups(
8220 initialize_account3(&program_id, &account_key, &mint_key, &account_key).unwrap(),
8221 vec![account_info.clone(), mint_info.clone()],
8222 )
8223 .unwrap();
8224
8225 do_process_instruction_dups(
8226 withdraw_excess_lamports(
8227 &program_id,
8228 &account_key,
8229 &destination_key,
8230 &account_key,
8231 &[],
8232 )
8233 .unwrap(),
8234 vec![
8235 account_info.clone(),
8236 destination_info.clone(),
8237 account_info.clone(),
8238 ],
8239 )
8240 .unwrap();
8241
8242 assert_eq!(destination_info.lamports(), excess_lamports);
8243 }
8244
8245 #[test]
8246 #[serial]
8247 fn test_withdraw_excess_lamports_from_mint() {
8248 let excess_lamports = 4_000_000_000_000;
8249
8250 let program_id = crate::id();
8251 let system_program_id = system_program::id();
8252
8253 let mut destination_lamports = 0;
8254 let mut destination_data = vec![];
8255 let destination_key = Pubkey::new_unique();
8256 let destination_info = AccountInfo::new(
8257 &destination_key,
8258 true,
8259 false,
8260 &mut destination_lamports,
8261 &mut destination_data,
8262 &system_program_id,
8263 false,
8264 Epoch::default(),
8265 );
8266 let mint_key = Pubkey::new_unique();
8267 let mut mint_account = SolanaAccount::new(
8268 excess_lamports + mint_minimum_balance(),
8269 Mint::get_packed_len(),
8270 &program_id,
8271 );
8272 let mut rent_sysvar = rent_sysvar();
8273
8274 do_process_instruction(
8275 initialize_mint(&program_id, &mint_key, &mint_key, None, 2).unwrap(),
8276 vec![&mut mint_account, &mut rent_sysvar],
8277 )
8278 .unwrap();
8279
8280 let mint_info: AccountInfo = (&mint_key, true, &mut mint_account).into();
8281
8282 do_process_instruction_dups(
8283 withdraw_excess_lamports(&program_id, &mint_key, &destination_key, &mint_key, &[])
8284 .unwrap(),
8285 vec![
8286 mint_info.clone(),
8287 destination_info.clone(),
8288 mint_info.clone(),
8289 ],
8290 )
8291 .unwrap();
8292
8293 assert_eq!(destination_info.lamports(), excess_lamports);
8294 }
8295}