Skip to main content

solana_system_program/
system_processor.rs

1use {
2    crate::system_instruction::{
3        advance_nonce_account, authorize_nonce_account, initialize_nonce_account,
4        withdraw_nonce_account,
5    },
6    log::*,
7    solana_bincode::limited_deserialize,
8    solana_instruction::error::InstructionError,
9    solana_nonce as nonce,
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// represents an address that may or may not have been generated
28//  from a seed
29#[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            // The conversion from `PubkeyError` to `InstructionError` through
50            // num-traits is incorrect, but it's the existing behavior.
51            let address_with_seed =
52                Pubkey::create_with_seed(base, seed, owner).map_err(|e| e as u64)?;
53            // re-derive the address, must match the supplied address
54            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 it looks like the `to` account is already in use, bail
92    //   (note that the id check is also enforced by message_processor)
93    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    // no work to do, just return
125    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    // if it looks like the `to` account is already in use, bail
162    {
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/// Create a new account without checking for 0 lamports. All other checks remain.
185/// Intended for use where account has already had rent paid in whole or in part
186/// before creation.
187#[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    // The conversion from `PubkeyError` to `InstructionError` through
289    // num-traits is incorrect, but it's the existing behavior.
290    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 =
324        limited_deserialize(instruction_data, solana_packet::PACKET_DATA_SIZE as u64)?;
325
326    trace!("process_instruction: {instruction:?}");
327
328    let signers = instruction_context.get_signers()?;
329    match instruction {
330        SystemInstruction::CreateAccount {
331            lamports,
332            space,
333            owner,
334        } => {
335            instruction_context.check_number_of_instruction_accounts(2)?;
336            let to_address = Address::create(
337                instruction_context.get_key_of_instruction_account(1)?,
338                None,
339                invoke_context,
340            )?;
341            create_account(
342                0,
343                1,
344                &to_address,
345                lamports,
346                space,
347                &owner,
348                &signers,
349                invoke_context,
350                &instruction_context,
351            )
352        }
353
354        SystemInstruction::CreateAccountWithSeed {
355            base,
356            seed,
357            lamports,
358            space,
359            owner,
360        } => {
361            instruction_context.check_number_of_instruction_accounts(2)?;
362            let to_address = Address::create(
363                instruction_context.get_key_of_instruction_account(1)?,
364                Some((&base, &seed, &owner)),
365                invoke_context,
366            )?;
367            create_account(
368                0,
369                1,
370                &to_address,
371                lamports,
372                space,
373                &owner,
374                &signers,
375                invoke_context,
376                &instruction_context,
377            )
378        }
379        SystemInstruction::Assign { owner } => {
380            instruction_context.check_number_of_instruction_accounts(1)?;
381            let mut account = instruction_context.try_borrow_instruction_account(0)?;
382            let address = Address::create(
383                instruction_context.get_key_of_instruction_account(0)?,
384                None,
385                invoke_context,
386            )?;
387            assign(&mut account, &address, &owner, &signers, invoke_context)
388        }
389        SystemInstruction::Transfer { lamports } => {
390            instruction_context.check_number_of_instruction_accounts(2)?;
391            transfer(0, 1, lamports, invoke_context, &instruction_context)
392        }
393        SystemInstruction::TransferWithSeed {
394            lamports,
395            from_seed,
396            from_owner,
397        } => {
398            instruction_context.check_number_of_instruction_accounts(3)?;
399            transfer_with_seed(
400                0,
401                1,
402                &from_seed,
403                &from_owner,
404                2,
405                lamports,
406                invoke_context,
407                &instruction_context,
408            )
409        }
410        SystemInstruction::AdvanceNonceAccount => {
411            instruction_context.check_number_of_instruction_accounts(1)?;
412            let mut me = instruction_context.try_borrow_instruction_account(0)?;
413            #[allow(deprecated)]
414            let recent_blockhashes = get_sysvar_with_account_check::recent_blockhashes(
415                invoke_context,
416                &instruction_context,
417                1,
418            )?;
419            if recent_blockhashes.is_empty() {
420                ic_msg!(
421                    invoke_context,
422                    "Advance nonce account: recent blockhash list is empty",
423                );
424                return Err(SystemError::NonceNoRecentBlockhashes.into());
425            }
426            advance_nonce_account(&mut me, &signers, invoke_context)
427        }
428        SystemInstruction::WithdrawNonceAccount(lamports) => {
429            instruction_context.check_number_of_instruction_accounts(2)?;
430            #[allow(deprecated)]
431            let _recent_blockhashes = get_sysvar_with_account_check::recent_blockhashes(
432                invoke_context,
433                &instruction_context,
434                2,
435            )?;
436            let rent =
437                get_sysvar_with_account_check::rent(invoke_context, &instruction_context, 3)?;
438            withdraw_nonce_account(
439                0,
440                lamports,
441                1,
442                &rent,
443                &signers,
444                invoke_context,
445                &instruction_context,
446            )
447        }
448        SystemInstruction::InitializeNonceAccount(authorized) => {
449            instruction_context.check_number_of_instruction_accounts(1)?;
450            let mut me = instruction_context.try_borrow_instruction_account(0)?;
451            #[allow(deprecated)]
452            let recent_blockhashes = get_sysvar_with_account_check::recent_blockhashes(
453                invoke_context,
454                &instruction_context,
455                1,
456            )?;
457            if recent_blockhashes.is_empty() {
458                ic_msg!(
459                    invoke_context,
460                    "Initialize nonce account: recent blockhash list is empty",
461                );
462                return Err(SystemError::NonceNoRecentBlockhashes.into());
463            }
464            let rent =
465                get_sysvar_with_account_check::rent(invoke_context, &instruction_context, 2)?;
466            initialize_nonce_account(&mut me, &authorized, &rent, invoke_context)
467        }
468        SystemInstruction::AuthorizeNonceAccount(nonce_authority) => {
469            instruction_context.check_number_of_instruction_accounts(1)?;
470            let mut me = instruction_context.try_borrow_instruction_account(0)?;
471            authorize_nonce_account(&mut me, &nonce_authority, &signers, invoke_context)
472        }
473        SystemInstruction::UpgradeNonceAccount => {
474            instruction_context.check_number_of_instruction_accounts(1)?;
475            let mut nonce_account = instruction_context.try_borrow_instruction_account(0)?;
476            if !system_program::check_id(nonce_account.get_owner()) {
477                return Err(InstructionError::InvalidAccountOwner);
478            }
479            if !nonce_account.is_writable() {
480                return Err(InstructionError::InvalidArgument);
481            }
482            let nonce_versions: nonce::versions::Versions = nonce_account.get_state()?;
483            match nonce_versions.upgrade() {
484                None => Err(InstructionError::InvalidArgument),
485                Some(nonce_versions) => nonce_account.set_state(&nonce_versions),
486            }
487        }
488        SystemInstruction::Allocate { space } => {
489            instruction_context.check_number_of_instruction_accounts(1)?;
490            let mut account = instruction_context.try_borrow_instruction_account(0)?;
491            let address = Address::create(
492                instruction_context.get_key_of_instruction_account(0)?,
493                None,
494                invoke_context,
495            )?;
496            allocate(&mut account, &address, space, &signers, invoke_context)
497        }
498        SystemInstruction::AllocateWithSeed {
499            base,
500            seed,
501            space,
502            owner,
503        } => {
504            instruction_context.check_number_of_instruction_accounts(1)?;
505            let mut account = instruction_context.try_borrow_instruction_account(0)?;
506            let address = Address::create(
507                instruction_context.get_key_of_instruction_account(0)?,
508                Some((&base, &seed, &owner)),
509                invoke_context,
510            )?;
511            allocate_and_assign(
512                &mut account,
513                &address,
514                space,
515                &owner,
516                &signers,
517                invoke_context,
518            )
519        }
520        SystemInstruction::AssignWithSeed { base, seed, owner } => {
521            instruction_context.check_number_of_instruction_accounts(1)?;
522            let mut account = instruction_context.try_borrow_instruction_account(0)?;
523            let address = Address::create(
524                instruction_context.get_key_of_instruction_account(0)?,
525                Some((&base, &seed, &owner)),
526                invoke_context,
527            )?;
528            assign(&mut account, &address, &owner, &signers, invoke_context)
529        }
530        SystemInstruction::CreateAccountAllowPrefund {
531            lamports,
532            space,
533            owner,
534        } => {
535            if !invoke_context
536                .get_feature_set()
537                .create_account_allow_prefund
538            {
539                return Err(InstructionError::InvalidInstructionData);
540            }
541            let from_and_lamports = if lamports > 0 {
542                instruction_context.check_number_of_instruction_accounts(2)?;
543                Some((1, lamports))
544            } else {
545                instruction_context.check_number_of_instruction_accounts(1)?;
546                None
547            };
548            let to_address = Address::create(
549                instruction_context.get_key_of_instruction_account(0)?,
550                None,
551                invoke_context,
552            )?;
553            create_account_allow_prefund(
554                0,
555                &to_address,
556                from_and_lamports,
557                space,
558                &owner,
559                &signers,
560                invoke_context,
561                &instruction_context,
562            )
563        }
564    }
565});
566
567#[cfg(test)]
568mod tests {
569    use {
570        super::*,
571        bincode::serialize,
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    };
579    #[allow(deprecated)]
580    use {
581        solana_account::{
582            self as account, Account, AccountSharedData, DUMMY_INHERITABLE_ACCOUNT_FIELDS,
583            ReadableAccount, create_account_shared_data_with_fields, to_account,
584        },
585        solana_fee_calculator::FeeCalculator,
586        solana_hash::Hash,
587        solana_instruction::{AccountMeta, Instruction, error::InstructionError},
588        solana_nonce::{
589            self as nonce,
590            state::{Data as NonceData, DurableNonce, State as NonceState},
591            versions::Versions as NonceVersions,
592        },
593        solana_nonce_account as nonce_account,
594        solana_sha256_hasher::hash,
595        solana_system_interface::{instruction as system_instruction, program as system_program},
596        solana_sysvar::{
597            self as sysvar,
598            recent_blockhashes::{IntoIterSorted, IterItem, MAX_ENTRIES, RecentBlockhashes},
599            rent::Rent,
600        },
601    };
602
603    impl From<Pubkey> for Address {
604        fn from(address: Pubkey) -> Self {
605            Self {
606                address,
607                base: None,
608            }
609        }
610    }
611
612    fn process_instruction(
613        instruction_data: &[u8],
614        transaction_accounts: Vec<(Pubkey, AccountSharedData)>,
615        instruction_accounts: Vec<AccountMeta>,
616        expected_result: Result<(), InstructionError>,
617    ) -> Vec<AccountSharedData> {
618        mock_process_instruction(
619            &system_program::id(),
620            instruction_data,
621            transaction_accounts,
622            instruction_accounts,
623            expected_result,
624            Entrypoint::register,
625            |_invoke_context| {},
626            |_invoke_context| {},
627        )
628    }
629
630    fn create_default_account() -> AccountSharedData {
631        AccountSharedData::new(0, 0, &Pubkey::new_unique())
632    }
633    #[allow(deprecated)]
634    fn create_recent_blockhashes_account_for_test<'a, I>(
635        recent_blockhash_iter: I,
636    ) -> AccountSharedData
637    where
638        I: IntoIterator<Item = IterItem<'a>>,
639    {
640        let mut account = create_account_shared_data_with_fields::<RecentBlockhashes>(
641            &RecentBlockhashes::default(),
642            DUMMY_INHERITABLE_ACCOUNT_FIELDS,
643        );
644        let sorted = BinaryHeap::from_iter(recent_blockhash_iter);
645        let sorted_iter = IntoIterSorted::new(sorted);
646        let recent_blockhash_iter = sorted_iter.take(MAX_ENTRIES);
647        let recent_blockhashes: RecentBlockhashes = recent_blockhash_iter.collect();
648        to_account(&recent_blockhashes, &mut account);
649        account
650    }
651    fn create_default_recent_blockhashes_account() -> AccountSharedData {
652        #[allow(deprecated)]
653        create_recent_blockhashes_account_for_test(vec![
654            IterItem(0u64, &Hash::default(), 0);
655            sysvar::recent_blockhashes::MAX_ENTRIES
656        ])
657    }
658    fn create_default_rent_account() -> AccountSharedData {
659        account::create_account_shared_data_for_test(&Rent::free())
660    }
661
662    #[test]
663    fn test_create_account() {
664        let new_owner = Pubkey::from([9; 32]);
665        let from = Pubkey::new_unique();
666        let to = Pubkey::new_unique();
667        let from_account = AccountSharedData::new(100, 0, &system_program::id());
668        let to_account = AccountSharedData::new(0, 0, &Pubkey::default());
669
670        let accounts = process_instruction(
671            &bincode::serialize(&SystemInstruction::CreateAccount {
672                lamports: 50,
673                space: 2,
674                owner: new_owner,
675            })
676            .unwrap(),
677            vec![(from, from_account), (to, to_account)],
678            vec![
679                AccountMeta {
680                    pubkey: from,
681                    is_signer: true,
682                    is_writable: true,
683                },
684                AccountMeta {
685                    pubkey: to,
686                    is_signer: true,
687                    is_writable: true,
688                },
689            ],
690            Ok(()),
691        );
692        assert_eq!(accounts[0].lamports(), 50);
693        assert_eq!(accounts[1].lamports(), 50);
694        assert_eq!(accounts[1].owner(), &new_owner);
695        assert_eq!(accounts[1].data(), &[0, 0]);
696    }
697
698    #[test]
699    fn test_create_account_with_seed() {
700        let new_owner = Pubkey::from([9; 32]);
701        let from = Pubkey::new_unique();
702        let seed = "shiny pepper";
703        let to = Pubkey::create_with_seed(&from, seed, &new_owner).unwrap();
704        let from_account = AccountSharedData::new(100, 0, &system_program::id());
705        let to_account = AccountSharedData::new(0, 0, &Pubkey::default());
706
707        let accounts = process_instruction(
708            &bincode::serialize(&SystemInstruction::CreateAccountWithSeed {
709                base: from,
710                seed: seed.to_string(),
711                lamports: 50,
712                space: 2,
713                owner: new_owner,
714            })
715            .unwrap(),
716            vec![(from, from_account), (to, to_account)],
717            vec![
718                AccountMeta {
719                    pubkey: from,
720                    is_signer: true,
721                    is_writable: true,
722                },
723                AccountMeta {
724                    pubkey: to,
725                    is_signer: true,
726                    is_writable: true,
727                },
728            ],
729            Ok(()),
730        );
731        assert_eq!(accounts[0].lamports(), 50);
732        assert_eq!(accounts[1].lamports(), 50);
733        assert_eq!(accounts[1].owner(), &new_owner);
734        assert_eq!(accounts[1].data(), &[0, 0]);
735    }
736
737    #[test]
738    fn test_create_account_with_seed_separate_base_account() {
739        let new_owner = Pubkey::from([9; 32]);
740        let from = Pubkey::new_unique();
741        let base = Pubkey::new_unique();
742        let seed = "shiny pepper";
743        let to = Pubkey::create_with_seed(&base, seed, &new_owner).unwrap();
744        let from_account = AccountSharedData::new(100, 0, &system_program::id());
745        let to_account = AccountSharedData::new(0, 0, &Pubkey::default());
746        let base_account = AccountSharedData::new(0, 0, &Pubkey::default());
747
748        let accounts = process_instruction(
749            &bincode::serialize(&SystemInstruction::CreateAccountWithSeed {
750                base,
751                seed: seed.to_string(),
752                lamports: 50,
753                space: 2,
754                owner: new_owner,
755            })
756            .unwrap(),
757            vec![(from, from_account), (to, to_account), (base, base_account)],
758            vec![
759                AccountMeta {
760                    pubkey: from,
761                    is_signer: true,
762                    is_writable: true,
763                },
764                AccountMeta {
765                    pubkey: to,
766                    is_signer: false,
767                    is_writable: true,
768                },
769                AccountMeta {
770                    pubkey: base,
771                    is_signer: true,
772                    is_writable: false,
773                },
774            ],
775            Ok(()),
776        );
777        assert_eq!(accounts[0].lamports(), 50);
778        assert_eq!(accounts[1].lamports(), 50);
779        assert_eq!(accounts[1].owner(), &new_owner);
780        assert_eq!(accounts[1].data(), &[0, 0]);
781    }
782
783    #[test]
784    fn test_address_create_with_seed_mismatch() {
785        with_mock_invoke_context!(invoke_context, transaction_context, Vec::new());
786        let from = Pubkey::new_unique();
787        let seed = "dull boy";
788        let to = Pubkey::new_unique();
789        let owner = Pubkey::new_unique();
790
791        assert_eq!(
792            Address::create(&to, Some((&from, seed, &owner)), &invoke_context),
793            Err(SystemError::AddressWithSeedMismatch.into())
794        );
795    }
796
797    #[test]
798    fn test_create_account_with_seed_missing_sig() {
799        let new_owner = Pubkey::from([9; 32]);
800        let from = Pubkey::new_unique();
801        let seed = "dull boy";
802        let to = Pubkey::create_with_seed(&from, seed, &new_owner).unwrap();
803        let from_account = AccountSharedData::new(100, 0, &system_program::id());
804        let to_account = AccountSharedData::new(0, 0, &Pubkey::default());
805
806        let accounts = process_instruction(
807            &bincode::serialize(&SystemInstruction::CreateAccount {
808                lamports: 50,
809                space: 2,
810                owner: new_owner,
811            })
812            .unwrap(),
813            vec![(from, from_account), (to, to_account)],
814            vec![
815                AccountMeta {
816                    pubkey: from,
817                    is_signer: true,
818                    is_writable: false,
819                },
820                AccountMeta {
821                    pubkey: to,
822                    is_signer: false,
823                    is_writable: false,
824                },
825            ],
826            Err(InstructionError::MissingRequiredSignature),
827        );
828        assert_eq!(accounts[0].lamports(), 100);
829        assert_eq!(accounts[1], AccountSharedData::default());
830    }
831
832    #[test]
833    fn test_create_with_zero_lamports() {
834        // create account with zero lamports transferred
835        let new_owner = Pubkey::from([9; 32]);
836        let from = Pubkey::new_unique();
837        let from_account = AccountSharedData::new(100, 0, &Pubkey::new_unique()); // not from system account
838        let to = Pubkey::new_unique();
839        let to_account = AccountSharedData::new(0, 0, &Pubkey::default());
840
841        let accounts = process_instruction(
842            &bincode::serialize(&SystemInstruction::CreateAccount {
843                lamports: 0,
844                space: 2,
845                owner: new_owner,
846            })
847            .unwrap(),
848            vec![(from, from_account), (to, to_account)],
849            vec![
850                AccountMeta {
851                    pubkey: from,
852                    is_signer: true,
853                    is_writable: true,
854                },
855                AccountMeta {
856                    pubkey: to,
857                    is_signer: true,
858                    is_writable: true,
859                },
860            ],
861            Ok(()),
862        );
863        assert_eq!(accounts[0].lamports(), 100);
864        assert_eq!(accounts[1].lamports(), 0);
865        assert_eq!(*accounts[1].owner(), new_owner);
866        assert_eq!(accounts[1].data(), &[0, 0]);
867    }
868
869    #[test]
870    fn test_create_negative_lamports() {
871        // Attempt to create account with more lamports than from_account has
872        let new_owner = Pubkey::from([9; 32]);
873        let from = Pubkey::new_unique();
874        let from_account = AccountSharedData::new(100, 0, &Pubkey::new_unique());
875        let to = Pubkey::new_unique();
876        let to_account = AccountSharedData::new(0, 0, &Pubkey::default());
877
878        process_instruction(
879            &bincode::serialize(&SystemInstruction::CreateAccount {
880                lamports: 150,
881                space: 2,
882                owner: new_owner,
883            })
884            .unwrap(),
885            vec![(from, from_account), (to, to_account)],
886            vec![
887                AccountMeta {
888                    pubkey: from,
889                    is_signer: true,
890                    is_writable: true,
891                },
892                AccountMeta {
893                    pubkey: to,
894                    is_signer: true,
895                    is_writable: true,
896                },
897            ],
898            Err(SystemError::ResultWithNegativeLamports.into()),
899        );
900    }
901
902    #[test]
903    fn test_request_more_than_allowed_data_length() {
904        let from = Pubkey::new_unique();
905        let from_account = AccountSharedData::new(100, 0, &system_program::id());
906        let to = Pubkey::new_unique();
907        let to_account = AccountSharedData::new(0, 0, &Pubkey::default());
908        let instruction_accounts = vec![
909            AccountMeta {
910                pubkey: from,
911                is_signer: true,
912                is_writable: true,
913            },
914            AccountMeta {
915                pubkey: to,
916                is_signer: true,
917                is_writable: true,
918            },
919        ];
920
921        // Trying to request more data length than permitted will result in failure
922        process_instruction(
923            &bincode::serialize(&SystemInstruction::CreateAccount {
924                lamports: 50,
925                space: MAX_PERMITTED_DATA_LENGTH + 1,
926                owner: system_program::id(),
927            })
928            .unwrap(),
929            vec![(from, from_account.clone()), (to, to_account.clone())],
930            instruction_accounts.clone(),
931            Err(SystemError::InvalidAccountDataLength.into()),
932        );
933
934        // Trying to request equal or less data length than permitted will be successful
935        let accounts = process_instruction(
936            &bincode::serialize(&SystemInstruction::CreateAccount {
937                lamports: 50,
938                space: MAX_PERMITTED_DATA_LENGTH,
939                owner: system_program::id(),
940            })
941            .unwrap(),
942            vec![(from, from_account), (to, to_account)],
943            instruction_accounts,
944            Ok(()),
945        );
946        assert_eq!(accounts[1].lamports(), 50);
947        assert_eq!(accounts[1].data().len() as u64, MAX_PERMITTED_DATA_LENGTH);
948    }
949
950    #[test]
951    fn test_create_already_in_use() {
952        let new_owner = Pubkey::from([9; 32]);
953        let from = Pubkey::new_unique();
954        let from_account = AccountSharedData::new(100, 0, &system_program::id());
955        let owned_key = Pubkey::new_unique();
956
957        // Attempt to create system account in account already owned by another program
958        let original_program_owner = Pubkey::from([5; 32]);
959        let owned_account = AccountSharedData::new(0, 0, &original_program_owner);
960        let unchanged_account = owned_account.clone();
961        let accounts = process_instruction(
962            &bincode::serialize(&SystemInstruction::CreateAccount {
963                lamports: 50,
964                space: 2,
965                owner: new_owner,
966            })
967            .unwrap(),
968            vec![(from, from_account.clone()), (owned_key, owned_account)],
969            vec![
970                AccountMeta {
971                    pubkey: from,
972                    is_signer: true,
973                    is_writable: false,
974                },
975                AccountMeta {
976                    pubkey: owned_key,
977                    is_signer: true,
978                    is_writable: false,
979                },
980            ],
981            Err(SystemError::AccountAlreadyInUse.into()),
982        );
983        assert_eq!(accounts[0].lamports(), 100);
984        assert_eq!(accounts[1], unchanged_account);
985
986        // Attempt to create system account in account that already has data
987        let owned_account = AccountSharedData::new(0, 1, &Pubkey::default());
988        let unchanged_account = owned_account.clone();
989        let accounts = process_instruction(
990            &bincode::serialize(&SystemInstruction::CreateAccount {
991                lamports: 50,
992                space: 2,
993                owner: new_owner,
994            })
995            .unwrap(),
996            vec![(from, from_account.clone()), (owned_key, owned_account)],
997            vec![
998                AccountMeta {
999                    pubkey: from,
1000                    is_signer: true,
1001                    is_writable: false,
1002                },
1003                AccountMeta {
1004                    pubkey: owned_key,
1005                    is_signer: true,
1006                    is_writable: false,
1007                },
1008            ],
1009            Err(SystemError::AccountAlreadyInUse.into()),
1010        );
1011        assert_eq!(accounts[0].lamports(), 100);
1012        assert_eq!(accounts[1], unchanged_account);
1013
1014        // Attempt to create an account that already has lamports
1015        let owned_account = AccountSharedData::new(1, 0, &Pubkey::default());
1016        let unchanged_account = owned_account.clone();
1017        let accounts = process_instruction(
1018            &bincode::serialize(&SystemInstruction::CreateAccount {
1019                lamports: 50,
1020                space: 2,
1021                owner: new_owner,
1022            })
1023            .unwrap(),
1024            vec![(from, from_account), (owned_key, owned_account)],
1025            vec![
1026                AccountMeta {
1027                    pubkey: from,
1028                    is_signer: true,
1029                    is_writable: false,
1030                },
1031                AccountMeta {
1032                    pubkey: owned_key,
1033                    is_signer: true,
1034                    is_writable: false,
1035                },
1036            ],
1037            Err(SystemError::AccountAlreadyInUse.into()),
1038        );
1039        assert_eq!(accounts[0].lamports(), 100);
1040        assert_eq!(accounts[1], unchanged_account);
1041    }
1042
1043    #[test]
1044    fn test_create_unsigned() {
1045        // Attempt to create an account without signing the transfer
1046        let new_owner = Pubkey::from([9; 32]);
1047        let from = Pubkey::new_unique();
1048        let from_account = AccountSharedData::new(100, 0, &system_program::id());
1049        let owned_key = Pubkey::new_unique();
1050        let owned_account = AccountSharedData::new(0, 0, &Pubkey::default());
1051
1052        // Haven't signed from account
1053        process_instruction(
1054            &bincode::serialize(&SystemInstruction::CreateAccount {
1055                lamports: 50,
1056                space: 2,
1057                owner: new_owner,
1058            })
1059            .unwrap(),
1060            vec![
1061                (from, from_account.clone()),
1062                (owned_key, owned_account.clone()),
1063            ],
1064            vec![
1065                AccountMeta {
1066                    pubkey: from,
1067                    is_signer: false,
1068                    is_writable: false,
1069                },
1070                AccountMeta {
1071                    pubkey: owned_key,
1072                    is_signer: false,
1073                    is_writable: false,
1074                },
1075            ],
1076            Err(InstructionError::MissingRequiredSignature),
1077        );
1078
1079        // Haven't signed to account
1080        process_instruction(
1081            &bincode::serialize(&SystemInstruction::CreateAccount {
1082                lamports: 50,
1083                space: 2,
1084                owner: new_owner,
1085            })
1086            .unwrap(),
1087            vec![(from, from_account.clone()), (owned_key, owned_account)],
1088            vec![
1089                AccountMeta {
1090                    pubkey: from,
1091                    is_signer: true,
1092                    is_writable: false,
1093                },
1094                AccountMeta {
1095                    pubkey: owned_key,
1096                    is_signer: false,
1097                    is_writable: false,
1098                },
1099            ],
1100            Err(InstructionError::MissingRequiredSignature),
1101        );
1102
1103        // Don't support unsigned creation with zero lamports (ephemeral account)
1104        let owned_account = AccountSharedData::new(0, 0, &Pubkey::default());
1105        process_instruction(
1106            &bincode::serialize(&SystemInstruction::CreateAccount {
1107                lamports: 50,
1108                space: 2,
1109                owner: new_owner,
1110            })
1111            .unwrap(),
1112            vec![(from, from_account), (owned_key, owned_account)],
1113            vec![
1114                AccountMeta {
1115                    pubkey: from,
1116                    is_signer: false,
1117                    is_writable: false,
1118                },
1119                AccountMeta {
1120                    pubkey: owned_key,
1121                    is_signer: false,
1122                    is_writable: false,
1123                },
1124            ],
1125            Err(InstructionError::MissingRequiredSignature),
1126        );
1127    }
1128
1129    #[test]
1130    fn test_create_sysvar_invalid_id_with_feature() {
1131        // Attempt to create system account in account already owned by another program
1132        let from = Pubkey::new_unique();
1133        let from_account = AccountSharedData::new(100, 0, &system_program::id());
1134        let to = Pubkey::new_unique();
1135        let to_account = AccountSharedData::new(0, 0, &system_program::id());
1136
1137        // fail to create a sysvar::id() owned account
1138        process_instruction(
1139            &bincode::serialize(&SystemInstruction::CreateAccount {
1140                lamports: 50,
1141                space: 2,
1142                owner: solana_sdk_ids::sysvar::id(),
1143            })
1144            .unwrap(),
1145            vec![(from, from_account), (to, to_account)],
1146            vec![
1147                AccountMeta {
1148                    pubkey: from,
1149                    is_signer: true,
1150                    is_writable: true,
1151                },
1152                AccountMeta {
1153                    pubkey: to,
1154                    is_signer: true,
1155                    is_writable: true,
1156                },
1157            ],
1158            Ok(()),
1159        );
1160    }
1161
1162    #[test]
1163    fn test_create_data_populated() {
1164        // Attempt to create system account in account with populated data
1165        let new_owner = Pubkey::from([9; 32]);
1166        let from = Pubkey::new_unique();
1167        let from_account = AccountSharedData::new(100, 0, &system_program::id());
1168        let populated_key = Pubkey::new_unique();
1169        let populated_account = AccountSharedData::from(Account {
1170            data: vec![0, 1, 2, 3],
1171            ..Account::default()
1172        });
1173
1174        process_instruction(
1175            &bincode::serialize(&SystemInstruction::CreateAccount {
1176                lamports: 50,
1177                space: 2,
1178                owner: new_owner,
1179            })
1180            .unwrap(),
1181            vec![(from, from_account), (populated_key, populated_account)],
1182            vec![
1183                AccountMeta {
1184                    pubkey: from,
1185                    is_signer: true,
1186                    is_writable: false,
1187                },
1188                AccountMeta {
1189                    pubkey: populated_key,
1190                    is_signer: true,
1191                    is_writable: false,
1192                },
1193            ],
1194            Err(SystemError::AccountAlreadyInUse.into()),
1195        );
1196    }
1197
1198    #[test]
1199    fn test_create_from_account_is_nonce_fail() {
1200        let nonce = Pubkey::new_unique();
1201        let nonce_account = AccountSharedData::new_data(
1202            42,
1203            &nonce::versions::Versions::new(nonce::state::State::Initialized(
1204                nonce::state::Data::default(),
1205            )),
1206            &system_program::id(),
1207        )
1208        .unwrap();
1209        let new = Pubkey::new_unique();
1210        let new_account = AccountSharedData::new(0, 0, &system_program::id());
1211
1212        process_instruction(
1213            &bincode::serialize(&SystemInstruction::CreateAccount {
1214                lamports: 42,
1215                space: 0,
1216                owner: Pubkey::new_unique(),
1217            })
1218            .unwrap(),
1219            vec![(nonce, nonce_account), (new, new_account)],
1220            vec![
1221                AccountMeta {
1222                    pubkey: nonce,
1223                    is_signer: true,
1224                    is_writable: false,
1225                },
1226                AccountMeta {
1227                    pubkey: new,
1228                    is_signer: true,
1229                    is_writable: true,
1230                },
1231            ],
1232            Err(InstructionError::InvalidArgument),
1233        );
1234    }
1235
1236    #[test]
1237    fn test_assign() {
1238        let new_owner = Pubkey::from([9; 32]);
1239        let pubkey = Pubkey::new_unique();
1240        let account = AccountSharedData::new(100, 0, &system_program::id());
1241
1242        // owner does not change, no signature needed
1243        process_instruction(
1244            &bincode::serialize(&SystemInstruction::Assign {
1245                owner: system_program::id(),
1246            })
1247            .unwrap(),
1248            vec![(pubkey, account.clone())],
1249            vec![AccountMeta {
1250                pubkey,
1251                is_signer: false,
1252                is_writable: true,
1253            }],
1254            Ok(()),
1255        );
1256
1257        // owner does change, signature needed
1258        process_instruction(
1259            &bincode::serialize(&SystemInstruction::Assign { owner: new_owner }).unwrap(),
1260            vec![(pubkey, account.clone())],
1261            vec![AccountMeta {
1262                pubkey,
1263                is_signer: false,
1264                is_writable: true,
1265            }],
1266            Err(InstructionError::MissingRequiredSignature),
1267        );
1268
1269        process_instruction(
1270            &bincode::serialize(&SystemInstruction::Assign { owner: new_owner }).unwrap(),
1271            vec![(pubkey, account.clone())],
1272            vec![AccountMeta {
1273                pubkey,
1274                is_signer: true,
1275                is_writable: true,
1276            }],
1277            Ok(()),
1278        );
1279
1280        // assign to sysvar instead of system_program
1281        process_instruction(
1282            &bincode::serialize(&SystemInstruction::Assign {
1283                owner: solana_sdk_ids::sysvar::id(),
1284            })
1285            .unwrap(),
1286            vec![(pubkey, account)],
1287            vec![AccountMeta {
1288                pubkey,
1289                is_signer: true,
1290                is_writable: true,
1291            }],
1292            Ok(()),
1293        );
1294    }
1295
1296    #[test]
1297    fn test_process_bogus_instruction() {
1298        // Attempt to assign with no accounts
1299        let instruction = SystemInstruction::Assign {
1300            owner: Pubkey::new_unique(),
1301        };
1302        let data = serialize(&instruction).unwrap();
1303        process_instruction(
1304            &data,
1305            Vec::new(),
1306            Vec::new(),
1307            Err(InstructionError::MissingAccount),
1308        );
1309
1310        // Attempt to transfer with no destination
1311        let from = Pubkey::new_unique();
1312        let from_account = AccountSharedData::new(100, 0, &system_program::id());
1313        let instruction = SystemInstruction::Transfer { lamports: 0 };
1314        let data = serialize(&instruction).unwrap();
1315        process_instruction(
1316            &data,
1317            vec![(from, from_account)],
1318            vec![AccountMeta {
1319                pubkey: from,
1320                is_signer: true,
1321                is_writable: false,
1322            }],
1323            Err(InstructionError::MissingAccount),
1324        );
1325    }
1326
1327    #[test]
1328    fn test_transfer_lamports() {
1329        let from = Pubkey::new_unique();
1330        let from_account = AccountSharedData::new(100, 0, &system_program::id());
1331        let to = Pubkey::from([3; 32]);
1332        let to_account = AccountSharedData::new(1, 0, &to); // account owner should not matter
1333        let transaction_accounts = vec![(from, from_account), (to, to_account)];
1334        let instruction_accounts = vec![
1335            AccountMeta {
1336                pubkey: from,
1337                is_signer: true,
1338                is_writable: true,
1339            },
1340            AccountMeta {
1341                pubkey: to,
1342                is_signer: false,
1343                is_writable: true,
1344            },
1345        ];
1346
1347        // Success case
1348        let accounts = process_instruction(
1349            &bincode::serialize(&SystemInstruction::Transfer { lamports: 50 }).unwrap(),
1350            transaction_accounts.clone(),
1351            instruction_accounts.clone(),
1352            Ok(()),
1353        );
1354        assert_eq!(accounts[0].lamports(), 50);
1355        assert_eq!(accounts[1].lamports(), 51);
1356
1357        // Attempt to move more lamports than from_account has
1358        let accounts = process_instruction(
1359            &bincode::serialize(&SystemInstruction::Transfer { lamports: 101 }).unwrap(),
1360            transaction_accounts.clone(),
1361            instruction_accounts.clone(),
1362            Err(SystemError::ResultWithNegativeLamports.into()),
1363        );
1364        assert_eq!(accounts[0].lamports(), 100);
1365        assert_eq!(accounts[1].lamports(), 1);
1366
1367        // test signed transfer of zero
1368        let accounts = process_instruction(
1369            &bincode::serialize(&SystemInstruction::Transfer { lamports: 0 }).unwrap(),
1370            transaction_accounts.clone(),
1371            instruction_accounts,
1372            Ok(()),
1373        );
1374        assert_eq!(accounts[0].lamports(), 100);
1375        assert_eq!(accounts[1].lamports(), 1);
1376
1377        // test unsigned transfer of zero
1378        let accounts = process_instruction(
1379            &bincode::serialize(&SystemInstruction::Transfer { lamports: 0 }).unwrap(),
1380            transaction_accounts,
1381            vec![
1382                AccountMeta {
1383                    pubkey: from,
1384                    is_signer: false,
1385                    is_writable: true,
1386                },
1387                AccountMeta {
1388                    pubkey: to,
1389                    is_signer: false,
1390                    is_writable: true,
1391                },
1392            ],
1393            Err(InstructionError::MissingRequiredSignature),
1394        );
1395        assert_eq!(accounts[0].lamports(), 100);
1396        assert_eq!(accounts[1].lamports(), 1);
1397    }
1398
1399    #[test]
1400    fn test_transfer_with_seed() {
1401        let base = Pubkey::new_unique();
1402        let base_account = AccountSharedData::new(100, 0, &Pubkey::from([2; 32])); // account owner should not matter
1403        let from_seed = "42".to_string();
1404        let from_owner = system_program::id();
1405        let from = Pubkey::create_with_seed(&base, from_seed.as_str(), &from_owner).unwrap();
1406        let from_account = AccountSharedData::new(100, 0, &system_program::id());
1407        let to = Pubkey::from([3; 32]);
1408        let to_account = AccountSharedData::new(1, 0, &to); // account owner should not matter
1409        let transaction_accounts =
1410            vec![(from, from_account), (base, base_account), (to, to_account)];
1411        let instruction_accounts = vec![
1412            AccountMeta {
1413                pubkey: from,
1414                is_signer: true,
1415                is_writable: true,
1416            },
1417            AccountMeta {
1418                pubkey: base,
1419                is_signer: true,
1420                is_writable: false,
1421            },
1422            AccountMeta {
1423                pubkey: to,
1424                is_signer: false,
1425                is_writable: true,
1426            },
1427        ];
1428
1429        // Success case
1430        let accounts = process_instruction(
1431            &bincode::serialize(&SystemInstruction::TransferWithSeed {
1432                lamports: 50,
1433                from_seed: from_seed.clone(),
1434                from_owner,
1435            })
1436            .unwrap(),
1437            transaction_accounts.clone(),
1438            instruction_accounts.clone(),
1439            Ok(()),
1440        );
1441        assert_eq!(accounts[0].lamports(), 50);
1442        assert_eq!(accounts[2].lamports(), 51);
1443
1444        // Attempt to move more lamports than from_account has
1445        let accounts = process_instruction(
1446            &bincode::serialize(&SystemInstruction::TransferWithSeed {
1447                lamports: 101,
1448                from_seed: from_seed.clone(),
1449                from_owner,
1450            })
1451            .unwrap(),
1452            transaction_accounts.clone(),
1453            instruction_accounts.clone(),
1454            Err(SystemError::ResultWithNegativeLamports.into()),
1455        );
1456        assert_eq!(accounts[0].lamports(), 100);
1457        assert_eq!(accounts[2].lamports(), 1);
1458
1459        // Test unsigned transfer of zero
1460        let accounts = process_instruction(
1461            &bincode::serialize(&SystemInstruction::TransferWithSeed {
1462                lamports: 0,
1463                from_seed,
1464                from_owner,
1465            })
1466            .unwrap(),
1467            transaction_accounts,
1468            instruction_accounts,
1469            Ok(()),
1470        );
1471        assert_eq!(accounts[0].lamports(), 100);
1472        assert_eq!(accounts[2].lamports(), 1);
1473    }
1474
1475    #[test]
1476    fn test_transfer_lamports_from_nonce_account_fail() {
1477        let from = Pubkey::new_unique();
1478        let from_account = AccountSharedData::new_data(
1479            100,
1480            &nonce::versions::Versions::new(nonce::state::State::Initialized(nonce::state::Data {
1481                authority: from,
1482                ..nonce::state::Data::default()
1483            })),
1484            &system_program::id(),
1485        )
1486        .unwrap();
1487        assert_eq!(
1488            get_system_account_kind(&from_account),
1489            Some(SystemAccountKind::Nonce)
1490        );
1491        let to = Pubkey::from([3; 32]);
1492        let to_account = AccountSharedData::new(1, 0, &to); // account owner should not matter
1493
1494        process_instruction(
1495            &bincode::serialize(&SystemInstruction::Transfer { lamports: 50 }).unwrap(),
1496            vec![(from, from_account), (to, to_account)],
1497            vec![
1498                AccountMeta {
1499                    pubkey: from,
1500                    is_signer: true,
1501                    is_writable: false,
1502                },
1503                AccountMeta {
1504                    pubkey: to,
1505                    is_signer: false,
1506                    is_writable: false,
1507                },
1508            ],
1509            Err(InstructionError::InvalidArgument),
1510        );
1511    }
1512
1513    fn process_nonce_instruction(
1514        instruction: Instruction,
1515        expected_result: Result<(), InstructionError>,
1516    ) -> Vec<AccountSharedData> {
1517        let transaction_accounts = instruction
1518            .accounts
1519            .iter()
1520            .map(|meta| {
1521                #[allow(deprecated)]
1522                (
1523                    meta.pubkey,
1524                    if sysvar::recent_blockhashes::check_id(&meta.pubkey) {
1525                        create_default_recent_blockhashes_account()
1526                    } else if sysvar::rent::check_id(&meta.pubkey) {
1527                        account::create_account_shared_data_for_test(&Rent::free())
1528                    } else {
1529                        AccountSharedData::new(0, 0, &Pubkey::new_unique())
1530                    },
1531                )
1532            })
1533            .collect();
1534        process_instruction(
1535            &instruction.data,
1536            transaction_accounts,
1537            instruction.accounts,
1538            expected_result,
1539        )
1540    }
1541
1542    #[test]
1543    fn test_process_nonce_ix_no_acc_data_fail() {
1544        let none_address = Pubkey::new_unique();
1545        process_nonce_instruction(
1546            system_instruction::advance_nonce_account(&none_address, &none_address),
1547            Err(InstructionError::InvalidAccountData),
1548        );
1549    }
1550
1551    #[test]
1552    fn test_process_nonce_ix_no_keyed_accs_fail() {
1553        process_instruction(
1554            &serialize(&SystemInstruction::AdvanceNonceAccount).unwrap(),
1555            Vec::new(),
1556            Vec::new(),
1557            Err(InstructionError::MissingAccount),
1558        );
1559    }
1560
1561    #[test]
1562    fn test_process_nonce_ix_only_nonce_acc_fail() {
1563        let pubkey = Pubkey::new_unique();
1564        process_instruction(
1565            &serialize(&SystemInstruction::AdvanceNonceAccount).unwrap(),
1566            vec![(pubkey, create_default_account())],
1567            vec![AccountMeta {
1568                pubkey,
1569                is_signer: true,
1570                is_writable: true,
1571            }],
1572            Err(InstructionError::MissingAccount),
1573        );
1574    }
1575
1576    #[test]
1577    fn test_process_nonce_ix_ok() {
1578        let nonce_address = Pubkey::new_unique();
1579        let nonce_account = nonce_account::create_account(1_000_000).into_inner();
1580        #[allow(deprecated)]
1581        let blockhash_id = sysvar::recent_blockhashes::id();
1582        let accounts = process_instruction(
1583            &serialize(&SystemInstruction::InitializeNonceAccount(nonce_address)).unwrap(),
1584            vec![
1585                (nonce_address, nonce_account),
1586                (blockhash_id, create_default_recent_blockhashes_account()),
1587                (sysvar::rent::id(), create_default_rent_account()),
1588            ],
1589            vec![
1590                AccountMeta {
1591                    pubkey: nonce_address,
1592                    is_signer: true,
1593                    is_writable: true,
1594                },
1595                AccountMeta {
1596                    pubkey: blockhash_id,
1597                    is_signer: false,
1598                    is_writable: false,
1599                },
1600                AccountMeta {
1601                    pubkey: sysvar::rent::id(),
1602                    is_signer: false,
1603                    is_writable: false,
1604                },
1605            ],
1606            Ok(()),
1607        );
1608        let blockhash = hash(&serialize(&0).unwrap());
1609        #[allow(deprecated)]
1610        let new_recent_blockhashes_account = create_recent_blockhashes_account_for_test(vec![
1611                IterItem(0u64, &blockhash, 0);
1612                sysvar::recent_blockhashes::MAX_ENTRIES
1613            ]);
1614        mock_process_instruction(
1615            &system_program::id(),
1616            &serialize(&SystemInstruction::AdvanceNonceAccount).unwrap(),
1617            vec![
1618                (nonce_address, accounts[0].clone()),
1619                (blockhash_id, new_recent_blockhashes_account),
1620            ],
1621            vec![
1622                AccountMeta {
1623                    pubkey: nonce_address,
1624                    is_signer: true,
1625                    is_writable: true,
1626                },
1627                AccountMeta {
1628                    pubkey: blockhash_id,
1629                    is_signer: false,
1630                    is_writable: false,
1631                },
1632            ],
1633            Ok(()),
1634            Entrypoint::register,
1635            |invoke_context: &mut InvokeContext| {
1636                invoke_context.environment_config.blockhash = hash(&serialize(&0).unwrap());
1637            },
1638            |_invoke_context| {},
1639        );
1640    }
1641
1642    #[test]
1643    fn test_process_withdraw_ix_no_acc_data_fail() {
1644        let nonce_address = Pubkey::new_unique();
1645        process_nonce_instruction(
1646            system_instruction::withdraw_nonce_account(
1647                &nonce_address,
1648                &Pubkey::new_unique(),
1649                &nonce_address,
1650                1,
1651            ),
1652            Err(InstructionError::InvalidAccountData),
1653        );
1654    }
1655
1656    #[test]
1657    fn test_process_withdraw_ix_no_keyed_accs_fail() {
1658        process_instruction(
1659            &serialize(&SystemInstruction::WithdrawNonceAccount(42)).unwrap(),
1660            Vec::new(),
1661            Vec::new(),
1662            Err(InstructionError::MissingAccount),
1663        );
1664    }
1665
1666    #[test]
1667    fn test_process_withdraw_ix_only_nonce_acc_fail() {
1668        let nonce_address = Pubkey::new_unique();
1669        process_instruction(
1670            &serialize(&SystemInstruction::WithdrawNonceAccount(42)).unwrap(),
1671            vec![(nonce_address, create_default_account())],
1672            vec![AccountMeta {
1673                pubkey: nonce_address,
1674                is_signer: true,
1675                is_writable: true,
1676            }],
1677            Err(InstructionError::MissingAccount),
1678        );
1679    }
1680
1681    #[test]
1682    fn test_process_withdraw_ix_ok() {
1683        let nonce_address = Pubkey::new_unique();
1684        let nonce_account = nonce_account::create_account(1_000_000).into_inner();
1685        let pubkey = Pubkey::new_unique();
1686        #[allow(deprecated)]
1687        let blockhash_id = sysvar::recent_blockhashes::id();
1688        process_instruction(
1689            &serialize(&SystemInstruction::WithdrawNonceAccount(42)).unwrap(),
1690            vec![
1691                (nonce_address, nonce_account),
1692                (pubkey, create_default_account()),
1693                (blockhash_id, create_default_recent_blockhashes_account()),
1694                (sysvar::rent::id(), create_default_rent_account()),
1695            ],
1696            vec![
1697                AccountMeta {
1698                    pubkey: nonce_address,
1699                    is_signer: true,
1700                    is_writable: true,
1701                },
1702                AccountMeta {
1703                    pubkey,
1704                    is_signer: true,
1705                    is_writable: true,
1706                },
1707                AccountMeta {
1708                    pubkey: blockhash_id,
1709                    is_signer: false,
1710                    is_writable: false,
1711                },
1712                AccountMeta {
1713                    pubkey: sysvar::rent::id(),
1714                    is_signer: false,
1715                    is_writable: false,
1716                },
1717            ],
1718            Ok(()),
1719        );
1720    }
1721
1722    #[test]
1723    fn test_process_initialize_ix_no_keyed_accs_fail() {
1724        process_instruction(
1725            &serialize(&SystemInstruction::InitializeNonceAccount(Pubkey::default())).unwrap(),
1726            Vec::new(),
1727            Vec::new(),
1728            Err(InstructionError::MissingAccount),
1729        );
1730    }
1731
1732    #[test]
1733    fn test_process_initialize_ix_only_nonce_acc_fail() {
1734        let nonce_address = Pubkey::new_unique();
1735        let nonce_account = nonce_account::create_account(1_000_000).into_inner();
1736        process_instruction(
1737            &serialize(&SystemInstruction::InitializeNonceAccount(nonce_address)).unwrap(),
1738            vec![(nonce_address, nonce_account)],
1739            vec![AccountMeta {
1740                pubkey: nonce_address,
1741                is_signer: true,
1742                is_writable: true,
1743            }],
1744            Err(InstructionError::MissingAccount),
1745        );
1746    }
1747
1748    #[test]
1749    fn test_process_initialize_ix_ok() {
1750        let nonce_address = Pubkey::new_unique();
1751        let nonce_account = nonce_account::create_account(1_000_000).into_inner();
1752        #[allow(deprecated)]
1753        let blockhash_id = sysvar::recent_blockhashes::id();
1754        process_instruction(
1755            &serialize(&SystemInstruction::InitializeNonceAccount(nonce_address)).unwrap(),
1756            vec![
1757                (nonce_address, nonce_account),
1758                (blockhash_id, create_default_recent_blockhashes_account()),
1759                (sysvar::rent::id(), create_default_rent_account()),
1760            ],
1761            vec![
1762                AccountMeta {
1763                    pubkey: nonce_address,
1764                    is_signer: true,
1765                    is_writable: true,
1766                },
1767                AccountMeta {
1768                    pubkey: blockhash_id,
1769                    is_signer: false,
1770                    is_writable: false,
1771                },
1772                AccountMeta {
1773                    pubkey: sysvar::rent::id(),
1774                    is_signer: false,
1775                    is_writable: false,
1776                },
1777            ],
1778            Ok(()),
1779        );
1780    }
1781
1782    #[test]
1783    fn test_process_authorize_ix_ok() {
1784        let nonce_address = Pubkey::new_unique();
1785        let nonce_account = nonce_account::create_account(1_000_000).into_inner();
1786        #[allow(deprecated)]
1787        let blockhash_id = sysvar::recent_blockhashes::id();
1788        let accounts = process_instruction(
1789            &serialize(&SystemInstruction::InitializeNonceAccount(nonce_address)).unwrap(),
1790            vec![
1791                (nonce_address, nonce_account),
1792                (blockhash_id, create_default_recent_blockhashes_account()),
1793                (sysvar::rent::id(), create_default_rent_account()),
1794            ],
1795            vec![
1796                AccountMeta {
1797                    pubkey: nonce_address,
1798                    is_signer: true,
1799                    is_writable: true,
1800                },
1801                AccountMeta {
1802                    pubkey: blockhash_id,
1803                    is_signer: false,
1804                    is_writable: false,
1805                },
1806                AccountMeta {
1807                    pubkey: sysvar::rent::id(),
1808                    is_signer: false,
1809                    is_writable: false,
1810                },
1811            ],
1812            Ok(()),
1813        );
1814        process_instruction(
1815            &serialize(&SystemInstruction::AuthorizeNonceAccount(nonce_address)).unwrap(),
1816            vec![(nonce_address, accounts[0].clone())],
1817            vec![AccountMeta {
1818                pubkey: nonce_address,
1819                is_signer: true,
1820                is_writable: true,
1821            }],
1822            Ok(()),
1823        );
1824    }
1825
1826    #[test]
1827    fn test_process_authorize_bad_account_data_fail() {
1828        let nonce_address = Pubkey::new_unique();
1829        process_nonce_instruction(
1830            system_instruction::authorize_nonce_account(
1831                &nonce_address,
1832                &Pubkey::new_unique(),
1833                &nonce_address,
1834            ),
1835            Err(InstructionError::InvalidAccountData),
1836        );
1837    }
1838
1839    #[test]
1840    fn test_nonce_initialize_with_empty_recent_blockhashes_fail() {
1841        let nonce_address = Pubkey::new_unique();
1842        let nonce_account = nonce_account::create_account(1_000_000).into_inner();
1843        #[allow(deprecated)]
1844        let blockhash_id = sysvar::recent_blockhashes::id();
1845        #[allow(deprecated)]
1846        let new_recent_blockhashes_account = create_recent_blockhashes_account_for_test(vec![]);
1847        process_instruction(
1848            &serialize(&SystemInstruction::InitializeNonceAccount(nonce_address)).unwrap(),
1849            vec![
1850                (nonce_address, nonce_account),
1851                (blockhash_id, new_recent_blockhashes_account),
1852                (sysvar::rent::id(), create_default_rent_account()),
1853            ],
1854            vec![
1855                AccountMeta {
1856                    pubkey: nonce_address,
1857                    is_signer: true,
1858                    is_writable: true,
1859                },
1860                AccountMeta {
1861                    pubkey: blockhash_id,
1862                    is_signer: false,
1863                    is_writable: false,
1864                },
1865                AccountMeta {
1866                    pubkey: sysvar::rent::id(),
1867                    is_signer: false,
1868                    is_writable: false,
1869                },
1870            ],
1871            Err(SystemError::NonceNoRecentBlockhashes.into()),
1872        );
1873    }
1874
1875    #[test]
1876    fn test_nonce_advance_with_empty_recent_blockhashes_fail() {
1877        let nonce_address = Pubkey::new_unique();
1878        let nonce_account = nonce_account::create_account(1_000_000).into_inner();
1879        #[allow(deprecated)]
1880        let blockhash_id = sysvar::recent_blockhashes::id();
1881        let accounts = process_instruction(
1882            &serialize(&SystemInstruction::InitializeNonceAccount(nonce_address)).unwrap(),
1883            vec![
1884                (nonce_address, nonce_account),
1885                (blockhash_id, create_default_recent_blockhashes_account()),
1886                (sysvar::rent::id(), create_default_rent_account()),
1887            ],
1888            vec![
1889                AccountMeta {
1890                    pubkey: nonce_address,
1891                    is_signer: true,
1892                    is_writable: true,
1893                },
1894                AccountMeta {
1895                    pubkey: blockhash_id,
1896                    is_signer: false,
1897                    is_writable: false,
1898                },
1899                AccountMeta {
1900                    pubkey: sysvar::rent::id(),
1901                    is_signer: false,
1902                    is_writable: false,
1903                },
1904            ],
1905            Ok(()),
1906        );
1907        #[allow(deprecated)]
1908        let new_recent_blockhashes_account = create_recent_blockhashes_account_for_test(vec![]);
1909        mock_process_instruction(
1910            &system_program::id(),
1911            &serialize(&SystemInstruction::AdvanceNonceAccount).unwrap(),
1912            vec![
1913                (nonce_address, accounts[0].clone()),
1914                (blockhash_id, new_recent_blockhashes_account),
1915            ],
1916            vec![
1917                AccountMeta {
1918                    pubkey: nonce_address,
1919                    is_signer: true,
1920                    is_writable: true,
1921                },
1922                AccountMeta {
1923                    pubkey: blockhash_id,
1924                    is_signer: false,
1925                    is_writable: false,
1926                },
1927            ],
1928            Err(SystemError::NonceNoRecentBlockhashes.into()),
1929            Entrypoint::register,
1930            |invoke_context: &mut InvokeContext| {
1931                invoke_context.environment_config.blockhash = hash(&serialize(&0).unwrap());
1932            },
1933            |_invoke_context| {},
1934        );
1935    }
1936
1937    #[test]
1938    fn test_nonce_account_upgrade_check_owner() {
1939        let nonce_address = Pubkey::new_unique();
1940        let versions = NonceVersions::Legacy(Box::new(NonceState::Uninitialized));
1941        let nonce_account = AccountSharedData::new_data(
1942            1_000_000,             // lamports
1943            &versions,             // state
1944            &Pubkey::new_unique(), // owner
1945        )
1946        .unwrap();
1947        let accounts = process_instruction(
1948            &serialize(&SystemInstruction::UpgradeNonceAccount).unwrap(),
1949            vec![(nonce_address, nonce_account.clone())],
1950            vec![AccountMeta {
1951                pubkey: nonce_address,
1952                is_signer: false,
1953                is_writable: true,
1954            }],
1955            Err(InstructionError::InvalidAccountOwner),
1956        );
1957        assert_eq!(accounts.len(), 1);
1958        assert_eq!(accounts[0], nonce_account);
1959    }
1960
1961    fn new_nonce_account(versions: NonceVersions) -> AccountSharedData {
1962        let nonce_account = AccountSharedData::new_data(
1963            1_000_000,             // lamports
1964            &versions,             // state
1965            &system_program::id(), // owner
1966        )
1967        .unwrap();
1968        assert_eq!(
1969            nonce_account.deserialize_data::<NonceVersions>().unwrap(),
1970            versions
1971        );
1972        nonce_account
1973    }
1974
1975    #[test]
1976    fn test_nonce_account_upgrade() {
1977        let nonce_address = Pubkey::new_unique();
1978        let versions = NonceVersions::Legacy(Box::new(NonceState::Uninitialized));
1979        let nonce_account = new_nonce_account(versions);
1980        let accounts = process_instruction(
1981            &serialize(&SystemInstruction::UpgradeNonceAccount).unwrap(),
1982            vec![(nonce_address, nonce_account.clone())],
1983            vec![AccountMeta {
1984                pubkey: nonce_address,
1985                is_signer: false,
1986                is_writable: true,
1987            }],
1988            Err(InstructionError::InvalidArgument),
1989        );
1990        assert_eq!(accounts.len(), 1);
1991        assert_eq!(accounts[0], nonce_account);
1992        let versions = NonceVersions::Current(Box::new(NonceState::Uninitialized));
1993        let nonce_account = new_nonce_account(versions);
1994        let accounts = process_instruction(
1995            &serialize(&SystemInstruction::UpgradeNonceAccount).unwrap(),
1996            vec![(nonce_address, nonce_account.clone())],
1997            vec![AccountMeta {
1998                pubkey: nonce_address,
1999                is_signer: false,
2000                is_writable: true,
2001            }],
2002            Err(InstructionError::InvalidArgument),
2003        );
2004        assert_eq!(accounts.len(), 1);
2005        assert_eq!(accounts[0], nonce_account);
2006        let blockhash = Hash::from([171; 32]);
2007        let durable_nonce = DurableNonce::from_blockhash(&blockhash);
2008        let data = NonceData {
2009            authority: Pubkey::new_unique(),
2010            durable_nonce,
2011            fee_calculator: FeeCalculator {
2012                lamports_per_signature: 2718,
2013            },
2014        };
2015        let versions = NonceVersions::Legacy(Box::new(NonceState::Initialized(data.clone())));
2016        let nonce_account = new_nonce_account(versions);
2017        let accounts = process_instruction(
2018            &serialize(&SystemInstruction::UpgradeNonceAccount).unwrap(),
2019            vec![(nonce_address, nonce_account.clone())],
2020            vec![AccountMeta {
2021                pubkey: nonce_address,
2022                is_signer: false,
2023                is_writable: false, // Should fail!
2024            }],
2025            Err(InstructionError::InvalidArgument),
2026        );
2027        assert_eq!(accounts.len(), 1);
2028        assert_eq!(accounts[0], nonce_account);
2029        let mut accounts = process_instruction(
2030            &serialize(&SystemInstruction::UpgradeNonceAccount).unwrap(),
2031            vec![(nonce_address, nonce_account)],
2032            vec![AccountMeta {
2033                pubkey: nonce_address,
2034                is_signer: false,
2035                is_writable: true,
2036            }],
2037            Ok(()),
2038        );
2039        assert_eq!(accounts.len(), 1);
2040        let nonce_account = accounts.remove(0);
2041        let durable_nonce = DurableNonce::from_blockhash(durable_nonce.as_hash());
2042        assert_ne!(data.durable_nonce, durable_nonce);
2043        let data = NonceData {
2044            durable_nonce,
2045            ..data
2046        };
2047        let upgraded_nonce_account =
2048            NonceVersions::Current(Box::new(NonceState::Initialized(data)));
2049        assert_eq!(
2050            nonce_account.deserialize_data::<NonceVersions>().unwrap(),
2051            upgraded_nonce_account
2052        );
2053        let accounts = process_instruction(
2054            &serialize(&SystemInstruction::UpgradeNonceAccount).unwrap(),
2055            vec![(nonce_address, nonce_account)],
2056            vec![AccountMeta {
2057                pubkey: nonce_address,
2058                is_signer: false,
2059                is_writable: true,
2060            }],
2061            Err(InstructionError::InvalidArgument),
2062        );
2063        assert_eq!(accounts.len(), 1);
2064        assert_eq!(
2065            accounts[0].deserialize_data::<NonceVersions>().unwrap(),
2066            upgraded_nonce_account
2067        );
2068    }
2069
2070    #[test]
2071    fn test_assign_native_loader_and_transfer() {
2072        for size in [0, 10] {
2073            let pubkey = Pubkey::new_unique();
2074            let account = AccountSharedData::new(100, size, &system_program::id());
2075            let accounts = process_instruction(
2076                &bincode::serialize(&SystemInstruction::Assign {
2077                    owner: solana_sdk_ids::native_loader::id(),
2078                })
2079                .unwrap(),
2080                vec![(pubkey, account.clone())],
2081                vec![AccountMeta {
2082                    pubkey,
2083                    is_signer: true,
2084                    is_writable: true,
2085                }],
2086                Ok(()),
2087            );
2088            assert_eq!(accounts[0].owner(), &solana_sdk_ids::native_loader::id());
2089            assert_eq!(accounts[0].lamports(), 100);
2090
2091            let pubkey2 = Pubkey::new_unique();
2092            let accounts = process_instruction(
2093                &bincode::serialize(&SystemInstruction::Transfer { lamports: 50 }).unwrap(),
2094                vec![
2095                    (
2096                        pubkey2,
2097                        AccountSharedData::new(100, 0, &system_program::id()),
2098                    ),
2099                    (pubkey, accounts[0].clone()),
2100                ],
2101                vec![
2102                    AccountMeta {
2103                        pubkey: pubkey2,
2104                        is_signer: true,
2105                        is_writable: true,
2106                    },
2107                    AccountMeta {
2108                        pubkey,
2109                        is_signer: false,
2110                        is_writable: true,
2111                    },
2112                ],
2113                Ok(()),
2114            );
2115            assert_eq!(accounts[1].owner(), &solana_sdk_ids::native_loader::id());
2116            assert_eq!(accounts[1].lamports(), 150);
2117        }
2118    }
2119
2120    #[test]
2121    fn test_create_account_allow_prefund() {
2122        let new_owner = Pubkey::from([9; 32]);
2123        let to = Pubkey::new_unique();
2124        let from = Pubkey::new_unique();
2125        let ix_accounts = vec![AccountMeta::new(to, true), AccountMeta::new(from, true)];
2126
2127        // With nonzero lamports (payer transfers additional funds)
2128        let accounts = process_instruction(
2129            &bincode::serialize(&SystemInstruction::CreateAccountAllowPrefund {
2130                lamports: 50,
2131                space: 2,
2132                owner: new_owner,
2133            })
2134            .unwrap(),
2135            vec![
2136                (to, AccountSharedData::new(100, 0, &Pubkey::default())),
2137                (from, AccountSharedData::new(100, 0, &system_program::id())),
2138            ],
2139            ix_accounts,
2140            Ok(()),
2141        );
2142        assert_eq!(accounts[0].lamports(), 150);
2143        assert_eq!(accounts[0].owner(), &new_owner);
2144        assert_eq!(accounts[0].data(), &[0, 0]);
2145        assert_eq!(accounts[1].lamports(), 50);
2146
2147        // With zero lamports (account prefunded), no payer needed
2148        let accounts = process_instruction(
2149            &bincode::serialize(&SystemInstruction::CreateAccountAllowPrefund {
2150                lamports: 0,
2151                space: 2,
2152                owner: new_owner,
2153            })
2154            .unwrap(),
2155            vec![(to, AccountSharedData::new(100, 0, &Pubkey::default()))],
2156            vec![AccountMeta::new(to, true)],
2157            Ok(()),
2158        );
2159        assert_eq!(accounts[0].lamports(), 100);
2160        assert_eq!(accounts[0].owner(), &new_owner);
2161        assert_eq!(accounts[0].data(), &[0, 0]);
2162
2163        // Feature gate off - instruction rejected
2164        use solana_program_runtime::invoke_context::mock_process_instruction_with_feature_set;
2165        mock_process_instruction_with_feature_set(
2166            &system_program::id(),
2167            &bincode::serialize(&SystemInstruction::CreateAccountAllowPrefund {
2168                lamports: 50,
2169                space: 0,
2170                owner: new_owner,
2171            })
2172            .unwrap(),
2173            vec![
2174                (to, AccountSharedData::new(0, 0, &Pubkey::default())),
2175                (from, AccountSharedData::new(100, 0, &system_program::id())),
2176            ],
2177            vec![AccountMeta::new(to, true), AccountMeta::new(from, true)],
2178            Err(InstructionError::InvalidInstructionData),
2179            Entrypoint::register,
2180            |_| {},
2181            |_| {},
2182            &solana_svm_feature_set::SVMFeatureSet::default(),
2183        );
2184    }
2185
2186    #[test]
2187    fn test_create_account_allow_prefund_already_in_use() {
2188        let new_owner = Pubkey::from([9; 32]);
2189        let to = Pubkey::new_unique();
2190        let from = Pubkey::new_unique();
2191        let from_account = AccountSharedData::new(100, 0, &system_program::id());
2192        let ix_data = bincode::serialize(&SystemInstruction::CreateAccountAllowPrefund {
2193            lamports: 50,
2194            space: 2,
2195            owner: new_owner,
2196        })
2197        .unwrap();
2198        let ix_accounts = vec![AccountMeta::new(to, true), AccountMeta::new(from, true)];
2199
2200        // Account already has data
2201        process_instruction(
2202            &ix_data,
2203            vec![
2204                (to, AccountSharedData::new(0, 1, &Pubkey::default())),
2205                (from, from_account.clone()),
2206            ],
2207            ix_accounts.clone(),
2208            Err(SystemError::AccountAlreadyInUse.into()),
2209        );
2210
2211        // Account already owned by another program
2212        process_instruction(
2213            &ix_data,
2214            vec![
2215                (to, AccountSharedData::new(0, 0, &Pubkey::from([5; 32]))),
2216                (from, from_account),
2217            ],
2218            ix_accounts,
2219            Err(SystemError::AccountAlreadyInUse.into()),
2220        );
2221    }
2222
2223    #[test]
2224    fn test_create_account_allow_prefund_missing_signer() {
2225        let new_owner = Pubkey::from([9; 32]);
2226        let to = Pubkey::new_unique();
2227        let from = Pubkey::new_unique();
2228        let tx_accounts = vec![
2229            (to, AccountSharedData::new(0, 0, &Pubkey::default())),
2230            (from, AccountSharedData::new(100, 0, &system_program::id())),
2231        ];
2232        let ix_data = bincode::serialize(&SystemInstruction::CreateAccountAllowPrefund {
2233            lamports: 50,
2234            space: 2,
2235            owner: new_owner,
2236        })
2237        .unwrap();
2238
2239        // Payer not signed
2240        process_instruction(
2241            &ix_data,
2242            tx_accounts.clone(),
2243            vec![AccountMeta::new(to, true), AccountMeta::new(from, false)],
2244            Err(InstructionError::MissingRequiredSignature),
2245        );
2246
2247        // New account not signed
2248        process_instruction(
2249            &ix_data,
2250            tx_accounts,
2251            vec![AccountMeta::new(to, false), AccountMeta::new(from, true)],
2252            Err(InstructionError::MissingRequiredSignature),
2253        );
2254    }
2255}