1use crate::{
4 amount_to_ui_amount_string_trimmed,
5 error::TokenError,
6 instruction::{is_valid_signer_index, AuthorityType, TokenInstruction, MAX_SIGNERS},
7 state::{Account, AccountState, Mint, Multisig},
8 try_ui_amount_into_amount,
9};
10use solana_program::{
11 account_info::{next_account_info, AccountInfo},
12 entrypoint::ProgramResult,
13 msg,
14 program::set_return_data,
15 program_error::ProgramError,
16 program_memory::sol_memcmp,
17 program_option::COption,
18 program_pack::{IsInitialized, Pack},
19 pubkey::{Pubkey, PUBKEY_BYTES},
20 system_program,
21 sysvar::{rent::Rent, Sysvar},
22};
23
24pub struct Processor {}
26impl Processor {
27 fn _process_initialize_mint(
28 accounts: &[AccountInfo],
29 decimals: u8,
30 mint_authority: Pubkey,
31 freeze_authority: COption<Pubkey>,
32 rent_sysvar_account: bool,
33 ) -> ProgramResult {
34 let account_info_iter = &mut accounts.iter();
35 let mint_info = next_account_info(account_info_iter)?;
36 let mint_data_len = mint_info.data_len();
37 let rent = if rent_sysvar_account {
38 Rent::from_account_info(next_account_info(account_info_iter)?)?
39 } else {
40 Rent::get()?
41 };
42
43 let mut mint = Mint::unpack_unchecked(&mint_info.data.borrow())?;
44 if mint.is_initialized {
45 return Err(TokenError::AlreadyInUse.into());
46 }
47
48 if !rent.is_exempt(mint_info.lamports(), mint_data_len) {
49 return Err(TokenError::NotRentExempt.into());
50 }
51
52 mint.mint_authority = COption::Some(mint_authority);
53 mint.decimals = decimals;
54 mint.is_initialized = true;
55 mint.freeze_authority = freeze_authority;
56
57 Mint::pack(mint, &mut mint_info.data.borrow_mut())?;
58
59 Ok(())
60 }
61
62 pub fn process_initialize_mint(
64 accounts: &[AccountInfo],
65 decimals: u8,
66 mint_authority: Pubkey,
67 freeze_authority: COption<Pubkey>,
68 ) -> ProgramResult {
69 Self::_process_initialize_mint(accounts, decimals, mint_authority, freeze_authority, true)
70 }
71
72 pub fn process_initialize_mint2(
74 accounts: &[AccountInfo],
75 decimals: u8,
76 mint_authority: Pubkey,
77 freeze_authority: COption<Pubkey>,
78 ) -> ProgramResult {
79 Self::_process_initialize_mint(accounts, decimals, mint_authority, freeze_authority, false)
80 }
81
82 fn _process_initialize_account(
83 program_id: &Pubkey,
84 accounts: &[AccountInfo],
85 owner: Option<&Pubkey>,
86 rent_sysvar_account: bool,
87 ) -> ProgramResult {
88 let account_info_iter = &mut accounts.iter();
89 let new_account_info = next_account_info(account_info_iter)?;
90 let mint_info = next_account_info(account_info_iter)?;
91 let owner = if let Some(owner) = owner {
92 owner
93 } else {
94 next_account_info(account_info_iter)?.key
95 };
96 let new_account_info_data_len = new_account_info.data_len();
97 let rent = if rent_sysvar_account {
98 Rent::from_account_info(next_account_info(account_info_iter)?)?
99 } else {
100 Rent::get()?
101 };
102
103 let mut account = Account::unpack_unchecked(&new_account_info.data.borrow())?;
104 if account.is_initialized() {
105 return Err(TokenError::AlreadyInUse.into());
106 }
107
108 if !rent.is_exempt(new_account_info.lamports(), new_account_info_data_len) {
109 return Err(TokenError::NotRentExempt.into());
110 }
111
112 let is_native_mint = Self::cmp_pubkeys(mint_info.key, &crate::native_mint::id());
113 if !is_native_mint {
114 Self::check_account_owner(program_id, mint_info)?;
115 let _ = Mint::unpack(&mint_info.data.borrow_mut())
116 .map_err(|_| Into::<ProgramError>::into(TokenError::InvalidMint))?;
117 }
118
119 account.mint = *mint_info.key;
120 account.owner = *owner;
121 account.close_authority = COption::None;
122 account.delegate = COption::None;
123 account.delegated_amount = 0;
124 account.state = AccountState::Initialized;
125 if is_native_mint {
126 let rent_exempt_reserve = rent.minimum_balance(new_account_info_data_len);
127 account.is_native = COption::Some(rent_exempt_reserve);
128 account.amount = new_account_info
129 .lamports()
130 .checked_sub(rent_exempt_reserve)
131 .ok_or(TokenError::Overflow)?;
132 } else {
133 account.is_native = COption::None;
134 account.amount = 0;
135 };
136
137 Account::pack(account, &mut new_account_info.data.borrow_mut())?;
138
139 Ok(())
140 }
141
142 pub fn process_initialize_account(
144 program_id: &Pubkey,
145 accounts: &[AccountInfo],
146 ) -> ProgramResult {
147 Self::_process_initialize_account(program_id, accounts, None, true)
148 }
149
150 pub fn process_initialize_account2(
152 program_id: &Pubkey,
153 accounts: &[AccountInfo],
154 owner: Pubkey,
155 ) -> ProgramResult {
156 Self::_process_initialize_account(program_id, accounts, Some(&owner), true)
157 }
158
159 pub fn process_initialize_account3(
161 program_id: &Pubkey,
162 accounts: &[AccountInfo],
163 owner: Pubkey,
164 ) -> ProgramResult {
165 Self::_process_initialize_account(program_id, accounts, Some(&owner), false)
166 }
167
168 fn _process_initialize_multisig(
169 accounts: &[AccountInfo],
170 m: u8,
171 rent_sysvar_account: bool,
172 ) -> ProgramResult {
173 let account_info_iter = &mut accounts.iter();
174 let multisig_info = next_account_info(account_info_iter)?;
175 let multisig_info_data_len = multisig_info.data_len();
176 let rent = if rent_sysvar_account {
177 Rent::from_account_info(next_account_info(account_info_iter)?)?
178 } else {
179 Rent::get()?
180 };
181
182 let mut multisig = Multisig::unpack_unchecked(&multisig_info.data.borrow())?;
183 if multisig.is_initialized {
184 return Err(TokenError::AlreadyInUse.into());
185 }
186
187 if !rent.is_exempt(multisig_info.lamports(), multisig_info_data_len) {
188 return Err(TokenError::NotRentExempt.into());
189 }
190
191 let signer_infos = account_info_iter.as_slice();
192 multisig.m = m;
193 multisig.n = signer_infos.len() as u8;
194 if !is_valid_signer_index(multisig.n as usize) {
195 return Err(TokenError::InvalidNumberOfProvidedSigners.into());
196 }
197 if !is_valid_signer_index(multisig.m as usize) {
198 return Err(TokenError::InvalidNumberOfRequiredSigners.into());
199 }
200 for (i, signer_info) in signer_infos.iter().enumerate() {
201 multisig.signers[i] = *signer_info.key;
202 }
203 multisig.is_initialized = true;
204
205 Multisig::pack(multisig, &mut multisig_info.data.borrow_mut())?;
206
207 Ok(())
208 }
209
210 pub fn process_initialize_multisig(accounts: &[AccountInfo], m: u8) -> ProgramResult {
212 Self::_process_initialize_multisig(accounts, m, true)
213 }
214
215 pub fn process_initialize_multisig2(accounts: &[AccountInfo], m: u8) -> ProgramResult {
217 Self::_process_initialize_multisig(accounts, m, false)
218 }
219
220 pub fn process_transfer(
222 program_id: &Pubkey,
223 accounts: &[AccountInfo],
224 amount: u64,
225 expected_decimals: Option<u8>,
226 ) -> ProgramResult {
227 let account_info_iter = &mut accounts.iter();
228
229 let source_account_info = next_account_info(account_info_iter)?;
230
231 let expected_mint_info = if let Some(expected_decimals) = expected_decimals {
232 Some((next_account_info(account_info_iter)?, expected_decimals))
233 } else {
234 None
235 };
236
237 let destination_account_info = next_account_info(account_info_iter)?;
238 let authority_info = next_account_info(account_info_iter)?;
239
240 let mut source_account = Account::unpack(&source_account_info.data.borrow())?;
241 let mut destination_account = Account::unpack(&destination_account_info.data.borrow())?;
242
243 if source_account.is_frozen() || destination_account.is_frozen() {
244 return Err(TokenError::AccountFrozen.into());
245 }
246 if source_account.amount < amount {
247 return Err(TokenError::InsufficientFunds.into());
248 }
249 if !Self::cmp_pubkeys(&source_account.mint, &destination_account.mint) {
250 return Err(TokenError::MintMismatch.into());
251 }
252
253 if let Some((mint_info, expected_decimals)) = expected_mint_info {
254 if !Self::cmp_pubkeys(mint_info.key, &source_account.mint) {
255 return Err(TokenError::MintMismatch.into());
256 }
257
258 let mint = Mint::unpack(&mint_info.data.borrow_mut())?;
259 if expected_decimals != mint.decimals {
260 return Err(TokenError::MintDecimalsMismatch.into());
261 }
262 }
263
264 let self_transfer =
265 Self::cmp_pubkeys(source_account_info.key, destination_account_info.key);
266
267 match source_account.delegate {
268 COption::Some(ref delegate) if Self::cmp_pubkeys(authority_info.key, delegate) => {
269 Self::validate_owner(
270 program_id,
271 delegate,
272 authority_info,
273 account_info_iter.as_slice(),
274 )?;
275 if source_account.delegated_amount < amount {
276 return Err(TokenError::InsufficientFunds.into());
277 }
278 if !self_transfer {
279 source_account.delegated_amount = source_account
280 .delegated_amount
281 .checked_sub(amount)
282 .ok_or(TokenError::Overflow)?;
283 if source_account.delegated_amount == 0 {
284 source_account.delegate = COption::None;
285 }
286 }
287 }
288 _ => Self::validate_owner(
289 program_id,
290 &source_account.owner,
291 authority_info,
292 account_info_iter.as_slice(),
293 )?,
294 };
295
296 if self_transfer || amount == 0 {
297 Self::check_account_owner(program_id, source_account_info)?;
298 Self::check_account_owner(program_id, destination_account_info)?;
299 }
300
301 if self_transfer {
304 return Ok(());
305 }
306
307 source_account.amount = source_account
308 .amount
309 .checked_sub(amount)
310 .ok_or(TokenError::Overflow)?;
311 destination_account.amount = destination_account
312 .amount
313 .checked_add(amount)
314 .ok_or(TokenError::Overflow)?;
315
316 if source_account.is_native() {
317 let source_starting_lamports = source_account_info.lamports();
318 **source_account_info.lamports.borrow_mut() = source_starting_lamports
319 .checked_sub(amount)
320 .ok_or(TokenError::Overflow)?;
321
322 let destination_starting_lamports = destination_account_info.lamports();
323 **destination_account_info.lamports.borrow_mut() = destination_starting_lamports
324 .checked_add(amount)
325 .ok_or(TokenError::Overflow)?;
326 }
327
328 Account::pack(source_account, &mut source_account_info.data.borrow_mut())?;
329 Account::pack(
330 destination_account,
331 &mut destination_account_info.data.borrow_mut(),
332 )?;
333
334 Ok(())
335 }
336
337 pub fn process_approve(
339 program_id: &Pubkey,
340 accounts: &[AccountInfo],
341 amount: u64,
342 expected_decimals: Option<u8>,
343 ) -> ProgramResult {
344 let account_info_iter = &mut accounts.iter();
345
346 let source_account_info = next_account_info(account_info_iter)?;
347
348 let expected_mint_info = if let Some(expected_decimals) = expected_decimals {
349 Some((next_account_info(account_info_iter)?, expected_decimals))
350 } else {
351 None
352 };
353 let delegate_info = next_account_info(account_info_iter)?;
354 let owner_info = next_account_info(account_info_iter)?;
355
356 let mut source_account = Account::unpack(&source_account_info.data.borrow())?;
357
358 if source_account.is_frozen() {
359 return Err(TokenError::AccountFrozen.into());
360 }
361
362 if let Some((mint_info, expected_decimals)) = expected_mint_info {
363 if !Self::cmp_pubkeys(mint_info.key, &source_account.mint) {
364 return Err(TokenError::MintMismatch.into());
365 }
366
367 let mint = Mint::unpack(&mint_info.data.borrow_mut())?;
368 if expected_decimals != mint.decimals {
369 return Err(TokenError::MintDecimalsMismatch.into());
370 }
371 }
372
373 Self::validate_owner(
374 program_id,
375 &source_account.owner,
376 owner_info,
377 account_info_iter.as_slice(),
378 )?;
379
380 source_account.delegate = COption::Some(*delegate_info.key);
381 source_account.delegated_amount = amount;
382
383 Account::pack(source_account, &mut source_account_info.data.borrow_mut())?;
384
385 Ok(())
386 }
387
388 pub fn process_revoke(program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult {
390 let account_info_iter = &mut accounts.iter();
391 let source_account_info = next_account_info(account_info_iter)?;
392
393 let mut source_account = Account::unpack(&source_account_info.data.borrow())?;
394
395 let owner_info = next_account_info(account_info_iter)?;
396
397 if source_account.is_frozen() {
398 return Err(TokenError::AccountFrozen.into());
399 }
400
401 Self::validate_owner(
402 program_id,
403 &source_account.owner,
404 owner_info,
405 account_info_iter.as_slice(),
406 )?;
407
408 source_account.delegate = COption::None;
409 source_account.delegated_amount = 0;
410
411 Account::pack(source_account, &mut source_account_info.data.borrow_mut())?;
412
413 Ok(())
414 }
415
416 pub fn process_set_authority(
418 program_id: &Pubkey,
419 accounts: &[AccountInfo],
420 authority_type: AuthorityType,
421 new_authority: COption<Pubkey>,
422 ) -> ProgramResult {
423 let account_info_iter = &mut accounts.iter();
424 let account_info = next_account_info(account_info_iter)?;
425 let authority_info = next_account_info(account_info_iter)?;
426
427 if account_info.data_len() == Account::get_packed_len() {
428 let mut account = Account::unpack(&account_info.data.borrow())?;
429
430 if account.is_frozen() {
431 return Err(TokenError::AccountFrozen.into());
432 }
433
434 match authority_type {
435 AuthorityType::AccountOwner => {
436 Self::validate_owner(
437 program_id,
438 &account.owner,
439 authority_info,
440 account_info_iter.as_slice(),
441 )?;
442
443 if let COption::Some(authority) = new_authority {
444 account.owner = authority;
445 } else {
446 return Err(TokenError::InvalidInstruction.into());
447 }
448
449 account.delegate = COption::None;
450 account.delegated_amount = 0;
451
452 if account.is_native() {
453 account.close_authority = COption::None;
454 }
455 }
456 AuthorityType::CloseAccount => {
457 let authority = account.close_authority.unwrap_or(account.owner);
458 Self::validate_owner(
459 program_id,
460 &authority,
461 authority_info,
462 account_info_iter.as_slice(),
463 )?;
464 account.close_authority = new_authority;
465 }
466 _ => {
467 return Err(TokenError::AuthorityTypeNotSupported.into());
468 }
469 }
470 Account::pack(account, &mut account_info.data.borrow_mut())?;
471 } else if account_info.data_len() == Mint::get_packed_len() {
472 let mut mint = Mint::unpack(&account_info.data.borrow())?;
473 match authority_type {
474 AuthorityType::MintTokens => {
475 let mint_authority = mint
478 .mint_authority
479 .ok_or(Into::<ProgramError>::into(TokenError::FixedSupply))?;
480 Self::validate_owner(
481 program_id,
482 &mint_authority,
483 authority_info,
484 account_info_iter.as_slice(),
485 )?;
486 mint.mint_authority = new_authority;
487 }
488 AuthorityType::FreezeAccount => {
489 let freeze_authority = mint
492 .freeze_authority
493 .ok_or(Into::<ProgramError>::into(TokenError::MintCannotFreeze))?;
494 Self::validate_owner(
495 program_id,
496 &freeze_authority,
497 authority_info,
498 account_info_iter.as_slice(),
499 )?;
500 mint.freeze_authority = new_authority;
501 }
502 _ => {
503 return Err(TokenError::AuthorityTypeNotSupported.into());
504 }
505 }
506 Mint::pack(mint, &mut account_info.data.borrow_mut())?;
507 } else {
508 return Err(ProgramError::InvalidArgument);
509 }
510
511 Ok(())
512 }
513
514 pub fn process_mint_to(
516 program_id: &Pubkey,
517 accounts: &[AccountInfo],
518 amount: u64,
519 expected_decimals: Option<u8>,
520 ) -> ProgramResult {
521 let account_info_iter = &mut accounts.iter();
522 let mint_info = next_account_info(account_info_iter)?;
523 let destination_account_info = next_account_info(account_info_iter)?;
524 let owner_info = next_account_info(account_info_iter)?;
525
526 let mut destination_account = Account::unpack(&destination_account_info.data.borrow())?;
527 if destination_account.is_frozen() {
528 return Err(TokenError::AccountFrozen.into());
529 }
530
531 if destination_account.is_native() {
532 return Err(TokenError::NativeNotSupported.into());
533 }
534 if !Self::cmp_pubkeys(mint_info.key, &destination_account.mint) {
535 return Err(TokenError::MintMismatch.into());
536 }
537
538 let mut mint = Mint::unpack(&mint_info.data.borrow())?;
539 if let Some(expected_decimals) = expected_decimals {
540 if expected_decimals != mint.decimals {
541 return Err(TokenError::MintDecimalsMismatch.into());
542 }
543 }
544
545 match mint.mint_authority {
546 COption::Some(mint_authority) => Self::validate_owner(
547 program_id,
548 &mint_authority,
549 owner_info,
550 account_info_iter.as_slice(),
551 )?,
552 COption::None => return Err(TokenError::FixedSupply.into()),
553 }
554
555 if amount == 0 {
556 Self::check_account_owner(program_id, mint_info)?;
557 Self::check_account_owner(program_id, destination_account_info)?;
558 }
559
560 destination_account.amount = destination_account
561 .amount
562 .checked_add(amount)
563 .ok_or(TokenError::Overflow)?;
564
565 mint.supply = mint
566 .supply
567 .checked_add(amount)
568 .ok_or(TokenError::Overflow)?;
569
570 Account::pack(
571 destination_account,
572 &mut destination_account_info.data.borrow_mut(),
573 )?;
574 Mint::pack(mint, &mut mint_info.data.borrow_mut())?;
575
576 Ok(())
577 }
578
579 pub fn process_burn(
581 program_id: &Pubkey,
582 accounts: &[AccountInfo],
583 amount: u64,
584 expected_decimals: Option<u8>,
585 ) -> ProgramResult {
586 let account_info_iter = &mut accounts.iter();
587
588 let source_account_info = next_account_info(account_info_iter)?;
589 let mint_info = next_account_info(account_info_iter)?;
590 let authority_info = next_account_info(account_info_iter)?;
591
592 let mut source_account = Account::unpack(&source_account_info.data.borrow())?;
593 let mut mint = Mint::unpack(&mint_info.data.borrow())?;
594
595 if source_account.is_frozen() {
596 return Err(TokenError::AccountFrozen.into());
597 }
598 if source_account.is_native() {
599 return Err(TokenError::NativeNotSupported.into());
600 }
601 if source_account.amount < amount {
602 return Err(TokenError::InsufficientFunds.into());
603 }
604 if !Self::cmp_pubkeys(mint_info.key, &source_account.mint) {
605 return Err(TokenError::MintMismatch.into());
606 }
607
608 if let Some(expected_decimals) = expected_decimals {
609 if expected_decimals != mint.decimals {
610 return Err(TokenError::MintDecimalsMismatch.into());
611 }
612 }
613
614 if !source_account.is_owned_by_system_program_or_incinerator() {
615 match source_account.delegate {
616 COption::Some(ref delegate) if Self::cmp_pubkeys(authority_info.key, delegate) => {
617 Self::validate_owner(
618 program_id,
619 delegate,
620 authority_info,
621 account_info_iter.as_slice(),
622 )?;
623
624 if source_account.delegated_amount < amount {
625 return Err(TokenError::InsufficientFunds.into());
626 }
627 source_account.delegated_amount = source_account
628 .delegated_amount
629 .checked_sub(amount)
630 .ok_or(TokenError::Overflow)?;
631 if source_account.delegated_amount == 0 {
632 source_account.delegate = COption::None;
633 }
634 }
635 _ => Self::validate_owner(
636 program_id,
637 &source_account.owner,
638 authority_info,
639 account_info_iter.as_slice(),
640 )?,
641 }
642 }
643
644 if amount == 0 {
645 Self::check_account_owner(program_id, source_account_info)?;
646 Self::check_account_owner(program_id, mint_info)?;
647 }
648
649 source_account.amount = source_account
650 .amount
651 .checked_sub(amount)
652 .ok_or(TokenError::Overflow)?;
653 mint.supply = mint
654 .supply
655 .checked_sub(amount)
656 .ok_or(TokenError::Overflow)?;
657
658 Account::pack(source_account, &mut source_account_info.data.borrow_mut())?;
659 Mint::pack(mint, &mut mint_info.data.borrow_mut())?;
660
661 Ok(())
662 }
663
664 pub fn process_close_account(program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult {
666 let account_info_iter = &mut accounts.iter();
667 let source_account_info = next_account_info(account_info_iter)?;
668 let destination_account_info = next_account_info(account_info_iter)?;
669 let authority_info = next_account_info(account_info_iter)?;
670
671 if Self::cmp_pubkeys(source_account_info.key, destination_account_info.key) {
672 return Err(ProgramError::InvalidAccountData);
673 }
674
675 let source_account = Account::unpack(&source_account_info.data.borrow())?;
676 if !source_account.is_native() && source_account.amount != 0 {
677 return Err(TokenError::NonNativeHasBalance.into());
678 }
679
680 let authority = source_account
681 .close_authority
682 .unwrap_or(source_account.owner);
683 if !source_account.is_owned_by_system_program_or_incinerator() {
684 Self::validate_owner(
685 program_id,
686 &authority,
687 authority_info,
688 account_info_iter.as_slice(),
689 )?;
690 } else if !solana_program::incinerator::check_id(destination_account_info.key) {
691 return Err(ProgramError::InvalidAccountData);
692 }
693
694 let destination_starting_lamports = destination_account_info.lamports();
695 **destination_account_info.lamports.borrow_mut() = destination_starting_lamports
696 .checked_add(source_account_info.lamports())
697 .ok_or(TokenError::Overflow)?;
698
699 **source_account_info.lamports.borrow_mut() = 0;
700 delete_account(source_account_info)?;
701
702 Ok(())
703 }
704
705 pub fn process_toggle_freeze_account(
708 program_id: &Pubkey,
709 accounts: &[AccountInfo],
710 freeze: bool,
711 ) -> ProgramResult {
712 let account_info_iter = &mut accounts.iter();
713 let source_account_info = next_account_info(account_info_iter)?;
714 let mint_info = next_account_info(account_info_iter)?;
715 let authority_info = next_account_info(account_info_iter)?;
716
717 let mut source_account = Account::unpack(&source_account_info.data.borrow())?;
718 if freeze && source_account.is_frozen() || !freeze && !source_account.is_frozen() {
719 return Err(TokenError::InvalidState.into());
720 }
721 if source_account.is_native() {
722 return Err(TokenError::NativeNotSupported.into());
723 }
724 if !Self::cmp_pubkeys(mint_info.key, &source_account.mint) {
725 return Err(TokenError::MintMismatch.into());
726 }
727
728 let mint = Mint::unpack(&mint_info.data.borrow_mut())?;
729 match mint.freeze_authority {
730 COption::Some(authority) => Self::validate_owner(
731 program_id,
732 &authority,
733 authority_info,
734 account_info_iter.as_slice(),
735 ),
736 COption::None => Err(TokenError::MintCannotFreeze.into()),
737 }?;
738
739 source_account.state = if freeze {
740 AccountState::Frozen
741 } else {
742 AccountState::Initialized
743 };
744
745 Account::pack(source_account, &mut source_account_info.data.borrow_mut())?;
746
747 Ok(())
748 }
749
750 pub fn process_sync_native(program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult {
752 let account_info_iter = &mut accounts.iter();
753 let native_account_info = next_account_info(account_info_iter)?;
754 Self::check_account_owner(program_id, native_account_info)?;
755
756 let mut native_account = Account::unpack(&native_account_info.data.borrow())?;
757
758 if let COption::Some(rent_exempt_reserve) = native_account.is_native {
759 let new_amount = native_account_info
760 .lamports()
761 .checked_sub(rent_exempt_reserve)
762 .ok_or(TokenError::Overflow)?;
763 if new_amount < native_account.amount {
764 return Err(TokenError::InvalidState.into());
765 }
766 native_account.amount = new_amount;
767 } else {
768 return Err(TokenError::NonNativeNotSupported.into());
769 }
770
771 Account::pack(native_account, &mut native_account_info.data.borrow_mut())?;
772 Ok(())
773 }
774
775 pub fn process_get_account_data_size(
777 program_id: &Pubkey,
778 accounts: &[AccountInfo],
779 ) -> ProgramResult {
780 let account_info_iter = &mut accounts.iter();
781 let mint_info = next_account_info(account_info_iter)?;
783 Self::check_account_owner(program_id, mint_info)?;
784 let _ = Mint::unpack(&mint_info.data.borrow())
785 .map_err(|_| Into::<ProgramError>::into(TokenError::InvalidMint))?;
786 set_return_data(&Account::LEN.to_le_bytes());
787 Ok(())
788 }
789
790 pub fn process_initialize_immutable_owner(accounts: &[AccountInfo]) -> ProgramResult {
792 let account_info_iter = &mut accounts.iter();
793 let token_account_info = next_account_info(account_info_iter)?;
794 let account = Account::unpack_unchecked(&token_account_info.data.borrow())?;
795 if account.is_initialized() {
796 return Err(TokenError::AlreadyInUse.into());
797 }
798 msg!("Please upgrade to SPL Token 2022 for immutable owner support");
799 Ok(())
800 }
801
802 pub fn process_amount_to_ui_amount(
804 program_id: &Pubkey,
805 accounts: &[AccountInfo],
806 amount: u64,
807 ) -> ProgramResult {
808 let account_info_iter = &mut accounts.iter();
809 let mint_info = next_account_info(account_info_iter)?;
810 Self::check_account_owner(program_id, mint_info)?;
811
812 let mint = Mint::unpack(&mint_info.data.borrow_mut())
813 .map_err(|_| Into::<ProgramError>::into(TokenError::InvalidMint))?;
814 let ui_amount = amount_to_ui_amount_string_trimmed(amount, mint.decimals);
815
816 set_return_data(&ui_amount.into_bytes());
817 Ok(())
818 }
819
820 pub fn process_ui_amount_to_amount(
822 program_id: &Pubkey,
823 accounts: &[AccountInfo],
824 ui_amount: &str,
825 ) -> ProgramResult {
826 let account_info_iter = &mut accounts.iter();
827 let mint_info = next_account_info(account_info_iter)?;
828 Self::check_account_owner(program_id, mint_info)?;
829
830 let mint = Mint::unpack(&mint_info.data.borrow_mut())
831 .map_err(|_| Into::<ProgramError>::into(TokenError::InvalidMint))?;
832 let amount = try_ui_amount_into_amount(ui_amount.to_string(), mint.decimals)?;
833
834 set_return_data(&amount.to_le_bytes());
835 Ok(())
836 }
837
838 pub fn process(program_id: &Pubkey, accounts: &[AccountInfo], input: &[u8]) -> ProgramResult {
840 let instruction = TokenInstruction::unpack(input)?;
841
842 match instruction {
843 TokenInstruction::InitializeMint {
844 decimals,
845 mint_authority,
846 freeze_authority,
847 } => {
848 msg!("Instruction: InitializeMint");
849 Self::process_initialize_mint(accounts, decimals, mint_authority, freeze_authority)
850 }
851 TokenInstruction::InitializeMint2 {
852 decimals,
853 mint_authority,
854 freeze_authority,
855 } => {
856 msg!("Instruction: InitializeMint2");
857 Self::process_initialize_mint2(accounts, decimals, mint_authority, freeze_authority)
858 }
859 TokenInstruction::InitializeAccount => {
860 msg!("Instruction: InitializeAccount");
861 Self::process_initialize_account(program_id, accounts)
862 }
863 TokenInstruction::InitializeAccount2 { owner } => {
864 msg!("Instruction: InitializeAccount2");
865 Self::process_initialize_account2(program_id, accounts, owner)
866 }
867 TokenInstruction::InitializeAccount3 { owner } => {
868 msg!("Instruction: InitializeAccount3");
869 Self::process_initialize_account3(program_id, accounts, owner)
870 }
871 TokenInstruction::InitializeMultisig { m } => {
872 msg!("Instruction: InitializeMultisig");
873 Self::process_initialize_multisig(accounts, m)
874 }
875 TokenInstruction::InitializeMultisig2 { m } => {
876 msg!("Instruction: InitializeMultisig2");
877 Self::process_initialize_multisig2(accounts, m)
878 }
879 TokenInstruction::Transfer { amount } => {
880 msg!("Instruction: Transfer");
881 Self::process_transfer(program_id, accounts, amount, None)
882 }
883 TokenInstruction::Approve { amount } => {
884 msg!("Instruction: Approve");
885 Self::process_approve(program_id, accounts, amount, None)
886 }
887 TokenInstruction::Revoke => {
888 msg!("Instruction: Revoke");
889 Self::process_revoke(program_id, accounts)
890 }
891 TokenInstruction::SetAuthority {
892 authority_type,
893 new_authority,
894 } => {
895 msg!("Instruction: SetAuthority");
896 Self::process_set_authority(program_id, accounts, authority_type, new_authority)
897 }
898 TokenInstruction::MintTo { amount } => {
899 msg!("Instruction: MintTo");
900 Self::process_mint_to(program_id, accounts, amount, None)
901 }
902 TokenInstruction::Burn { amount } => {
903 msg!("Instruction: Burn");
904 Self::process_burn(program_id, accounts, amount, None)
905 }
906 TokenInstruction::CloseAccount => {
907 msg!("Instruction: CloseAccount");
908 Self::process_close_account(program_id, accounts)
909 }
910 TokenInstruction::FreezeAccount => {
911 msg!("Instruction: FreezeAccount");
912 Self::process_toggle_freeze_account(program_id, accounts, true)
913 }
914 TokenInstruction::ThawAccount => {
915 msg!("Instruction: ThawAccount");
916 Self::process_toggle_freeze_account(program_id, accounts, false)
917 }
918 TokenInstruction::TransferChecked { amount, decimals } => {
919 msg!("Instruction: TransferChecked");
920 Self::process_transfer(program_id, accounts, amount, Some(decimals))
921 }
922 TokenInstruction::ApproveChecked { amount, decimals } => {
923 msg!("Instruction: ApproveChecked");
924 Self::process_approve(program_id, accounts, amount, Some(decimals))
925 }
926 TokenInstruction::MintToChecked { amount, decimals } => {
927 msg!("Instruction: MintToChecked");
928 Self::process_mint_to(program_id, accounts, amount, Some(decimals))
929 }
930 TokenInstruction::BurnChecked { amount, decimals } => {
931 msg!("Instruction: BurnChecked");
932 Self::process_burn(program_id, accounts, amount, Some(decimals))
933 }
934 TokenInstruction::SyncNative => {
935 msg!("Instruction: SyncNative");
936 Self::process_sync_native(program_id, accounts)
937 }
938 TokenInstruction::GetAccountDataSize => {
939 msg!("Instruction: GetAccountDataSize");
940 Self::process_get_account_data_size(program_id, accounts)
941 }
942 TokenInstruction::InitializeImmutableOwner => {
943 msg!("Instruction: InitializeImmutableOwner");
944 Self::process_initialize_immutable_owner(accounts)
945 }
946 TokenInstruction::AmountToUiAmount { amount } => {
947 msg!("Instruction: AmountToUiAmount");
948 Self::process_amount_to_ui_amount(program_id, accounts, amount)
949 }
950 TokenInstruction::UiAmountToAmount { ui_amount } => {
951 msg!("Instruction: UiAmountToAmount");
952 Self::process_ui_amount_to_amount(program_id, accounts, ui_amount)
953 }
954 }
955 }
956
957 pub fn check_account_owner(program_id: &Pubkey, account_info: &AccountInfo) -> ProgramResult {
959 if !Self::cmp_pubkeys(program_id, account_info.owner) {
960 Err(ProgramError::IncorrectProgramId)
961 } else {
962 Ok(())
963 }
964 }
965
966 pub fn cmp_pubkeys(a: &Pubkey, b: &Pubkey) -> bool {
969 sol_memcmp(a.as_ref(), b.as_ref(), PUBKEY_BYTES) == 0
970 }
971
972 pub fn validate_owner(
974 program_id: &Pubkey,
975 expected_owner: &Pubkey,
976 owner_account_info: &AccountInfo,
977 signers: &[AccountInfo],
978 ) -> ProgramResult {
979 if !Self::cmp_pubkeys(expected_owner, owner_account_info.key) {
980 return Err(TokenError::OwnerMismatch.into());
981 }
982 if Self::cmp_pubkeys(program_id, owner_account_info.owner)
983 && owner_account_info.data_len() == Multisig::get_packed_len()
984 {
985 let multisig = Multisig::unpack(&owner_account_info.data.borrow())?;
986 let mut num_signers = 0;
987 let mut matched = [false; MAX_SIGNERS];
988 for signer in signers.iter() {
989 for (position, key) in multisig.signers[0..multisig.n as usize].iter().enumerate() {
990 if Self::cmp_pubkeys(key, signer.key) && !matched[position] {
991 if !signer.is_signer {
992 return Err(ProgramError::MissingRequiredSignature);
993 }
994 matched[position] = true;
995 num_signers += 1;
996 }
997 }
998 }
999 if num_signers < multisig.m {
1000 return Err(ProgramError::MissingRequiredSignature);
1001 }
1002 return Ok(());
1003 } else if !owner_account_info.is_signer {
1004 return Err(ProgramError::MissingRequiredSignature);
1005 }
1006 Ok(())
1007 }
1008}
1009
1010#[cfg(not(target_os = "solana"))]
1014fn delete_account(account_info: &AccountInfo) -> Result<(), ProgramError> {
1015 account_info.assign(&system_program::id());
1016 let mut account_data = account_info.data.borrow_mut();
1017 let data_len = account_data.len();
1018 solana_program::program_memory::sol_memset(*account_data, 0, data_len);
1019 Ok(())
1020}
1021
1022#[cfg(target_os = "solana")]
1024fn delete_account(account_info: &AccountInfo) -> Result<(), ProgramError> {
1025 account_info.assign(&system_program::id());
1026 account_info.realloc(0, false)
1027}
1028
1029#[cfg(test)]
1030mod tests {
1031 use super::*;
1032 use crate::instruction::*;
1033 use serial_test::serial;
1034 use solana_program::{
1035 account_info::IntoAccountInfo,
1036 clock::Epoch,
1037 instruction::Instruction,
1038 program_error::{self, PrintProgramError},
1039 sysvar::rent,
1040 };
1041 use solana_sdk::account::{
1042 create_account_for_test, create_is_signer_account_infos, Account as SafecoinAccount,
1043 };
1044 use std::sync::{Arc, RwLock};
1045
1046 lazy_static::lazy_static! {
1047 static ref EXPECTED_DATA: Arc<RwLock<Vec<u8>>> = Arc::new(RwLock::new(Vec::new()));
1048 }
1049
1050 fn set_expected_data(expected_data: Vec<u8>) {
1051 *EXPECTED_DATA.write().unwrap() = expected_data;
1052 }
1053
1054 struct SyscallStubs {}
1055 impl solana_sdk::program_stubs::SyscallStubs for SyscallStubs {
1056 fn sol_log(&self, _message: &str) {}
1057
1058 fn sol_invoke_signed(
1059 &self,
1060 _instruction: &Instruction,
1061 _account_infos: &[AccountInfo],
1062 _signers_seeds: &[&[&[u8]]],
1063 ) -> ProgramResult {
1064 Err(ProgramError::Custom(42)) }
1066
1067 fn sol_get_clock_sysvar(&self, _var_addr: *mut u8) -> u64 {
1068 program_error::UNSUPPORTED_SYSVAR
1069 }
1070
1071 fn sol_get_epoch_schedule_sysvar(&self, _var_addr: *mut u8) -> u64 {
1072 program_error::UNSUPPORTED_SYSVAR
1073 }
1074
1075 #[allow(deprecated)]
1076 fn sol_get_fees_sysvar(&self, _var_addr: *mut u8) -> u64 {
1077 program_error::UNSUPPORTED_SYSVAR
1078 }
1079
1080 fn sol_get_rent_sysvar(&self, var_addr: *mut u8) -> u64 {
1081 unsafe {
1082 *(var_addr as *mut _ as *mut Rent) = Rent::default();
1083 }
1084 solana_program::entrypoint::SUCCESS
1085 }
1086
1087 fn sol_set_return_data(&self, data: &[u8]) {
1088 assert_eq!(&*EXPECTED_DATA.write().unwrap(), data)
1089 }
1090 }
1091
1092 fn do_process_instruction(
1093 instruction: Instruction,
1094 accounts: Vec<&mut SafecoinAccount>,
1095 ) -> ProgramResult {
1096 {
1097 use std::sync::Once;
1098 static ONCE: Once = Once::new();
1099
1100 ONCE.call_once(|| {
1101 solana_sdk::program_stubs::set_syscall_stubs(Box::new(SyscallStubs {}));
1102 });
1103 }
1104
1105 let mut meta = instruction
1106 .accounts
1107 .iter()
1108 .zip(accounts)
1109 .map(|(account_meta, account)| (&account_meta.pubkey, account_meta.is_signer, account))
1110 .collect::<Vec<_>>();
1111
1112 let account_infos = create_is_signer_account_infos(&mut meta);
1113 Processor::process(&instruction.program_id, &account_infos, &instruction.data)
1114 }
1115
1116 fn do_process_instruction_dups(
1117 instruction: Instruction,
1118 account_infos: Vec<AccountInfo>,
1119 ) -> ProgramResult {
1120 Processor::process(&instruction.program_id, &account_infos, &instruction.data)
1121 }
1122
1123 fn return_token_error_as_program_error() -> ProgramError {
1124 TokenError::MintMismatch.into()
1125 }
1126
1127 fn rent_sysvar() -> SafecoinAccount {
1128 create_account_for_test(&Rent::default())
1129 }
1130
1131 fn mint_minimum_balance() -> u64 {
1132 Rent::default().minimum_balance(Mint::get_packed_len())
1133 }
1134
1135 fn account_minimum_balance() -> u64 {
1136 Rent::default().minimum_balance(Account::get_packed_len())
1137 }
1138
1139 fn multisig_minimum_balance() -> u64 {
1140 Rent::default().minimum_balance(Multisig::get_packed_len())
1141 }
1142
1143 #[test]
1144 fn test_print_error() {
1145 let error = return_token_error_as_program_error();
1146 error.print::<TokenError>();
1147 }
1148
1149 #[test]
1150 #[should_panic(expected = "Custom(3)")]
1151 fn test_error_unwrap() {
1152 Err::<(), ProgramError>(return_token_error_as_program_error()).unwrap();
1153 }
1154
1155 #[test]
1156 fn test_unique_account_sizes() {
1157 assert_ne!(Mint::get_packed_len(), 0);
1158 assert_ne!(Mint::get_packed_len(), Account::get_packed_len());
1159 assert_ne!(Mint::get_packed_len(), Multisig::get_packed_len());
1160 assert_ne!(Account::get_packed_len(), 0);
1161 assert_ne!(Account::get_packed_len(), Multisig::get_packed_len());
1162 assert_ne!(Multisig::get_packed_len(), 0);
1163 }
1164
1165 #[test]
1166 fn test_pack_unpack() {
1167 let check = Mint {
1169 mint_authority: COption::Some(Pubkey::new(&[1; 32])),
1170 supply: 42,
1171 decimals: 7,
1172 is_initialized: true,
1173 freeze_authority: COption::Some(Pubkey::new(&[2; 32])),
1174 };
1175 let mut packed = vec![0; Mint::get_packed_len() + 1];
1176 assert_eq!(
1177 Err(ProgramError::InvalidAccountData),
1178 Mint::pack(check, &mut packed)
1179 );
1180 let mut packed = vec![0; Mint::get_packed_len() - 1];
1181 assert_eq!(
1182 Err(ProgramError::InvalidAccountData),
1183 Mint::pack(check, &mut packed)
1184 );
1185 let mut packed = vec![0; Mint::get_packed_len()];
1186 Mint::pack(check, &mut packed).unwrap();
1187 let expect = vec![
1188 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1189 1, 1, 1, 1, 1, 1, 1, 42, 0, 0, 0, 0, 0, 0, 0, 7, 1, 1, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2,
1190 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
1191 ];
1192 assert_eq!(packed, expect);
1193 let unpacked = Mint::unpack(&packed).unwrap();
1194 assert_eq!(unpacked, check);
1195
1196 let check = Account {
1198 mint: Pubkey::new(&[1; 32]),
1199 owner: Pubkey::new(&[2; 32]),
1200 amount: 3,
1201 delegate: COption::Some(Pubkey::new(&[4; 32])),
1202 state: AccountState::Frozen,
1203 is_native: COption::Some(5),
1204 delegated_amount: 6,
1205 close_authority: COption::Some(Pubkey::new(&[7; 32])),
1206 };
1207 let mut packed = vec![0; Account::get_packed_len() + 1];
1208 assert_eq!(
1209 Err(ProgramError::InvalidAccountData),
1210 Account::pack(check, &mut packed)
1211 );
1212 let mut packed = vec![0; Account::get_packed_len() - 1];
1213 assert_eq!(
1214 Err(ProgramError::InvalidAccountData),
1215 Account::pack(check, &mut packed)
1216 );
1217 let mut packed = vec![0; Account::get_packed_len()];
1218 Account::pack(check, &mut packed).unwrap();
1219 let expect = vec![
1220 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1221 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
1222 2, 2, 2, 2, 2, 2, 3, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
1223 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 1, 0, 0, 0, 5, 0, 0,
1224 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1225 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1226 ];
1227 assert_eq!(packed, expect);
1228 let unpacked = Account::unpack(&packed).unwrap();
1229 assert_eq!(unpacked, check);
1230
1231 let check = Multisig {
1233 m: 1,
1234 n: 2,
1235 is_initialized: true,
1236 signers: [Pubkey::new(&[3; 32]); MAX_SIGNERS],
1237 };
1238 let mut packed = vec![0; Multisig::get_packed_len() + 1];
1239 assert_eq!(
1240 Err(ProgramError::InvalidAccountData),
1241 Multisig::pack(check, &mut packed)
1242 );
1243 let mut packed = vec![0; Multisig::get_packed_len() - 1];
1244 assert_eq!(
1245 Err(ProgramError::InvalidAccountData),
1246 Multisig::pack(check, &mut packed)
1247 );
1248 let mut packed = vec![0; Multisig::get_packed_len()];
1249 Multisig::pack(check, &mut packed).unwrap();
1250 let expect = vec![
1251 1, 2, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1252 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1253 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1254 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1255 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1256 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1257 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1258 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1259 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1260 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1261 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1262 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1263 3, 3, 3, 3, 3, 3, 3,
1264 ];
1265 assert_eq!(packed, expect);
1266 let unpacked = Multisig::unpack(&packed).unwrap();
1267 assert_eq!(unpacked, check);
1268 }
1269
1270 #[test]
1271 fn test_initialize_mint() {
1272 let program_id = crate::id();
1273 let owner_key = Pubkey::new_unique();
1274 let mint_key = Pubkey::new_unique();
1275 let mut mint_account = SafecoinAccount::new(42, Mint::get_packed_len(), &program_id);
1276 let mint2_key = Pubkey::new_unique();
1277 let mut mint2_account =
1278 SafecoinAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
1279 let mut rent_sysvar = rent_sysvar();
1280
1281 assert_eq!(
1283 Err(TokenError::NotRentExempt.into()),
1284 do_process_instruction(
1285 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
1286 vec![&mut mint_account, &mut rent_sysvar]
1287 )
1288 );
1289
1290 mint_account.lamports = mint_minimum_balance();
1291
1292 do_process_instruction(
1294 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
1295 vec![&mut mint_account, &mut rent_sysvar],
1296 )
1297 .unwrap();
1298
1299 assert_eq!(
1301 Err(TokenError::AlreadyInUse.into()),
1302 do_process_instruction(
1303 initialize_mint(&program_id, &mint_key, &owner_key, None, 2,).unwrap(),
1304 vec![&mut mint_account, &mut rent_sysvar]
1305 )
1306 );
1307
1308 do_process_instruction(
1310 initialize_mint(&program_id, &mint2_key, &owner_key, Some(&owner_key), 2).unwrap(),
1311 vec![&mut mint2_account, &mut rent_sysvar],
1312 )
1313 .unwrap();
1314 let mint = Mint::unpack_unchecked(&mint2_account.data).unwrap();
1315 assert_eq!(mint.freeze_authority, COption::Some(owner_key));
1316 }
1317
1318 #[test]
1319 fn test_initialize_mint2() {
1320 let program_id = crate::id();
1321 let owner_key = Pubkey::new_unique();
1322 let mint_key = Pubkey::new_unique();
1323 let mut mint_account = SafecoinAccount::new(42, Mint::get_packed_len(), &program_id);
1324 let mint2_key = Pubkey::new_unique();
1325 let mut mint2_account =
1326 SafecoinAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
1327
1328 assert_eq!(
1330 Err(TokenError::NotRentExempt.into()),
1331 do_process_instruction(
1332 initialize_mint2(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
1333 vec![&mut mint_account]
1334 )
1335 );
1336
1337 mint_account.lamports = mint_minimum_balance();
1338
1339 do_process_instruction(
1341 initialize_mint2(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
1342 vec![&mut mint_account],
1343 )
1344 .unwrap();
1345
1346 assert_eq!(
1348 Err(TokenError::AlreadyInUse.into()),
1349 do_process_instruction(
1350 initialize_mint2(&program_id, &mint_key, &owner_key, None, 2,).unwrap(),
1351 vec![&mut mint_account]
1352 )
1353 );
1354
1355 do_process_instruction(
1357 initialize_mint2(&program_id, &mint2_key, &owner_key, Some(&owner_key), 2).unwrap(),
1358 vec![&mut mint2_account],
1359 )
1360 .unwrap();
1361 let mint = Mint::unpack_unchecked(&mint2_account.data).unwrap();
1362 assert_eq!(mint.freeze_authority, COption::Some(owner_key));
1363 }
1364
1365 #[test]
1366 fn test_initialize_mint_account() {
1367 let program_id = crate::id();
1368 let account_key = Pubkey::new_unique();
1369 let mut account_account = SafecoinAccount::new(42, Account::get_packed_len(), &program_id);
1370 let owner_key = Pubkey::new_unique();
1371 let mut owner_account = SafecoinAccount::default();
1372 let mint_key = Pubkey::new_unique();
1373 let mut mint_account =
1374 SafecoinAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
1375 let mut rent_sysvar = rent_sysvar();
1376
1377 assert_eq!(
1379 Err(TokenError::NotRentExempt.into()),
1380 do_process_instruction(
1381 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
1382 vec![
1383 &mut account_account,
1384 &mut mint_account,
1385 &mut owner_account,
1386 &mut rent_sysvar
1387 ],
1388 )
1389 );
1390
1391 account_account.lamports = account_minimum_balance();
1392
1393 assert_eq!(
1395 Err(TokenError::InvalidMint.into()),
1396 do_process_instruction(
1397 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
1398 vec![
1399 &mut account_account,
1400 &mut mint_account,
1401 &mut owner_account,
1402 &mut rent_sysvar
1403 ],
1404 )
1405 );
1406
1407 do_process_instruction(
1409 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
1410 vec![&mut mint_account, &mut rent_sysvar],
1411 )
1412 .unwrap();
1413
1414 let not_program_id = Pubkey::new_unique();
1416 mint_account.owner = not_program_id;
1417 assert_eq!(
1418 Err(ProgramError::IncorrectProgramId),
1419 do_process_instruction(
1420 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
1421 vec![
1422 &mut account_account,
1423 &mut mint_account,
1424 &mut owner_account,
1425 &mut rent_sysvar
1426 ],
1427 )
1428 );
1429 mint_account.owner = program_id;
1430
1431 do_process_instruction(
1433 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
1434 vec![
1435 &mut account_account,
1436 &mut mint_account,
1437 &mut owner_account,
1438 &mut rent_sysvar,
1439 ],
1440 )
1441 .unwrap();
1442
1443 assert_eq!(
1445 Err(TokenError::AlreadyInUse.into()),
1446 do_process_instruction(
1447 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
1448 vec![
1449 &mut account_account,
1450 &mut mint_account,
1451 &mut owner_account,
1452 &mut rent_sysvar
1453 ],
1454 )
1455 );
1456 }
1457
1458 #[test]
1459 fn test_transfer_dups() {
1460 let program_id = crate::id();
1461 let account1_key = Pubkey::new_unique();
1462 let mut account1_account = SafecoinAccount::new(
1463 account_minimum_balance(),
1464 Account::get_packed_len(),
1465 &program_id,
1466 );
1467 let mut account1_info: AccountInfo = (&account1_key, true, &mut account1_account).into();
1468 let account2_key = Pubkey::new_unique();
1469 let mut account2_account = SafecoinAccount::new(
1470 account_minimum_balance(),
1471 Account::get_packed_len(),
1472 &program_id,
1473 );
1474 let mut account2_info: AccountInfo = (&account2_key, false, &mut account2_account).into();
1475 let account3_key = Pubkey::new_unique();
1476 let mut account3_account = SafecoinAccount::new(
1477 account_minimum_balance(),
1478 Account::get_packed_len(),
1479 &program_id,
1480 );
1481 let account3_info: AccountInfo = (&account3_key, false, &mut account3_account).into();
1482 let account4_key = Pubkey::new_unique();
1483 let mut account4_account = SafecoinAccount::new(
1484 account_minimum_balance(),
1485 Account::get_packed_len(),
1486 &program_id,
1487 );
1488 let account4_info: AccountInfo = (&account4_key, true, &mut account4_account).into();
1489 let multisig_key = Pubkey::new_unique();
1490 let mut multisig_account = SafecoinAccount::new(
1491 multisig_minimum_balance(),
1492 Multisig::get_packed_len(),
1493 &program_id,
1494 );
1495 let multisig_info: AccountInfo = (&multisig_key, true, &mut multisig_account).into();
1496 let owner_key = Pubkey::new_unique();
1497 let mut owner_account = SafecoinAccount::default();
1498 let owner_info: AccountInfo = (&owner_key, true, &mut owner_account).into();
1499 let mint_key = Pubkey::new_unique();
1500 let mut mint_account =
1501 SafecoinAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
1502 let mint_info: AccountInfo = (&mint_key, false, &mut mint_account).into();
1503 let rent_key = rent::id();
1504 let mut rent_sysvar = rent_sysvar();
1505 let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
1506
1507 do_process_instruction_dups(
1509 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
1510 vec![mint_info.clone(), rent_info.clone()],
1511 )
1512 .unwrap();
1513
1514 do_process_instruction_dups(
1516 initialize_account(&program_id, &account1_key, &mint_key, &account1_key).unwrap(),
1517 vec![
1518 account1_info.clone(),
1519 mint_info.clone(),
1520 account1_info.clone(),
1521 rent_info.clone(),
1522 ],
1523 )
1524 .unwrap();
1525
1526 do_process_instruction_dups(
1528 initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
1529 vec![
1530 account2_info.clone(),
1531 mint_info.clone(),
1532 owner_info.clone(),
1533 rent_info.clone(),
1534 ],
1535 )
1536 .unwrap();
1537
1538 do_process_instruction_dups(
1540 mint_to(&program_id, &mint_key, &account1_key, &owner_key, &[], 1000).unwrap(),
1541 vec![mint_info.clone(), account1_info.clone(), owner_info.clone()],
1542 )
1543 .unwrap();
1544
1545 do_process_instruction_dups(
1547 transfer(
1548 &program_id,
1549 &account1_key,
1550 &account2_key,
1551 &account1_key,
1552 &[],
1553 500,
1554 )
1555 .unwrap(),
1556 vec![
1557 account1_info.clone(),
1558 account2_info.clone(),
1559 account1_info.clone(),
1560 ],
1561 )
1562 .unwrap();
1563
1564 do_process_instruction_dups(
1566 transfer_checked(
1567 &program_id,
1568 &account1_key,
1569 &mint_key,
1570 &account2_key,
1571 &account1_key,
1572 &[],
1573 500,
1574 2,
1575 )
1576 .unwrap(),
1577 vec![
1578 account1_info.clone(),
1579 mint_info.clone(),
1580 account2_info.clone(),
1581 account1_info.clone(),
1582 ],
1583 )
1584 .unwrap();
1585
1586 let mut account = Account::unpack_unchecked(&account1_info.data.borrow()).unwrap();
1588 account.amount = 1000;
1589 account.delegated_amount = 1000;
1590 account.delegate = COption::Some(account1_key);
1591 account.owner = owner_key;
1592 Account::pack(account, &mut account1_info.data.borrow_mut()).unwrap();
1593
1594 do_process_instruction_dups(
1595 transfer(
1596 &program_id,
1597 &account1_key,
1598 &account2_key,
1599 &account1_key,
1600 &[],
1601 500,
1602 )
1603 .unwrap(),
1604 vec![
1605 account1_info.clone(),
1606 account2_info.clone(),
1607 account1_info.clone(),
1608 ],
1609 )
1610 .unwrap();
1611
1612 do_process_instruction_dups(
1614 transfer_checked(
1615 &program_id,
1616 &account1_key,
1617 &mint_key,
1618 &account2_key,
1619 &account1_key,
1620 &[],
1621 500,
1622 2,
1623 )
1624 .unwrap(),
1625 vec![
1626 account1_info.clone(),
1627 mint_info.clone(),
1628 account2_info.clone(),
1629 account1_info.clone(),
1630 ],
1631 )
1632 .unwrap();
1633
1634 do_process_instruction_dups(
1636 initialize_account(&program_id, &account3_key, &mint_key, &account2_key).unwrap(),
1637 vec![
1638 account3_info.clone(),
1639 mint_info.clone(),
1640 account2_info.clone(),
1641 rent_info.clone(),
1642 ],
1643 )
1644 .unwrap();
1645 do_process_instruction_dups(
1646 mint_to(&program_id, &mint_key, &account3_key, &owner_key, &[], 1000).unwrap(),
1647 vec![mint_info.clone(), account3_info.clone(), owner_info.clone()],
1648 )
1649 .unwrap();
1650
1651 account1_info.is_signer = false;
1652 account2_info.is_signer = true;
1653 do_process_instruction_dups(
1654 transfer(
1655 &program_id,
1656 &account3_key,
1657 &account2_key,
1658 &account2_key,
1659 &[],
1660 500,
1661 )
1662 .unwrap(),
1663 vec![
1664 account3_info.clone(),
1665 account2_info.clone(),
1666 account2_info.clone(),
1667 ],
1668 )
1669 .unwrap();
1670
1671 do_process_instruction_dups(
1673 transfer_checked(
1674 &program_id,
1675 &account3_key,
1676 &mint_key,
1677 &account2_key,
1678 &account2_key,
1679 &[],
1680 500,
1681 2,
1682 )
1683 .unwrap(),
1684 vec![
1685 account3_info.clone(),
1686 mint_info.clone(),
1687 account2_info.clone(),
1688 account2_info.clone(),
1689 ],
1690 )
1691 .unwrap();
1692
1693 do_process_instruction_dups(
1695 initialize_multisig(&program_id, &multisig_key, &[&account4_key], 1).unwrap(),
1696 vec![
1697 multisig_info.clone(),
1698 rent_info.clone(),
1699 account4_info.clone(),
1700 ],
1701 )
1702 .unwrap();
1703
1704 do_process_instruction_dups(
1705 initialize_account(&program_id, &account4_key, &mint_key, &multisig_key).unwrap(),
1706 vec![
1707 account4_info.clone(),
1708 mint_info.clone(),
1709 multisig_info.clone(),
1710 rent_info.clone(),
1711 ],
1712 )
1713 .unwrap();
1714
1715 do_process_instruction_dups(
1716 mint_to(&program_id, &mint_key, &account4_key, &owner_key, &[], 1000).unwrap(),
1717 vec![mint_info.clone(), account4_info.clone(), owner_info.clone()],
1718 )
1719 .unwrap();
1720
1721 do_process_instruction_dups(
1723 transfer(
1724 &program_id,
1725 &account4_key,
1726 &account2_key,
1727 &multisig_key,
1728 &[&account4_key],
1729 500,
1730 )
1731 .unwrap(),
1732 vec![
1733 account4_info.clone(),
1734 account2_info.clone(),
1735 multisig_info.clone(),
1736 account4_info.clone(),
1737 ],
1738 )
1739 .unwrap();
1740
1741 do_process_instruction_dups(
1743 transfer_checked(
1744 &program_id,
1745 &account4_key,
1746 &mint_key,
1747 &account2_key,
1748 &multisig_key,
1749 &[&account4_key],
1750 500,
1751 2,
1752 )
1753 .unwrap(),
1754 vec![
1755 account4_info.clone(),
1756 mint_info.clone(),
1757 account2_info.clone(),
1758 multisig_info.clone(),
1759 account4_info.clone(),
1760 ],
1761 )
1762 .unwrap();
1763 }
1764
1765 #[test]
1766 fn test_transfer() {
1767 let program_id = crate::id();
1768 let account_key = Pubkey::new_unique();
1769 let mut account_account = SafecoinAccount::new(
1770 account_minimum_balance(),
1771 Account::get_packed_len(),
1772 &program_id,
1773 );
1774 let account2_key = Pubkey::new_unique();
1775 let mut account2_account = SafecoinAccount::new(
1776 account_minimum_balance(),
1777 Account::get_packed_len(),
1778 &program_id,
1779 );
1780 let account3_key = Pubkey::new_unique();
1781 let mut account3_account = SafecoinAccount::new(
1782 account_minimum_balance(),
1783 Account::get_packed_len(),
1784 &program_id,
1785 );
1786 let delegate_key = Pubkey::new_unique();
1787 let mut delegate_account = SafecoinAccount::default();
1788 let mismatch_key = Pubkey::new_unique();
1789 let mut mismatch_account = SafecoinAccount::new(
1790 account_minimum_balance(),
1791 Account::get_packed_len(),
1792 &program_id,
1793 );
1794 let owner_key = Pubkey::new_unique();
1795 let mut owner_account = SafecoinAccount::default();
1796 let owner2_key = Pubkey::new_unique();
1797 let mut owner2_account = SafecoinAccount::default();
1798 let mint_key = Pubkey::new_unique();
1799 let mut mint_account =
1800 SafecoinAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
1801 let mint2_key = Pubkey::new_unique();
1802 let mut rent_sysvar = rent_sysvar();
1803
1804 do_process_instruction(
1806 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
1807 vec![&mut mint_account, &mut rent_sysvar],
1808 )
1809 .unwrap();
1810
1811 do_process_instruction(
1813 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
1814 vec![
1815 &mut account_account,
1816 &mut mint_account,
1817 &mut owner_account,
1818 &mut rent_sysvar,
1819 ],
1820 )
1821 .unwrap();
1822
1823 do_process_instruction(
1825 initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
1826 vec![
1827 &mut account2_account,
1828 &mut mint_account,
1829 &mut owner_account,
1830 &mut rent_sysvar,
1831 ],
1832 )
1833 .unwrap();
1834
1835 do_process_instruction(
1837 initialize_account(&program_id, &account3_key, &mint_key, &owner_key).unwrap(),
1838 vec![
1839 &mut account3_account,
1840 &mut mint_account,
1841 &mut owner_account,
1842 &mut rent_sysvar,
1843 ],
1844 )
1845 .unwrap();
1846
1847 do_process_instruction(
1849 initialize_account(&program_id, &mismatch_key, &mint_key, &owner_key).unwrap(),
1850 vec![
1851 &mut mismatch_account,
1852 &mut mint_account,
1853 &mut owner_account,
1854 &mut rent_sysvar,
1855 ],
1856 )
1857 .unwrap();
1858 let mut account = Account::unpack_unchecked(&mismatch_account.data).unwrap();
1859 account.mint = mint2_key;
1860 Account::pack(account, &mut mismatch_account.data).unwrap();
1861
1862 do_process_instruction(
1864 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
1865 vec![&mut mint_account, &mut account_account, &mut owner_account],
1866 )
1867 .unwrap();
1868
1869 let mut instruction = transfer(
1871 &program_id,
1872 &account_key,
1873 &account2_key,
1874 &owner_key,
1875 &[],
1876 1000,
1877 )
1878 .unwrap();
1879 instruction.accounts[2].is_signer = false;
1880 assert_eq!(
1881 Err(ProgramError::MissingRequiredSignature),
1882 do_process_instruction(
1883 instruction,
1884 vec![
1885 &mut account_account,
1886 &mut account2_account,
1887 &mut owner_account,
1888 ],
1889 )
1890 );
1891
1892 assert_eq!(
1894 Err(TokenError::MintMismatch.into()),
1895 do_process_instruction(
1896 transfer(
1897 &program_id,
1898 &account_key,
1899 &mismatch_key,
1900 &owner_key,
1901 &[],
1902 1000
1903 )
1904 .unwrap(),
1905 vec![
1906 &mut account_account,
1907 &mut mismatch_account,
1908 &mut owner_account,
1909 ],
1910 )
1911 );
1912
1913 assert_eq!(
1915 Err(TokenError::OwnerMismatch.into()),
1916 do_process_instruction(
1917 transfer(
1918 &program_id,
1919 &account_key,
1920 &account2_key,
1921 &owner2_key,
1922 &[],
1923 1000
1924 )
1925 .unwrap(),
1926 vec![
1927 &mut account_account,
1928 &mut account2_account,
1929 &mut owner2_account,
1930 ],
1931 )
1932 );
1933
1934 let not_program_id = Pubkey::new_unique();
1936 account_account.owner = not_program_id;
1937 assert_eq!(
1938 Err(ProgramError::IncorrectProgramId),
1939 do_process_instruction(
1940 transfer(&program_id, &account_key, &account2_key, &owner_key, &[], 0,).unwrap(),
1941 vec![
1942 &mut account_account,
1943 &mut account2_account,
1944 &mut owner2_account,
1945 ],
1946 )
1947 );
1948 account_account.owner = program_id;
1949
1950 let not_program_id = Pubkey::new_unique();
1952 account2_account.owner = not_program_id;
1953 assert_eq!(
1954 Err(ProgramError::IncorrectProgramId),
1955 do_process_instruction(
1956 transfer(&program_id, &account_key, &account2_key, &owner_key, &[], 0,).unwrap(),
1957 vec![
1958 &mut account_account,
1959 &mut account2_account,
1960 &mut owner2_account,
1961 ],
1962 )
1963 );
1964 account2_account.owner = program_id;
1965
1966 do_process_instruction(
1968 transfer(
1969 &program_id,
1970 &account_key,
1971 &account2_key,
1972 &owner_key,
1973 &[],
1974 1000,
1975 )
1976 .unwrap(),
1977 vec![
1978 &mut account_account,
1979 &mut account2_account,
1980 &mut owner_account,
1981 ],
1982 )
1983 .unwrap();
1984
1985 assert_eq!(
1987 Err(TokenError::InsufficientFunds.into()),
1988 do_process_instruction(
1989 transfer(&program_id, &account_key, &account2_key, &owner_key, &[], 1).unwrap(),
1990 vec![
1991 &mut account_account,
1992 &mut account2_account,
1993 &mut owner_account,
1994 ],
1995 )
1996 );
1997
1998 do_process_instruction(
2000 transfer(
2001 &program_id,
2002 &account2_key,
2003 &account_key,
2004 &owner_key,
2005 &[],
2006 500,
2007 )
2008 .unwrap(),
2009 vec![
2010 &mut account2_account,
2011 &mut account_account,
2012 &mut owner_account,
2013 ],
2014 )
2015 .unwrap();
2016
2017 assert_eq!(
2019 Err(TokenError::MintDecimalsMismatch.into()),
2020 do_process_instruction(
2021 transfer_checked(
2022 &program_id,
2023 &account2_key,
2024 &mint_key,
2025 &account_key,
2026 &owner_key,
2027 &[],
2028 1,
2029 10 )
2031 .unwrap(),
2032 vec![
2033 &mut account2_account,
2034 &mut mint_account,
2035 &mut account_account,
2036 &mut owner_account,
2037 ],
2038 )
2039 );
2040
2041 assert_eq!(
2043 Err(TokenError::MintMismatch.into()),
2044 do_process_instruction(
2045 transfer_checked(
2046 &program_id,
2047 &account2_key,
2048 &account3_key, &account_key,
2050 &owner_key,
2051 &[],
2052 1,
2053 2
2054 )
2055 .unwrap(),
2056 vec![
2057 &mut account2_account,
2058 &mut account3_account, &mut account_account,
2060 &mut owner_account,
2061 ],
2062 )
2063 );
2064 do_process_instruction(
2066 transfer_checked(
2067 &program_id,
2068 &account2_key,
2069 &mint_key,
2070 &account_key,
2071 &owner_key,
2072 &[],
2073 500,
2074 2,
2075 )
2076 .unwrap(),
2077 vec![
2078 &mut account2_account,
2079 &mut mint_account,
2080 &mut account_account,
2081 &mut owner_account,
2082 ],
2083 )
2084 .unwrap();
2085
2086 assert_eq!(
2088 Err(TokenError::InsufficientFunds.into()),
2089 do_process_instruction(
2090 transfer(&program_id, &account2_key, &account_key, &owner_key, &[], 1).unwrap(),
2091 vec![
2092 &mut account2_account,
2093 &mut account_account,
2094 &mut owner_account,
2095 ],
2096 )
2097 );
2098
2099 do_process_instruction(
2101 approve(
2102 &program_id,
2103 &account_key,
2104 &delegate_key,
2105 &owner_key,
2106 &[],
2107 100,
2108 )
2109 .unwrap(),
2110 vec![
2111 &mut account_account,
2112 &mut delegate_account,
2113 &mut owner_account,
2114 ],
2115 )
2116 .unwrap();
2117
2118 do_process_instruction(
2120 transfer(
2121 &program_id,
2122 &account_key,
2123 &account2_key,
2124 &delegate_key,
2125 &[],
2126 100,
2127 )
2128 .unwrap(),
2129 vec![
2130 &mut account_account,
2131 &mut account2_account,
2132 &mut delegate_account,
2133 ],
2134 )
2135 .unwrap();
2136
2137 assert_eq!(
2139 Err(TokenError::OwnerMismatch.into()),
2140 do_process_instruction(
2141 transfer(
2142 &program_id,
2143 &account_key,
2144 &account2_key,
2145 &delegate_key,
2146 &[],
2147 100
2148 )
2149 .unwrap(),
2150 vec![
2151 &mut account_account,
2152 &mut account2_account,
2153 &mut delegate_account,
2154 ],
2155 )
2156 );
2157
2158 do_process_instruction(
2160 transfer(
2161 &program_id,
2162 &account_key,
2163 &account2_key,
2164 &owner_key,
2165 &[],
2166 900,
2167 )
2168 .unwrap(),
2169 vec![
2170 &mut account_account,
2171 &mut account2_account,
2172 &mut owner_account,
2173 ],
2174 )
2175 .unwrap();
2176
2177 do_process_instruction(
2179 approve(
2180 &program_id,
2181 &account_key,
2182 &delegate_key,
2183 &owner_key,
2184 &[],
2185 100,
2186 )
2187 .unwrap(),
2188 vec![
2189 &mut account_account,
2190 &mut delegate_account,
2191 &mut owner_account,
2192 ],
2193 )
2194 .unwrap();
2195
2196 assert_eq!(
2198 Err(TokenError::InsufficientFunds.into()),
2199 do_process_instruction(
2200 transfer(
2201 &program_id,
2202 &account_key,
2203 &account2_key,
2204 &delegate_key,
2205 &[],
2206 100
2207 )
2208 .unwrap(),
2209 vec![
2210 &mut account_account,
2211 &mut account2_account,
2212 &mut delegate_account,
2213 ],
2214 )
2215 );
2216 }
2217
2218 #[test]
2219 fn test_self_transfer() {
2220 let program_id = crate::id();
2221 let account_key = Pubkey::new_unique();
2222 let mut account_account = SafecoinAccount::new(
2223 account_minimum_balance(),
2224 Account::get_packed_len(),
2225 &program_id,
2226 );
2227 let account2_key = Pubkey::new_unique();
2228 let mut account2_account = SafecoinAccount::new(
2229 account_minimum_balance(),
2230 Account::get_packed_len(),
2231 &program_id,
2232 );
2233 let account3_key = Pubkey::new_unique();
2234 let mut account3_account = SafecoinAccount::new(
2235 account_minimum_balance(),
2236 Account::get_packed_len(),
2237 &program_id,
2238 );
2239 let delegate_key = Pubkey::new_unique();
2240 let mut delegate_account = SafecoinAccount::default();
2241 let owner_key = Pubkey::new_unique();
2242 let mut owner_account = SafecoinAccount::default();
2243 let owner2_key = Pubkey::new_unique();
2244 let mut owner2_account = SafecoinAccount::default();
2245 let mint_key = Pubkey::new_unique();
2246 let mut mint_account =
2247 SafecoinAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
2248 let mut rent_sysvar = rent_sysvar();
2249
2250 do_process_instruction(
2252 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
2253 vec![&mut mint_account, &mut rent_sysvar],
2254 )
2255 .unwrap();
2256
2257 do_process_instruction(
2259 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
2260 vec![
2261 &mut account_account,
2262 &mut mint_account,
2263 &mut owner_account,
2264 &mut rent_sysvar,
2265 ],
2266 )
2267 .unwrap();
2268
2269 do_process_instruction(
2271 initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
2272 vec![
2273 &mut account2_account,
2274 &mut mint_account,
2275 &mut owner_account,
2276 &mut rent_sysvar,
2277 ],
2278 )
2279 .unwrap();
2280
2281 do_process_instruction(
2283 initialize_account(&program_id, &account3_key, &mint_key, &owner_key).unwrap(),
2284 vec![
2285 &mut account3_account,
2286 &mut mint_account,
2287 &mut owner_account,
2288 &mut rent_sysvar,
2289 ],
2290 )
2291 .unwrap();
2292
2293 do_process_instruction(
2295 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
2296 vec![&mut mint_account, &mut account_account, &mut owner_account],
2297 )
2298 .unwrap();
2299
2300 let account_info = (&account_key, false, &mut account_account).into_account_info();
2301 let account3_info = (&account3_key, false, &mut account3_account).into_account_info();
2302 let delegate_info = (&delegate_key, true, &mut delegate_account).into_account_info();
2303 let owner_info = (&owner_key, true, &mut owner_account).into_account_info();
2304 let owner2_info = (&owner2_key, true, &mut owner2_account).into_account_info();
2305 let mint_info = (&mint_key, false, &mut mint_account).into_account_info();
2306
2307 let instruction = transfer(
2309 &program_id,
2310 account_info.key,
2311 account_info.key,
2312 owner_info.key,
2313 &[],
2314 1000,
2315 )
2316 .unwrap();
2317 assert_eq!(
2318 Ok(()),
2319 Processor::process(
2320 &instruction.program_id,
2321 &[
2322 account_info.clone(),
2323 account_info.clone(),
2324 owner_info.clone(),
2325 ],
2326 &instruction.data,
2327 )
2328 );
2329 let account = Account::unpack_unchecked(&account_info.try_borrow_data().unwrap()).unwrap();
2331 assert_eq!(account.amount, 1000);
2332
2333 let instruction = transfer_checked(
2335 &program_id,
2336 account_info.key,
2337 mint_info.key,
2338 account_info.key,
2339 owner_info.key,
2340 &[],
2341 1000,
2342 2,
2343 )
2344 .unwrap();
2345 assert_eq!(
2346 Ok(()),
2347 Processor::process(
2348 &instruction.program_id,
2349 &[
2350 account_info.clone(),
2351 mint_info.clone(),
2352 account_info.clone(),
2353 owner_info.clone(),
2354 ],
2355 &instruction.data,
2356 )
2357 );
2358 let account = Account::unpack_unchecked(&account_info.try_borrow_data().unwrap()).unwrap();
2360 assert_eq!(account.amount, 1000);
2361
2362 let mut owner_no_sign_info = owner_info.clone();
2364 let mut instruction = transfer(
2365 &program_id,
2366 account_info.key,
2367 account_info.key,
2368 owner_no_sign_info.key,
2369 &[],
2370 1000,
2371 )
2372 .unwrap();
2373 instruction.accounts[2].is_signer = false;
2374 owner_no_sign_info.is_signer = false;
2375 assert_eq!(
2376 Err(ProgramError::MissingRequiredSignature),
2377 Processor::process(
2378 &instruction.program_id,
2379 &[
2380 account_info.clone(),
2381 account_info.clone(),
2382 owner_no_sign_info.clone(),
2383 ],
2384 &instruction.data,
2385 )
2386 );
2387
2388 let mut instruction = transfer_checked(
2390 &program_id,
2391 account_info.key,
2392 mint_info.key,
2393 account_info.key,
2394 owner_no_sign_info.key,
2395 &[],
2396 1000,
2397 2,
2398 )
2399 .unwrap();
2400 instruction.accounts[3].is_signer = false;
2401 assert_eq!(
2402 Err(ProgramError::MissingRequiredSignature),
2403 Processor::process(
2404 &instruction.program_id,
2405 &[
2406 account_info.clone(),
2407 mint_info.clone(),
2408 account_info.clone(),
2409 owner_no_sign_info,
2410 ],
2411 &instruction.data,
2412 )
2413 );
2414
2415 let instruction = transfer(
2417 &program_id,
2418 account_info.key,
2419 account_info.key,
2420 owner2_info.key,
2421 &[],
2422 1000,
2423 )
2424 .unwrap();
2425 assert_eq!(
2426 Err(TokenError::OwnerMismatch.into()),
2427 Processor::process(
2428 &instruction.program_id,
2429 &[
2430 account_info.clone(),
2431 account_info.clone(),
2432 owner2_info.clone(),
2433 ],
2434 &instruction.data,
2435 )
2436 );
2437
2438 let instruction = transfer_checked(
2440 &program_id,
2441 account_info.key,
2442 mint_info.key,
2443 account_info.key,
2444 owner2_info.key,
2445 &[],
2446 1000,
2447 2,
2448 )
2449 .unwrap();
2450 assert_eq!(
2451 Err(TokenError::OwnerMismatch.into()),
2452 Processor::process(
2453 &instruction.program_id,
2454 &[
2455 account_info.clone(),
2456 mint_info.clone(),
2457 account_info.clone(),
2458 owner2_info.clone(),
2459 ],
2460 &instruction.data,
2461 )
2462 );
2463
2464 let instruction = transfer(
2466 &program_id,
2467 account_info.key,
2468 account_info.key,
2469 owner_info.key,
2470 &[],
2471 1001,
2472 )
2473 .unwrap();
2474 assert_eq!(
2475 Err(TokenError::InsufficientFunds.into()),
2476 Processor::process(
2477 &instruction.program_id,
2478 &[
2479 account_info.clone(),
2480 account_info.clone(),
2481 owner_info.clone(),
2482 ],
2483 &instruction.data,
2484 )
2485 );
2486
2487 let instruction = transfer_checked(
2489 &program_id,
2490 account_info.key,
2491 mint_info.key,
2492 account_info.key,
2493 owner_info.key,
2494 &[],
2495 1001,
2496 2,
2497 )
2498 .unwrap();
2499 assert_eq!(
2500 Err(TokenError::InsufficientFunds.into()),
2501 Processor::process(
2502 &instruction.program_id,
2503 &[
2504 account_info.clone(),
2505 mint_info.clone(),
2506 account_info.clone(),
2507 owner_info.clone(),
2508 ],
2509 &instruction.data,
2510 )
2511 );
2512
2513 let instruction = transfer_checked(
2515 &program_id,
2516 account_info.key,
2517 mint_info.key,
2518 account_info.key,
2519 owner_info.key,
2520 &[],
2521 1,
2522 10, )
2524 .unwrap();
2525 assert_eq!(
2526 Err(TokenError::MintDecimalsMismatch.into()),
2527 Processor::process(
2528 &instruction.program_id,
2529 &[
2530 account_info.clone(),
2531 mint_info.clone(),
2532 account_info.clone(),
2533 owner_info.clone(),
2534 ],
2535 &instruction.data,
2536 )
2537 );
2538
2539 let instruction = transfer_checked(
2541 &program_id,
2542 account_info.key,
2543 account3_info.key, account_info.key,
2545 owner_info.key,
2546 &[],
2547 1,
2548 2,
2549 )
2550 .unwrap();
2551 assert_eq!(
2552 Err(TokenError::MintMismatch.into()),
2553 Processor::process(
2554 &instruction.program_id,
2555 &[
2556 account_info.clone(),
2557 account3_info.clone(), account_info.clone(),
2559 owner_info.clone(),
2560 ],
2561 &instruction.data,
2562 )
2563 );
2564
2565 let instruction = approve(
2567 &program_id,
2568 account_info.key,
2569 delegate_info.key,
2570 owner_info.key,
2571 &[],
2572 100,
2573 )
2574 .unwrap();
2575 Processor::process(
2576 &instruction.program_id,
2577 &[
2578 account_info.clone(),
2579 delegate_info.clone(),
2580 owner_info.clone(),
2581 ],
2582 &instruction.data,
2583 )
2584 .unwrap();
2585
2586 let instruction = transfer(
2588 &program_id,
2589 account_info.key,
2590 account_info.key,
2591 delegate_info.key,
2592 &[],
2593 100,
2594 )
2595 .unwrap();
2596 assert_eq!(
2597 Ok(()),
2598 Processor::process(
2599 &instruction.program_id,
2600 &[
2601 account_info.clone(),
2602 account_info.clone(),
2603 delegate_info.clone(),
2604 ],
2605 &instruction.data,
2606 )
2607 );
2608 let account = Account::unpack_unchecked(&account_info.try_borrow_data().unwrap()).unwrap();
2610 assert_eq!(account.amount, 1000);
2611 assert_eq!(account.delegated_amount, 100);
2612
2613 let instruction = transfer_checked(
2615 &program_id,
2616 account_info.key,
2617 mint_info.key,
2618 account_info.key,
2619 delegate_info.key,
2620 &[],
2621 100,
2622 2,
2623 )
2624 .unwrap();
2625 assert_eq!(
2626 Ok(()),
2627 Processor::process(
2628 &instruction.program_id,
2629 &[
2630 account_info.clone(),
2631 mint_info.clone(),
2632 account_info.clone(),
2633 delegate_info.clone(),
2634 ],
2635 &instruction.data,
2636 )
2637 );
2638 let account = Account::unpack_unchecked(&account_info.try_borrow_data().unwrap()).unwrap();
2640 assert_eq!(account.amount, 1000);
2641 assert_eq!(account.delegated_amount, 100);
2642
2643 let instruction = transfer(
2645 &program_id,
2646 account_info.key,
2647 account_info.key,
2648 delegate_info.key,
2649 &[],
2650 101,
2651 )
2652 .unwrap();
2653 assert_eq!(
2654 Err(TokenError::InsufficientFunds.into()),
2655 Processor::process(
2656 &instruction.program_id,
2657 &[
2658 account_info.clone(),
2659 account_info.clone(),
2660 delegate_info.clone(),
2661 ],
2662 &instruction.data,
2663 )
2664 );
2665
2666 let instruction = transfer_checked(
2668 &program_id,
2669 account_info.key,
2670 mint_info.key,
2671 account_info.key,
2672 delegate_info.key,
2673 &[],
2674 101,
2675 2,
2676 )
2677 .unwrap();
2678 assert_eq!(
2679 Err(TokenError::InsufficientFunds.into()),
2680 Processor::process(
2681 &instruction.program_id,
2682 &[
2683 account_info.clone(),
2684 mint_info.clone(),
2685 account_info.clone(),
2686 delegate_info.clone(),
2687 ],
2688 &instruction.data,
2689 )
2690 );
2691
2692 let instruction = transfer(
2694 &program_id,
2695 account_info.key,
2696 account_info.key,
2697 owner_info.key,
2698 &[],
2699 1000,
2700 )
2701 .unwrap();
2702 assert_eq!(
2703 Ok(()),
2704 Processor::process(
2705 &instruction.program_id,
2706 &[
2707 account_info.clone(),
2708 account_info.clone(),
2709 owner_info.clone(),
2710 ],
2711 &instruction.data,
2712 )
2713 );
2714 let account = Account::unpack_unchecked(&account_info.try_borrow_data().unwrap()).unwrap();
2716 assert_eq!(account.amount, 1000);
2717
2718 let instruction = transfer_checked(
2720 &program_id,
2721 account_info.key,
2722 mint_info.key,
2723 account_info.key,
2724 owner_info.key,
2725 &[],
2726 1000,
2727 2,
2728 )
2729 .unwrap();
2730 assert_eq!(
2731 Ok(()),
2732 Processor::process(
2733 &instruction.program_id,
2734 &[
2735 account_info.clone(),
2736 mint_info.clone(),
2737 account_info.clone(),
2738 owner_info.clone(),
2739 ],
2740 &instruction.data,
2741 )
2742 );
2743 let account = Account::unpack_unchecked(&account_info.try_borrow_data().unwrap()).unwrap();
2745 assert_eq!(account.amount, 1000);
2746 }
2747
2748 #[test]
2749 fn test_mintable_token_with_zero_supply() {
2750 let program_id = crate::id();
2751 let account_key = Pubkey::new_unique();
2752 let mut account_account = SafecoinAccount::new(
2753 account_minimum_balance(),
2754 Account::get_packed_len(),
2755 &program_id,
2756 );
2757 let owner_key = Pubkey::new_unique();
2758 let mut owner_account = SafecoinAccount::default();
2759 let mint_key = Pubkey::new_unique();
2760 let mut mint_account =
2761 SafecoinAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
2762 let mut rent_sysvar = rent_sysvar();
2763
2764 let decimals = 2;
2766 do_process_instruction(
2767 initialize_mint(&program_id, &mint_key, &owner_key, None, decimals).unwrap(),
2768 vec![&mut mint_account, &mut rent_sysvar],
2769 )
2770 .unwrap();
2771 let mint = Mint::unpack_unchecked(&mint_account.data).unwrap();
2772 assert_eq!(
2773 mint,
2774 Mint {
2775 mint_authority: COption::Some(owner_key),
2776 supply: 0,
2777 decimals,
2778 is_initialized: true,
2779 freeze_authority: COption::None,
2780 }
2781 );
2782
2783 do_process_instruction(
2785 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
2786 vec![
2787 &mut account_account,
2788 &mut mint_account,
2789 &mut owner_account,
2790 &mut rent_sysvar,
2791 ],
2792 )
2793 .unwrap();
2794
2795 do_process_instruction(
2797 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 42).unwrap(),
2798 vec![&mut mint_account, &mut account_account, &mut owner_account],
2799 )
2800 .unwrap();
2801 let _ = Mint::unpack(&mint_account.data).unwrap();
2802 let account = Account::unpack_unchecked(&account_account.data).unwrap();
2803 assert_eq!(account.amount, 42);
2804
2805 assert_eq!(
2807 Err(TokenError::MintDecimalsMismatch.into()),
2808 do_process_instruction(
2809 mint_to_checked(
2810 &program_id,
2811 &mint_key,
2812 &account_key,
2813 &owner_key,
2814 &[],
2815 42,
2816 decimals + 1
2817 )
2818 .unwrap(),
2819 vec![&mut mint_account, &mut account_account, &mut owner_account],
2820 )
2821 );
2822
2823 let _ = Mint::unpack(&mint_account.data).unwrap();
2824 let account = Account::unpack_unchecked(&account_account.data).unwrap();
2825 assert_eq!(account.amount, 42);
2826
2827 do_process_instruction(
2829 mint_to_checked(
2830 &program_id,
2831 &mint_key,
2832 &account_key,
2833 &owner_key,
2834 &[],
2835 42,
2836 decimals,
2837 )
2838 .unwrap(),
2839 vec![&mut mint_account, &mut account_account, &mut owner_account],
2840 )
2841 .unwrap();
2842 let _ = Mint::unpack(&mint_account.data).unwrap();
2843 let account = Account::unpack_unchecked(&account_account.data).unwrap();
2844 assert_eq!(account.amount, 84);
2845 }
2846
2847 #[test]
2848 fn test_approve_dups() {
2849 let program_id = crate::id();
2850 let account1_key = Pubkey::new_unique();
2851 let mut account1_account = SafecoinAccount::new(
2852 account_minimum_balance(),
2853 Account::get_packed_len(),
2854 &program_id,
2855 );
2856 let account1_info: AccountInfo = (&account1_key, true, &mut account1_account).into();
2857 let account2_key = Pubkey::new_unique();
2858 let mut account2_account = SafecoinAccount::new(
2859 account_minimum_balance(),
2860 Account::get_packed_len(),
2861 &program_id,
2862 );
2863 let account2_info: AccountInfo = (&account2_key, false, &mut account2_account).into();
2864 let account3_key = Pubkey::new_unique();
2865 let mut account3_account = SafecoinAccount::new(
2866 account_minimum_balance(),
2867 Account::get_packed_len(),
2868 &program_id,
2869 );
2870 let account3_info: AccountInfo = (&account3_key, true, &mut account3_account).into();
2871 let multisig_key = Pubkey::new_unique();
2872 let mut multisig_account = SafecoinAccount::new(
2873 multisig_minimum_balance(),
2874 Multisig::get_packed_len(),
2875 &program_id,
2876 );
2877 let multisig_info: AccountInfo = (&multisig_key, true, &mut multisig_account).into();
2878 let owner_key = Pubkey::new_unique();
2879 let mut owner_account = SafecoinAccount::default();
2880 let owner_info: AccountInfo = (&owner_key, true, &mut owner_account).into();
2881 let mint_key = Pubkey::new_unique();
2882 let mut mint_account =
2883 SafecoinAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
2884 let mint_info: AccountInfo = (&mint_key, false, &mut mint_account).into();
2885 let rent_key = rent::id();
2886 let mut rent_sysvar = rent_sysvar();
2887 let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
2888
2889 do_process_instruction_dups(
2891 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
2892 vec![mint_info.clone(), rent_info.clone()],
2893 )
2894 .unwrap();
2895
2896 do_process_instruction_dups(
2898 initialize_account(&program_id, &account1_key, &mint_key, &account1_key).unwrap(),
2899 vec![
2900 account1_info.clone(),
2901 mint_info.clone(),
2902 account1_info.clone(),
2903 rent_info.clone(),
2904 ],
2905 )
2906 .unwrap();
2907
2908 do_process_instruction_dups(
2910 initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
2911 vec![
2912 account2_info.clone(),
2913 mint_info.clone(),
2914 owner_info.clone(),
2915 rent_info.clone(),
2916 ],
2917 )
2918 .unwrap();
2919
2920 do_process_instruction_dups(
2922 mint_to(&program_id, &mint_key, &account1_key, &owner_key, &[], 1000).unwrap(),
2923 vec![mint_info.clone(), account1_info.clone(), owner_info.clone()],
2924 )
2925 .unwrap();
2926
2927 do_process_instruction_dups(
2929 approve(
2930 &program_id,
2931 &account1_key,
2932 &account2_key,
2933 &account1_key,
2934 &[],
2935 500,
2936 )
2937 .unwrap(),
2938 vec![
2939 account1_info.clone(),
2940 account2_info.clone(),
2941 account1_info.clone(),
2942 ],
2943 )
2944 .unwrap();
2945
2946 do_process_instruction_dups(
2948 approve_checked(
2949 &program_id,
2950 &account1_key,
2951 &mint_key,
2952 &account2_key,
2953 &account1_key,
2954 &[],
2955 500,
2956 2,
2957 )
2958 .unwrap(),
2959 vec![
2960 account1_info.clone(),
2961 mint_info.clone(),
2962 account2_info.clone(),
2963 account1_info.clone(),
2964 ],
2965 )
2966 .unwrap();
2967
2968 do_process_instruction_dups(
2970 revoke(&program_id, &account1_key, &account1_key, &[]).unwrap(),
2971 vec![account1_info.clone(), account1_info.clone()],
2972 )
2973 .unwrap();
2974
2975 do_process_instruction_dups(
2977 initialize_multisig(&program_id, &multisig_key, &[&account3_key], 1).unwrap(),
2978 vec![
2979 multisig_info.clone(),
2980 rent_info.clone(),
2981 account3_info.clone(),
2982 ],
2983 )
2984 .unwrap();
2985
2986 do_process_instruction_dups(
2987 initialize_account(&program_id, &account3_key, &mint_key, &multisig_key).unwrap(),
2988 vec![
2989 account3_info.clone(),
2990 mint_info.clone(),
2991 multisig_info.clone(),
2992 rent_info.clone(),
2993 ],
2994 )
2995 .unwrap();
2996
2997 do_process_instruction_dups(
2998 mint_to(&program_id, &mint_key, &account3_key, &owner_key, &[], 1000).unwrap(),
2999 vec![mint_info.clone(), account3_info.clone(), owner_info.clone()],
3000 )
3001 .unwrap();
3002
3003 do_process_instruction_dups(
3005 approve(
3006 &program_id,
3007 &account3_key,
3008 &account2_key,
3009 &multisig_key,
3010 &[&account3_key],
3011 500,
3012 )
3013 .unwrap(),
3014 vec![
3015 account3_info.clone(),
3016 account2_info.clone(),
3017 multisig_info.clone(),
3018 account3_info.clone(),
3019 ],
3020 )
3021 .unwrap();
3022
3023 do_process_instruction_dups(
3025 approve_checked(
3026 &program_id,
3027 &account3_key,
3028 &mint_key,
3029 &account2_key,
3030 &multisig_key,
3031 &[&account3_key],
3032 500,
3033 2,
3034 )
3035 .unwrap(),
3036 vec![
3037 account3_info.clone(),
3038 mint_info.clone(),
3039 account2_info.clone(),
3040 multisig_info.clone(),
3041 account3_info.clone(),
3042 ],
3043 )
3044 .unwrap();
3045
3046 do_process_instruction_dups(
3048 revoke(&program_id, &account3_key, &multisig_key, &[&account3_key]).unwrap(),
3049 vec![
3050 account3_info.clone(),
3051 multisig_info.clone(),
3052 account3_info.clone(),
3053 ],
3054 )
3055 .unwrap();
3056 }
3057
3058 #[test]
3059 fn test_approve() {
3060 let program_id = crate::id();
3061 let account_key = Pubkey::new_unique();
3062 let mut account_account = SafecoinAccount::new(
3063 account_minimum_balance(),
3064 Account::get_packed_len(),
3065 &program_id,
3066 );
3067 let account2_key = Pubkey::new_unique();
3068 let mut account2_account = SafecoinAccount::new(
3069 account_minimum_balance(),
3070 Account::get_packed_len(),
3071 &program_id,
3072 );
3073 let delegate_key = Pubkey::new_unique();
3074 let mut delegate_account = SafecoinAccount::default();
3075 let owner_key = Pubkey::new_unique();
3076 let mut owner_account = SafecoinAccount::default();
3077 let owner2_key = Pubkey::new_unique();
3078 let mut owner2_account = SafecoinAccount::default();
3079 let mint_key = Pubkey::new_unique();
3080 let mut mint_account =
3081 SafecoinAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
3082 let mut rent_sysvar = rent_sysvar();
3083
3084 do_process_instruction(
3086 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
3087 vec![&mut mint_account, &mut rent_sysvar],
3088 )
3089 .unwrap();
3090
3091 do_process_instruction(
3093 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
3094 vec![
3095 &mut account_account,
3096 &mut mint_account,
3097 &mut owner_account,
3098 &mut rent_sysvar,
3099 ],
3100 )
3101 .unwrap();
3102
3103 do_process_instruction(
3105 initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
3106 vec![
3107 &mut account2_account,
3108 &mut mint_account,
3109 &mut owner_account,
3110 &mut rent_sysvar,
3111 ],
3112 )
3113 .unwrap();
3114
3115 do_process_instruction(
3117 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
3118 vec![&mut mint_account, &mut account_account, &mut owner_account],
3119 )
3120 .unwrap();
3121
3122 let mut instruction = approve(
3124 &program_id,
3125 &account_key,
3126 &delegate_key,
3127 &owner_key,
3128 &[],
3129 100,
3130 )
3131 .unwrap();
3132 instruction.accounts[2].is_signer = false;
3133 assert_eq!(
3134 Err(ProgramError::MissingRequiredSignature),
3135 do_process_instruction(
3136 instruction,
3137 vec![
3138 &mut account_account,
3139 &mut delegate_account,
3140 &mut owner_account,
3141 ],
3142 )
3143 );
3144
3145 assert_eq!(
3147 Err(TokenError::OwnerMismatch.into()),
3148 do_process_instruction(
3149 approve(
3150 &program_id,
3151 &account_key,
3152 &delegate_key,
3153 &owner2_key,
3154 &[],
3155 100
3156 )
3157 .unwrap(),
3158 vec![
3159 &mut account_account,
3160 &mut delegate_account,
3161 &mut owner2_account,
3162 ],
3163 )
3164 );
3165
3166 do_process_instruction(
3168 approve(
3169 &program_id,
3170 &account_key,
3171 &delegate_key,
3172 &owner_key,
3173 &[],
3174 100,
3175 )
3176 .unwrap(),
3177 vec![
3178 &mut account_account,
3179 &mut delegate_account,
3180 &mut owner_account,
3181 ],
3182 )
3183 .unwrap();
3184
3185 assert_eq!(
3187 Err(TokenError::MintDecimalsMismatch.into()),
3188 do_process_instruction(
3189 approve_checked(
3190 &program_id,
3191 &account_key,
3192 &mint_key,
3193 &delegate_key,
3194 &owner_key,
3195 &[],
3196 100,
3197 0 )
3199 .unwrap(),
3200 vec![
3201 &mut account_account,
3202 &mut mint_account,
3203 &mut delegate_account,
3204 &mut owner_account,
3205 ],
3206 )
3207 );
3208
3209 assert_eq!(
3211 Err(TokenError::MintMismatch.into()),
3212 do_process_instruction(
3213 approve_checked(
3214 &program_id,
3215 &account_key,
3216 &account2_key, &delegate_key,
3218 &owner_key,
3219 &[],
3220 100,
3221 0
3222 )
3223 .unwrap(),
3224 vec![
3225 &mut account_account,
3226 &mut account2_account, &mut delegate_account,
3228 &mut owner_account,
3229 ],
3230 )
3231 );
3232
3233 do_process_instruction(
3235 approve_checked(
3236 &program_id,
3237 &account_key,
3238 &mint_key,
3239 &delegate_key,
3240 &owner_key,
3241 &[],
3242 100,
3243 2,
3244 )
3245 .unwrap(),
3246 vec![
3247 &mut account_account,
3248 &mut mint_account,
3249 &mut delegate_account,
3250 &mut owner_account,
3251 ],
3252 )
3253 .unwrap();
3254
3255 do_process_instruction(
3257 revoke(&program_id, &account_key, &owner_key, &[]).unwrap(),
3258 vec![&mut account_account, &mut owner_account],
3259 )
3260 .unwrap();
3261 }
3262
3263 #[test]
3264 fn test_set_authority_dups() {
3265 let program_id = crate::id();
3266 let account1_key = Pubkey::new_unique();
3267 let mut account1_account = SafecoinAccount::new(
3268 account_minimum_balance(),
3269 Account::get_packed_len(),
3270 &program_id,
3271 );
3272 let account1_info: AccountInfo = (&account1_key, true, &mut account1_account).into();
3273 let owner_key = Pubkey::new_unique();
3274 let mint_key = Pubkey::new_unique();
3275 let mut mint_account =
3276 SafecoinAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
3277 let mint_info: AccountInfo = (&mint_key, true, &mut mint_account).into();
3278 let rent_key = rent::id();
3279 let mut rent_sysvar = rent_sysvar();
3280 let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
3281
3282 do_process_instruction_dups(
3284 initialize_mint(&program_id, &mint_key, &mint_key, Some(&mint_key), 2).unwrap(),
3285 vec![mint_info.clone(), rent_info.clone()],
3286 )
3287 .unwrap();
3288
3289 do_process_instruction_dups(
3291 initialize_account(&program_id, &account1_key, &mint_key, &account1_key).unwrap(),
3292 vec![
3293 account1_info.clone(),
3294 mint_info.clone(),
3295 account1_info.clone(),
3296 rent_info.clone(),
3297 ],
3298 )
3299 .unwrap();
3300
3301 do_process_instruction_dups(
3303 set_authority(
3304 &program_id,
3305 &mint_key,
3306 Some(&owner_key),
3307 AuthorityType::MintTokens,
3308 &mint_key,
3309 &[],
3310 )
3311 .unwrap(),
3312 vec![mint_info.clone(), mint_info.clone()],
3313 )
3314 .unwrap();
3315
3316 do_process_instruction_dups(
3318 set_authority(
3319 &program_id,
3320 &mint_key,
3321 Some(&owner_key),
3322 AuthorityType::FreezeAccount,
3323 &mint_key,
3324 &[],
3325 )
3326 .unwrap(),
3327 vec![mint_info.clone(), mint_info.clone()],
3328 )
3329 .unwrap();
3330
3331 do_process_instruction_dups(
3333 set_authority(
3334 &program_id,
3335 &account1_key,
3336 Some(&owner_key),
3337 AuthorityType::AccountOwner,
3338 &account1_key,
3339 &[],
3340 )
3341 .unwrap(),
3342 vec![account1_info.clone(), account1_info.clone()],
3343 )
3344 .unwrap();
3345
3346 let mut account = Account::unpack_unchecked(&account1_info.data.borrow()).unwrap();
3348 account.close_authority = COption::Some(account1_key);
3349 Account::pack(account, &mut account1_info.data.borrow_mut()).unwrap();
3350
3351 do_process_instruction_dups(
3352 set_authority(
3353 &program_id,
3354 &account1_key,
3355 Some(&owner_key),
3356 AuthorityType::CloseAccount,
3357 &account1_key,
3358 &[],
3359 )
3360 .unwrap(),
3361 vec![account1_info.clone(), account1_info.clone()],
3362 )
3363 .unwrap();
3364 }
3365
3366 #[test]
3367 fn test_set_authority() {
3368 let program_id = crate::id();
3369 let account_key = Pubkey::new_unique();
3370 let mut account_account = SafecoinAccount::new(
3371 account_minimum_balance(),
3372 Account::get_packed_len(),
3373 &program_id,
3374 );
3375 let account2_key = Pubkey::new_unique();
3376 let mut account2_account = SafecoinAccount::new(
3377 account_minimum_balance(),
3378 Account::get_packed_len(),
3379 &program_id,
3380 );
3381 let owner_key = Pubkey::new_unique();
3382 let mut owner_account = SafecoinAccount::default();
3383 let owner2_key = Pubkey::new_unique();
3384 let mut owner2_account = SafecoinAccount::default();
3385 let owner3_key = Pubkey::new_unique();
3386 let mut owner3_account = SafecoinAccount::default();
3387 let mint_key = Pubkey::new_unique();
3388 let mut mint_account =
3389 SafecoinAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
3390 let mint2_key = Pubkey::new_unique();
3391 let mut mint2_account =
3392 SafecoinAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
3393 let mut rent_sysvar = rent_sysvar();
3394
3395 do_process_instruction(
3397 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
3398 vec![&mut mint_account, &mut rent_sysvar],
3399 )
3400 .unwrap();
3401
3402 do_process_instruction(
3404 initialize_mint(&program_id, &mint2_key, &owner_key, Some(&owner_key), 2).unwrap(),
3405 vec![&mut mint2_account, &mut rent_sysvar],
3406 )
3407 .unwrap();
3408
3409 assert_eq!(
3411 Err(ProgramError::UninitializedAccount),
3412 do_process_instruction(
3413 set_authority(
3414 &program_id,
3415 &account_key,
3416 Some(&owner2_key),
3417 AuthorityType::AccountOwner,
3418 &owner_key,
3419 &[]
3420 )
3421 .unwrap(),
3422 vec![&mut account_account, &mut owner_account],
3423 )
3424 );
3425
3426 do_process_instruction(
3428 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
3429 vec![
3430 &mut account_account,
3431 &mut mint_account,
3432 &mut owner_account,
3433 &mut rent_sysvar,
3434 ],
3435 )
3436 .unwrap();
3437
3438 do_process_instruction(
3440 initialize_account(&program_id, &account2_key, &mint2_key, &owner_key).unwrap(),
3441 vec![
3442 &mut account2_account,
3443 &mut mint2_account,
3444 &mut owner_account,
3445 &mut rent_sysvar,
3446 ],
3447 )
3448 .unwrap();
3449
3450 assert_eq!(
3452 Err(TokenError::OwnerMismatch.into()),
3453 do_process_instruction(
3454 set_authority(
3455 &program_id,
3456 &account_key,
3457 Some(&owner_key),
3458 AuthorityType::AccountOwner,
3459 &owner2_key,
3460 &[]
3461 )
3462 .unwrap(),
3463 vec![&mut account_account, &mut owner2_account],
3464 )
3465 );
3466
3467 let mut instruction = set_authority(
3469 &program_id,
3470 &account_key,
3471 Some(&owner2_key),
3472 AuthorityType::AccountOwner,
3473 &owner_key,
3474 &[],
3475 )
3476 .unwrap();
3477 instruction.accounts[1].is_signer = false;
3478 assert_eq!(
3479 Err(ProgramError::MissingRequiredSignature),
3480 do_process_instruction(instruction, vec![&mut account_account, &mut owner_account,],)
3481 );
3482
3483 assert_eq!(
3485 Err(TokenError::AuthorityTypeNotSupported.into()),
3486 do_process_instruction(
3487 set_authority(
3488 &program_id,
3489 &account_key,
3490 Some(&owner2_key),
3491 AuthorityType::FreezeAccount,
3492 &owner_key,
3493 &[],
3494 )
3495 .unwrap(),
3496 vec![&mut account_account, &mut owner_account],
3497 )
3498 );
3499
3500 assert_eq!(
3502 Err(TokenError::InvalidInstruction.into()),
3503 do_process_instruction(
3504 set_authority(
3505 &program_id,
3506 &account_key,
3507 None,
3508 AuthorityType::AccountOwner,
3509 &owner_key,
3510 &[],
3511 )
3512 .unwrap(),
3513 vec![&mut account_account, &mut owner_account],
3514 )
3515 );
3516
3517 do_process_instruction(
3519 approve(
3520 &program_id,
3521 &account_key,
3522 &owner2_key,
3523 &owner_key,
3524 &[],
3525 u64::MAX,
3526 )
3527 .unwrap(),
3528 vec![
3529 &mut account_account,
3530 &mut owner2_account,
3531 &mut owner_account,
3532 ],
3533 )
3534 .unwrap();
3535 let account = Account::unpack_unchecked(&account_account.data).unwrap();
3536 assert_eq!(account.delegate, COption::Some(owner2_key));
3537 assert_eq!(account.delegated_amount, u64::MAX);
3538
3539 do_process_instruction(
3541 set_authority(
3542 &program_id,
3543 &account_key,
3544 Some(&owner3_key),
3545 AuthorityType::AccountOwner,
3546 &owner_key,
3547 &[],
3548 )
3549 .unwrap(),
3550 vec![&mut account_account, &mut owner_account],
3551 )
3552 .unwrap();
3553
3554 let account = Account::unpack_unchecked(&account_account.data).unwrap();
3556 assert_eq!(account.delegate, COption::None);
3557 assert_eq!(account.delegated_amount, 0);
3558
3559 do_process_instruction(
3561 set_authority(
3562 &program_id,
3563 &account_key,
3564 Some(&owner2_key),
3565 AuthorityType::AccountOwner,
3566 &owner3_key,
3567 &[],
3568 )
3569 .unwrap(),
3570 vec![&mut account_account, &mut owner3_account],
3571 )
3572 .unwrap();
3573
3574 do_process_instruction(
3576 set_authority(
3577 &program_id,
3578 &account_key,
3579 Some(&owner2_key),
3580 AuthorityType::CloseAccount,
3581 &owner2_key,
3582 &[],
3583 )
3584 .unwrap(),
3585 vec![&mut account_account, &mut owner2_account],
3586 )
3587 .unwrap();
3588
3589 do_process_instruction(
3591 set_authority(
3592 &program_id,
3593 &account_key,
3594 None,
3595 AuthorityType::CloseAccount,
3596 &owner2_key,
3597 &[],
3598 )
3599 .unwrap(),
3600 vec![&mut account_account, &mut owner2_account],
3601 )
3602 .unwrap();
3603
3604 assert_eq!(
3606 Err(TokenError::OwnerMismatch.into()),
3607 do_process_instruction(
3608 set_authority(
3609 &program_id,
3610 &mint_key,
3611 Some(&owner3_key),
3612 AuthorityType::MintTokens,
3613 &owner2_key,
3614 &[]
3615 )
3616 .unwrap(),
3617 vec![&mut mint_account, &mut owner2_account],
3618 )
3619 );
3620
3621 let mut instruction = set_authority(
3623 &program_id,
3624 &mint_key,
3625 Some(&owner2_key),
3626 AuthorityType::MintTokens,
3627 &owner_key,
3628 &[],
3629 )
3630 .unwrap();
3631 instruction.accounts[1].is_signer = false;
3632 assert_eq!(
3633 Err(ProgramError::MissingRequiredSignature),
3634 do_process_instruction(instruction, vec![&mut mint_account, &mut owner_account],)
3635 );
3636
3637 assert_eq!(
3639 Err(TokenError::MintCannotFreeze.into()),
3640 do_process_instruction(
3641 set_authority(
3642 &program_id,
3643 &mint_key,
3644 Some(&owner2_key),
3645 AuthorityType::FreezeAccount,
3646 &owner_key,
3647 &[],
3648 )
3649 .unwrap(),
3650 vec![&mut mint_account, &mut owner_account],
3651 )
3652 );
3653
3654 do_process_instruction(
3656 set_authority(
3657 &program_id,
3658 &mint_key,
3659 Some(&owner2_key),
3660 AuthorityType::MintTokens,
3661 &owner_key,
3662 &[],
3663 )
3664 .unwrap(),
3665 vec![&mut mint_account, &mut owner_account],
3666 )
3667 .unwrap();
3668
3669 do_process_instruction(
3671 set_authority(
3672 &program_id,
3673 &mint_key,
3674 None,
3675 AuthorityType::MintTokens,
3676 &owner2_key,
3677 &[],
3678 )
3679 .unwrap(),
3680 vec![&mut mint_account, &mut owner2_account],
3681 )
3682 .unwrap();
3683
3684 assert_eq!(
3686 Err(TokenError::FixedSupply.into()),
3687 do_process_instruction(
3688 set_authority(
3689 &program_id,
3690 &mint2_key,
3691 Some(&owner2_key),
3692 AuthorityType::MintTokens,
3693 &owner_key,
3694 &[]
3695 )
3696 .unwrap(),
3697 vec![&mut mint_account, &mut owner_account],
3698 )
3699 );
3700
3701 do_process_instruction(
3703 set_authority(
3704 &program_id,
3705 &mint2_key,
3706 Some(&owner2_key),
3707 AuthorityType::FreezeAccount,
3708 &owner_key,
3709 &[],
3710 )
3711 .unwrap(),
3712 vec![&mut mint2_account, &mut owner_account],
3713 )
3714 .unwrap();
3715
3716 do_process_instruction(
3718 set_authority(
3719 &program_id,
3720 &mint2_key,
3721 None,
3722 AuthorityType::FreezeAccount,
3723 &owner2_key,
3724 &[],
3725 )
3726 .unwrap(),
3727 vec![&mut mint2_account, &mut owner2_account],
3728 )
3729 .unwrap();
3730
3731 assert_eq!(
3732 Err(TokenError::MintCannotFreeze.into()),
3733 do_process_instruction(
3734 set_authority(
3735 &program_id,
3736 &mint2_key,
3737 Some(&owner2_key),
3738 AuthorityType::FreezeAccount,
3739 &owner_key,
3740 &[],
3741 )
3742 .unwrap(),
3743 vec![&mut mint2_account, &mut owner2_account],
3744 )
3745 );
3746 }
3747
3748 #[test]
3749 fn test_mint_to_dups() {
3750 let program_id = crate::id();
3751 let account1_key = Pubkey::new_unique();
3752 let mut account1_account = SafecoinAccount::new(
3753 account_minimum_balance(),
3754 Account::get_packed_len(),
3755 &program_id,
3756 );
3757 let account1_info: AccountInfo = (&account1_key, true, &mut account1_account).into();
3758 let owner_key = Pubkey::new_unique();
3759 let mut owner_account = SafecoinAccount::default();
3760 let owner_info: AccountInfo = (&owner_key, true, &mut owner_account).into();
3761 let mint_key = Pubkey::new_unique();
3762 let mut mint_account =
3763 SafecoinAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
3764 let mint_info: AccountInfo = (&mint_key, true, &mut mint_account).into();
3765 let rent_key = rent::id();
3766 let mut rent_sysvar = rent_sysvar();
3767 let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
3768
3769 do_process_instruction_dups(
3771 initialize_mint(&program_id, &mint_key, &mint_key, None, 2).unwrap(),
3772 vec![mint_info.clone(), rent_info.clone()],
3773 )
3774 .unwrap();
3775
3776 do_process_instruction_dups(
3778 initialize_account(&program_id, &account1_key, &mint_key, &owner_key).unwrap(),
3779 vec![
3780 account1_info.clone(),
3781 mint_info.clone(),
3782 owner_info.clone(),
3783 rent_info.clone(),
3784 ],
3785 )
3786 .unwrap();
3787
3788 do_process_instruction_dups(
3790 mint_to(&program_id, &mint_key, &account1_key, &mint_key, &[], 42).unwrap(),
3791 vec![mint_info.clone(), account1_info.clone(), mint_info.clone()],
3792 )
3793 .unwrap();
3794
3795 do_process_instruction_dups(
3797 mint_to_checked(&program_id, &mint_key, &account1_key, &mint_key, &[], 42, 2).unwrap(),
3798 vec![mint_info.clone(), account1_info.clone(), mint_info.clone()],
3799 )
3800 .unwrap();
3801
3802 let mut mint = Mint::unpack_unchecked(&mint_info.data.borrow()).unwrap();
3804 mint.mint_authority = COption::Some(account1_key);
3805 Mint::pack(mint, &mut mint_info.data.borrow_mut()).unwrap();
3806 do_process_instruction_dups(
3807 mint_to(
3808 &program_id,
3809 &mint_key,
3810 &account1_key,
3811 &account1_key,
3812 &[],
3813 42,
3814 )
3815 .unwrap(),
3816 vec![
3817 mint_info.clone(),
3818 account1_info.clone(),
3819 account1_info.clone(),
3820 ],
3821 )
3822 .unwrap();
3823
3824 do_process_instruction_dups(
3826 mint_to(
3827 &program_id,
3828 &mint_key,
3829 &account1_key,
3830 &account1_key,
3831 &[],
3832 42,
3833 )
3834 .unwrap(),
3835 vec![
3836 mint_info.clone(),
3837 account1_info.clone(),
3838 account1_info.clone(),
3839 ],
3840 )
3841 .unwrap();
3842 }
3843
3844 #[test]
3845 fn test_mint_to() {
3846 let program_id = crate::id();
3847 let account_key = Pubkey::new_unique();
3848 let mut account_account = SafecoinAccount::new(
3849 account_minimum_balance(),
3850 Account::get_packed_len(),
3851 &program_id,
3852 );
3853 let account2_key = Pubkey::new_unique();
3854 let mut account2_account = SafecoinAccount::new(
3855 account_minimum_balance(),
3856 Account::get_packed_len(),
3857 &program_id,
3858 );
3859 let account3_key = Pubkey::new_unique();
3860 let mut account3_account = SafecoinAccount::new(
3861 account_minimum_balance(),
3862 Account::get_packed_len(),
3863 &program_id,
3864 );
3865 let mismatch_key = Pubkey::new_unique();
3866 let mut mismatch_account = SafecoinAccount::new(
3867 account_minimum_balance(),
3868 Account::get_packed_len(),
3869 &program_id,
3870 );
3871 let owner_key = Pubkey::new_unique();
3872 let mut owner_account = SafecoinAccount::default();
3873 let owner2_key = Pubkey::new_unique();
3874 let mut owner2_account = SafecoinAccount::default();
3875 let mint_key = Pubkey::new_unique();
3876 let mut mint_account =
3877 SafecoinAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
3878 let mint2_key = Pubkey::new_unique();
3879 let uninitialized_key = Pubkey::new_unique();
3880 let mut uninitialized_account = SafecoinAccount::new(
3881 account_minimum_balance(),
3882 Account::get_packed_len(),
3883 &program_id,
3884 );
3885 let mut rent_sysvar = rent_sysvar();
3886
3887 do_process_instruction(
3889 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
3890 vec![&mut mint_account, &mut rent_sysvar],
3891 )
3892 .unwrap();
3893
3894 do_process_instruction(
3896 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
3897 vec![
3898 &mut account_account,
3899 &mut mint_account,
3900 &mut owner_account,
3901 &mut rent_sysvar,
3902 ],
3903 )
3904 .unwrap();
3905
3906 do_process_instruction(
3908 initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
3909 vec![
3910 &mut account2_account,
3911 &mut mint_account,
3912 &mut owner_account,
3913 &mut rent_sysvar,
3914 ],
3915 )
3916 .unwrap();
3917
3918 do_process_instruction(
3920 initialize_account(&program_id, &account3_key, &mint_key, &owner_key).unwrap(),
3921 vec![
3922 &mut account3_account,
3923 &mut mint_account,
3924 &mut owner_account,
3925 &mut rent_sysvar,
3926 ],
3927 )
3928 .unwrap();
3929
3930 do_process_instruction(
3932 initialize_account(&program_id, &mismatch_key, &mint_key, &owner_key).unwrap(),
3933 vec![
3934 &mut mismatch_account,
3935 &mut mint_account,
3936 &mut owner_account,
3937 &mut rent_sysvar,
3938 ],
3939 )
3940 .unwrap();
3941 let mut account = Account::unpack_unchecked(&mismatch_account.data).unwrap();
3942 account.mint = mint2_key;
3943 Account::pack(account, &mut mismatch_account.data).unwrap();
3944
3945 do_process_instruction(
3947 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 42).unwrap(),
3948 vec![&mut mint_account, &mut account_account, &mut owner_account],
3949 )
3950 .unwrap();
3951
3952 let mint = Mint::unpack_unchecked(&mint_account.data).unwrap();
3953 assert_eq!(mint.supply, 42);
3954 let account = Account::unpack_unchecked(&account_account.data).unwrap();
3955 assert_eq!(account.amount, 42);
3956
3957 do_process_instruction(
3959 mint_to(&program_id, &mint_key, &account2_key, &owner_key, &[], 42).unwrap(),
3960 vec![&mut mint_account, &mut account2_account, &mut owner_account],
3961 )
3962 .unwrap();
3963
3964 let mint = Mint::unpack_unchecked(&mint_account.data).unwrap();
3965 assert_eq!(mint.supply, 84);
3966 let account = Account::unpack_unchecked(&account2_account.data).unwrap();
3967 assert_eq!(account.amount, 42);
3968
3969 let mut instruction =
3971 mint_to(&program_id, &mint_key, &account2_key, &owner_key, &[], 42).unwrap();
3972 instruction.accounts[2].is_signer = false;
3973 assert_eq!(
3974 Err(ProgramError::MissingRequiredSignature),
3975 do_process_instruction(
3976 instruction,
3977 vec![&mut mint_account, &mut account2_account, &mut owner_account],
3978 )
3979 );
3980
3981 assert_eq!(
3983 Err(TokenError::MintMismatch.into()),
3984 do_process_instruction(
3985 mint_to(&program_id, &mint_key, &mismatch_key, &owner_key, &[], 42).unwrap(),
3986 vec![&mut mint_account, &mut mismatch_account, &mut owner_account],
3987 )
3988 );
3989
3990 assert_eq!(
3992 Err(TokenError::OwnerMismatch.into()),
3993 do_process_instruction(
3994 mint_to(&program_id, &mint_key, &account2_key, &owner2_key, &[], 42).unwrap(),
3995 vec![
3996 &mut mint_account,
3997 &mut account2_account,
3998 &mut owner2_account,
3999 ],
4000 )
4001 );
4002
4003 let not_program_id = Pubkey::new_unique();
4005 mint_account.owner = not_program_id;
4006 assert_eq!(
4007 Err(ProgramError::IncorrectProgramId),
4008 do_process_instruction(
4009 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 0).unwrap(),
4010 vec![&mut mint_account, &mut account_account, &mut owner_account],
4011 )
4012 );
4013 mint_account.owner = program_id;
4014
4015 let not_program_id = Pubkey::new_unique();
4017 account_account.owner = not_program_id;
4018 assert_eq!(
4019 Err(ProgramError::IncorrectProgramId),
4020 do_process_instruction(
4021 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 0).unwrap(),
4022 vec![&mut mint_account, &mut account_account, &mut owner_account],
4023 )
4024 );
4025 account_account.owner = program_id;
4026
4027 assert_eq!(
4029 Err(ProgramError::UninitializedAccount),
4030 do_process_instruction(
4031 mint_to(
4032 &program_id,
4033 &mint_key,
4034 &uninitialized_key,
4035 &owner_key,
4036 &[],
4037 42
4038 )
4039 .unwrap(),
4040 vec![
4041 &mut mint_account,
4042 &mut uninitialized_account,
4043 &mut owner_account,
4044 ],
4045 )
4046 );
4047
4048 do_process_instruction(
4050 set_authority(
4051 &program_id,
4052 &mint_key,
4053 None,
4054 AuthorityType::MintTokens,
4055 &owner_key,
4056 &[],
4057 )
4058 .unwrap(),
4059 vec![&mut mint_account, &mut owner_account],
4060 )
4061 .unwrap();
4062 assert_eq!(
4063 Err(TokenError::FixedSupply.into()),
4064 do_process_instruction(
4065 mint_to(&program_id, &mint_key, &account2_key, &owner_key, &[], 42).unwrap(),
4066 vec![&mut mint_account, &mut account2_account, &mut owner_account],
4067 )
4068 );
4069 }
4070
4071 #[test]
4072 fn test_burn_dups() {
4073 let program_id = crate::id();
4074 let account1_key = Pubkey::new_unique();
4075 let mut account1_account = SafecoinAccount::new(
4076 account_minimum_balance(),
4077 Account::get_packed_len(),
4078 &program_id,
4079 );
4080 let account1_info: AccountInfo = (&account1_key, true, &mut account1_account).into();
4081 let owner_key = Pubkey::new_unique();
4082 let mut owner_account = SafecoinAccount::default();
4083 let owner_info: AccountInfo = (&owner_key, true, &mut owner_account).into();
4084 let mint_key = Pubkey::new_unique();
4085 let mut mint_account =
4086 SafecoinAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
4087 let mint_info: AccountInfo = (&mint_key, true, &mut mint_account).into();
4088 let rent_key = rent::id();
4089 let mut rent_sysvar = rent_sysvar();
4090 let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
4091
4092 do_process_instruction_dups(
4094 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
4095 vec![mint_info.clone(), rent_info.clone()],
4096 )
4097 .unwrap();
4098
4099 do_process_instruction_dups(
4101 initialize_account(&program_id, &account1_key, &mint_key, &account1_key).unwrap(),
4102 vec![
4103 account1_info.clone(),
4104 mint_info.clone(),
4105 account1_info.clone(),
4106 rent_info.clone(),
4107 ],
4108 )
4109 .unwrap();
4110
4111 do_process_instruction_dups(
4113 mint_to(&program_id, &mint_key, &account1_key, &owner_key, &[], 1000).unwrap(),
4114 vec![mint_info.clone(), account1_info.clone(), owner_info.clone()],
4115 )
4116 .unwrap();
4117
4118 do_process_instruction_dups(
4120 burn(
4121 &program_id,
4122 &mint_key,
4123 &account1_key,
4124 &account1_key,
4125 &[],
4126 500,
4127 )
4128 .unwrap(),
4129 vec![
4130 account1_info.clone(),
4131 mint_info.clone(),
4132 account1_info.clone(),
4133 ],
4134 )
4135 .unwrap();
4136
4137 do_process_instruction_dups(
4139 burn_checked(
4140 &program_id,
4141 &account1_key,
4142 &mint_key,
4143 &account1_key,
4144 &[],
4145 500,
4146 2,
4147 )
4148 .unwrap(),
4149 vec![
4150 account1_info.clone(),
4151 mint_info.clone(),
4152 account1_info.clone(),
4153 ],
4154 )
4155 .unwrap();
4156
4157 do_process_instruction_dups(
4159 mint_to(&program_id, &mint_key, &account1_key, &owner_key, &[], 1000).unwrap(),
4160 vec![mint_info.clone(), account1_info.clone(), owner_info.clone()],
4161 )
4162 .unwrap();
4163 let mut account = Account::unpack_unchecked(&account1_info.data.borrow()).unwrap();
4164 account.owner = mint_key;
4165 Account::pack(account, &mut account1_info.data.borrow_mut()).unwrap();
4166 do_process_instruction_dups(
4167 burn(&program_id, &account1_key, &mint_key, &mint_key, &[], 500).unwrap(),
4168 vec![account1_info.clone(), mint_info.clone(), mint_info.clone()],
4169 )
4170 .unwrap();
4171
4172 do_process_instruction_dups(
4174 burn_checked(
4175 &program_id,
4176 &account1_key,
4177 &mint_key,
4178 &mint_key,
4179 &[],
4180 500,
4181 2,
4182 )
4183 .unwrap(),
4184 vec![account1_info.clone(), mint_info.clone(), mint_info.clone()],
4185 )
4186 .unwrap();
4187
4188 do_process_instruction_dups(
4190 mint_to(&program_id, &mint_key, &account1_key, &owner_key, &[], 1000).unwrap(),
4191 vec![mint_info.clone(), account1_info.clone(), owner_info.clone()],
4192 )
4193 .unwrap();
4194 let mut account = Account::unpack_unchecked(&account1_info.data.borrow()).unwrap();
4195 account.delegated_amount = 1000;
4196 account.delegate = COption::Some(account1_key);
4197 account.owner = owner_key;
4198 Account::pack(account, &mut account1_info.data.borrow_mut()).unwrap();
4199 do_process_instruction_dups(
4200 burn(
4201 &program_id,
4202 &account1_key,
4203 &mint_key,
4204 &account1_key,
4205 &[],
4206 500,
4207 )
4208 .unwrap(),
4209 vec![
4210 account1_info.clone(),
4211 mint_info.clone(),
4212 account1_info.clone(),
4213 ],
4214 )
4215 .unwrap();
4216
4217 do_process_instruction_dups(
4219 burn_checked(
4220 &program_id,
4221 &account1_key,
4222 &mint_key,
4223 &account1_key,
4224 &[],
4225 500,
4226 2,
4227 )
4228 .unwrap(),
4229 vec![
4230 account1_info.clone(),
4231 mint_info.clone(),
4232 account1_info.clone(),
4233 ],
4234 )
4235 .unwrap();
4236
4237 do_process_instruction_dups(
4239 mint_to(&program_id, &mint_key, &account1_key, &owner_key, &[], 1000).unwrap(),
4240 vec![mint_info.clone(), account1_info.clone(), owner_info.clone()],
4241 )
4242 .unwrap();
4243 let mut account = Account::unpack_unchecked(&account1_info.data.borrow()).unwrap();
4244 account.delegated_amount = 1000;
4245 account.delegate = COption::Some(mint_key);
4246 account.owner = owner_key;
4247 Account::pack(account, &mut account1_info.data.borrow_mut()).unwrap();
4248 do_process_instruction_dups(
4249 burn(&program_id, &account1_key, &mint_key, &mint_key, &[], 500).unwrap(),
4250 vec![account1_info.clone(), mint_info.clone(), mint_info.clone()],
4251 )
4252 .unwrap();
4253
4254 do_process_instruction_dups(
4256 burn_checked(
4257 &program_id,
4258 &account1_key,
4259 &mint_key,
4260 &mint_key,
4261 &[],
4262 500,
4263 2,
4264 )
4265 .unwrap(),
4266 vec![account1_info.clone(), mint_info.clone(), mint_info.clone()],
4267 )
4268 .unwrap();
4269 }
4270
4271 #[test]
4272 fn test_burn() {
4273 let program_id = crate::id();
4274 let account_key = Pubkey::new_unique();
4275 let mut account_account = SafecoinAccount::new(
4276 account_minimum_balance(),
4277 Account::get_packed_len(),
4278 &program_id,
4279 );
4280 let account2_key = Pubkey::new_unique();
4281 let mut account2_account = SafecoinAccount::new(
4282 account_minimum_balance(),
4283 Account::get_packed_len(),
4284 &program_id,
4285 );
4286 let account3_key = Pubkey::new_unique();
4287 let mut account3_account = SafecoinAccount::new(
4288 account_minimum_balance(),
4289 Account::get_packed_len(),
4290 &program_id,
4291 );
4292 let delegate_key = Pubkey::new_unique();
4293 let mut delegate_account = SafecoinAccount::default();
4294 let mismatch_key = Pubkey::new_unique();
4295 let mut mismatch_account = SafecoinAccount::new(
4296 account_minimum_balance(),
4297 Account::get_packed_len(),
4298 &program_id,
4299 );
4300 let owner_key = Pubkey::new_unique();
4301 let mut owner_account = SafecoinAccount::default();
4302 let owner2_key = Pubkey::new_unique();
4303 let mut owner2_account = SafecoinAccount::default();
4304 let mint_key = Pubkey::new_unique();
4305 let mut mint_account =
4306 SafecoinAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
4307 let mint2_key = Pubkey::new_unique();
4308 let mut rent_sysvar = rent_sysvar();
4309
4310 do_process_instruction(
4312 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
4313 vec![&mut mint_account, &mut rent_sysvar],
4314 )
4315 .unwrap();
4316
4317 do_process_instruction(
4319 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
4320 vec![
4321 &mut account_account,
4322 &mut mint_account,
4323 &mut owner_account,
4324 &mut rent_sysvar,
4325 ],
4326 )
4327 .unwrap();
4328
4329 do_process_instruction(
4331 initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
4332 vec![
4333 &mut account2_account,
4334 &mut mint_account,
4335 &mut owner_account,
4336 &mut rent_sysvar,
4337 ],
4338 )
4339 .unwrap();
4340
4341 do_process_instruction(
4343 initialize_account(&program_id, &account3_key, &mint_key, &owner_key).unwrap(),
4344 vec![
4345 &mut account3_account,
4346 &mut mint_account,
4347 &mut owner_account,
4348 &mut rent_sysvar,
4349 ],
4350 )
4351 .unwrap();
4352
4353 do_process_instruction(
4355 initialize_account(&program_id, &mismatch_key, &mint_key, &owner_key).unwrap(),
4356 vec![
4357 &mut mismatch_account,
4358 &mut mint_account,
4359 &mut owner_account,
4360 &mut rent_sysvar,
4361 ],
4362 )
4363 .unwrap();
4364
4365 do_process_instruction(
4367 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
4368 vec![&mut mint_account, &mut account_account, &mut owner_account],
4369 )
4370 .unwrap();
4371
4372 do_process_instruction(
4374 mint_to(&program_id, &mint_key, &mismatch_key, &owner_key, &[], 1000).unwrap(),
4375 vec![&mut mint_account, &mut mismatch_account, &mut owner_account],
4376 )
4377 .unwrap();
4378 let mut account = Account::unpack_unchecked(&mismatch_account.data).unwrap();
4379 account.mint = mint2_key;
4380 Account::pack(account, &mut mismatch_account.data).unwrap();
4381
4382 let mut instruction =
4384 burn(&program_id, &account_key, &mint_key, &delegate_key, &[], 42).unwrap();
4385 instruction.accounts[1].is_signer = false;
4386 assert_eq!(
4387 Err(TokenError::OwnerMismatch.into()),
4388 do_process_instruction(
4389 instruction,
4390 vec![
4391 &mut account_account,
4392 &mut mint_account,
4393 &mut delegate_account
4394 ],
4395 )
4396 );
4397
4398 assert_eq!(
4400 Err(TokenError::OwnerMismatch.into()),
4401 do_process_instruction(
4402 burn(&program_id, &account_key, &mint_key, &owner2_key, &[], 42).unwrap(),
4403 vec![&mut account_account, &mut mint_account, &mut owner2_account],
4404 )
4405 );
4406
4407 let not_program_id = Pubkey::new_unique();
4409 account_account.owner = not_program_id;
4410 assert_eq!(
4411 Err(ProgramError::IncorrectProgramId),
4412 do_process_instruction(
4413 burn(&program_id, &account_key, &mint_key, &owner_key, &[], 0).unwrap(),
4414 vec![&mut account_account, &mut mint_account, &mut owner_account],
4415 )
4416 );
4417 account_account.owner = program_id;
4418
4419 let not_program_id = Pubkey::new_unique();
4421 mint_account.owner = not_program_id;
4422 assert_eq!(
4423 Err(ProgramError::IncorrectProgramId),
4424 do_process_instruction(
4425 burn(&program_id, &account_key, &mint_key, &owner_key, &[], 0).unwrap(),
4426 vec![&mut account_account, &mut mint_account, &mut owner_account],
4427 )
4428 );
4429 mint_account.owner = program_id;
4430
4431 assert_eq!(
4433 Err(TokenError::MintMismatch.into()),
4434 do_process_instruction(
4435 burn(&program_id, &mismatch_key, &mint_key, &owner_key, &[], 42).unwrap(),
4436 vec![&mut mismatch_account, &mut mint_account, &mut owner_account],
4437 )
4438 );
4439
4440 do_process_instruction(
4442 burn(&program_id, &account_key, &mint_key, &owner_key, &[], 21).unwrap(),
4443 vec![&mut account_account, &mut mint_account, &mut owner_account],
4444 )
4445 .unwrap();
4446
4447 assert_eq!(
4449 Err(TokenError::MintDecimalsMismatch.into()),
4450 do_process_instruction(
4451 burn_checked(&program_id, &account_key, &mint_key, &owner_key, &[], 21, 3).unwrap(),
4452 vec![&mut account_account, &mut mint_account, &mut owner_account],
4453 )
4454 );
4455
4456 do_process_instruction(
4458 burn_checked(&program_id, &account_key, &mint_key, &owner_key, &[], 21, 2).unwrap(),
4459 vec![&mut account_account, &mut mint_account, &mut owner_account],
4460 )
4461 .unwrap();
4462
4463 let mint = Mint::unpack_unchecked(&mint_account.data).unwrap();
4464 assert_eq!(mint.supply, 2000 - 42);
4465 let account = Account::unpack_unchecked(&account_account.data).unwrap();
4466 assert_eq!(account.amount, 1000 - 42);
4467
4468 assert_eq!(
4470 Err(TokenError::InsufficientFunds.into()),
4471 do_process_instruction(
4472 burn(
4473 &program_id,
4474 &account_key,
4475 &mint_key,
4476 &owner_key,
4477 &[],
4478 100_000_000
4479 )
4480 .unwrap(),
4481 vec![&mut account_account, &mut mint_account, &mut owner_account],
4482 )
4483 );
4484
4485 do_process_instruction(
4487 approve(
4488 &program_id,
4489 &account_key,
4490 &delegate_key,
4491 &owner_key,
4492 &[],
4493 84,
4494 )
4495 .unwrap(),
4496 vec![
4497 &mut account_account,
4498 &mut delegate_account,
4499 &mut owner_account,
4500 ],
4501 )
4502 .unwrap();
4503
4504 assert_eq!(
4506 Err(TokenError::InsufficientFunds.into()),
4507 do_process_instruction(
4508 burn(
4509 &program_id,
4510 &account_key,
4511 &mint_key,
4512 &owner_key,
4513 &[],
4514 100_000_000
4515 )
4516 .unwrap(),
4517 vec![&mut account_account, &mut mint_account, &mut owner_account],
4518 )
4519 );
4520
4521 do_process_instruction(
4523 burn(&program_id, &account_key, &mint_key, &delegate_key, &[], 84).unwrap(),
4524 vec![
4525 &mut account_account,
4526 &mut mint_account,
4527 &mut delegate_account,
4528 ],
4529 )
4530 .unwrap();
4531
4532 let mint = Mint::unpack_unchecked(&mint_account.data).unwrap();
4534 assert_eq!(mint.supply, 2000 - 42 - 84);
4535 let account = Account::unpack_unchecked(&account_account.data).unwrap();
4536 assert_eq!(account.amount, 1000 - 42 - 84);
4537
4538 assert_eq!(
4540 Err(TokenError::OwnerMismatch.into()),
4541 do_process_instruction(
4542 burn(
4543 &program_id,
4544 &account_key,
4545 &mint_key,
4546 &delegate_key,
4547 &[],
4548 100
4549 )
4550 .unwrap(),
4551 vec![
4552 &mut account_account,
4553 &mut mint_account,
4554 &mut delegate_account
4555 ],
4556 )
4557 );
4558 }
4559
4560 #[test]
4561 fn test_burn_and_close_system_and_incinerator_tokens() {
4562 let program_id = crate::id();
4563 let account_key = Pubkey::new_unique();
4564 let mut account_account = SafecoinAccount::new(
4565 account_minimum_balance(),
4566 Account::get_packed_len(),
4567 &program_id,
4568 );
4569 let incinerator_account_key = Pubkey::new_unique();
4570 let mut incinerator_account = SafecoinAccount::new(
4571 account_minimum_balance(),
4572 Account::get_packed_len(),
4573 &program_id,
4574 );
4575 let system_account_key = Pubkey::new_unique();
4576 let mut system_account = SafecoinAccount::new(
4577 account_minimum_balance(),
4578 Account::get_packed_len(),
4579 &program_id,
4580 );
4581 let owner_key = Pubkey::new_unique();
4582 let mut owner_account = SafecoinAccount::default();
4583 let recipient_key = Pubkey::new_unique();
4584 let mut recipient_account = SafecoinAccount::default();
4585 let mut mock_incinerator_account = SafecoinAccount::default();
4586 let mint_key = Pubkey::new_unique();
4587 let mut mint_account =
4588 SafecoinAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
4589
4590 do_process_instruction(
4592 initialize_mint2(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
4593 vec![&mut mint_account],
4594 )
4595 .unwrap();
4596
4597 do_process_instruction(
4599 initialize_account3(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
4600 vec![&mut account_account, &mut mint_account],
4601 )
4602 .unwrap();
4603
4604 do_process_instruction(
4606 initialize_account3(
4607 &program_id,
4608 &incinerator_account_key,
4609 &mint_key,
4610 &solana_program::incinerator::id(),
4611 )
4612 .unwrap(),
4613 vec![&mut incinerator_account, &mut mint_account],
4614 )
4615 .unwrap();
4616 do_process_instruction(
4617 initialize_account3(
4618 &program_id,
4619 &system_account_key,
4620 &mint_key,
4621 &solana_program::system_program::id(),
4622 )
4623 .unwrap(),
4624 vec![&mut system_account, &mut mint_account],
4625 )
4626 .unwrap();
4627
4628 do_process_instruction(
4630 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
4631 vec![&mut mint_account, &mut account_account, &mut owner_account],
4632 )
4633 .unwrap();
4634
4635 do_process_instruction(
4637 transfer(
4638 &program_id,
4639 &account_key,
4640 &incinerator_account_key,
4641 &owner_key,
4642 &[],
4643 500,
4644 )
4645 .unwrap(),
4646 vec![
4647 &mut account_account,
4648 &mut incinerator_account,
4649 &mut owner_account,
4650 ],
4651 )
4652 .unwrap();
4653 do_process_instruction(
4654 transfer(
4655 &program_id,
4656 &account_key,
4657 &system_account_key,
4658 &owner_key,
4659 &[],
4660 500,
4661 )
4662 .unwrap(),
4663 vec![
4664 &mut account_account,
4665 &mut system_account,
4666 &mut owner_account,
4667 ],
4668 )
4669 .unwrap();
4670
4671 assert_eq!(
4673 Err(TokenError::NonNativeHasBalance.into()),
4674 do_process_instruction(
4675 close_account(
4676 &program_id,
4677 &incinerator_account_key,
4678 &solana_program::incinerator::id(),
4679 &owner_key,
4680 &[]
4681 )
4682 .unwrap(),
4683 vec![
4684 &mut incinerator_account,
4685 &mut mock_incinerator_account,
4686 &mut owner_account,
4687 ],
4688 )
4689 );
4690 assert_eq!(
4691 Err(TokenError::NonNativeHasBalance.into()),
4692 do_process_instruction(
4693 close_account(
4694 &program_id,
4695 &system_account_key,
4696 &solana_program::incinerator::id(),
4697 &owner_key,
4698 &[]
4699 )
4700 .unwrap(),
4701 vec![
4702 &mut system_account,
4703 &mut mock_incinerator_account,
4704 &mut owner_account,
4705 ],
4706 )
4707 );
4708
4709 do_process_instruction(
4711 burn(
4712 &program_id,
4713 &incinerator_account_key,
4714 &mint_key,
4715 &recipient_key,
4716 &[],
4717 500,
4718 )
4719 .unwrap(),
4720 vec![
4721 &mut incinerator_account,
4722 &mut mint_account,
4723 &mut recipient_account,
4724 ],
4725 )
4726 .unwrap();
4727 do_process_instruction(
4728 burn(
4729 &program_id,
4730 &system_account_key,
4731 &mint_key,
4732 &recipient_key,
4733 &[],
4734 500,
4735 )
4736 .unwrap(),
4737 vec![
4738 &mut system_account,
4739 &mut mint_account,
4740 &mut recipient_account,
4741 ],
4742 )
4743 .unwrap();
4744
4745 assert_eq!(
4747 Err(ProgramError::InvalidAccountData),
4748 do_process_instruction(
4749 close_account(
4750 &program_id,
4751 &incinerator_account_key,
4752 &recipient_key,
4753 &owner_key,
4754 &[]
4755 )
4756 .unwrap(),
4757 vec![
4758 &mut incinerator_account,
4759 &mut recipient_account,
4760 &mut owner_account,
4761 ],
4762 )
4763 );
4764 assert_eq!(
4765 Err(ProgramError::InvalidAccountData),
4766 do_process_instruction(
4767 close_account(
4768 &program_id,
4769 &system_account_key,
4770 &recipient_key,
4771 &owner_key,
4772 &[]
4773 )
4774 .unwrap(),
4775 vec![
4776 &mut system_account,
4777 &mut recipient_account,
4778 &mut owner_account,
4779 ],
4780 )
4781 );
4782
4783 do_process_instruction(
4785 close_account(
4786 &program_id,
4787 &incinerator_account_key,
4788 &solana_program::incinerator::id(),
4789 &owner_key,
4790 &[],
4791 )
4792 .unwrap(),
4793 vec![
4794 &mut incinerator_account,
4795 &mut mock_incinerator_account,
4796 &mut owner_account,
4797 ],
4798 )
4799 .unwrap();
4800
4801 do_process_instruction(
4802 close_account(
4803 &program_id,
4804 &system_account_key,
4805 &solana_program::incinerator::id(),
4806 &owner_key,
4807 &[],
4808 )
4809 .unwrap(),
4810 vec![
4811 &mut system_account,
4812 &mut mock_incinerator_account,
4813 &mut owner_account,
4814 ],
4815 )
4816 .unwrap();
4817 }
4818
4819 #[test]
4820 fn test_multisig() {
4821 let program_id = crate::id();
4822 let mint_key = Pubkey::new_unique();
4823 let mut mint_account =
4824 SafecoinAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
4825 let account_key = Pubkey::new_unique();
4826 let mut account = SafecoinAccount::new(
4827 account_minimum_balance(),
4828 Account::get_packed_len(),
4829 &program_id,
4830 );
4831 let account2_key = Pubkey::new_unique();
4832 let mut account2_account = SafecoinAccount::new(
4833 account_minimum_balance(),
4834 Account::get_packed_len(),
4835 &program_id,
4836 );
4837 let owner_key = Pubkey::new_unique();
4838 let mut owner_account = SafecoinAccount::default();
4839 let multisig_key = Pubkey::new_unique();
4840 let mut multisig_account = SafecoinAccount::new(42, Multisig::get_packed_len(), &program_id);
4841 let multisig_delegate_key = Pubkey::new_unique();
4842 let mut multisig_delegate_account = SafecoinAccount::new(
4843 multisig_minimum_balance(),
4844 Multisig::get_packed_len(),
4845 &program_id,
4846 );
4847 let signer_keys = vec![Pubkey::new_unique(); MAX_SIGNERS];
4848 let signer_key_refs: Vec<&Pubkey> = signer_keys.iter().collect();
4849 let mut signer_accounts = vec![SafecoinAccount::new(0, 0, &program_id); MAX_SIGNERS];
4850 let mut rent_sysvar = rent_sysvar();
4851
4852 let account_info_iter = &mut signer_accounts.iter_mut();
4854 assert_eq!(
4855 Err(TokenError::NotRentExempt.into()),
4856 do_process_instruction(
4857 initialize_multisig(&program_id, &multisig_key, &[&signer_keys[0]], 1).unwrap(),
4858 vec![
4859 &mut multisig_account,
4860 &mut rent_sysvar,
4861 account_info_iter.next().unwrap(),
4862 ],
4863 )
4864 );
4865
4866 multisig_account.lamports = multisig_minimum_balance();
4867 let mut multisig_account2 = multisig_account.clone();
4868
4869 let account_info_iter = &mut signer_accounts.iter_mut();
4871 do_process_instruction(
4872 initialize_multisig(&program_id, &multisig_key, &[&signer_keys[0]], 1).unwrap(),
4873 vec![
4874 &mut multisig_account,
4875 &mut rent_sysvar,
4876 account_info_iter.next().unwrap(),
4877 ],
4878 )
4879 .unwrap();
4880
4881 let account_info_iter = &mut signer_accounts.iter_mut();
4883 do_process_instruction(
4884 initialize_multisig2(&program_id, &multisig_key, &[&signer_keys[0]], 1).unwrap(),
4885 vec![&mut multisig_account2, account_info_iter.next().unwrap()],
4886 )
4887 .unwrap();
4888
4889 let account_info_iter = &mut signer_accounts.iter_mut();
4891 do_process_instruction(
4892 initialize_multisig(
4893 &program_id,
4894 &multisig_delegate_key,
4895 &signer_key_refs,
4896 MAX_SIGNERS as u8,
4897 )
4898 .unwrap(),
4899 vec![
4900 &mut multisig_delegate_account,
4901 &mut rent_sysvar,
4902 account_info_iter.next().unwrap(),
4903 account_info_iter.next().unwrap(),
4904 account_info_iter.next().unwrap(),
4905 account_info_iter.next().unwrap(),
4906 account_info_iter.next().unwrap(),
4907 account_info_iter.next().unwrap(),
4908 account_info_iter.next().unwrap(),
4909 account_info_iter.next().unwrap(),
4910 account_info_iter.next().unwrap(),
4911 account_info_iter.next().unwrap(),
4912 account_info_iter.next().unwrap(),
4913 ],
4914 )
4915 .unwrap();
4916
4917 do_process_instruction(
4919 initialize_mint(&program_id, &mint_key, &multisig_key, None, 2).unwrap(),
4920 vec![&mut mint_account, &mut rent_sysvar],
4921 )
4922 .unwrap();
4923
4924 do_process_instruction(
4926 initialize_account(&program_id, &account_key, &mint_key, &multisig_key).unwrap(),
4927 vec![
4928 &mut account,
4929 &mut mint_account,
4930 &mut multisig_account,
4931 &mut rent_sysvar,
4932 ],
4933 )
4934 .unwrap();
4935
4936 do_process_instruction(
4938 initialize_account(
4939 &program_id,
4940 &account2_key,
4941 &mint_key,
4942 &multisig_delegate_key,
4943 )
4944 .unwrap(),
4945 vec![
4946 &mut account2_account,
4947 &mut mint_account,
4948 &mut multisig_account,
4949 &mut rent_sysvar,
4950 ],
4951 )
4952 .unwrap();
4953
4954 let account_info_iter = &mut signer_accounts.iter_mut();
4956 do_process_instruction(
4957 mint_to(
4958 &program_id,
4959 &mint_key,
4960 &account_key,
4961 &multisig_key,
4962 &[&signer_keys[0]],
4963 1000,
4964 )
4965 .unwrap(),
4966 vec![
4967 &mut mint_account,
4968 &mut account,
4969 &mut multisig_account,
4970 account_info_iter.next().unwrap(),
4971 ],
4972 )
4973 .unwrap();
4974
4975 let account_info_iter = &mut signer_accounts.iter_mut();
4977 do_process_instruction(
4978 approve(
4979 &program_id,
4980 &account_key,
4981 &multisig_delegate_key,
4982 &multisig_key,
4983 &[&signer_keys[0]],
4984 100,
4985 )
4986 .unwrap(),
4987 vec![
4988 &mut account,
4989 &mut multisig_delegate_account,
4990 &mut multisig_account,
4991 account_info_iter.next().unwrap(),
4992 ],
4993 )
4994 .unwrap();
4995
4996 let account_info_iter = &mut signer_accounts.iter_mut();
4998 do_process_instruction(
4999 transfer(
5000 &program_id,
5001 &account_key,
5002 &account2_key,
5003 &multisig_key,
5004 &[&signer_keys[0]],
5005 42,
5006 )
5007 .unwrap(),
5008 vec![
5009 &mut account,
5010 &mut account2_account,
5011 &mut multisig_account,
5012 account_info_iter.next().unwrap(),
5013 ],
5014 )
5015 .unwrap();
5016
5017 let account_info_iter = &mut signer_accounts.iter_mut();
5019 do_process_instruction(
5020 transfer(
5021 &program_id,
5022 &account_key,
5023 &account2_key,
5024 &multisig_delegate_key,
5025 &signer_key_refs,
5026 42,
5027 )
5028 .unwrap(),
5029 vec![
5030 &mut account,
5031 &mut account2_account,
5032 &mut multisig_delegate_account,
5033 account_info_iter.next().unwrap(),
5034 account_info_iter.next().unwrap(),
5035 account_info_iter.next().unwrap(),
5036 account_info_iter.next().unwrap(),
5037 account_info_iter.next().unwrap(),
5038 account_info_iter.next().unwrap(),
5039 account_info_iter.next().unwrap(),
5040 account_info_iter.next().unwrap(),
5041 account_info_iter.next().unwrap(),
5042 account_info_iter.next().unwrap(),
5043 account_info_iter.next().unwrap(),
5044 ],
5045 )
5046 .unwrap();
5047
5048 let account_info_iter = &mut signer_accounts.iter_mut();
5050 do_process_instruction(
5051 mint_to(
5052 &program_id,
5053 &mint_key,
5054 &account2_key,
5055 &multisig_key,
5056 &[&signer_keys[0]],
5057 42,
5058 )
5059 .unwrap(),
5060 vec![
5061 &mut mint_account,
5062 &mut account2_account,
5063 &mut multisig_account,
5064 account_info_iter.next().unwrap(),
5065 ],
5066 )
5067 .unwrap();
5068
5069 let account_info_iter = &mut signer_accounts.iter_mut();
5071 do_process_instruction(
5072 burn(
5073 &program_id,
5074 &account_key,
5075 &mint_key,
5076 &multisig_key,
5077 &[&signer_keys[0]],
5078 42,
5079 )
5080 .unwrap(),
5081 vec![
5082 &mut account,
5083 &mut mint_account,
5084 &mut multisig_account,
5085 account_info_iter.next().unwrap(),
5086 ],
5087 )
5088 .unwrap();
5089
5090 let account_info_iter = &mut signer_accounts.iter_mut();
5092 do_process_instruction(
5093 burn(
5094 &program_id,
5095 &account_key,
5096 &mint_key,
5097 &multisig_delegate_key,
5098 &signer_key_refs,
5099 42,
5100 )
5101 .unwrap(),
5102 vec![
5103 &mut account,
5104 &mut mint_account,
5105 &mut multisig_delegate_account,
5106 account_info_iter.next().unwrap(),
5107 account_info_iter.next().unwrap(),
5108 account_info_iter.next().unwrap(),
5109 account_info_iter.next().unwrap(),
5110 account_info_iter.next().unwrap(),
5111 account_info_iter.next().unwrap(),
5112 account_info_iter.next().unwrap(),
5113 account_info_iter.next().unwrap(),
5114 account_info_iter.next().unwrap(),
5115 account_info_iter.next().unwrap(),
5116 account_info_iter.next().unwrap(),
5117 ],
5118 )
5119 .unwrap();
5120
5121 let account3_key = Pubkey::new_unique();
5123 let mut account3_account = SafecoinAccount::new(
5124 account_minimum_balance(),
5125 Account::get_packed_len(),
5126 &program_id,
5127 );
5128 let mint2_key = Pubkey::new_unique();
5129 let mut mint2_account =
5130 SafecoinAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
5131 do_process_instruction(
5132 initialize_mint(
5133 &program_id,
5134 &mint2_key,
5135 &multisig_key,
5136 Some(&multisig_key),
5137 2,
5138 )
5139 .unwrap(),
5140 vec![&mut mint2_account, &mut rent_sysvar],
5141 )
5142 .unwrap();
5143 do_process_instruction(
5144 initialize_account(&program_id, &account3_key, &mint2_key, &owner_key).unwrap(),
5145 vec![
5146 &mut account3_account,
5147 &mut mint2_account,
5148 &mut owner_account,
5149 &mut rent_sysvar,
5150 ],
5151 )
5152 .unwrap();
5153 let account_info_iter = &mut signer_accounts.iter_mut();
5154 do_process_instruction(
5155 mint_to(
5156 &program_id,
5157 &mint2_key,
5158 &account3_key,
5159 &multisig_key,
5160 &[&signer_keys[0]],
5161 1000,
5162 )
5163 .unwrap(),
5164 vec![
5165 &mut mint2_account,
5166 &mut account3_account,
5167 &mut multisig_account,
5168 account_info_iter.next().unwrap(),
5169 ],
5170 )
5171 .unwrap();
5172 let account_info_iter = &mut signer_accounts.iter_mut();
5173 do_process_instruction(
5174 freeze_account(
5175 &program_id,
5176 &account3_key,
5177 &mint2_key,
5178 &multisig_key,
5179 &[&signer_keys[0]],
5180 )
5181 .unwrap(),
5182 vec![
5183 &mut account3_account,
5184 &mut mint2_account,
5185 &mut multisig_account,
5186 account_info_iter.next().unwrap(),
5187 ],
5188 )
5189 .unwrap();
5190
5191 let account_info_iter = &mut signer_accounts.iter_mut();
5193 do_process_instruction(
5194 set_authority(
5195 &program_id,
5196 &mint_key,
5197 Some(&owner_key),
5198 AuthorityType::MintTokens,
5199 &multisig_key,
5200 &[&signer_keys[0]],
5201 )
5202 .unwrap(),
5203 vec![
5204 &mut mint_account,
5205 &mut multisig_account,
5206 account_info_iter.next().unwrap(),
5207 ],
5208 )
5209 .unwrap();
5210
5211 let account_info_iter = &mut signer_accounts.iter_mut();
5213 do_process_instruction(
5214 set_authority(
5215 &program_id,
5216 &account_key,
5217 Some(&owner_key),
5218 AuthorityType::AccountOwner,
5219 &multisig_key,
5220 &[&signer_keys[0]],
5221 )
5222 .unwrap(),
5223 vec![
5224 &mut account,
5225 &mut multisig_account,
5226 account_info_iter.next().unwrap(),
5227 ],
5228 )
5229 .unwrap();
5230 }
5231
5232 #[test]
5233 fn test_validate_owner() {
5234 let program_id = crate::id();
5235 let owner_key = Pubkey::new_unique();
5236 let mut signer_keys = [Pubkey::default(); MAX_SIGNERS];
5237 for signer_key in signer_keys.iter_mut().take(MAX_SIGNERS) {
5238 *signer_key = Pubkey::new_unique();
5239 }
5240 let mut signer_lamports = 0;
5241 let mut signer_data = vec![];
5242 let mut signers = vec![
5243 AccountInfo::new(
5244 &owner_key,
5245 true,
5246 false,
5247 &mut signer_lamports,
5248 &mut signer_data,
5249 &program_id,
5250 false,
5251 Epoch::default(),
5252 );
5253 MAX_SIGNERS + 1
5254 ];
5255 for (signer, key) in signers.iter_mut().zip(&signer_keys) {
5256 signer.key = key;
5257 }
5258 let mut lamports = 0;
5259 let mut data = vec![0; Multisig::get_packed_len()];
5260 let mut multisig = Multisig::unpack_unchecked(&data).unwrap();
5261 multisig.m = MAX_SIGNERS as u8;
5262 multisig.n = MAX_SIGNERS as u8;
5263 multisig.signers = signer_keys;
5264 multisig.is_initialized = true;
5265 Multisig::pack(multisig, &mut data).unwrap();
5266 let owner_account_info = AccountInfo::new(
5267 &owner_key,
5268 false,
5269 false,
5270 &mut lamports,
5271 &mut data,
5272 &program_id,
5273 false,
5274 Epoch::default(),
5275 );
5276
5277 Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers).unwrap();
5279
5280 {
5282 let mut multisig =
5283 Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
5284 multisig.m = 1;
5285 Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
5286 }
5287 Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers).unwrap();
5288
5289 {
5291 let mut multisig =
5292 Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
5293 multisig.m = 2;
5294 multisig.n = 1;
5295 Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
5296 }
5297 assert_eq!(
5298 Err(ProgramError::MissingRequiredSignature),
5299 Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers)
5300 );
5301
5302 {
5304 let mut multisig =
5305 Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
5306 multisig.m = 0;
5307 multisig.n = 11;
5308 Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
5309 }
5310 Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers).unwrap();
5311
5312 {
5314 let mut multisig =
5315 Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
5316 multisig.m = 2;
5317 multisig.n = 11;
5318 Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
5319 }
5320 assert_eq!(
5321 Err(ProgramError::MissingRequiredSignature),
5322 Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &[])
5323 );
5324 {
5326 let mut multisig =
5327 Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
5328 multisig.m = 2;
5329 multisig.n = 11;
5330 Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
5331 }
5332 assert_eq!(
5333 Err(ProgramError::MissingRequiredSignature),
5334 Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers[0..1])
5335 );
5336
5337 {
5339 let mut multisig =
5340 Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
5341 multisig.m = 2;
5342 multisig.n = 11;
5343 Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
5344 }
5345 Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers[5..7])
5346 .unwrap();
5347
5348 {
5350 let mut multisig =
5351 Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
5352 multisig.m = 11;
5353 multisig.n = 11;
5354 Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
5355 }
5356 signers[5].is_signer = false;
5357 assert_eq!(
5358 Err(ProgramError::MissingRequiredSignature),
5359 Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers)
5360 );
5361 signers[5].is_signer = true;
5362
5363 {
5365 let mut signer_lamports = 0;
5366 let mut signer_data = vec![];
5367 let signers = vec![
5368 AccountInfo::new(
5369 &signer_keys[5],
5370 true,
5371 false,
5372 &mut signer_lamports,
5373 &mut signer_data,
5374 &program_id,
5375 false,
5376 Epoch::default(),
5377 );
5378 MAX_SIGNERS + 1
5379 ];
5380 let mut multisig =
5381 Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
5382 multisig.m = 11;
5383 multisig.n = 11;
5384 Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
5385 assert_eq!(
5386 Err(ProgramError::MissingRequiredSignature),
5387 Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers)
5388 );
5389 }
5390 }
5391
5392 #[test]
5393 fn test_owner_close_account_dups() {
5394 let program_id = crate::id();
5395 let owner_key = Pubkey::new_unique();
5396 let mint_key = Pubkey::new_unique();
5397 let mut mint_account =
5398 SafecoinAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
5399 let mint_info: AccountInfo = (&mint_key, false, &mut mint_account).into();
5400 let rent_key = rent::id();
5401 let mut rent_sysvar = rent_sysvar();
5402 let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
5403
5404 do_process_instruction_dups(
5406 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
5407 vec![mint_info.clone(), rent_info.clone()],
5408 )
5409 .unwrap();
5410
5411 let to_close_key = Pubkey::new_unique();
5412 let mut to_close_account = SafecoinAccount::new(
5413 account_minimum_balance(),
5414 Account::get_packed_len(),
5415 &program_id,
5416 );
5417 let to_close_account_info: AccountInfo =
5418 (&to_close_key, true, &mut to_close_account).into();
5419 let destination_account_key = Pubkey::new_unique();
5420 let mut destination_account = SafecoinAccount::new(
5421 account_minimum_balance(),
5422 Account::get_packed_len(),
5423 &program_id,
5424 );
5425 let destination_account_info: AccountInfo =
5426 (&destination_account_key, true, &mut destination_account).into();
5427 do_process_instruction_dups(
5429 initialize_account(&program_id, &to_close_key, &mint_key, &to_close_key).unwrap(),
5430 vec![
5431 to_close_account_info.clone(),
5432 mint_info.clone(),
5433 to_close_account_info.clone(),
5434 rent_info.clone(),
5435 ],
5436 )
5437 .unwrap();
5438
5439 do_process_instruction_dups(
5441 close_account(
5442 &program_id,
5443 &to_close_key,
5444 &destination_account_key,
5445 &to_close_key,
5446 &[],
5447 )
5448 .unwrap(),
5449 vec![
5450 to_close_account_info.clone(),
5451 destination_account_info.clone(),
5452 to_close_account_info.clone(),
5453 ],
5454 )
5455 .unwrap();
5456 assert_eq!(*to_close_account_info.data.borrow(), &[0u8; Account::LEN]);
5457 }
5458
5459 #[test]
5460 fn test_close_authority_close_account_dups() {
5461 let program_id = crate::id();
5462 let owner_key = Pubkey::new_unique();
5463 let mint_key = Pubkey::new_unique();
5464 let mut mint_account =
5465 SafecoinAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
5466 let mint_info: AccountInfo = (&mint_key, false, &mut mint_account).into();
5467 let rent_key = rent::id();
5468 let mut rent_sysvar = rent_sysvar();
5469 let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
5470
5471 do_process_instruction_dups(
5473 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
5474 vec![mint_info.clone(), rent_info.clone()],
5475 )
5476 .unwrap();
5477
5478 let to_close_key = Pubkey::new_unique();
5479 let mut to_close_account = SafecoinAccount::new(
5480 account_minimum_balance(),
5481 Account::get_packed_len(),
5482 &program_id,
5483 );
5484 let to_close_account_info: AccountInfo =
5485 (&to_close_key, true, &mut to_close_account).into();
5486 let destination_account_key = Pubkey::new_unique();
5487 let mut destination_account = SafecoinAccount::new(
5488 account_minimum_balance(),
5489 Account::get_packed_len(),
5490 &program_id,
5491 );
5492 let destination_account_info: AccountInfo =
5493 (&destination_account_key, true, &mut destination_account).into();
5494 do_process_instruction_dups(
5496 initialize_account(&program_id, &to_close_key, &mint_key, &to_close_key).unwrap(),
5497 vec![
5498 to_close_account_info.clone(),
5499 mint_info.clone(),
5500 to_close_account_info.clone(),
5501 rent_info.clone(),
5502 ],
5503 )
5504 .unwrap();
5505 let mut account = Account::unpack_unchecked(&to_close_account_info.data.borrow()).unwrap();
5506 account.close_authority = COption::Some(to_close_key);
5507 account.owner = owner_key;
5508 Account::pack(account, &mut to_close_account_info.data.borrow_mut()).unwrap();
5509 do_process_instruction_dups(
5510 close_account(
5511 &program_id,
5512 &to_close_key,
5513 &destination_account_key,
5514 &to_close_key,
5515 &[],
5516 )
5517 .unwrap(),
5518 vec![
5519 to_close_account_info.clone(),
5520 destination_account_info.clone(),
5521 to_close_account_info.clone(),
5522 ],
5523 )
5524 .unwrap();
5525 assert_eq!(*to_close_account_info.data.borrow(), &[0u8; Account::LEN]);
5526 }
5527
5528 #[test]
5529 fn test_close_account() {
5530 let program_id = crate::id();
5531 let mint_key = Pubkey::new_unique();
5532 let mut mint_account =
5533 SafecoinAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
5534 let account_key = Pubkey::new_unique();
5535 let mut account_account = SafecoinAccount::new(
5536 account_minimum_balance(),
5537 Account::get_packed_len(),
5538 &program_id,
5539 );
5540 let account2_key = Pubkey::new_unique();
5541 let mut account2_account = SafecoinAccount::new(
5542 account_minimum_balance() + 42,
5543 Account::get_packed_len(),
5544 &program_id,
5545 );
5546 let account3_key = Pubkey::new_unique();
5547 let mut account3_account = SafecoinAccount::new(
5548 account_minimum_balance(),
5549 Account::get_packed_len(),
5550 &program_id,
5551 );
5552 let owner_key = Pubkey::new_unique();
5553 let mut owner_account = SafecoinAccount::default();
5554 let owner2_key = Pubkey::new_unique();
5555 let mut owner2_account = SafecoinAccount::default();
5556 let mut rent_sysvar = rent_sysvar();
5557
5558 assert_eq!(
5560 Err(ProgramError::UninitializedAccount),
5561 do_process_instruction(
5562 close_account(&program_id, &account_key, &account3_key, &owner2_key, &[]).unwrap(),
5563 vec![
5564 &mut account_account,
5565 &mut account3_account,
5566 &mut owner2_account,
5567 ],
5568 )
5569 );
5570
5571 do_process_instruction(
5573 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
5574 vec![&mut mint_account, &mut rent_sysvar],
5575 )
5576 .unwrap();
5577 do_process_instruction(
5578 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
5579 vec![
5580 &mut account_account,
5581 &mut mint_account,
5582 &mut owner_account,
5583 &mut rent_sysvar,
5584 ],
5585 )
5586 .unwrap();
5587 do_process_instruction(
5588 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 42).unwrap(),
5589 vec![
5590 &mut mint_account,
5591 &mut account_account,
5592 &mut owner_account,
5593 &mut rent_sysvar,
5594 ],
5595 )
5596 .unwrap();
5597 let account = Account::unpack_unchecked(&account_account.data).unwrap();
5598 assert_eq!(account.amount, 42);
5599
5600 do_process_instruction(
5602 initialize_account(
5603 &program_id,
5604 &account2_key,
5605 &crate::native_mint::id(),
5606 &owner_key,
5607 )
5608 .unwrap(),
5609 vec![
5610 &mut account2_account,
5611 &mut mint_account,
5612 &mut owner_account,
5613 &mut rent_sysvar,
5614 ],
5615 )
5616 .unwrap();
5617 let account = Account::unpack_unchecked(&account2_account.data).unwrap();
5618 assert!(account.is_native());
5619 assert_eq!(account.amount, 42);
5620
5621 assert_eq!(
5623 Err(TokenError::NonNativeHasBalance.into()),
5624 do_process_instruction(
5625 close_account(&program_id, &account_key, &account3_key, &owner_key, &[]).unwrap(),
5626 vec![
5627 &mut account_account,
5628 &mut account3_account,
5629 &mut owner_account,
5630 ],
5631 )
5632 );
5633 assert_eq!(account_account.lamports, account_minimum_balance());
5634
5635 do_process_instruction(
5637 burn(&program_id, &account_key, &mint_key, &owner_key, &[], 42).unwrap(),
5638 vec![&mut account_account, &mut mint_account, &mut owner_account],
5639 )
5640 .unwrap();
5641
5642 assert_eq!(
5644 Err(TokenError::OwnerMismatch.into()),
5645 do_process_instruction(
5646 close_account(&program_id, &account_key, &account3_key, &owner2_key, &[]).unwrap(),
5647 vec![
5648 &mut account_account,
5649 &mut account3_account,
5650 &mut owner2_account,
5651 ],
5652 )
5653 );
5654
5655 do_process_instruction(
5657 close_account(&program_id, &account_key, &account3_key, &owner_key, &[]).unwrap(),
5658 vec![
5659 &mut account_account,
5660 &mut account3_account,
5661 &mut owner_account,
5662 ],
5663 )
5664 .unwrap();
5665 assert_eq!(account_account.lamports, 0);
5666 assert_eq!(account3_account.lamports, 2 * account_minimum_balance());
5667 let account = Account::unpack_unchecked(&account_account.data).unwrap();
5668 assert_eq!(account.amount, 0);
5669
5670 let account_key = Pubkey::new_unique();
5672 let mut account_account = SafecoinAccount::new(
5673 account_minimum_balance(),
5674 Account::get_packed_len(),
5675 &program_id,
5676 );
5677 let owner2_key = Pubkey::new_unique();
5678 let mut owner2_account = SafecoinAccount::new(
5679 account_minimum_balance(),
5680 Account::get_packed_len(),
5681 &program_id,
5682 );
5683 do_process_instruction(
5684 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
5685 vec![
5686 &mut account_account,
5687 &mut mint_account,
5688 &mut owner_account,
5689 &mut rent_sysvar,
5690 ],
5691 )
5692 .unwrap();
5693 account_account.lamports = 2;
5694
5695 do_process_instruction(
5696 set_authority(
5697 &program_id,
5698 &account_key,
5699 Some(&owner2_key),
5700 AuthorityType::CloseAccount,
5701 &owner_key,
5702 &[],
5703 )
5704 .unwrap(),
5705 vec![&mut account_account, &mut owner_account],
5706 )
5707 .unwrap();
5708
5709 assert_eq!(
5711 Err(TokenError::OwnerMismatch.into()),
5712 do_process_instruction(
5713 close_account(&program_id, &account_key, &account3_key, &owner_key, &[]).unwrap(),
5714 vec![
5715 &mut account_account,
5716 &mut account3_account,
5717 &mut owner_account,
5718 ],
5719 )
5720 );
5721
5722 do_process_instruction(
5724 close_account(&program_id, &account_key, &account3_key, &owner2_key, &[]).unwrap(),
5725 vec![
5726 &mut account_account,
5727 &mut account3_account,
5728 &mut owner2_account,
5729 ],
5730 )
5731 .unwrap();
5732 assert_eq!(account_account.lamports, 0);
5733 assert_eq!(account3_account.lamports, 2 * account_minimum_balance() + 2);
5734 let account = Account::unpack_unchecked(&account_account.data).unwrap();
5735 assert_eq!(account.amount, 0);
5736
5737 do_process_instruction(
5739 close_account(&program_id, &account2_key, &account3_key, &owner_key, &[]).unwrap(),
5740 vec![
5741 &mut account2_account,
5742 &mut account3_account,
5743 &mut owner_account,
5744 ],
5745 )
5746 .unwrap();
5747 assert_eq!(account2_account.data, [0u8; Account::LEN]);
5748 assert_eq!(
5749 account3_account.lamports,
5750 3 * account_minimum_balance() + 2 + 42
5751 );
5752 }
5753
5754 #[test]
5755 fn test_native_token() {
5756 let program_id = crate::id();
5757 let mut mint_account =
5758 SafecoinAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
5759 let account_key = Pubkey::new_unique();
5760 let mut account_account = SafecoinAccount::new(
5761 account_minimum_balance() + 40,
5762 Account::get_packed_len(),
5763 &program_id,
5764 );
5765 let account2_key = Pubkey::new_unique();
5766 let mut account2_account = SafecoinAccount::new(
5767 account_minimum_balance(),
5768 Account::get_packed_len(),
5769 &program_id,
5770 );
5771 let account3_key = Pubkey::new_unique();
5772 let mut account3_account = SafecoinAccount::new(account_minimum_balance(), 0, &program_id);
5773 let owner_key = Pubkey::new_unique();
5774 let mut owner_account = SafecoinAccount::default();
5775 let owner2_key = Pubkey::new_unique();
5776 let mut owner2_account = SafecoinAccount::default();
5777 let owner3_key = Pubkey::new_unique();
5778 let mut rent_sysvar = rent_sysvar();
5779
5780 do_process_instruction(
5782 initialize_account(
5783 &program_id,
5784 &account_key,
5785 &crate::native_mint::id(),
5786 &owner_key,
5787 )
5788 .unwrap(),
5789 vec![
5790 &mut account_account,
5791 &mut mint_account,
5792 &mut owner_account,
5793 &mut rent_sysvar,
5794 ],
5795 )
5796 .unwrap();
5797 let account = Account::unpack_unchecked(&account_account.data).unwrap();
5798 assert!(account.is_native());
5799 assert_eq!(account.amount, 40);
5800
5801 do_process_instruction(
5803 initialize_account(
5804 &program_id,
5805 &account2_key,
5806 &crate::native_mint::id(),
5807 &owner_key,
5808 )
5809 .unwrap(),
5810 vec![
5811 &mut account2_account,
5812 &mut mint_account,
5813 &mut owner_account,
5814 &mut rent_sysvar,
5815 ],
5816 )
5817 .unwrap();
5818 let account = Account::unpack_unchecked(&account2_account.data).unwrap();
5819 assert!(account.is_native());
5820 assert_eq!(account.amount, 0);
5821
5822 assert_eq!(
5824 Err(TokenError::NativeNotSupported.into()),
5825 do_process_instruction(
5826 mint_to(
5827 &program_id,
5828 &crate::native_mint::id(),
5829 &account_key,
5830 &owner_key,
5831 &[],
5832 42
5833 )
5834 .unwrap(),
5835 vec![&mut mint_account, &mut account_account, &mut owner_account],
5836 )
5837 );
5838
5839 let bogus_mint_key = Pubkey::new_unique();
5841 let mut bogus_mint_account =
5842 SafecoinAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
5843 do_process_instruction(
5844 initialize_mint(&program_id, &bogus_mint_key, &owner_key, None, 2).unwrap(),
5845 vec![&mut bogus_mint_account, &mut rent_sysvar],
5846 )
5847 .unwrap();
5848
5849 assert_eq!(
5850 Err(TokenError::NativeNotSupported.into()),
5851 do_process_instruction(
5852 burn(
5853 &program_id,
5854 &account_key,
5855 &bogus_mint_key,
5856 &owner_key,
5857 &[],
5858 42
5859 )
5860 .unwrap(),
5861 vec![
5862 &mut account_account,
5863 &mut bogus_mint_account,
5864 &mut owner_account
5865 ],
5866 )
5867 );
5868
5869 assert_eq!(
5871 Err(TokenError::InsufficientFunds.into()),
5872 do_process_instruction(
5873 transfer(
5874 &program_id,
5875 &account_key,
5876 &account2_key,
5877 &owner_key,
5878 &[],
5879 50,
5880 )
5881 .unwrap(),
5882 vec![
5883 &mut account_account,
5884 &mut account2_account,
5885 &mut owner_account,
5886 ],
5887 )
5888 );
5889
5890 do_process_instruction(
5892 transfer(
5893 &program_id,
5894 &account_key,
5895 &account2_key,
5896 &owner_key,
5897 &[],
5898 40,
5899 )
5900 .unwrap(),
5901 vec![
5902 &mut account_account,
5903 &mut account2_account,
5904 &mut owner_account,
5905 ],
5906 )
5907 .unwrap();
5908 assert_eq!(account_account.lamports, account_minimum_balance());
5909 let account = Account::unpack_unchecked(&account_account.data).unwrap();
5910 assert!(account.is_native());
5911 assert_eq!(account.amount, 0);
5912 assert_eq!(account2_account.lamports, account_minimum_balance() + 40);
5913 let account = Account::unpack_unchecked(&account2_account.data).unwrap();
5914 assert!(account.is_native());
5915 assert_eq!(account.amount, 40);
5916
5917 do_process_instruction(
5919 set_authority(
5920 &program_id,
5921 &account_key,
5922 Some(&owner3_key),
5923 AuthorityType::CloseAccount,
5924 &owner_key,
5925 &[],
5926 )
5927 .unwrap(),
5928 vec![&mut account_account, &mut owner_account],
5929 )
5930 .unwrap();
5931 let account = Account::unpack_unchecked(&account_account.data).unwrap();
5932 assert_eq!(account.close_authority, COption::Some(owner3_key));
5933
5934 do_process_instruction(
5936 set_authority(
5937 &program_id,
5938 &account_key,
5939 Some(&owner2_key),
5940 AuthorityType::AccountOwner,
5941 &owner_key,
5942 &[],
5943 )
5944 .unwrap(),
5945 vec![&mut account_account, &mut owner_account],
5946 )
5947 .unwrap();
5948
5949 let account = Account::unpack_unchecked(&account_account.data).unwrap();
5951 assert_eq!(account.close_authority, COption::None);
5952
5953 do_process_instruction(
5955 close_account(&program_id, &account_key, &account3_key, &owner2_key, &[]).unwrap(),
5956 vec![
5957 &mut account_account,
5958 &mut account3_account,
5959 &mut owner2_account,
5960 ],
5961 )
5962 .unwrap();
5963 assert_eq!(account_account.lamports, 0);
5964 assert_eq!(account3_account.lamports, 2 * account_minimum_balance());
5965 assert_eq!(account_account.data, [0u8; Account::LEN]);
5966 }
5967
5968 #[test]
5969 fn test_overflow() {
5970 let program_id = crate::id();
5971 let account_key = Pubkey::new_unique();
5972 let mut account_account = SafecoinAccount::new(
5973 account_minimum_balance(),
5974 Account::get_packed_len(),
5975 &program_id,
5976 );
5977 let account2_key = Pubkey::new_unique();
5978 let mut account2_account = SafecoinAccount::new(
5979 account_minimum_balance(),
5980 Account::get_packed_len(),
5981 &program_id,
5982 );
5983 let owner_key = Pubkey::new_unique();
5984 let mut owner_account = SafecoinAccount::default();
5985 let owner2_key = Pubkey::new_unique();
5986 let mut owner2_account = SafecoinAccount::default();
5987 let mint_owner_key = Pubkey::new_unique();
5988 let mut mint_owner_account = SafecoinAccount::default();
5989 let mint_key = Pubkey::new_unique();
5990 let mut mint_account =
5991 SafecoinAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
5992 let mut rent_sysvar = rent_sysvar();
5993
5994 do_process_instruction(
5996 initialize_mint(&program_id, &mint_key, &mint_owner_key, None, 2).unwrap(),
5997 vec![&mut mint_account, &mut rent_sysvar],
5998 )
5999 .unwrap();
6000
6001 do_process_instruction(
6003 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
6004 vec![
6005 &mut account_account,
6006 &mut mint_account,
6007 &mut owner_account,
6008 &mut rent_sysvar,
6009 ],
6010 )
6011 .unwrap();
6012
6013 do_process_instruction(
6015 initialize_account(&program_id, &account2_key, &mint_key, &owner2_key).unwrap(),
6016 vec![
6017 &mut account2_account,
6018 &mut mint_account,
6019 &mut owner2_account,
6020 &mut rent_sysvar,
6021 ],
6022 )
6023 .unwrap();
6024
6025 do_process_instruction(
6027 mint_to(
6028 &program_id,
6029 &mint_key,
6030 &account_key,
6031 &mint_owner_key,
6032 &[],
6033 u64::MAX,
6034 )
6035 .unwrap(),
6036 vec![
6037 &mut mint_account,
6038 &mut account_account,
6039 &mut mint_owner_account,
6040 ],
6041 )
6042 .unwrap();
6043 let account = Account::unpack_unchecked(&account_account.data).unwrap();
6044 assert_eq!(account.amount, u64::MAX);
6045
6046 assert_eq!(
6048 Err(TokenError::Overflow.into()),
6049 do_process_instruction(
6050 mint_to(
6051 &program_id,
6052 &mint_key,
6053 &account_key,
6054 &mint_owner_key,
6055 &[],
6056 1,
6057 )
6058 .unwrap(),
6059 vec![
6060 &mut mint_account,
6061 &mut account_account,
6062 &mut mint_owner_account,
6063 ],
6064 )
6065 );
6066 let account = Account::unpack_unchecked(&account_account.data).unwrap();
6067 assert_eq!(account.amount, u64::MAX);
6068
6069 assert_eq!(
6071 Err(TokenError::Overflow.into()),
6072 do_process_instruction(
6073 mint_to(
6074 &program_id,
6075 &mint_key,
6076 &account2_key,
6077 &mint_owner_key,
6078 &[],
6079 1,
6080 )
6081 .unwrap(),
6082 vec![
6083 &mut mint_account,
6084 &mut account2_account,
6085 &mut mint_owner_account,
6086 ],
6087 )
6088 );
6089
6090 do_process_instruction(
6092 burn(&program_id, &account_key, &mint_key, &owner_key, &[], 100).unwrap(),
6093 vec![&mut account_account, &mut mint_account, &mut owner_account],
6094 )
6095 .unwrap();
6096 let account = Account::unpack_unchecked(&account_account.data).unwrap();
6097 assert_eq!(account.amount, u64::MAX - 100);
6098
6099 do_process_instruction(
6100 mint_to(
6101 &program_id,
6102 &mint_key,
6103 &account_key,
6104 &mint_owner_key,
6105 &[],
6106 100,
6107 )
6108 .unwrap(),
6109 vec![
6110 &mut mint_account,
6111 &mut account_account,
6112 &mut mint_owner_account,
6113 ],
6114 )
6115 .unwrap();
6116 let account = Account::unpack_unchecked(&account_account.data).unwrap();
6117 assert_eq!(account.amount, u64::MAX);
6118
6119 let mut account = Account::unpack_unchecked(&account2_account.data).unwrap();
6121 account.amount = 1;
6122 Account::pack(account, &mut account2_account.data).unwrap();
6123
6124 assert_eq!(
6125 Err(TokenError::Overflow.into()),
6126 do_process_instruction(
6127 transfer(
6128 &program_id,
6129 &account2_key,
6130 &account_key,
6131 &owner2_key,
6132 &[],
6133 1,
6134 )
6135 .unwrap(),
6136 vec![
6137 &mut account2_account,
6138 &mut account_account,
6139 &mut owner2_account,
6140 ],
6141 )
6142 );
6143 }
6144
6145 #[test]
6146 fn test_frozen() {
6147 let program_id = crate::id();
6148 let account_key = Pubkey::new_unique();
6149 let mut account_account = SafecoinAccount::new(
6150 account_minimum_balance(),
6151 Account::get_packed_len(),
6152 &program_id,
6153 );
6154 let account2_key = Pubkey::new_unique();
6155 let mut account2_account = SafecoinAccount::new(
6156 account_minimum_balance(),
6157 Account::get_packed_len(),
6158 &program_id,
6159 );
6160 let owner_key = Pubkey::new_unique();
6161 let mut owner_account = SafecoinAccount::default();
6162 let mint_key = Pubkey::new_unique();
6163 let mut mint_account =
6164 SafecoinAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
6165 let mut rent_sysvar = rent_sysvar();
6166
6167 do_process_instruction(
6169 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
6170 vec![&mut mint_account, &mut rent_sysvar],
6171 )
6172 .unwrap();
6173
6174 do_process_instruction(
6176 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
6177 vec![
6178 &mut account_account,
6179 &mut mint_account,
6180 &mut owner_account,
6181 &mut rent_sysvar,
6182 ],
6183 )
6184 .unwrap();
6185
6186 do_process_instruction(
6188 initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
6189 vec![
6190 &mut account2_account,
6191 &mut mint_account,
6192 &mut owner_account,
6193 &mut rent_sysvar,
6194 ],
6195 )
6196 .unwrap();
6197
6198 do_process_instruction(
6200 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
6201 vec![&mut mint_account, &mut account_account, &mut owner_account],
6202 )
6203 .unwrap();
6204
6205 let mut account = Account::unpack_unchecked(&account2_account.data).unwrap();
6207 account.state = AccountState::Frozen;
6208 Account::pack(account, &mut account2_account.data).unwrap();
6209 assert_eq!(
6210 Err(TokenError::AccountFrozen.into()),
6211 do_process_instruction(
6212 transfer(
6213 &program_id,
6214 &account_key,
6215 &account2_key,
6216 &owner_key,
6217 &[],
6218 500,
6219 )
6220 .unwrap(),
6221 vec![
6222 &mut account_account,
6223 &mut account2_account,
6224 &mut owner_account,
6225 ],
6226 )
6227 );
6228
6229 let mut account = Account::unpack_unchecked(&account_account.data).unwrap();
6230 account.state = AccountState::Initialized;
6231 Account::pack(account, &mut account_account.data).unwrap();
6232 let mut account = Account::unpack_unchecked(&account2_account.data).unwrap();
6233 account.state = AccountState::Frozen;
6234 Account::pack(account, &mut account2_account.data).unwrap();
6235 assert_eq!(
6236 Err(TokenError::AccountFrozen.into()),
6237 do_process_instruction(
6238 transfer(
6239 &program_id,
6240 &account_key,
6241 &account2_key,
6242 &owner_key,
6243 &[],
6244 500,
6245 )
6246 .unwrap(),
6247 vec![
6248 &mut account_account,
6249 &mut account2_account,
6250 &mut owner_account,
6251 ],
6252 )
6253 );
6254
6255 let mut account = Account::unpack_unchecked(&account_account.data).unwrap();
6257 account.state = AccountState::Frozen;
6258 Account::pack(account, &mut account_account.data).unwrap();
6259 let delegate_key = Pubkey::new_unique();
6260 let mut delegate_account = SafecoinAccount::default();
6261 assert_eq!(
6262 Err(TokenError::AccountFrozen.into()),
6263 do_process_instruction(
6264 approve(
6265 &program_id,
6266 &account_key,
6267 &delegate_key,
6268 &owner_key,
6269 &[],
6270 100
6271 )
6272 .unwrap(),
6273 vec![
6274 &mut account_account,
6275 &mut delegate_account,
6276 &mut owner_account,
6277 ],
6278 )
6279 );
6280
6281 let mut account = Account::unpack_unchecked(&account_account.data).unwrap();
6283 account.delegate = COption::Some(delegate_key);
6284 account.delegated_amount = 100;
6285 Account::pack(account, &mut account_account.data).unwrap();
6286 assert_eq!(
6287 Err(TokenError::AccountFrozen.into()),
6288 do_process_instruction(
6289 revoke(&program_id, &account_key, &owner_key, &[]).unwrap(),
6290 vec![&mut account_account, &mut owner_account],
6291 )
6292 );
6293
6294 let new_owner_key = Pubkey::new_unique();
6296 assert_eq!(
6297 Err(TokenError::AccountFrozen.into()),
6298 do_process_instruction(
6299 set_authority(
6300 &program_id,
6301 &account_key,
6302 Some(&new_owner_key),
6303 AuthorityType::AccountOwner,
6304 &owner_key,
6305 &[]
6306 )
6307 .unwrap(),
6308 vec![&mut account_account, &mut owner_account,],
6309 )
6310 );
6311
6312 assert_eq!(
6314 Err(TokenError::AccountFrozen.into()),
6315 do_process_instruction(
6316 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 100).unwrap(),
6317 vec![&mut mint_account, &mut account_account, &mut owner_account,],
6318 )
6319 );
6320
6321 assert_eq!(
6323 Err(TokenError::AccountFrozen.into()),
6324 do_process_instruction(
6325 burn(&program_id, &account_key, &mint_key, &owner_key, &[], 100).unwrap(),
6326 vec![&mut account_account, &mut mint_account, &mut owner_account],
6327 )
6328 );
6329 }
6330
6331 #[test]
6332 fn test_freeze_thaw_dups() {
6333 let program_id = crate::id();
6334 let account1_key = Pubkey::new_unique();
6335 let mut account1_account = SafecoinAccount::new(
6336 account_minimum_balance(),
6337 Account::get_packed_len(),
6338 &program_id,
6339 );
6340 let account1_info: AccountInfo = (&account1_key, true, &mut account1_account).into();
6341 let owner_key = Pubkey::new_unique();
6342 let mint_key = Pubkey::new_unique();
6343 let mut mint_account =
6344 SafecoinAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
6345 let mint_info: AccountInfo = (&mint_key, true, &mut mint_account).into();
6346 let rent_key = rent::id();
6347 let mut rent_sysvar = rent_sysvar();
6348 let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
6349
6350 do_process_instruction_dups(
6352 initialize_mint(&program_id, &mint_key, &owner_key, Some(&account1_key), 2).unwrap(),
6353 vec![mint_info.clone(), rent_info.clone()],
6354 )
6355 .unwrap();
6356
6357 do_process_instruction_dups(
6359 initialize_account(&program_id, &account1_key, &mint_key, &account1_key).unwrap(),
6360 vec![
6361 account1_info.clone(),
6362 mint_info.clone(),
6363 account1_info.clone(),
6364 rent_info.clone(),
6365 ],
6366 )
6367 .unwrap();
6368
6369 do_process_instruction_dups(
6371 freeze_account(&program_id, &account1_key, &mint_key, &account1_key, &[]).unwrap(),
6372 vec![
6373 account1_info.clone(),
6374 mint_info.clone(),
6375 account1_info.clone(),
6376 ],
6377 )
6378 .unwrap();
6379
6380 let mut account = Account::unpack_unchecked(&account1_info.data.borrow()).unwrap();
6382 account.state = AccountState::Frozen;
6383 Account::pack(account, &mut account1_info.data.borrow_mut()).unwrap();
6384 do_process_instruction_dups(
6385 thaw_account(&program_id, &account1_key, &mint_key, &account1_key, &[]).unwrap(),
6386 vec![
6387 account1_info.clone(),
6388 mint_info.clone(),
6389 account1_info.clone(),
6390 ],
6391 )
6392 .unwrap();
6393 }
6394
6395 #[test]
6396 fn test_freeze_account() {
6397 let program_id = crate::id();
6398 let account_key = Pubkey::new_unique();
6399 let mut account_account = SafecoinAccount::new(
6400 account_minimum_balance(),
6401 Account::get_packed_len(),
6402 &program_id,
6403 );
6404 let account_owner_key = Pubkey::new_unique();
6405 let mut account_owner_account = SafecoinAccount::default();
6406 let owner_key = Pubkey::new_unique();
6407 let mut owner_account = SafecoinAccount::default();
6408 let owner2_key = Pubkey::new_unique();
6409 let mut owner2_account = SafecoinAccount::default();
6410 let mint_key = Pubkey::new_unique();
6411 let mut mint_account =
6412 SafecoinAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
6413 let mut rent_sysvar = rent_sysvar();
6414
6415 do_process_instruction(
6417 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
6418 vec![&mut mint_account, &mut rent_sysvar],
6419 )
6420 .unwrap();
6421
6422 do_process_instruction(
6424 initialize_account(&program_id, &account_key, &mint_key, &account_owner_key).unwrap(),
6425 vec![
6426 &mut account_account,
6427 &mut mint_account,
6428 &mut account_owner_account,
6429 &mut rent_sysvar,
6430 ],
6431 )
6432 .unwrap();
6433
6434 do_process_instruction(
6436 mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
6437 vec![&mut mint_account, &mut account_account, &mut owner_account],
6438 )
6439 .unwrap();
6440
6441 assert_eq!(
6443 Err(TokenError::MintCannotFreeze.into()),
6444 do_process_instruction(
6445 freeze_account(&program_id, &account_key, &mint_key, &owner_key, &[]).unwrap(),
6446 vec![&mut account_account, &mut mint_account, &mut owner_account],
6447 )
6448 );
6449
6450 let mut mint = Mint::unpack_unchecked(&mint_account.data).unwrap();
6452 mint.freeze_authority = COption::Some(owner_key);
6453 Mint::pack(mint, &mut mint_account.data).unwrap();
6454 assert_eq!(
6455 Err(TokenError::OwnerMismatch.into()),
6456 do_process_instruction(
6457 freeze_account(&program_id, &account_key, &mint_key, &owner2_key, &[]).unwrap(),
6458 vec![&mut account_account, &mut mint_account, &mut owner2_account],
6459 )
6460 );
6461
6462 assert_eq!(
6464 Err(TokenError::InvalidState.into()),
6465 do_process_instruction(
6466 thaw_account(&program_id, &account_key, &mint_key, &owner2_key, &[]).unwrap(),
6467 vec![&mut account_account, &mut mint_account, &mut owner2_account],
6468 )
6469 );
6470
6471 do_process_instruction(
6473 freeze_account(&program_id, &account_key, &mint_key, &owner_key, &[]).unwrap(),
6474 vec![&mut account_account, &mut mint_account, &mut owner_account],
6475 )
6476 .unwrap();
6477 let account = Account::unpack_unchecked(&account_account.data).unwrap();
6478 assert_eq!(account.state, AccountState::Frozen);
6479
6480 assert_eq!(
6482 Err(TokenError::InvalidState.into()),
6483 do_process_instruction(
6484 freeze_account(&program_id, &account_key, &mint_key, &owner_key, &[]).unwrap(),
6485 vec![&mut account_account, &mut mint_account, &mut owner_account],
6486 )
6487 );
6488
6489 assert_eq!(
6491 Err(TokenError::OwnerMismatch.into()),
6492 do_process_instruction(
6493 thaw_account(&program_id, &account_key, &mint_key, &owner2_key, &[]).unwrap(),
6494 vec![&mut account_account, &mut mint_account, &mut owner2_account],
6495 )
6496 );
6497
6498 do_process_instruction(
6500 thaw_account(&program_id, &account_key, &mint_key, &owner_key, &[]).unwrap(),
6501 vec![&mut account_account, &mut mint_account, &mut owner_account],
6502 )
6503 .unwrap();
6504 let account = Account::unpack_unchecked(&account_account.data).unwrap();
6505 assert_eq!(account.state, AccountState::Initialized);
6506 }
6507
6508 #[test]
6509 fn test_initialize_account2_and_3() {
6510 let program_id = crate::id();
6511 let account_key = Pubkey::new_unique();
6512 let mut account_account = SafecoinAccount::new(
6513 account_minimum_balance(),
6514 Account::get_packed_len(),
6515 &program_id,
6516 );
6517 let mut account2_account = SafecoinAccount::new(
6518 account_minimum_balance(),
6519 Account::get_packed_len(),
6520 &program_id,
6521 );
6522 let mut account3_account = SafecoinAccount::new(
6523 account_minimum_balance(),
6524 Account::get_packed_len(),
6525 &program_id,
6526 );
6527 let owner_key = Pubkey::new_unique();
6528 let mut owner_account = SafecoinAccount::default();
6529 let mint_key = Pubkey::new_unique();
6530 let mut mint_account =
6531 SafecoinAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
6532 let mut rent_sysvar = rent_sysvar();
6533
6534 do_process_instruction(
6536 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
6537 vec![&mut mint_account, &mut rent_sysvar],
6538 )
6539 .unwrap();
6540
6541 do_process_instruction(
6542 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
6543 vec![
6544 &mut account_account,
6545 &mut mint_account,
6546 &mut owner_account,
6547 &mut rent_sysvar,
6548 ],
6549 )
6550 .unwrap();
6551
6552 do_process_instruction(
6553 initialize_account2(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
6554 vec![&mut account2_account, &mut mint_account, &mut rent_sysvar],
6555 )
6556 .unwrap();
6557
6558 assert_eq!(account_account, account2_account);
6559
6560 do_process_instruction(
6561 initialize_account3(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
6562 vec![&mut account3_account, &mut mint_account],
6563 )
6564 .unwrap();
6565
6566 assert_eq!(account_account, account3_account);
6567 }
6568
6569 #[test]
6570 fn test_sync_native() {
6571 let program_id = crate::id();
6572 let mint_key = Pubkey::new_unique();
6573 let mut mint_account =
6574 SafecoinAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
6575 let native_account_key = Pubkey::new_unique();
6576 let lamports = 40;
6577 let mut native_account = SafecoinAccount::new(
6578 account_minimum_balance() + lamports,
6579 Account::get_packed_len(),
6580 &program_id,
6581 );
6582 let non_native_account_key = Pubkey::new_unique();
6583 let mut non_native_account = SafecoinAccount::new(
6584 account_minimum_balance() + 50,
6585 Account::get_packed_len(),
6586 &program_id,
6587 );
6588
6589 let owner_key = Pubkey::new_unique();
6590 let mut owner_account = SafecoinAccount::default();
6591 let mut rent_sysvar = rent_sysvar();
6592
6593 do_process_instruction(
6595 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
6596 vec![&mut mint_account, &mut rent_sysvar],
6597 )
6598 .unwrap();
6599
6600 do_process_instruction(
6602 initialize_account(&program_id, &non_native_account_key, &mint_key, &owner_key)
6603 .unwrap(),
6604 vec![
6605 &mut non_native_account,
6606 &mut mint_account,
6607 &mut owner_account,
6608 &mut rent_sysvar,
6609 ],
6610 )
6611 .unwrap();
6612
6613 let account = Account::unpack_unchecked(&non_native_account.data).unwrap();
6614 assert!(!account.is_native());
6615 assert_eq!(account.amount, 0);
6616
6617 assert_eq!(
6619 Err(TokenError::NonNativeNotSupported.into()),
6620 do_process_instruction(
6621 sync_native(&program_id, &non_native_account_key,).unwrap(),
6622 vec![&mut non_native_account],
6623 )
6624 );
6625
6626 assert_eq!(
6628 Err(ProgramError::UninitializedAccount),
6629 do_process_instruction(
6630 sync_native(&program_id, &native_account_key,).unwrap(),
6631 vec![&mut native_account],
6632 )
6633 );
6634
6635 do_process_instruction(
6637 initialize_account(
6638 &program_id,
6639 &native_account_key,
6640 &crate::native_mint::id(),
6641 &owner_key,
6642 )
6643 .unwrap(),
6644 vec![
6645 &mut native_account,
6646 &mut mint_account,
6647 &mut owner_account,
6648 &mut rent_sysvar,
6649 ],
6650 )
6651 .unwrap();
6652
6653 let not_program_id = Pubkey::new_unique();
6655 native_account.owner = not_program_id;
6656 assert_eq!(
6657 Err(ProgramError::IncorrectProgramId),
6658 do_process_instruction(
6659 sync_native(&program_id, &native_account_key,).unwrap(),
6660 vec![&mut native_account],
6661 )
6662 );
6663 native_account.owner = program_id;
6664
6665 let account = Account::unpack_unchecked(&native_account.data).unwrap();
6666 assert!(account.is_native());
6667 assert_eq!(account.amount, lamports);
6668
6669 do_process_instruction(
6671 sync_native(&program_id, &native_account_key).unwrap(),
6672 vec![&mut native_account],
6673 )
6674 .unwrap();
6675 let account = Account::unpack_unchecked(&native_account.data).unwrap();
6676 assert_eq!(account.amount, lamports);
6677
6678 let new_lamports = lamports + 50;
6680 native_account.lamports = account_minimum_balance() + new_lamports;
6681
6682 do_process_instruction(
6684 sync_native(&program_id, &native_account_key).unwrap(),
6685 vec![&mut native_account],
6686 )
6687 .unwrap();
6688 let account = Account::unpack_unchecked(&native_account.data).unwrap();
6689 assert_eq!(account.amount, new_lamports);
6690
6691 native_account.lamports -= 1;
6693
6694 assert_eq!(
6696 Err(TokenError::InvalidState.into()),
6697 do_process_instruction(
6698 sync_native(&program_id, &native_account_key,).unwrap(),
6699 vec![&mut native_account],
6700 )
6701 );
6702 }
6703
6704 #[test]
6705 #[serial]
6706 fn test_get_account_data_size() {
6707 let program_id = crate::id();
6709 let owner_key = Pubkey::new_unique();
6710 let mut rent_sysvar = rent_sysvar();
6711 let mut mint_account =
6712 SafecoinAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
6713 let mint_key = Pubkey::new_unique();
6714 assert_eq!(
6716 Err(TokenError::InvalidMint.into()),
6717 do_process_instruction(
6718 get_account_data_size(&program_id, &mint_key).unwrap(),
6719 vec![&mut mint_account],
6720 )
6721 );
6722
6723 do_process_instruction(
6724 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
6725 vec![&mut mint_account, &mut rent_sysvar],
6726 )
6727 .unwrap();
6728
6729 set_expected_data(Account::LEN.to_le_bytes().to_vec());
6730 do_process_instruction(
6731 get_account_data_size(&program_id, &mint_key).unwrap(),
6732 vec![&mut mint_account],
6733 )
6734 .unwrap();
6735 }
6736
6737 #[test]
6738 fn test_initialize_immutable_owner() {
6739 let program_id = crate::id();
6740 let account_key = Pubkey::new_unique();
6741 let mut account_account = SafecoinAccount::new(
6742 account_minimum_balance(),
6743 Account::get_packed_len(),
6744 &program_id,
6745 );
6746 let owner_key = Pubkey::new_unique();
6747 let mut owner_account = SafecoinAccount::default();
6748 let mint_key = Pubkey::new_unique();
6749 let mut mint_account =
6750 SafecoinAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
6751 let mut rent_sysvar = rent_sysvar();
6752
6753 do_process_instruction(
6755 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
6756 vec![&mut mint_account, &mut rent_sysvar],
6757 )
6758 .unwrap();
6759
6760 do_process_instruction(
6762 initialize_immutable_owner(&program_id, &account_key).unwrap(),
6763 vec![&mut account_account],
6764 )
6765 .unwrap();
6766
6767 do_process_instruction(
6769 initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
6770 vec![
6771 &mut account_account,
6772 &mut mint_account,
6773 &mut owner_account,
6774 &mut rent_sysvar,
6775 ],
6776 )
6777 .unwrap();
6778
6779 assert_eq!(
6781 Err(TokenError::AlreadyInUse.into()),
6782 do_process_instruction(
6783 initialize_immutable_owner(&program_id, &account_key).unwrap(),
6784 vec![&mut account_account],
6785 )
6786 );
6787 }
6788
6789 #[test]
6790 #[serial]
6791 fn test_amount_to_ui_amount() {
6792 let program_id = crate::id();
6793 let owner_key = Pubkey::new_unique();
6794 let mint_key = Pubkey::new_unique();
6795 let mut mint_account =
6796 SafecoinAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
6797 let mut rent_sysvar = rent_sysvar();
6798
6799 assert_eq!(
6801 Err(TokenError::InvalidMint.into()),
6802 do_process_instruction(
6803 amount_to_ui_amount(&program_id, &mint_key, 110).unwrap(),
6804 vec![&mut mint_account],
6805 )
6806 );
6807
6808 do_process_instruction(
6810 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
6811 vec![&mut mint_account, &mut rent_sysvar],
6812 )
6813 .unwrap();
6814
6815 set_expected_data("0.23".as_bytes().to_vec());
6816 do_process_instruction(
6817 amount_to_ui_amount(&program_id, &mint_key, 23).unwrap(),
6818 vec![&mut mint_account],
6819 )
6820 .unwrap();
6821
6822 set_expected_data("1.1".as_bytes().to_vec());
6823 do_process_instruction(
6824 amount_to_ui_amount(&program_id, &mint_key, 110).unwrap(),
6825 vec![&mut mint_account],
6826 )
6827 .unwrap();
6828
6829 set_expected_data("42".as_bytes().to_vec());
6830 do_process_instruction(
6831 amount_to_ui_amount(&program_id, &mint_key, 4200).unwrap(),
6832 vec![&mut mint_account],
6833 )
6834 .unwrap();
6835
6836 set_expected_data("0".as_bytes().to_vec());
6837 do_process_instruction(
6838 amount_to_ui_amount(&program_id, &mint_key, 0).unwrap(),
6839 vec![&mut mint_account],
6840 )
6841 .unwrap();
6842 }
6843
6844 #[test]
6845 #[serial]
6846 fn test_ui_amount_to_amount() {
6847 let program_id = crate::id();
6848 let owner_key = Pubkey::new_unique();
6849 let mint_key = Pubkey::new_unique();
6850 let mut mint_account =
6851 SafecoinAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
6852 let mut rent_sysvar = rent_sysvar();
6853
6854 assert_eq!(
6856 Err(TokenError::InvalidMint.into()),
6857 do_process_instruction(
6858 ui_amount_to_amount(&program_id, &mint_key, "1.1").unwrap(),
6859 vec![&mut mint_account],
6860 )
6861 );
6862
6863 do_process_instruction(
6865 initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
6866 vec![&mut mint_account, &mut rent_sysvar],
6867 )
6868 .unwrap();
6869
6870 set_expected_data(23u64.to_le_bytes().to_vec());
6871 do_process_instruction(
6872 ui_amount_to_amount(&program_id, &mint_key, "0.23").unwrap(),
6873 vec![&mut mint_account],
6874 )
6875 .unwrap();
6876
6877 set_expected_data(20u64.to_le_bytes().to_vec());
6878 do_process_instruction(
6879 ui_amount_to_amount(&program_id, &mint_key, "0.20").unwrap(),
6880 vec![&mut mint_account],
6881 )
6882 .unwrap();
6883
6884 set_expected_data(20u64.to_le_bytes().to_vec());
6885 do_process_instruction(
6886 ui_amount_to_amount(&program_id, &mint_key, "0.2000").unwrap(),
6887 vec![&mut mint_account],
6888 )
6889 .unwrap();
6890
6891 set_expected_data(20u64.to_le_bytes().to_vec());
6892 do_process_instruction(
6893 ui_amount_to_amount(&program_id, &mint_key, ".20").unwrap(),
6894 vec![&mut mint_account],
6895 )
6896 .unwrap();
6897
6898 set_expected_data(110u64.to_le_bytes().to_vec());
6899 do_process_instruction(
6900 ui_amount_to_amount(&program_id, &mint_key, "1.1").unwrap(),
6901 vec![&mut mint_account],
6902 )
6903 .unwrap();
6904
6905 set_expected_data(110u64.to_le_bytes().to_vec());
6906 do_process_instruction(
6907 ui_amount_to_amount(&program_id, &mint_key, "1.10").unwrap(),
6908 vec![&mut mint_account],
6909 )
6910 .unwrap();
6911
6912 set_expected_data(4200u64.to_le_bytes().to_vec());
6913 do_process_instruction(
6914 ui_amount_to_amount(&program_id, &mint_key, "42").unwrap(),
6915 vec![&mut mint_account],
6916 )
6917 .unwrap();
6918
6919 set_expected_data(4200u64.to_le_bytes().to_vec());
6920 do_process_instruction(
6921 ui_amount_to_amount(&program_id, &mint_key, "42.").unwrap(),
6922 vec![&mut mint_account],
6923 )
6924 .unwrap();
6925
6926 set_expected_data(0u64.to_le_bytes().to_vec());
6927 do_process_instruction(
6928 ui_amount_to_amount(&program_id, &mint_key, "0").unwrap(),
6929 vec![&mut mint_account],
6930 )
6931 .unwrap();
6932
6933 assert_eq!(
6935 Err(ProgramError::InvalidArgument),
6936 do_process_instruction(
6937 ui_amount_to_amount(&program_id, &mint_key, "").unwrap(),
6938 vec![&mut mint_account],
6939 )
6940 );
6941 assert_eq!(
6942 Err(ProgramError::InvalidArgument),
6943 do_process_instruction(
6944 ui_amount_to_amount(&program_id, &mint_key, ".").unwrap(),
6945 vec![&mut mint_account],
6946 )
6947 );
6948 assert_eq!(
6949 Err(ProgramError::InvalidArgument),
6950 do_process_instruction(
6951 ui_amount_to_amount(&program_id, &mint_key, "0.111").unwrap(),
6952 vec![&mut mint_account],
6953 )
6954 );
6955 assert_eq!(
6956 Err(ProgramError::InvalidArgument),
6957 do_process_instruction(
6958 ui_amount_to_amount(&program_id, &mint_key, "0.t").unwrap(),
6959 vec![&mut mint_account],
6960 )
6961 );
6962 }
6963}