1use {
2 crate::system_instruction::{
3 advance_nonce_account, authorize_nonce_account, initialize_nonce_account,
4 withdraw_nonce_account,
5 },
6 log::*,
7 solana_instruction_error::InstructionError,
8 solana_nonce as nonce,
9 solana_packet::PACKET_DATA_WINCODE_CONFIG,
10 solana_program_runtime::{
11 declare_process_instruction, invoke_context::InvokeContext,
12 sysvar_cache::get_sysvar_with_account_check,
13 },
14 solana_pubkey::Pubkey,
15 solana_sdk_ids::system_program,
16 solana_svm_log_collector::ic_msg,
17 solana_system_interface::{
18 MAX_PERMITTED_DATA_LENGTH, error::SystemError, instruction::SystemInstruction,
19 },
20 solana_transaction_context::{
21 IndexOfAccount, instruction::InstructionContext,
22 instruction_accounts::BorrowedInstructionAccount,
23 },
24 std::collections::HashSet,
25};
26
27#[derive(PartialEq, Eq, Default, Debug)]
30struct Address {
31 address: Pubkey,
32 base: Option<Pubkey>,
33}
34
35impl Address {
36 fn is_signer(&self, signers: &HashSet<Pubkey>) -> bool {
37 if let Some(base) = self.base {
38 signers.contains(&base)
39 } else {
40 signers.contains(&self.address)
41 }
42 }
43 fn create(
44 address: &Pubkey,
45 with_seed: Option<(&Pubkey, &str, &Pubkey)>,
46 invoke_context: &InvokeContext,
47 ) -> Result<Self, InstructionError> {
48 let base = if let Some((base, seed, owner)) = with_seed {
49 let address_with_seed =
52 Pubkey::create_with_seed(base, seed, owner).map_err(|e| e as u64)?;
53 if *address != address_with_seed {
55 ic_msg!(
56 invoke_context,
57 "Create: address {} does not match derived address {}",
58 address,
59 address_with_seed
60 );
61 return Err(SystemError::AddressWithSeedMismatch.into());
62 }
63 Some(*base)
64 } else {
65 None
66 };
67
68 Ok(Self {
69 address: *address,
70 base,
71 })
72 }
73}
74
75fn allocate(
76 account: &mut BorrowedInstructionAccount,
77 address: &Address,
78 space: u64,
79 signers: &HashSet<Pubkey>,
80 invoke_context: &InvokeContext,
81) -> Result<(), InstructionError> {
82 if !address.is_signer(signers) {
83 ic_msg!(
84 invoke_context,
85 "Allocate: 'to' account {:?} must sign",
86 address
87 );
88 return Err(InstructionError::MissingRequiredSignature);
89 }
90
91 if !account.get_data().is_empty() || !system_program::check_id(account.get_owner()) {
94 ic_msg!(
95 invoke_context,
96 "Allocate: account {:?} already in use",
97 address
98 );
99 return Err(SystemError::AccountAlreadyInUse.into());
100 }
101
102 if space > MAX_PERMITTED_DATA_LENGTH {
103 ic_msg!(
104 invoke_context,
105 "Allocate: requested {}, max allowed {}",
106 space,
107 MAX_PERMITTED_DATA_LENGTH
108 );
109 return Err(SystemError::InvalidAccountDataLength.into());
110 }
111
112 account.set_data_length(space as usize)?;
113
114 Ok(())
115}
116
117fn assign(
118 account: &mut BorrowedInstructionAccount,
119 address: &Address,
120 owner: &Pubkey,
121 signers: &HashSet<Pubkey>,
122 invoke_context: &InvokeContext,
123) -> Result<(), InstructionError> {
124 if account.get_owner() == owner {
126 return Ok(());
127 }
128
129 if !address.is_signer(signers) {
130 ic_msg!(invoke_context, "Assign: account {:?} must sign", address);
131 return Err(InstructionError::MissingRequiredSignature);
132 }
133
134 account.set_owner(&owner.to_bytes())
135}
136
137fn allocate_and_assign(
138 to: &mut BorrowedInstructionAccount,
139 to_address: &Address,
140 space: u64,
141 owner: &Pubkey,
142 signers: &HashSet<Pubkey>,
143 invoke_context: &InvokeContext,
144) -> Result<(), InstructionError> {
145 allocate(to, to_address, space, signers, invoke_context)?;
146 assign(to, to_address, owner, signers, invoke_context)
147}
148
149#[allow(clippy::too_many_arguments)]
150fn create_account(
151 from_account_index: IndexOfAccount,
152 to_account_index: IndexOfAccount,
153 to_address: &Address,
154 lamports: u64,
155 space: u64,
156 owner: &Pubkey,
157 signers: &HashSet<Pubkey>,
158 invoke_context: &InvokeContext,
159 instruction_context: &InstructionContext,
160) -> Result<(), InstructionError> {
161 {
163 let mut to = instruction_context.try_borrow_instruction_account(to_account_index)?;
164 if to.get_lamports() > 0 {
165 ic_msg!(
166 invoke_context,
167 "Create Account: account {:?} already in use",
168 to_address
169 );
170 return Err(SystemError::AccountAlreadyInUse.into());
171 }
172
173 allocate_and_assign(&mut to, to_address, space, owner, signers, invoke_context)?;
174 }
175 transfer(
176 from_account_index,
177 to_account_index,
178 lamports,
179 invoke_context,
180 instruction_context,
181 )
182}
183
184#[allow(clippy::too_many_arguments)]
188fn create_account_allow_prefund(
189 to_account_index: IndexOfAccount,
190 to_address: &Address,
191 from_and_lamports: Option<(IndexOfAccount, u64)>,
192 space: u64,
193 owner: &Pubkey,
194 signers: &HashSet<Pubkey>,
195 invoke_context: &InvokeContext,
196 instruction_context: &InstructionContext,
197) -> Result<(), InstructionError> {
198 {
199 let mut to = instruction_context.try_borrow_instruction_account(to_account_index)?;
200 allocate_and_assign(&mut to, to_address, space, owner, signers, invoke_context)?;
201 }
202 if let Some((from_account_index, lamports)) = from_and_lamports
203 && lamports > 0
204 {
205 transfer(
206 from_account_index,
207 to_account_index,
208 lamports,
209 invoke_context,
210 instruction_context,
211 )?;
212 }
213 Ok(())
214}
215
216fn transfer_verified(
217 from_account_index: IndexOfAccount,
218 to_account_index: IndexOfAccount,
219 lamports: u64,
220 invoke_context: &InvokeContext,
221 instruction_context: &InstructionContext,
222) -> Result<(), InstructionError> {
223 let mut from = instruction_context.try_borrow_instruction_account(from_account_index)?;
224 if !from.get_data().is_empty() {
225 ic_msg!(invoke_context, "Transfer: `from` must not carry data");
226 return Err(InstructionError::InvalidArgument);
227 }
228 if lamports > from.get_lamports() {
229 ic_msg!(
230 invoke_context,
231 "Transfer: insufficient lamports {}, need {}",
232 from.get_lamports(),
233 lamports
234 );
235 return Err(SystemError::ResultWithNegativeLamports.into());
236 }
237
238 from.checked_sub_lamports(lamports)?;
239 drop(from);
240 let mut to = instruction_context.try_borrow_instruction_account(to_account_index)?;
241 to.checked_add_lamports(lamports)?;
242 Ok(())
243}
244
245fn transfer(
246 from_account_index: IndexOfAccount,
247 to_account_index: IndexOfAccount,
248 lamports: u64,
249 invoke_context: &InvokeContext,
250 instruction_context: &InstructionContext,
251) -> Result<(), InstructionError> {
252 if !instruction_context.is_instruction_account_signer(from_account_index)? {
253 ic_msg!(
254 invoke_context,
255 "Transfer: `from` account {} must sign",
256 instruction_context.get_key_of_instruction_account(from_account_index)?,
257 );
258 return Err(InstructionError::MissingRequiredSignature);
259 }
260
261 transfer_verified(
262 from_account_index,
263 to_account_index,
264 lamports,
265 invoke_context,
266 instruction_context,
267 )
268}
269
270fn transfer_with_seed(
271 from_account_index: IndexOfAccount,
272 from_base_account_index: IndexOfAccount,
273 from_seed: &str,
274 from_owner: &Pubkey,
275 to_account_index: IndexOfAccount,
276 lamports: u64,
277 invoke_context: &InvokeContext,
278 instruction_context: &InstructionContext,
279) -> Result<(), InstructionError> {
280 if !instruction_context.is_instruction_account_signer(from_base_account_index)? {
281 ic_msg!(
282 invoke_context,
283 "Transfer: 'from' account {:?} must sign",
284 instruction_context.get_key_of_instruction_account(from_base_account_index,)?,
285 );
286 return Err(InstructionError::MissingRequiredSignature);
287 }
288 let address_from_seed = Pubkey::create_with_seed(
291 instruction_context.get_key_of_instruction_account(from_base_account_index)?,
292 from_seed,
293 from_owner,
294 )
295 .map_err(|e| e as u64)?;
296
297 let from_key = instruction_context.get_key_of_instruction_account(from_account_index)?;
298 if *from_key != address_from_seed {
299 ic_msg!(
300 invoke_context,
301 "Transfer: 'from' address {} does not match derived address {}",
302 from_key,
303 address_from_seed
304 );
305 return Err(SystemError::AddressWithSeedMismatch.into());
306 }
307
308 transfer_verified(
309 from_account_index,
310 to_account_index,
311 lamports,
312 invoke_context,
313 instruction_context,
314 )
315}
316
317pub const DEFAULT_COMPUTE_UNITS: u64 = 150;
318
319declare_process_instruction!(Entrypoint, DEFAULT_COMPUTE_UNITS, |invoke_context| {
320 let transaction_context = &invoke_context.transaction_context;
321 let instruction_context = transaction_context.get_current_instruction_context()?;
322 let instruction_data = instruction_context.get_instruction_data();
323 let instruction: SystemInstruction =
324 wincode::config::deserialize(instruction_data, PACKET_DATA_WINCODE_CONFIG)
325 .map_err(|_| InstructionError::InvalidInstructionData)?;
326
327 trace!("process_instruction: {instruction:?}");
328
329 let signers = instruction_context.get_signers()?;
330 match instruction {
331 SystemInstruction::CreateAccount {
332 lamports,
333 space,
334 owner,
335 } => {
336 instruction_context.check_number_of_instruction_accounts(2)?;
337 let to_address = Address::create(
338 instruction_context.get_key_of_instruction_account(1)?,
339 None,
340 invoke_context,
341 )?;
342 create_account(
343 0,
344 1,
345 &to_address,
346 lamports,
347 space,
348 &owner,
349 &signers,
350 invoke_context,
351 &instruction_context,
352 )
353 }
354
355 SystemInstruction::CreateAccountWithSeed {
356 base,
357 seed,
358 lamports,
359 space,
360 owner,
361 } => {
362 instruction_context.check_number_of_instruction_accounts(2)?;
363 let to_address = Address::create(
364 instruction_context.get_key_of_instruction_account(1)?,
365 Some((&base, &seed, &owner)),
366 invoke_context,
367 )?;
368 create_account(
369 0,
370 1,
371 &to_address,
372 lamports,
373 space,
374 &owner,
375 &signers,
376 invoke_context,
377 &instruction_context,
378 )
379 }
380 SystemInstruction::Assign { owner } => {
381 instruction_context.check_number_of_instruction_accounts(1)?;
382 let mut account = instruction_context.try_borrow_instruction_account(0)?;
383 let address = Address::create(
384 instruction_context.get_key_of_instruction_account(0)?,
385 None,
386 invoke_context,
387 )?;
388 assign(&mut account, &address, &owner, &signers, invoke_context)
389 }
390 SystemInstruction::Transfer { lamports } => {
391 instruction_context.check_number_of_instruction_accounts(2)?;
392 transfer(0, 1, lamports, invoke_context, &instruction_context)
393 }
394 SystemInstruction::TransferWithSeed {
395 lamports,
396 from_seed,
397 from_owner,
398 } => {
399 instruction_context.check_number_of_instruction_accounts(3)?;
400 transfer_with_seed(
401 0,
402 1,
403 &from_seed,
404 &from_owner,
405 2,
406 lamports,
407 invoke_context,
408 &instruction_context,
409 )
410 }
411 SystemInstruction::AdvanceNonceAccount => {
412 instruction_context.check_number_of_instruction_accounts(1)?;
413 let mut me = instruction_context.try_borrow_instruction_account(0)?;
414 #[allow(deprecated)]
415 let recent_blockhashes = get_sysvar_with_account_check::recent_blockhashes(
416 invoke_context,
417 &instruction_context,
418 1,
419 )?;
420 if recent_blockhashes.is_empty() {
421 ic_msg!(
422 invoke_context,
423 "Advance nonce account: recent blockhash list is empty",
424 );
425 return Err(SystemError::NonceNoRecentBlockhashes.into());
426 }
427 advance_nonce_account(&mut me, &signers, invoke_context)
428 }
429 SystemInstruction::WithdrawNonceAccount(lamports) => {
430 instruction_context.check_number_of_instruction_accounts(2)?;
431 #[allow(deprecated)]
432 let _recent_blockhashes = get_sysvar_with_account_check::recent_blockhashes(
433 invoke_context,
434 &instruction_context,
435 2,
436 )?;
437 let rent =
438 get_sysvar_with_account_check::rent(invoke_context, &instruction_context, 3)?;
439 withdraw_nonce_account(
440 0,
441 lamports,
442 1,
443 &rent,
444 &signers,
445 invoke_context,
446 &instruction_context,
447 )
448 }
449 SystemInstruction::InitializeNonceAccount(authorized) => {
450 instruction_context.check_number_of_instruction_accounts(1)?;
451 let mut me = instruction_context.try_borrow_instruction_account(0)?;
452 #[allow(deprecated)]
453 let recent_blockhashes = get_sysvar_with_account_check::recent_blockhashes(
454 invoke_context,
455 &instruction_context,
456 1,
457 )?;
458 if recent_blockhashes.is_empty() {
459 ic_msg!(
460 invoke_context,
461 "Initialize nonce account: recent blockhash list is empty",
462 );
463 return Err(SystemError::NonceNoRecentBlockhashes.into());
464 }
465 let rent =
466 get_sysvar_with_account_check::rent(invoke_context, &instruction_context, 2)?;
467 initialize_nonce_account(&mut me, &authorized, &rent, invoke_context)
468 }
469 SystemInstruction::AuthorizeNonceAccount(nonce_authority) => {
470 instruction_context.check_number_of_instruction_accounts(1)?;
471 let mut me = instruction_context.try_borrow_instruction_account(0)?;
472 authorize_nonce_account(&mut me, &nonce_authority, &signers, invoke_context)
473 }
474 SystemInstruction::UpgradeNonceAccount => {
475 instruction_context.check_number_of_instruction_accounts(1)?;
476 let mut nonce_account = instruction_context.try_borrow_instruction_account(0)?;
477 if !system_program::check_id(nonce_account.get_owner()) {
478 return Err(InstructionError::InvalidAccountOwner);
479 }
480 if !nonce_account.is_writable() {
481 return Err(InstructionError::InvalidArgument);
482 }
483 let nonce_versions: nonce::versions::Versions = nonce_account.get_state()?;
484 match nonce_versions.upgrade() {
485 None => Err(InstructionError::InvalidArgument),
486 Some(nonce_versions) => nonce_account.set_state(&nonce_versions),
487 }
488 }
489 SystemInstruction::Allocate { space } => {
490 instruction_context.check_number_of_instruction_accounts(1)?;
491 let mut account = instruction_context.try_borrow_instruction_account(0)?;
492 let address = Address::create(
493 instruction_context.get_key_of_instruction_account(0)?,
494 None,
495 invoke_context,
496 )?;
497 allocate(&mut account, &address, space, &signers, invoke_context)
498 }
499 SystemInstruction::AllocateWithSeed {
500 base,
501 seed,
502 space,
503 owner,
504 } => {
505 instruction_context.check_number_of_instruction_accounts(1)?;
506 let mut account = instruction_context.try_borrow_instruction_account(0)?;
507 let address = Address::create(
508 instruction_context.get_key_of_instruction_account(0)?,
509 Some((&base, &seed, &owner)),
510 invoke_context,
511 )?;
512 allocate_and_assign(
513 &mut account,
514 &address,
515 space,
516 &owner,
517 &signers,
518 invoke_context,
519 )
520 }
521 SystemInstruction::AssignWithSeed { base, seed, owner } => {
522 instruction_context.check_number_of_instruction_accounts(1)?;
523 let mut account = instruction_context.try_borrow_instruction_account(0)?;
524 let address = Address::create(
525 instruction_context.get_key_of_instruction_account(0)?,
526 Some((&base, &seed, &owner)),
527 invoke_context,
528 )?;
529 assign(&mut account, &address, &owner, &signers, invoke_context)
530 }
531 SystemInstruction::CreateAccountAllowPrefund {
532 lamports,
533 space,
534 owner,
535 } => {
536 if !invoke_context
537 .get_feature_set()
538 .create_account_allow_prefund
539 {
540 return Err(InstructionError::InvalidInstructionData);
541 }
542 let from_and_lamports = if lamports > 0 {
543 instruction_context.check_number_of_instruction_accounts(2)?;
544 Some((1, lamports))
545 } else {
546 instruction_context.check_number_of_instruction_accounts(1)?;
547 None
548 };
549 let to_address = Address::create(
550 instruction_context.get_key_of_instruction_account(0)?,
551 None,
552 invoke_context,
553 )?;
554 create_account_allow_prefund(
555 0,
556 &to_address,
557 from_and_lamports,
558 space,
559 &owner,
560 &signers,
561 invoke_context,
562 &instruction_context,
563 )
564 }
565 }
566});
567
568#[cfg(test)]
569mod tests {
570 use {
571 super::*,
572 solana_nonce_account::{SystemAccountKind, get_system_account_kind},
573 solana_program_runtime::{
574 invoke_context::mock_process_instruction,
575 solana_sbpf::program::BuiltinFunctionDefinition, with_mock_invoke_context,
576 },
577 std::collections::BinaryHeap,
578 wincode::serialize,
579 };
580 #[allow(deprecated)]
581 use {
582 solana_account::{
583 Account, AccountSharedData, ReadableAccount, state_traits::StateMutWincode as _,
584 },
585 solana_fee_calculator::FeeCalculator,
586 solana_hash::Hash,
587 solana_instruction::{AccountMeta, Instruction},
588 solana_instruction_error::InstructionError,
589 solana_nonce::{
590 self as nonce,
591 state::{Data as NonceData, DurableNonce, State as NonceState},
592 versions::Versions as NonceVersions,
593 },
594 solana_nonce_account as nonce_account,
595 solana_sha256_hasher::hash,
596 solana_system_interface::{instruction as system_instruction, program as system_program},
597 solana_sysvar::{
598 self as sysvar,
599 recent_blockhashes::{IntoIterSorted, IterItem, MAX_ENTRIES, RecentBlockhashes},
600 rent::Rent,
601 },
602 solana_sysvar_id::SysvarId,
603 };
604
605 fn create_sysvar_account<T>(value: &T) -> AccountSharedData
606 where
607 T: wincode::SchemaWrite<solana_account::WincodeConfig, Src = T>
608 + for<'de> wincode::SchemaRead<'de, solana_account::WincodeConfig, Dst = T>
609 + SysvarId,
610 {
611 let serialized_len = wincode::config::serialized_size(value, solana_account::WINCODE_CONFIG)
612 .unwrap() as usize;
613 let canonical_data_len = match T::id() {
614 sysvar::recent_blockhashes::ID => sysvar::recent_blockhashes::SIZE,
615 sysvar::rent::ID => solana_rent::SIZE,
616 id => panic!("unsupported sysvar: {id}"),
617 };
618 let required_data_len = canonical_data_len.max(serialized_len);
619 AccountSharedData::new_data_with_space(
620 1,
621 value,
622 required_data_len,
623 &solana_sdk_ids::sysvar::id(),
624 )
625 .unwrap()
626 }
627
628 impl From<Pubkey> for Address {
629 fn from(address: Pubkey) -> Self {
630 Self {
631 address,
632 base: None,
633 }
634 }
635 }
636
637 fn process_instruction(
638 instruction_data: &[u8],
639 transaction_accounts: Vec<(Pubkey, AccountSharedData)>,
640 instruction_accounts: Vec<AccountMeta>,
641 expected_result: Result<(), InstructionError>,
642 ) -> Vec<AccountSharedData> {
643 mock_process_instruction(
644 &system_program::id(),
645 instruction_data,
646 transaction_accounts,
647 instruction_accounts,
648 expected_result,
649 Entrypoint::register,
650 |_invoke_context| {},
651 |_invoke_context| {},
652 )
653 }
654
655 fn create_default_account() -> AccountSharedData {
656 AccountSharedData::new(0, 0, &Pubkey::new_unique())
657 }
658 #[allow(deprecated)]
659 fn create_recent_blockhashes_account_for_test<'a, I>(
660 recent_blockhash_iter: I,
661 ) -> AccountSharedData
662 where
663 I: IntoIterator<Item = IterItem<'a>>,
664 {
665 let sorted = BinaryHeap::from_iter(recent_blockhash_iter);
666 let sorted_iter = IntoIterSorted::new(sorted);
667 let recent_blockhash_iter = sorted_iter.take(MAX_ENTRIES);
668 let recent_blockhashes: RecentBlockhashes = recent_blockhash_iter.collect();
669 create_sysvar_account(&recent_blockhashes)
670 }
671 fn create_default_recent_blockhashes_account() -> AccountSharedData {
672 #[allow(deprecated)]
673 create_recent_blockhashes_account_for_test(vec![
674 IterItem(0u64, &Hash::default(), 0);
675 sysvar::recent_blockhashes::MAX_ENTRIES
676 ])
677 }
678 fn create_default_rent_account() -> AccountSharedData {
679 create_sysvar_account(&Rent::free())
680 }
681
682 #[test]
683 fn test_create_account() {
684 let new_owner = Pubkey::from([9; 32]);
685 let from = Pubkey::new_unique();
686 let to = Pubkey::new_unique();
687 let from_account = AccountSharedData::new(100, 0, &system_program::id());
688 let to_account = AccountSharedData::new(0, 0, &Pubkey::default());
689
690 let accounts = process_instruction(
691 &wincode::serialize(&SystemInstruction::CreateAccount {
692 lamports: 50,
693 space: 2,
694 owner: new_owner,
695 })
696 .unwrap(),
697 vec![(from, from_account), (to, to_account)],
698 vec![
699 AccountMeta {
700 pubkey: from,
701 is_signer: true,
702 is_writable: true,
703 },
704 AccountMeta {
705 pubkey: to,
706 is_signer: true,
707 is_writable: true,
708 },
709 ],
710 Ok(()),
711 );
712 assert_eq!(accounts[0].lamports(), 50);
713 assert_eq!(accounts[1].lamports(), 50);
714 assert_eq!(accounts[1].owner(), &new_owner);
715 assert_eq!(accounts[1].data(), &[0, 0]);
716 }
717
718 #[test]
719 fn test_create_account_with_seed() {
720 let new_owner = Pubkey::from([9; 32]);
721 let from = Pubkey::new_unique();
722 let seed = "shiny pepper";
723 let to = Pubkey::create_with_seed(&from, seed, &new_owner).unwrap();
724 let from_account = AccountSharedData::new(100, 0, &system_program::id());
725 let to_account = AccountSharedData::new(0, 0, &Pubkey::default());
726
727 let accounts = process_instruction(
728 &wincode::serialize(&SystemInstruction::CreateAccountWithSeed {
729 base: from,
730 seed: seed.to_string(),
731 lamports: 50,
732 space: 2,
733 owner: new_owner,
734 })
735 .unwrap(),
736 vec![(from, from_account), (to, to_account)],
737 vec![
738 AccountMeta {
739 pubkey: from,
740 is_signer: true,
741 is_writable: true,
742 },
743 AccountMeta {
744 pubkey: to,
745 is_signer: true,
746 is_writable: true,
747 },
748 ],
749 Ok(()),
750 );
751 assert_eq!(accounts[0].lamports(), 50);
752 assert_eq!(accounts[1].lamports(), 50);
753 assert_eq!(accounts[1].owner(), &new_owner);
754 assert_eq!(accounts[1].data(), &[0, 0]);
755 }
756
757 #[test]
758 fn test_create_account_with_seed_separate_base_account() {
759 let new_owner = Pubkey::from([9; 32]);
760 let from = Pubkey::new_unique();
761 let base = Pubkey::new_unique();
762 let seed = "shiny pepper";
763 let to = Pubkey::create_with_seed(&base, seed, &new_owner).unwrap();
764 let from_account = AccountSharedData::new(100, 0, &system_program::id());
765 let to_account = AccountSharedData::new(0, 0, &Pubkey::default());
766 let base_account = AccountSharedData::new(0, 0, &Pubkey::default());
767
768 let accounts = process_instruction(
769 &wincode::serialize(&SystemInstruction::CreateAccountWithSeed {
770 base,
771 seed: seed.to_string(),
772 lamports: 50,
773 space: 2,
774 owner: new_owner,
775 })
776 .unwrap(),
777 vec![(from, from_account), (to, to_account), (base, base_account)],
778 vec![
779 AccountMeta {
780 pubkey: from,
781 is_signer: true,
782 is_writable: true,
783 },
784 AccountMeta {
785 pubkey: to,
786 is_signer: false,
787 is_writable: true,
788 },
789 AccountMeta {
790 pubkey: base,
791 is_signer: true,
792 is_writable: false,
793 },
794 ],
795 Ok(()),
796 );
797 assert_eq!(accounts[0].lamports(), 50);
798 assert_eq!(accounts[1].lamports(), 50);
799 assert_eq!(accounts[1].owner(), &new_owner);
800 assert_eq!(accounts[1].data(), &[0, 0]);
801 }
802
803 #[test]
804 fn test_address_create_with_seed_mismatch() {
805 with_mock_invoke_context!(invoke_context, transaction_context, Vec::new());
806 let from = Pubkey::new_unique();
807 let seed = "dull boy";
808 let to = Pubkey::new_unique();
809 let owner = Pubkey::new_unique();
810
811 assert_eq!(
812 Address::create(&to, Some((&from, seed, &owner)), &invoke_context),
813 Err(SystemError::AddressWithSeedMismatch.into())
814 );
815 }
816
817 #[test]
818 fn test_create_account_with_seed_missing_sig() {
819 let new_owner = Pubkey::from([9; 32]);
820 let from = Pubkey::new_unique();
821 let seed = "dull boy";
822 let to = Pubkey::create_with_seed(&from, seed, &new_owner).unwrap();
823 let from_account = AccountSharedData::new(100, 0, &system_program::id());
824 let to_account = AccountSharedData::new(0, 0, &Pubkey::default());
825
826 let accounts = process_instruction(
827 &wincode::serialize(&SystemInstruction::CreateAccount {
828 lamports: 50,
829 space: 2,
830 owner: new_owner,
831 })
832 .unwrap(),
833 vec![(from, from_account), (to, to_account)],
834 vec![
835 AccountMeta {
836 pubkey: from,
837 is_signer: true,
838 is_writable: false,
839 },
840 AccountMeta {
841 pubkey: to,
842 is_signer: false,
843 is_writable: false,
844 },
845 ],
846 Err(InstructionError::MissingRequiredSignature),
847 );
848 assert_eq!(accounts[0].lamports(), 100);
849 assert_eq!(accounts[1], AccountSharedData::default());
850 }
851
852 #[test]
853 fn test_create_with_zero_lamports() {
854 let new_owner = Pubkey::from([9; 32]);
856 let from = Pubkey::new_unique();
857 let from_account = AccountSharedData::new(100, 0, &Pubkey::new_unique()); let to = Pubkey::new_unique();
859 let to_account = AccountSharedData::new(0, 0, &Pubkey::default());
860
861 let accounts = process_instruction(
862 &wincode::serialize(&SystemInstruction::CreateAccount {
863 lamports: 0,
864 space: 2,
865 owner: new_owner,
866 })
867 .unwrap(),
868 vec![(from, from_account), (to, to_account)],
869 vec![
870 AccountMeta {
871 pubkey: from,
872 is_signer: true,
873 is_writable: true,
874 },
875 AccountMeta {
876 pubkey: to,
877 is_signer: true,
878 is_writable: true,
879 },
880 ],
881 Ok(()),
882 );
883 assert_eq!(accounts[0].lamports(), 100);
884 assert_eq!(accounts[1].lamports(), 0);
885 assert_eq!(*accounts[1].owner(), new_owner);
886 assert_eq!(accounts[1].data(), &[0, 0]);
887 }
888
889 #[test]
890 fn test_create_negative_lamports() {
891 let new_owner = Pubkey::from([9; 32]);
893 let from = Pubkey::new_unique();
894 let from_account = AccountSharedData::new(100, 0, &Pubkey::new_unique());
895 let to = Pubkey::new_unique();
896 let to_account = AccountSharedData::new(0, 0, &Pubkey::default());
897
898 process_instruction(
899 &wincode::serialize(&SystemInstruction::CreateAccount {
900 lamports: 150,
901 space: 2,
902 owner: new_owner,
903 })
904 .unwrap(),
905 vec![(from, from_account), (to, to_account)],
906 vec![
907 AccountMeta {
908 pubkey: from,
909 is_signer: true,
910 is_writable: true,
911 },
912 AccountMeta {
913 pubkey: to,
914 is_signer: true,
915 is_writable: true,
916 },
917 ],
918 Err(SystemError::ResultWithNegativeLamports.into()),
919 );
920 }
921
922 #[test]
923 fn test_request_more_than_allowed_data_length() {
924 let from = Pubkey::new_unique();
925 let from_account = AccountSharedData::new(100, 0, &system_program::id());
926 let to = Pubkey::new_unique();
927 let to_account = AccountSharedData::new(0, 0, &Pubkey::default());
928 let instruction_accounts = vec![
929 AccountMeta {
930 pubkey: from,
931 is_signer: true,
932 is_writable: true,
933 },
934 AccountMeta {
935 pubkey: to,
936 is_signer: true,
937 is_writable: true,
938 },
939 ];
940
941 process_instruction(
943 &wincode::serialize(&SystemInstruction::CreateAccount {
944 lamports: 50,
945 space: MAX_PERMITTED_DATA_LENGTH + 1,
946 owner: system_program::id(),
947 })
948 .unwrap(),
949 vec![(from, from_account.clone()), (to, to_account.clone())],
950 instruction_accounts.clone(),
951 Err(SystemError::InvalidAccountDataLength.into()),
952 );
953
954 let accounts = process_instruction(
956 &wincode::serialize(&SystemInstruction::CreateAccount {
957 lamports: 50,
958 space: MAX_PERMITTED_DATA_LENGTH,
959 owner: system_program::id(),
960 })
961 .unwrap(),
962 vec![(from, from_account), (to, to_account)],
963 instruction_accounts,
964 Ok(()),
965 );
966 assert_eq!(accounts[1].lamports(), 50);
967 assert_eq!(accounts[1].data().len() as u64, MAX_PERMITTED_DATA_LENGTH);
968 }
969
970 #[test]
971 fn test_create_already_in_use() {
972 let new_owner = Pubkey::from([9; 32]);
973 let from = Pubkey::new_unique();
974 let from_account = AccountSharedData::new(100, 0, &system_program::id());
975 let owned_key = Pubkey::new_unique();
976
977 let original_program_owner = Pubkey::from([5; 32]);
979 let owned_account = AccountSharedData::new(0, 0, &original_program_owner);
980 let unchanged_account = owned_account.clone();
981 let accounts = process_instruction(
982 &wincode::serialize(&SystemInstruction::CreateAccount {
983 lamports: 50,
984 space: 2,
985 owner: new_owner,
986 })
987 .unwrap(),
988 vec![(from, from_account.clone()), (owned_key, owned_account)],
989 vec![
990 AccountMeta {
991 pubkey: from,
992 is_signer: true,
993 is_writable: false,
994 },
995 AccountMeta {
996 pubkey: owned_key,
997 is_signer: true,
998 is_writable: false,
999 },
1000 ],
1001 Err(SystemError::AccountAlreadyInUse.into()),
1002 );
1003 assert_eq!(accounts[0].lamports(), 100);
1004 assert_eq!(accounts[1], unchanged_account);
1005
1006 let owned_account = AccountSharedData::new(0, 1, &Pubkey::default());
1008 let unchanged_account = owned_account.clone();
1009 let accounts = process_instruction(
1010 &wincode::serialize(&SystemInstruction::CreateAccount {
1011 lamports: 50,
1012 space: 2,
1013 owner: new_owner,
1014 })
1015 .unwrap(),
1016 vec![(from, from_account.clone()), (owned_key, owned_account)],
1017 vec![
1018 AccountMeta {
1019 pubkey: from,
1020 is_signer: true,
1021 is_writable: false,
1022 },
1023 AccountMeta {
1024 pubkey: owned_key,
1025 is_signer: true,
1026 is_writable: false,
1027 },
1028 ],
1029 Err(SystemError::AccountAlreadyInUse.into()),
1030 );
1031 assert_eq!(accounts[0].lamports(), 100);
1032 assert_eq!(accounts[1], unchanged_account);
1033
1034 let owned_account = AccountSharedData::new(1, 0, &Pubkey::default());
1036 let unchanged_account = owned_account.clone();
1037 let accounts = process_instruction(
1038 &wincode::serialize(&SystemInstruction::CreateAccount {
1039 lamports: 50,
1040 space: 2,
1041 owner: new_owner,
1042 })
1043 .unwrap(),
1044 vec![(from, from_account), (owned_key, owned_account)],
1045 vec![
1046 AccountMeta {
1047 pubkey: from,
1048 is_signer: true,
1049 is_writable: false,
1050 },
1051 AccountMeta {
1052 pubkey: owned_key,
1053 is_signer: true,
1054 is_writable: false,
1055 },
1056 ],
1057 Err(SystemError::AccountAlreadyInUse.into()),
1058 );
1059 assert_eq!(accounts[0].lamports(), 100);
1060 assert_eq!(accounts[1], unchanged_account);
1061 }
1062
1063 #[test]
1064 fn test_create_unsigned() {
1065 let new_owner = Pubkey::from([9; 32]);
1067 let from = Pubkey::new_unique();
1068 let from_account = AccountSharedData::new(100, 0, &system_program::id());
1069 let owned_key = Pubkey::new_unique();
1070 let owned_account = AccountSharedData::new(0, 0, &Pubkey::default());
1071
1072 process_instruction(
1074 &wincode::serialize(&SystemInstruction::CreateAccount {
1075 lamports: 50,
1076 space: 2,
1077 owner: new_owner,
1078 })
1079 .unwrap(),
1080 vec![
1081 (from, from_account.clone()),
1082 (owned_key, owned_account.clone()),
1083 ],
1084 vec![
1085 AccountMeta {
1086 pubkey: from,
1087 is_signer: false,
1088 is_writable: false,
1089 },
1090 AccountMeta {
1091 pubkey: owned_key,
1092 is_signer: false,
1093 is_writable: false,
1094 },
1095 ],
1096 Err(InstructionError::MissingRequiredSignature),
1097 );
1098
1099 process_instruction(
1101 &wincode::serialize(&SystemInstruction::CreateAccount {
1102 lamports: 50,
1103 space: 2,
1104 owner: new_owner,
1105 })
1106 .unwrap(),
1107 vec![(from, from_account.clone()), (owned_key, owned_account)],
1108 vec![
1109 AccountMeta {
1110 pubkey: from,
1111 is_signer: true,
1112 is_writable: false,
1113 },
1114 AccountMeta {
1115 pubkey: owned_key,
1116 is_signer: false,
1117 is_writable: false,
1118 },
1119 ],
1120 Err(InstructionError::MissingRequiredSignature),
1121 );
1122
1123 let owned_account = AccountSharedData::new(0, 0, &Pubkey::default());
1125 process_instruction(
1126 &wincode::serialize(&SystemInstruction::CreateAccount {
1127 lamports: 50,
1128 space: 2,
1129 owner: new_owner,
1130 })
1131 .unwrap(),
1132 vec![(from, from_account), (owned_key, owned_account)],
1133 vec![
1134 AccountMeta {
1135 pubkey: from,
1136 is_signer: false,
1137 is_writable: false,
1138 },
1139 AccountMeta {
1140 pubkey: owned_key,
1141 is_signer: false,
1142 is_writable: false,
1143 },
1144 ],
1145 Err(InstructionError::MissingRequiredSignature),
1146 );
1147 }
1148
1149 #[test]
1150 fn test_create_sysvar_invalid_id_with_feature() {
1151 let from = Pubkey::new_unique();
1153 let from_account = AccountSharedData::new(100, 0, &system_program::id());
1154 let to = Pubkey::new_unique();
1155 let to_account = AccountSharedData::new(0, 0, &system_program::id());
1156
1157 process_instruction(
1159 &wincode::serialize(&SystemInstruction::CreateAccount {
1160 lamports: 50,
1161 space: 2,
1162 owner: solana_sdk_ids::sysvar::id(),
1163 })
1164 .unwrap(),
1165 vec![(from, from_account), (to, to_account)],
1166 vec![
1167 AccountMeta {
1168 pubkey: from,
1169 is_signer: true,
1170 is_writable: true,
1171 },
1172 AccountMeta {
1173 pubkey: to,
1174 is_signer: true,
1175 is_writable: true,
1176 },
1177 ],
1178 Ok(()),
1179 );
1180 }
1181
1182 #[test]
1183 fn test_create_data_populated() {
1184 let new_owner = Pubkey::from([9; 32]);
1186 let from = Pubkey::new_unique();
1187 let from_account = AccountSharedData::new(100, 0, &system_program::id());
1188 let populated_key = Pubkey::new_unique();
1189 let populated_account = AccountSharedData::from(Account {
1190 data: vec![0, 1, 2, 3],
1191 ..Account::default()
1192 });
1193
1194 process_instruction(
1195 &wincode::serialize(&SystemInstruction::CreateAccount {
1196 lamports: 50,
1197 space: 2,
1198 owner: new_owner,
1199 })
1200 .unwrap(),
1201 vec![(from, from_account), (populated_key, populated_account)],
1202 vec![
1203 AccountMeta {
1204 pubkey: from,
1205 is_signer: true,
1206 is_writable: false,
1207 },
1208 AccountMeta {
1209 pubkey: populated_key,
1210 is_signer: true,
1211 is_writable: false,
1212 },
1213 ],
1214 Err(SystemError::AccountAlreadyInUse.into()),
1215 );
1216 }
1217
1218 #[test]
1219 fn test_create_from_account_is_nonce_fail() {
1220 let nonce = Pubkey::new_unique();
1221 let nonce_account = AccountSharedData::new_data(
1222 42,
1223 &nonce::versions::Versions::new(nonce::state::State::Initialized(
1224 nonce::state::Data::default(),
1225 )),
1226 &system_program::id(),
1227 )
1228 .unwrap();
1229 let new = Pubkey::new_unique();
1230 let new_account = AccountSharedData::new(0, 0, &system_program::id());
1231
1232 process_instruction(
1233 &wincode::serialize(&SystemInstruction::CreateAccount {
1234 lamports: 42,
1235 space: 0,
1236 owner: Pubkey::new_unique(),
1237 })
1238 .unwrap(),
1239 vec![(nonce, nonce_account), (new, new_account)],
1240 vec![
1241 AccountMeta {
1242 pubkey: nonce,
1243 is_signer: true,
1244 is_writable: false,
1245 },
1246 AccountMeta {
1247 pubkey: new,
1248 is_signer: true,
1249 is_writable: true,
1250 },
1251 ],
1252 Err(InstructionError::InvalidArgument),
1253 );
1254 }
1255
1256 #[test]
1257 fn test_assign() {
1258 let new_owner = Pubkey::from([9; 32]);
1259 let pubkey = Pubkey::new_unique();
1260 let account = AccountSharedData::new(100, 0, &system_program::id());
1261
1262 process_instruction(
1264 &wincode::serialize(&SystemInstruction::Assign {
1265 owner: system_program::id(),
1266 })
1267 .unwrap(),
1268 vec![(pubkey, account.clone())],
1269 vec![AccountMeta {
1270 pubkey,
1271 is_signer: false,
1272 is_writable: true,
1273 }],
1274 Ok(()),
1275 );
1276
1277 process_instruction(
1279 &wincode::serialize(&SystemInstruction::Assign { owner: new_owner }).unwrap(),
1280 vec![(pubkey, account.clone())],
1281 vec![AccountMeta {
1282 pubkey,
1283 is_signer: false,
1284 is_writable: true,
1285 }],
1286 Err(InstructionError::MissingRequiredSignature),
1287 );
1288
1289 process_instruction(
1290 &wincode::serialize(&SystemInstruction::Assign { owner: new_owner }).unwrap(),
1291 vec![(pubkey, account.clone())],
1292 vec![AccountMeta {
1293 pubkey,
1294 is_signer: true,
1295 is_writable: true,
1296 }],
1297 Ok(()),
1298 );
1299
1300 process_instruction(
1302 &wincode::serialize(&SystemInstruction::Assign {
1303 owner: solana_sdk_ids::sysvar::id(),
1304 })
1305 .unwrap(),
1306 vec![(pubkey, account)],
1307 vec![AccountMeta {
1308 pubkey,
1309 is_signer: true,
1310 is_writable: true,
1311 }],
1312 Ok(()),
1313 );
1314 }
1315
1316 #[test]
1317 fn test_process_bogus_instruction() {
1318 let instruction = SystemInstruction::Assign {
1320 owner: Pubkey::new_unique(),
1321 };
1322 let data = serialize(&instruction).unwrap();
1323 process_instruction(
1324 &data,
1325 Vec::new(),
1326 Vec::new(),
1327 Err(InstructionError::MissingAccount),
1328 );
1329
1330 let from = Pubkey::new_unique();
1332 let from_account = AccountSharedData::new(100, 0, &system_program::id());
1333 let instruction = SystemInstruction::Transfer { lamports: 0 };
1334 let data = serialize(&instruction).unwrap();
1335 process_instruction(
1336 &data,
1337 vec![(from, from_account)],
1338 vec![AccountMeta {
1339 pubkey: from,
1340 is_signer: true,
1341 is_writable: false,
1342 }],
1343 Err(InstructionError::MissingAccount),
1344 );
1345 }
1346
1347 #[test]
1348 fn test_transfer_lamports() {
1349 let from = Pubkey::new_unique();
1350 let from_account = AccountSharedData::new(100, 0, &system_program::id());
1351 let to = Pubkey::from([3; 32]);
1352 let to_account = AccountSharedData::new(1, 0, &to); let transaction_accounts = vec![(from, from_account), (to, to_account)];
1354 let instruction_accounts = vec![
1355 AccountMeta {
1356 pubkey: from,
1357 is_signer: true,
1358 is_writable: true,
1359 },
1360 AccountMeta {
1361 pubkey: to,
1362 is_signer: false,
1363 is_writable: true,
1364 },
1365 ];
1366
1367 let accounts = process_instruction(
1369 &wincode::serialize(&SystemInstruction::Transfer { lamports: 50 }).unwrap(),
1370 transaction_accounts.clone(),
1371 instruction_accounts.clone(),
1372 Ok(()),
1373 );
1374 assert_eq!(accounts[0].lamports(), 50);
1375 assert_eq!(accounts[1].lamports(), 51);
1376
1377 let accounts = process_instruction(
1379 &wincode::serialize(&SystemInstruction::Transfer { lamports: 101 }).unwrap(),
1380 transaction_accounts.clone(),
1381 instruction_accounts.clone(),
1382 Err(SystemError::ResultWithNegativeLamports.into()),
1383 );
1384 assert_eq!(accounts[0].lamports(), 100);
1385 assert_eq!(accounts[1].lamports(), 1);
1386
1387 let accounts = process_instruction(
1389 &wincode::serialize(&SystemInstruction::Transfer { lamports: 0 }).unwrap(),
1390 transaction_accounts.clone(),
1391 instruction_accounts,
1392 Ok(()),
1393 );
1394 assert_eq!(accounts[0].lamports(), 100);
1395 assert_eq!(accounts[1].lamports(), 1);
1396
1397 let accounts = process_instruction(
1399 &wincode::serialize(&SystemInstruction::Transfer { lamports: 0 }).unwrap(),
1400 transaction_accounts,
1401 vec![
1402 AccountMeta {
1403 pubkey: from,
1404 is_signer: false,
1405 is_writable: true,
1406 },
1407 AccountMeta {
1408 pubkey: to,
1409 is_signer: false,
1410 is_writable: true,
1411 },
1412 ],
1413 Err(InstructionError::MissingRequiredSignature),
1414 );
1415 assert_eq!(accounts[0].lamports(), 100);
1416 assert_eq!(accounts[1].lamports(), 1);
1417 }
1418
1419 #[test]
1420 fn test_transfer_with_seed() {
1421 let base = Pubkey::new_unique();
1422 let base_account = AccountSharedData::new(100, 0, &Pubkey::from([2; 32])); let from_seed = "42".to_string();
1424 let from_owner = system_program::id();
1425 let from = Pubkey::create_with_seed(&base, from_seed.as_str(), &from_owner).unwrap();
1426 let from_account = AccountSharedData::new(100, 0, &system_program::id());
1427 let to = Pubkey::from([3; 32]);
1428 let to_account = AccountSharedData::new(1, 0, &to); let transaction_accounts =
1430 vec![(from, from_account), (base, base_account), (to, to_account)];
1431 let instruction_accounts = vec![
1432 AccountMeta {
1433 pubkey: from,
1434 is_signer: true,
1435 is_writable: true,
1436 },
1437 AccountMeta {
1438 pubkey: base,
1439 is_signer: true,
1440 is_writable: false,
1441 },
1442 AccountMeta {
1443 pubkey: to,
1444 is_signer: false,
1445 is_writable: true,
1446 },
1447 ];
1448
1449 let accounts = process_instruction(
1451 &wincode::serialize(&SystemInstruction::TransferWithSeed {
1452 lamports: 50,
1453 from_seed: from_seed.clone(),
1454 from_owner,
1455 })
1456 .unwrap(),
1457 transaction_accounts.clone(),
1458 instruction_accounts.clone(),
1459 Ok(()),
1460 );
1461 assert_eq!(accounts[0].lamports(), 50);
1462 assert_eq!(accounts[2].lamports(), 51);
1463
1464 let accounts = process_instruction(
1466 &wincode::serialize(&SystemInstruction::TransferWithSeed {
1467 lamports: 101,
1468 from_seed: from_seed.clone(),
1469 from_owner,
1470 })
1471 .unwrap(),
1472 transaction_accounts.clone(),
1473 instruction_accounts.clone(),
1474 Err(SystemError::ResultWithNegativeLamports.into()),
1475 );
1476 assert_eq!(accounts[0].lamports(), 100);
1477 assert_eq!(accounts[2].lamports(), 1);
1478
1479 let accounts = process_instruction(
1481 &wincode::serialize(&SystemInstruction::TransferWithSeed {
1482 lamports: 0,
1483 from_seed,
1484 from_owner,
1485 })
1486 .unwrap(),
1487 transaction_accounts,
1488 instruction_accounts,
1489 Ok(()),
1490 );
1491 assert_eq!(accounts[0].lamports(), 100);
1492 assert_eq!(accounts[2].lamports(), 1);
1493 }
1494
1495 #[test]
1496 fn test_transfer_lamports_from_nonce_account_fail() {
1497 let from = Pubkey::new_unique();
1498 let from_account = AccountSharedData::new_data(
1499 100,
1500 &nonce::versions::Versions::new(nonce::state::State::Initialized(nonce::state::Data {
1501 authority: from,
1502 ..nonce::state::Data::default()
1503 })),
1504 &system_program::id(),
1505 )
1506 .unwrap();
1507 assert_eq!(
1508 get_system_account_kind(&from_account),
1509 Some(SystemAccountKind::Nonce)
1510 );
1511 let to = Pubkey::from([3; 32]);
1512 let to_account = AccountSharedData::new(1, 0, &to); process_instruction(
1515 &wincode::serialize(&SystemInstruction::Transfer { lamports: 50 }).unwrap(),
1516 vec![(from, from_account), (to, to_account)],
1517 vec![
1518 AccountMeta {
1519 pubkey: from,
1520 is_signer: true,
1521 is_writable: false,
1522 },
1523 AccountMeta {
1524 pubkey: to,
1525 is_signer: false,
1526 is_writable: false,
1527 },
1528 ],
1529 Err(InstructionError::InvalidArgument),
1530 );
1531 }
1532
1533 fn process_nonce_instruction(
1534 instruction: Instruction,
1535 expected_result: Result<(), InstructionError>,
1536 ) -> Vec<AccountSharedData> {
1537 let transaction_accounts = instruction
1538 .accounts
1539 .iter()
1540 .map(|meta| {
1541 #[allow(deprecated)]
1542 (
1543 meta.pubkey,
1544 if sysvar::recent_blockhashes::check_id(&meta.pubkey) {
1545 create_default_recent_blockhashes_account()
1546 } else if sysvar::rent::check_id(&meta.pubkey) {
1547 create_sysvar_account(&Rent::free())
1548 } else {
1549 AccountSharedData::new(0, 0, &Pubkey::new_unique())
1550 },
1551 )
1552 })
1553 .collect();
1554 process_instruction(
1555 &instruction.data,
1556 transaction_accounts,
1557 instruction.accounts,
1558 expected_result,
1559 )
1560 }
1561
1562 #[test]
1563 fn test_process_nonce_ix_no_acc_data_fail() {
1564 let none_address = Pubkey::new_unique();
1565 process_nonce_instruction(
1566 system_instruction::advance_nonce_account(&none_address, &none_address),
1567 Err(InstructionError::InvalidAccountData),
1568 );
1569 }
1570
1571 #[test]
1572 fn test_process_nonce_ix_no_keyed_accs_fail() {
1573 process_instruction(
1574 &serialize(&SystemInstruction::AdvanceNonceAccount).unwrap(),
1575 Vec::new(),
1576 Vec::new(),
1577 Err(InstructionError::MissingAccount),
1578 );
1579 }
1580
1581 #[test]
1582 fn test_process_nonce_ix_only_nonce_acc_fail() {
1583 let pubkey = Pubkey::new_unique();
1584 process_instruction(
1585 &serialize(&SystemInstruction::AdvanceNonceAccount).unwrap(),
1586 vec![(pubkey, create_default_account())],
1587 vec![AccountMeta {
1588 pubkey,
1589 is_signer: true,
1590 is_writable: true,
1591 }],
1592 Err(InstructionError::MissingAccount),
1593 );
1594 }
1595
1596 #[test]
1597 fn test_process_nonce_ix_ok() {
1598 let nonce_address = Pubkey::new_unique();
1599 let nonce_account = nonce_account::create_account(1_000_000).into_inner();
1600 #[allow(deprecated)]
1601 let blockhash_id = sysvar::recent_blockhashes::id();
1602 let accounts = process_instruction(
1603 &serialize(&SystemInstruction::InitializeNonceAccount(nonce_address)).unwrap(),
1604 vec![
1605 (nonce_address, nonce_account),
1606 (blockhash_id, create_default_recent_blockhashes_account()),
1607 (sysvar::rent::id(), create_default_rent_account()),
1608 ],
1609 vec![
1610 AccountMeta {
1611 pubkey: nonce_address,
1612 is_signer: true,
1613 is_writable: true,
1614 },
1615 AccountMeta {
1616 pubkey: blockhash_id,
1617 is_signer: false,
1618 is_writable: false,
1619 },
1620 AccountMeta {
1621 pubkey: sysvar::rent::id(),
1622 is_signer: false,
1623 is_writable: false,
1624 },
1625 ],
1626 Ok(()),
1627 );
1628 let blockhash = hash(&serialize(&0).unwrap());
1629 #[allow(deprecated)]
1630 let new_recent_blockhashes_account = create_recent_blockhashes_account_for_test(vec![
1631 IterItem(0u64, &blockhash, 0);
1632 sysvar::recent_blockhashes::MAX_ENTRIES
1633 ]);
1634 mock_process_instruction(
1635 &system_program::id(),
1636 &serialize(&SystemInstruction::AdvanceNonceAccount).unwrap(),
1637 vec![
1638 (nonce_address, accounts[0].clone()),
1639 (blockhash_id, new_recent_blockhashes_account),
1640 ],
1641 vec![
1642 AccountMeta {
1643 pubkey: nonce_address,
1644 is_signer: true,
1645 is_writable: true,
1646 },
1647 AccountMeta {
1648 pubkey: blockhash_id,
1649 is_signer: false,
1650 is_writable: false,
1651 },
1652 ],
1653 Ok(()),
1654 Entrypoint::register,
1655 |invoke_context: &mut InvokeContext| {
1656 invoke_context.environment_config.blockhash = hash(&serialize(&0).unwrap());
1657 },
1658 |_invoke_context| {},
1659 );
1660 }
1661
1662 #[test]
1663 fn test_process_withdraw_ix_no_acc_data_fail() {
1664 let nonce_address = Pubkey::new_unique();
1665 process_nonce_instruction(
1666 system_instruction::withdraw_nonce_account(
1667 &nonce_address,
1668 &Pubkey::new_unique(),
1669 &nonce_address,
1670 1,
1671 ),
1672 Err(InstructionError::InvalidAccountData),
1673 );
1674 }
1675
1676 #[test]
1677 fn test_process_withdraw_ix_no_keyed_accs_fail() {
1678 process_instruction(
1679 &serialize(&SystemInstruction::WithdrawNonceAccount(42)).unwrap(),
1680 Vec::new(),
1681 Vec::new(),
1682 Err(InstructionError::MissingAccount),
1683 );
1684 }
1685
1686 #[test]
1687 fn test_process_withdraw_ix_only_nonce_acc_fail() {
1688 let nonce_address = Pubkey::new_unique();
1689 process_instruction(
1690 &serialize(&SystemInstruction::WithdrawNonceAccount(42)).unwrap(),
1691 vec![(nonce_address, create_default_account())],
1692 vec![AccountMeta {
1693 pubkey: nonce_address,
1694 is_signer: true,
1695 is_writable: true,
1696 }],
1697 Err(InstructionError::MissingAccount),
1698 );
1699 }
1700
1701 #[test]
1702 fn test_process_withdraw_ix_ok() {
1703 let nonce_address = Pubkey::new_unique();
1704 let nonce_account = nonce_account::create_account(1_000_000).into_inner();
1705 let pubkey = Pubkey::new_unique();
1706 #[allow(deprecated)]
1707 let blockhash_id = sysvar::recent_blockhashes::id();
1708 process_instruction(
1709 &serialize(&SystemInstruction::WithdrawNonceAccount(42)).unwrap(),
1710 vec![
1711 (nonce_address, nonce_account),
1712 (pubkey, create_default_account()),
1713 (blockhash_id, create_default_recent_blockhashes_account()),
1714 (sysvar::rent::id(), create_default_rent_account()),
1715 ],
1716 vec![
1717 AccountMeta {
1718 pubkey: nonce_address,
1719 is_signer: true,
1720 is_writable: true,
1721 },
1722 AccountMeta {
1723 pubkey,
1724 is_signer: true,
1725 is_writable: true,
1726 },
1727 AccountMeta {
1728 pubkey: blockhash_id,
1729 is_signer: false,
1730 is_writable: false,
1731 },
1732 AccountMeta {
1733 pubkey: sysvar::rent::id(),
1734 is_signer: false,
1735 is_writable: false,
1736 },
1737 ],
1738 Ok(()),
1739 );
1740 }
1741
1742 #[test]
1743 fn test_process_initialize_ix_no_keyed_accs_fail() {
1744 process_instruction(
1745 &serialize(&SystemInstruction::InitializeNonceAccount(Pubkey::default())).unwrap(),
1746 Vec::new(),
1747 Vec::new(),
1748 Err(InstructionError::MissingAccount),
1749 );
1750 }
1751
1752 #[test]
1753 fn test_process_initialize_ix_only_nonce_acc_fail() {
1754 let nonce_address = Pubkey::new_unique();
1755 let nonce_account = nonce_account::create_account(1_000_000).into_inner();
1756 process_instruction(
1757 &serialize(&SystemInstruction::InitializeNonceAccount(nonce_address)).unwrap(),
1758 vec![(nonce_address, nonce_account)],
1759 vec![AccountMeta {
1760 pubkey: nonce_address,
1761 is_signer: true,
1762 is_writable: true,
1763 }],
1764 Err(InstructionError::MissingAccount),
1765 );
1766 }
1767
1768 #[test]
1769 fn test_process_initialize_ix_ok() {
1770 let nonce_address = Pubkey::new_unique();
1771 let nonce_account = nonce_account::create_account(1_000_000).into_inner();
1772 #[allow(deprecated)]
1773 let blockhash_id = sysvar::recent_blockhashes::id();
1774 process_instruction(
1775 &serialize(&SystemInstruction::InitializeNonceAccount(nonce_address)).unwrap(),
1776 vec![
1777 (nonce_address, nonce_account),
1778 (blockhash_id, create_default_recent_blockhashes_account()),
1779 (sysvar::rent::id(), create_default_rent_account()),
1780 ],
1781 vec![
1782 AccountMeta {
1783 pubkey: nonce_address,
1784 is_signer: true,
1785 is_writable: true,
1786 },
1787 AccountMeta {
1788 pubkey: blockhash_id,
1789 is_signer: false,
1790 is_writable: false,
1791 },
1792 AccountMeta {
1793 pubkey: sysvar::rent::id(),
1794 is_signer: false,
1795 is_writable: false,
1796 },
1797 ],
1798 Ok(()),
1799 );
1800 }
1801
1802 #[test]
1803 fn test_process_authorize_ix_ok() {
1804 let nonce_address = Pubkey::new_unique();
1805 let nonce_account = nonce_account::create_account(1_000_000).into_inner();
1806 #[allow(deprecated)]
1807 let blockhash_id = sysvar::recent_blockhashes::id();
1808 let accounts = process_instruction(
1809 &serialize(&SystemInstruction::InitializeNonceAccount(nonce_address)).unwrap(),
1810 vec![
1811 (nonce_address, nonce_account),
1812 (blockhash_id, create_default_recent_blockhashes_account()),
1813 (sysvar::rent::id(), create_default_rent_account()),
1814 ],
1815 vec![
1816 AccountMeta {
1817 pubkey: nonce_address,
1818 is_signer: true,
1819 is_writable: true,
1820 },
1821 AccountMeta {
1822 pubkey: blockhash_id,
1823 is_signer: false,
1824 is_writable: false,
1825 },
1826 AccountMeta {
1827 pubkey: sysvar::rent::id(),
1828 is_signer: false,
1829 is_writable: false,
1830 },
1831 ],
1832 Ok(()),
1833 );
1834 process_instruction(
1835 &serialize(&SystemInstruction::AuthorizeNonceAccount(nonce_address)).unwrap(),
1836 vec![(nonce_address, accounts[0].clone())],
1837 vec![AccountMeta {
1838 pubkey: nonce_address,
1839 is_signer: true,
1840 is_writable: true,
1841 }],
1842 Ok(()),
1843 );
1844 }
1845
1846 #[test]
1847 fn test_process_authorize_bad_account_data_fail() {
1848 let nonce_address = Pubkey::new_unique();
1849 process_nonce_instruction(
1850 system_instruction::authorize_nonce_account(
1851 &nonce_address,
1852 &Pubkey::new_unique(),
1853 &nonce_address,
1854 ),
1855 Err(InstructionError::InvalidAccountData),
1856 );
1857 }
1858
1859 #[test]
1860 fn test_nonce_initialize_with_empty_recent_blockhashes_fail() {
1861 let nonce_address = Pubkey::new_unique();
1862 let nonce_account = nonce_account::create_account(1_000_000).into_inner();
1863 #[allow(deprecated)]
1864 let blockhash_id = sysvar::recent_blockhashes::id();
1865 #[allow(deprecated)]
1866 let new_recent_blockhashes_account = create_recent_blockhashes_account_for_test(vec![]);
1867 process_instruction(
1868 &serialize(&SystemInstruction::InitializeNonceAccount(nonce_address)).unwrap(),
1869 vec![
1870 (nonce_address, nonce_account),
1871 (blockhash_id, new_recent_blockhashes_account),
1872 (sysvar::rent::id(), create_default_rent_account()),
1873 ],
1874 vec![
1875 AccountMeta {
1876 pubkey: nonce_address,
1877 is_signer: true,
1878 is_writable: true,
1879 },
1880 AccountMeta {
1881 pubkey: blockhash_id,
1882 is_signer: false,
1883 is_writable: false,
1884 },
1885 AccountMeta {
1886 pubkey: sysvar::rent::id(),
1887 is_signer: false,
1888 is_writable: false,
1889 },
1890 ],
1891 Err(SystemError::NonceNoRecentBlockhashes.into()),
1892 );
1893 }
1894
1895 #[test]
1896 fn test_nonce_advance_with_empty_recent_blockhashes_fail() {
1897 let nonce_address = Pubkey::new_unique();
1898 let nonce_account = nonce_account::create_account(1_000_000).into_inner();
1899 #[allow(deprecated)]
1900 let blockhash_id = sysvar::recent_blockhashes::id();
1901 let accounts = process_instruction(
1902 &serialize(&SystemInstruction::InitializeNonceAccount(nonce_address)).unwrap(),
1903 vec![
1904 (nonce_address, nonce_account),
1905 (blockhash_id, create_default_recent_blockhashes_account()),
1906 (sysvar::rent::id(), create_default_rent_account()),
1907 ],
1908 vec![
1909 AccountMeta {
1910 pubkey: nonce_address,
1911 is_signer: true,
1912 is_writable: true,
1913 },
1914 AccountMeta {
1915 pubkey: blockhash_id,
1916 is_signer: false,
1917 is_writable: false,
1918 },
1919 AccountMeta {
1920 pubkey: sysvar::rent::id(),
1921 is_signer: false,
1922 is_writable: false,
1923 },
1924 ],
1925 Ok(()),
1926 );
1927 #[allow(deprecated)]
1928 let new_recent_blockhashes_account = create_recent_blockhashes_account_for_test(vec![]);
1929 mock_process_instruction(
1930 &system_program::id(),
1931 &serialize(&SystemInstruction::AdvanceNonceAccount).unwrap(),
1932 vec![
1933 (nonce_address, accounts[0].clone()),
1934 (blockhash_id, new_recent_blockhashes_account),
1935 ],
1936 vec![
1937 AccountMeta {
1938 pubkey: nonce_address,
1939 is_signer: true,
1940 is_writable: true,
1941 },
1942 AccountMeta {
1943 pubkey: blockhash_id,
1944 is_signer: false,
1945 is_writable: false,
1946 },
1947 ],
1948 Err(SystemError::NonceNoRecentBlockhashes.into()),
1949 Entrypoint::register,
1950 |invoke_context: &mut InvokeContext| {
1951 invoke_context.environment_config.blockhash = hash(&serialize(&0).unwrap());
1952 },
1953 |_invoke_context| {},
1954 );
1955 }
1956
1957 #[test]
1958 fn test_nonce_account_upgrade_check_owner() {
1959 let nonce_address = Pubkey::new_unique();
1960 let versions = NonceVersions::Legacy(Box::new(NonceState::Uninitialized));
1961 let nonce_account = AccountSharedData::new_data(
1962 1_000_000, &versions, &Pubkey::new_unique(), )
1966 .unwrap();
1967 let accounts = process_instruction(
1968 &serialize(&SystemInstruction::UpgradeNonceAccount).unwrap(),
1969 vec![(nonce_address, nonce_account.clone())],
1970 vec![AccountMeta {
1971 pubkey: nonce_address,
1972 is_signer: false,
1973 is_writable: true,
1974 }],
1975 Err(InstructionError::InvalidAccountOwner),
1976 );
1977 assert_eq!(accounts.len(), 1);
1978 assert_eq!(accounts[0], nonce_account);
1979 }
1980
1981 fn new_nonce_account(versions: NonceVersions) -> AccountSharedData {
1982 let nonce_account = AccountSharedData::new_data(
1983 1_000_000, &versions, &system_program::id(), )
1987 .unwrap();
1988 let stored: NonceVersions = nonce_account.state().unwrap();
1989 assert_eq!(stored, versions);
1990 nonce_account
1991 }
1992
1993 #[test]
1994 fn test_nonce_account_upgrade() {
1995 let nonce_address = Pubkey::new_unique();
1996 let versions = NonceVersions::Legacy(Box::new(NonceState::Uninitialized));
1997 let nonce_account = new_nonce_account(versions);
1998 let accounts = process_instruction(
1999 &serialize(&SystemInstruction::UpgradeNonceAccount).unwrap(),
2000 vec![(nonce_address, nonce_account.clone())],
2001 vec![AccountMeta {
2002 pubkey: nonce_address,
2003 is_signer: false,
2004 is_writable: true,
2005 }],
2006 Err(InstructionError::InvalidArgument),
2007 );
2008 assert_eq!(accounts.len(), 1);
2009 assert_eq!(accounts[0], nonce_account);
2010 let versions = NonceVersions::Current(Box::new(NonceState::Uninitialized));
2011 let nonce_account = new_nonce_account(versions);
2012 let accounts = process_instruction(
2013 &serialize(&SystemInstruction::UpgradeNonceAccount).unwrap(),
2014 vec![(nonce_address, nonce_account.clone())],
2015 vec![AccountMeta {
2016 pubkey: nonce_address,
2017 is_signer: false,
2018 is_writable: true,
2019 }],
2020 Err(InstructionError::InvalidArgument),
2021 );
2022 assert_eq!(accounts.len(), 1);
2023 assert_eq!(accounts[0], nonce_account);
2024 let blockhash = Hash::from([171; 32]);
2025 let durable_nonce = DurableNonce::from_blockhash(&blockhash);
2026 let data = NonceData {
2027 authority: Pubkey::new_unique(),
2028 durable_nonce,
2029 fee_calculator: FeeCalculator {
2030 lamports_per_signature: 2718,
2031 },
2032 };
2033 let versions = NonceVersions::Legacy(Box::new(NonceState::Initialized(data.clone())));
2034 let nonce_account = new_nonce_account(versions);
2035 let accounts = process_instruction(
2036 &serialize(&SystemInstruction::UpgradeNonceAccount).unwrap(),
2037 vec![(nonce_address, nonce_account.clone())],
2038 vec![AccountMeta {
2039 pubkey: nonce_address,
2040 is_signer: false,
2041 is_writable: false, }],
2043 Err(InstructionError::InvalidArgument),
2044 );
2045 assert_eq!(accounts.len(), 1);
2046 assert_eq!(accounts[0], nonce_account);
2047 let mut accounts = process_instruction(
2048 &serialize(&SystemInstruction::UpgradeNonceAccount).unwrap(),
2049 vec![(nonce_address, nonce_account)],
2050 vec![AccountMeta {
2051 pubkey: nonce_address,
2052 is_signer: false,
2053 is_writable: true,
2054 }],
2055 Ok(()),
2056 );
2057 assert_eq!(accounts.len(), 1);
2058 let nonce_account = accounts.remove(0);
2059 let durable_nonce = DurableNonce::from_blockhash(durable_nonce.as_hash());
2060 assert_ne!(data.durable_nonce, durable_nonce);
2061 let data = NonceData {
2062 durable_nonce,
2063 ..data
2064 };
2065 let upgraded_nonce_account =
2066 NonceVersions::Current(Box::new(NonceState::Initialized(data)));
2067 let stored: NonceVersions = nonce_account.state().unwrap();
2068 assert_eq!(stored, upgraded_nonce_account);
2069 let accounts = process_instruction(
2070 &serialize(&SystemInstruction::UpgradeNonceAccount).unwrap(),
2071 vec![(nonce_address, nonce_account)],
2072 vec![AccountMeta {
2073 pubkey: nonce_address,
2074 is_signer: false,
2075 is_writable: true,
2076 }],
2077 Err(InstructionError::InvalidArgument),
2078 );
2079 assert_eq!(accounts.len(), 1);
2080 let stored: NonceVersions = accounts[0].state().unwrap();
2081 assert_eq!(stored, upgraded_nonce_account);
2082 }
2083
2084 #[test]
2085 fn test_assign_native_loader_and_transfer() {
2086 for size in [0, 10] {
2087 let pubkey = Pubkey::new_unique();
2088 let account = AccountSharedData::new(100, size, &system_program::id());
2089 let accounts = process_instruction(
2090 &wincode::serialize(&SystemInstruction::Assign {
2091 owner: solana_sdk_ids::native_loader::id(),
2092 })
2093 .unwrap(),
2094 vec![(pubkey, account.clone())],
2095 vec![AccountMeta {
2096 pubkey,
2097 is_signer: true,
2098 is_writable: true,
2099 }],
2100 Ok(()),
2101 );
2102 assert_eq!(accounts[0].owner(), &solana_sdk_ids::native_loader::id());
2103 assert_eq!(accounts[0].lamports(), 100);
2104
2105 let pubkey2 = Pubkey::new_unique();
2106 let accounts = process_instruction(
2107 &wincode::serialize(&SystemInstruction::Transfer { lamports: 50 }).unwrap(),
2108 vec![
2109 (
2110 pubkey2,
2111 AccountSharedData::new(100, 0, &system_program::id()),
2112 ),
2113 (pubkey, accounts[0].clone()),
2114 ],
2115 vec![
2116 AccountMeta {
2117 pubkey: pubkey2,
2118 is_signer: true,
2119 is_writable: true,
2120 },
2121 AccountMeta {
2122 pubkey,
2123 is_signer: false,
2124 is_writable: true,
2125 },
2126 ],
2127 Ok(()),
2128 );
2129 assert_eq!(accounts[1].owner(), &solana_sdk_ids::native_loader::id());
2130 assert_eq!(accounts[1].lamports(), 150);
2131 }
2132 }
2133
2134 #[test]
2135 fn test_create_account_allow_prefund() {
2136 let new_owner = Pubkey::from([9; 32]);
2137 let to = Pubkey::new_unique();
2138 let from = Pubkey::new_unique();
2139 let ix_accounts = vec![AccountMeta::new(to, true), AccountMeta::new(from, true)];
2140
2141 let accounts = process_instruction(
2143 &wincode::serialize(&SystemInstruction::CreateAccountAllowPrefund {
2144 lamports: 50,
2145 space: 2,
2146 owner: new_owner,
2147 })
2148 .unwrap(),
2149 vec![
2150 (to, AccountSharedData::new(100, 0, &Pubkey::default())),
2151 (from, AccountSharedData::new(100, 0, &system_program::id())),
2152 ],
2153 ix_accounts,
2154 Ok(()),
2155 );
2156 assert_eq!(accounts[0].lamports(), 150);
2157 assert_eq!(accounts[0].owner(), &new_owner);
2158 assert_eq!(accounts[0].data(), &[0, 0]);
2159 assert_eq!(accounts[1].lamports(), 50);
2160
2161 let accounts = process_instruction(
2163 &wincode::serialize(&SystemInstruction::CreateAccountAllowPrefund {
2164 lamports: 0,
2165 space: 2,
2166 owner: new_owner,
2167 })
2168 .unwrap(),
2169 vec![(to, AccountSharedData::new(100, 0, &Pubkey::default()))],
2170 vec![AccountMeta::new(to, true)],
2171 Ok(()),
2172 );
2173 assert_eq!(accounts[0].lamports(), 100);
2174 assert_eq!(accounts[0].owner(), &new_owner);
2175 assert_eq!(accounts[0].data(), &[0, 0]);
2176
2177 use solana_program_runtime::invoke_context::mock_process_instruction_with_feature_set;
2179 mock_process_instruction_with_feature_set(
2180 &system_program::id(),
2181 &wincode::serialize(&SystemInstruction::CreateAccountAllowPrefund {
2182 lamports: 50,
2183 space: 0,
2184 owner: new_owner,
2185 })
2186 .unwrap(),
2187 vec![
2188 (to, AccountSharedData::new(0, 0, &Pubkey::default())),
2189 (from, AccountSharedData::new(100, 0, &system_program::id())),
2190 ],
2191 vec![AccountMeta::new(to, true), AccountMeta::new(from, true)],
2192 Err(InstructionError::InvalidInstructionData),
2193 Entrypoint::register,
2194 |_| {},
2195 |_| {},
2196 &solana_svm_feature_set::SVMFeatureSet::default(),
2197 );
2198 }
2199
2200 #[test]
2201 fn test_create_account_allow_prefund_already_in_use() {
2202 let new_owner = Pubkey::from([9; 32]);
2203 let to = Pubkey::new_unique();
2204 let from = Pubkey::new_unique();
2205 let from_account = AccountSharedData::new(100, 0, &system_program::id());
2206 let ix_data = wincode::serialize(&SystemInstruction::CreateAccountAllowPrefund {
2207 lamports: 50,
2208 space: 2,
2209 owner: new_owner,
2210 })
2211 .unwrap();
2212 let ix_accounts = vec![AccountMeta::new(to, true), AccountMeta::new(from, true)];
2213
2214 process_instruction(
2216 &ix_data,
2217 vec![
2218 (to, AccountSharedData::new(0, 1, &Pubkey::default())),
2219 (from, from_account.clone()),
2220 ],
2221 ix_accounts.clone(),
2222 Err(SystemError::AccountAlreadyInUse.into()),
2223 );
2224
2225 process_instruction(
2227 &ix_data,
2228 vec![
2229 (to, AccountSharedData::new(0, 0, &Pubkey::from([5; 32]))),
2230 (from, from_account),
2231 ],
2232 ix_accounts,
2233 Err(SystemError::AccountAlreadyInUse.into()),
2234 );
2235 }
2236
2237 #[test]
2238 fn test_create_account_allow_prefund_missing_signer() {
2239 let new_owner = Pubkey::from([9; 32]);
2240 let to = Pubkey::new_unique();
2241 let from = Pubkey::new_unique();
2242 let tx_accounts = vec![
2243 (to, AccountSharedData::new(0, 0, &Pubkey::default())),
2244 (from, AccountSharedData::new(100, 0, &system_program::id())),
2245 ];
2246 let ix_data = wincode::serialize(&SystemInstruction::CreateAccountAllowPrefund {
2247 lamports: 50,
2248 space: 2,
2249 owner: new_owner,
2250 })
2251 .unwrap();
2252
2253 process_instruction(
2255 &ix_data,
2256 tx_accounts.clone(),
2257 vec![AccountMeta::new(to, true), AccountMeta::new(from, false)],
2258 Err(InstructionError::MissingRequiredSignature),
2259 );
2260
2261 process_instruction(
2263 &ix_data,
2264 tx_accounts,
2265 vec![AccountMeta::new(to, false), AccountMeta::new(from, true)],
2266 Err(InstructionError::MissingRequiredSignature),
2267 );
2268 }
2269}