diff --git a/fetch-spl.sh b/fetch-spl.sh index 3882f536c..9787bab50 100755 --- a/fetch-spl.sh +++ b/fetch-spl.sh @@ -39,6 +39,7 @@ fetch_program() { } fetch_program token 3.5.0 TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA BPFLoader2111111111111111111111111111111111 +fetch_program token-2022 0.5.0 TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb BPFLoader2111111111111111111111111111111111 fetch_program memo 1.0.0 Memo1UhkJRfHyvLMcVucJwxXeuD728EqVDDwQDxFMNo BPFLoader1111111111111111111111111111111111 fetch_program memo 3.0.0 MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr BPFLoader2111111111111111111111111111111111 fetch_program associated-token-account 1.1.2 ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL BPFLoader2111111111111111111111111111111111 diff --git a/program-test/src/programs.rs b/program-test/src/programs.rs index 4eacd0013..78d67453d 100644 --- a/program-test/src/programs.rs +++ b/program-test/src/programs.rs @@ -1,5 +1,6 @@ use solana_sdk::{ account::{Account, AccountSharedData}, + bpf_loader_upgradeable::UpgradeableLoaderState, pubkey::Pubkey, rent::Rent, }; @@ -7,6 +8,9 @@ use solana_sdk::{ mod spl_token { solana_sdk::declare_id!("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"); } +mod spl_token_2022 { + solana_sdk::declare_id!("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"); +} mod spl_memo_1_0 { solana_sdk::declare_id!("Memo1UhkJRfHyvLMcVucJwxXeuD728EqVDDwQDxFMNo"); } @@ -17,18 +21,30 @@ mod spl_associated_token_account { solana_sdk::declare_id!("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"); } -static SPL_PROGRAMS: &[(Pubkey, &[u8])] = &[ - (spl_token::ID, include_bytes!("programs/spl_token-3.5.0.so")), +static SPL_PROGRAMS: &[(Pubkey, Pubkey, &[u8])] = &[ + ( + spl_token::ID, + solana_sdk::bpf_loader::ID, + include_bytes!("programs/spl_token-3.5.0.so"), + ), + ( + spl_token_2022::ID, + solana_sdk::bpf_loader_upgradeable::ID, + include_bytes!("programs/spl_token_2022-0.5.0.so"), + ), ( spl_memo_1_0::ID, + solana_sdk::bpf_loader::ID, include_bytes!("programs/spl_memo-1.0.0.so"), ), ( spl_memo_3_0::ID, + solana_sdk::bpf_loader::ID, include_bytes!("programs/spl_memo-3.0.0.so"), ), ( spl_associated_token_account::ID, + solana_sdk::bpf_loader::ID, include_bytes!("programs/spl_associated_token_account-1.1.1.so"), ), ]; @@ -36,17 +52,45 @@ static SPL_PROGRAMS: &[(Pubkey, &[u8])] = &[ pub fn spl_programs(rent: &Rent) -> Vec<(Pubkey, AccountSharedData)> { SPL_PROGRAMS .iter() - .map(|(program_id, elf)| { - ( + .flat_map(|(program_id, loader_id, elf)| { + let mut accounts = vec![]; + let data = if *loader_id == solana_sdk::bpf_loader_upgradeable::ID { + let (programdata_address, _) = + Pubkey::find_program_address(&[program_id.as_ref()], loader_id); + let mut program_data = bincode::serialize(&UpgradeableLoaderState::ProgramData { + slot: 0, + upgrade_authority_address: Some(Pubkey::default()), + }) + .unwrap(); + program_data.extend_from_slice(elf); + accounts.push(( + programdata_address, + AccountSharedData::from(Account { + lamports: rent.minimum_balance(program_data.len()).max(1), + data: program_data, + owner: *loader_id, + executable: false, + rent_epoch: 0, + }), + )); + bincode::serialize(&UpgradeableLoaderState::Program { + programdata_address, + }) + .unwrap() + } else { + elf.to_vec() + }; + accounts.push(( *program_id, AccountSharedData::from(Account { - lamports: rent.minimum_balance(elf.len()).max(1), - data: elf.to_vec(), - owner: solana_sdk::bpf_loader::id(), + lamports: rent.minimum_balance(data.len()).max(1), + data, + owner: *loader_id, executable: true, rent_epoch: 0, }), - ) + )); + accounts.into_iter() }) .collect() } diff --git a/program-test/src/programs/spl_token_2022-0.5.0.so b/program-test/src/programs/spl_token_2022-0.5.0.so new file mode 100644 index 000000000..4253bfb1b Binary files /dev/null and b/program-test/src/programs/spl_token_2022-0.5.0.so differ diff --git a/program-test/tests/spl.rs b/program-test/tests/spl.rs new file mode 100644 index 000000000..a97cdc51b --- /dev/null +++ b/program-test/tests/spl.rs @@ -0,0 +1,65 @@ +use { + solana_program_test::{programs::spl_programs, ProgramTest}, + solana_sdk::{ + bpf_loader, bpf_loader_upgradeable, + instruction::{AccountMeta, Instruction}, + pubkey::Pubkey, + signature::Signer, + signer::keypair::Keypair, + system_instruction, + sysvar::rent, + transaction::Transaction, + }, +}; + +#[tokio::test] +async fn programs_present() { + let (mut banks_client, _, _) = ProgramTest::default().start().await; + let rent = banks_client.get_rent().await.unwrap(); + let token_2022_id = Pubkey::try_from("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb").unwrap(); + let (token_2022_programdata_id, _) = + Pubkey::find_program_address(&[token_2022_id.as_ref()], &bpf_loader_upgradeable::id()); + + for (program_id, _) in spl_programs(&rent) { + let program_account = banks_client.get_account(program_id).await.unwrap().unwrap(); + if program_id == token_2022_id || program_id == token_2022_programdata_id { + assert_eq!(program_account.owner, bpf_loader_upgradeable::id()); + } else { + assert_eq!(program_account.owner, bpf_loader::id()); + } + } +} + +#[tokio::test] +async fn token_2022() { + let (mut banks_client, payer, recent_blockhash) = ProgramTest::default().start().await; + + let token_2022_id = Pubkey::try_from("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb").unwrap(); + let mint = Keypair::new(); + let rent = banks_client.get_rent().await.unwrap(); + let space = 82; + let transaction = Transaction::new_signed_with_payer( + &[ + system_instruction::create_account( + &payer.pubkey(), + &mint.pubkey(), + rent.minimum_balance(space), + space as u64, + &token_2022_id, + ), + Instruction::new_with_bytes( + token_2022_id, + &[0; 35], // initialize mint + vec![ + AccountMeta::new(mint.pubkey(), false), + AccountMeta::new_readonly(rent::id(), false), + ], + ), + ], + Some(&payer.pubkey()), + &[&payer, &mint], + recent_blockhash, + ); + + banks_client.process_transaction(transaction).await.unwrap(); +}