Feature/token metadata tests(negative) (#182)

* feature: update borsh version, wip testing module

* Fixed signatures for create metadata in tests

* feature: success test for create_metadata_account

* feature: success test for update_metadata_account, added is_mutable param to create method

* feature: success test for update_primary_sale_happened_via_token, added token account creation in test metadata structure

* feature: success test for create_master_edition

* feature: success test for mint_new_edition_from_master_edition_via_token

* feature: added more success tests checks, wip: added necessary accounts

* feature: added more internal mocks, added mint_new_edition_from_master_edition_via_vault_proxy

* feature: added basic negative tests

Co-authored-by: Yuriy Savchenko <yuriy.savchenko@gmail.com>
This commit is contained in:
Ilia 2021-08-04 21:17:00 +03:00 committed by GitHub
parent 8fac1aca13
commit bf95a0723b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 1027 additions and 8 deletions

View File

@ -1,7 +1,17 @@
mod utils;
use num_traits::FromPrimitive;
use solana_program_test::*;
use solana_sdk::signature::Keypair;
use solana_sdk::{
instruction::InstructionError,
signature::Signer,
transaction::{Transaction, TransactionError},
transport::TransportError,
};
use spl_token_metadata::error::MetadataError;
use spl_token_metadata::state::Key;
use spl_token_metadata::{id, instruction};
use utils::*;
#[tokio::test]
@ -42,3 +52,177 @@ async fn success() {
assert_eq!(master_edition.max_supply.unwrap(), 10);
assert_eq!(master_edition.key, Key::MasterEditionV2);
}
#[tokio::test]
async fn fail_invalid_mint_authority() {
let mut context = program_test().start_with_context().await;
let test_metadata = Metadata::new();
let test_master_edition = MasterEditionV2::new(&test_metadata);
let fake_mint_authority = Keypair::new();
test_metadata
.create(
&mut context,
"Test".to_string(),
"TST".to_string(),
"uri".to_string(),
None,
10,
false,
)
.await
.unwrap();
let tx = Transaction::new_signed_with_payer(
&[instruction::create_master_edition(
id(),
test_master_edition.pubkey,
test_master_edition.mint_pubkey,
context.payer.pubkey(),
fake_mint_authority.pubkey(),
test_master_edition.metadata_pubkey,
context.payer.pubkey(),
Some(10),
)],
Some(&context.payer.pubkey()),
&[&context.payer, &context.payer, &fake_mint_authority],
context.last_blockhash,
);
let result = context
.banks_client
.process_transaction(tx)
.await
.unwrap_err();
assert_custom_error!(result, MetadataError::InvalidMintAuthority);
}
#[tokio::test]
async fn fail_invalid_token_program() {
let mut context = program_test().start_with_context().await;
let test_metadata = Metadata::new();
let test_master_edition = MasterEditionV2::new(&test_metadata);
test_metadata
.create(
&mut context,
"Test".to_string(),
"TST".to_string(),
"uri".to_string(),
None,
10,
false,
)
.await
.unwrap();
let result = test_master_edition
.create_with_invalid_token_program(&mut context, Some(10))
.await
.unwrap_err();
assert_custom_error!(result, MetadataError::InvalidTokenProgram);
}
#[tokio::test]
async fn fail_invalid_mint() {
let mut context = program_test().start_with_context().await;
let test_metadata = Metadata::new();
let fake_mint = Keypair::new();
let fake_account = Keypair::new();
let payer_pubkey = context.payer.pubkey();
test_metadata
.create(
&mut context,
"Test".to_string(),
"TST".to_string(),
"uri".to_string(),
None,
10,
false,
)
.await
.unwrap();
create_mint(&mut context, &fake_mint, &payer_pubkey, None)
.await
.unwrap();
create_token_account(
&mut context,
&fake_account,
&fake_mint.pubkey(),
&payer_pubkey,
)
.await
.unwrap();
mint_tokens(
&mut context,
&fake_mint.pubkey(),
&fake_account.pubkey(),
1000000,
&payer_pubkey,
None,
)
.await
.unwrap();
let test_master_edition = MasterEditionV2::new(&Metadata {
mint: fake_mint,
pubkey: test_metadata.pubkey.clone(),
token: fake_account,
});
let result = test_master_edition
.create(&mut context, Some(10))
.await
.unwrap_err();
assert_custom_error!(result, MetadataError::MintMismatch);
}
#[tokio::test]
async fn fail_invalid_update_authority() {
let mut context = program_test().start_with_context().await;
let test_metadata = Metadata::new();
let test_master_edition = MasterEditionV2::new(&test_metadata);
let fake_update_authority = Keypair::new();
test_metadata
.create(
&mut context,
"Test".to_string(),
"TST".to_string(),
"uri".to_string(),
None,
10,
false,
)
.await
.unwrap();
let tx = Transaction::new_signed_with_payer(
&[instruction::create_master_edition(
id(),
test_master_edition.pubkey,
test_master_edition.mint_pubkey,
fake_update_authority.pubkey(),
context.payer.pubkey(),
test_master_edition.metadata_pubkey,
context.payer.pubkey(),
Some(10),
)],
Some(&context.payer.pubkey()),
&[&context.payer, &context.payer, &fake_update_authority],
context.last_blockhash,
);
let result = context
.banks_client
.process_transaction(tx)
.await
.unwrap_err();
assert_custom_error!(result, MetadataError::UpdateAuthorityIncorrect);
}

View File

@ -1,8 +1,17 @@
mod utils;
use num_traits::FromPrimitive;
use solana_program::pubkey::Pubkey;
use solana_program_test::*;
use solana_sdk::signature::Signer;
use solana_sdk::{
instruction::InstructionError,
signature::{Keypair, Signer},
transaction::{Transaction, TransactionError},
transport::TransportError,
};
use spl_token_metadata::error::MetadataError;
use spl_token_metadata::state::Key;
use spl_token_metadata::{id, instruction};
use utils::*;
#[tokio::test]
@ -37,3 +46,84 @@ async fn success() {
assert_eq!(metadata.update_authority, context.payer.pubkey());
assert_eq!(metadata.key, Key::MetadataV1);
}
#[tokio::test]
async fn fail_invalid_mint_authority() {
let mut context = program_test().start_with_context().await;
let test_metadata = Metadata::new();
let fake_mint_authority = Keypair::new();
let payer_pubkey = context.payer.pubkey();
create_mint(&mut context, &test_metadata.mint, &payer_pubkey, None)
.await
.unwrap();
create_token_account(
&mut context,
&test_metadata.token,
&test_metadata.mint.pubkey(),
&payer_pubkey,
)
.await
.unwrap();
mint_tokens(
&mut context,
&test_metadata.mint.pubkey(),
&test_metadata.token.pubkey(),
1,
&payer_pubkey,
None,
)
.await
.unwrap();
let tx = Transaction::new_signed_with_payer(
&[instruction::create_metadata_accounts(
id(),
test_metadata.pubkey.clone(),
test_metadata.mint.pubkey(),
fake_mint_authority.pubkey(),
context.payer.pubkey().clone(),
context.payer.pubkey().clone(),
"Test".to_string(),
"TST".to_string(),
"uri".to_string(),
None,
10,
false,
false,
)],
Some(&context.payer.pubkey()),
&[&context.payer, &fake_mint_authority],
context.last_blockhash,
);
let result = context
.banks_client
.process_transaction(tx)
.await
.unwrap_err();
assert_custom_error!(result, MetadataError::InvalidMintAuthority);
}
#[tokio::test]
async fn fail_invalid_metadata_pda() {
let mut context = program_test().start_with_context().await;
let mut test_metadata = Metadata::new();
test_metadata.pubkey = Pubkey::new_unique();
let result = test_metadata
.create(
&mut context,
"Test".to_string(),
"TST".to_string(),
"uri".to_string(),
None,
10,
false,
)
.await
.unwrap_err();
assert_custom_error!(result, MetadataError::InvalidMetadataKey);
}

View File

@ -1,7 +1,16 @@
mod utils;
use num_traits::FromPrimitive;
use solana_program_test::*;
use solana_sdk::{
instruction::InstructionError,
signature::{Keypair, Signer},
transaction::{Transaction, TransactionError},
transport::TransportError,
};
use spl_token_metadata::error::MetadataError;
use spl_token_metadata::state::Key;
use spl_token_metadata::{id, instruction};
use utils::*;
#[tokio::test]
@ -36,3 +45,148 @@ async fn success() {
assert_eq!(edition_marker.ledger[0], 64);
assert_eq!(edition_marker.key, Key::EditionMarker);
}
#[tokio::test]
async fn fail_invalid_token_program() {
let mut context = program_test().start_with_context().await;
let test_metadata = Metadata::new();
let test_master_edition = MasterEditionV2::new(&test_metadata);
let test_edition_marker = EditionMarker::new(&test_metadata, &test_master_edition, 1);
test_metadata
.create(
&mut context,
"Test".to_string(),
"TST".to_string(),
"uri".to_string(),
None,
10,
false,
)
.await
.unwrap();
test_master_edition
.create(&mut context, Some(10))
.await
.unwrap();
let result = test_edition_marker
.create_with_invalid_token_program(&mut context)
.await
.unwrap_err();
assert_custom_error!(result, MetadataError::InvalidTokenProgram);
}
#[tokio::test]
async fn fail_invalid_mint() {
let mut context = program_test().start_with_context().await;
let test_metadata = Metadata::new();
let test_master_edition = MasterEditionV2::new(&test_metadata);
let test_edition_marker = EditionMarker::new(&test_metadata, &test_master_edition, 1);
let fake_mint = Keypair::new();
let fake_account = Keypair::new();
let payer_pubkey = context.payer.pubkey();
test_metadata
.create(
&mut context,
"Test".to_string(),
"TST".to_string(),
"uri".to_string(),
None,
10,
false,
)
.await
.unwrap();
test_master_edition
.create(&mut context, Some(10))
.await
.unwrap();
create_mint(&mut context, &fake_mint, &payer_pubkey, None)
.await
.unwrap();
create_token_account(
&mut context,
&fake_account,
&fake_mint.pubkey(),
&payer_pubkey,
)
.await
.unwrap();
mint_tokens(
&mut context,
&fake_mint.pubkey(),
&fake_account.pubkey(),
1,
&payer_pubkey,
None,
)
.await
.unwrap();
let tx = Transaction::new_signed_with_payer(
&[instruction::mint_new_edition_from_master_edition_via_token(
id(),
test_edition_marker.new_metadata_pubkey,
test_edition_marker.new_edition_pubkey,
test_edition_marker.master_edition_pubkey,
fake_mint.pubkey(),
context.payer.pubkey(),
context.payer.pubkey(),
context.payer.pubkey(),
fake_account.pubkey(),
context.payer.pubkey(),
test_edition_marker.metadata_pubkey,
test_edition_marker.metadata_mint_pubkey,
test_edition_marker.edition,
)],
Some(&context.payer.pubkey()),
&[&context.payer, &context.payer, &context.payer],
context.last_blockhash,
);
let result = context
.banks_client
.process_transaction(tx)
.await
.unwrap_err();
assert_custom_error!(result, MetadataError::TokenAccountMintMismatchV2);
}
#[tokio::test]
async fn fail_edition_already_initialized() {
let mut context = program_test().start_with_context().await;
let test_metadata = Metadata::new();
let test_master_edition = MasterEditionV2::new(&test_metadata);
let test_edition_marker = EditionMarker::new(&test_metadata, &test_master_edition, 1);
let test_edition_marker1 = EditionMarker::new(&test_metadata, &test_master_edition, 1);
test_metadata
.create(
&mut context,
"Test".to_string(),
"TST".to_string(),
"uri".to_string(),
None,
10,
false,
)
.await
.unwrap();
test_master_edition
.create(&mut context, Some(10))
.await
.unwrap();
test_edition_marker.create(&mut context).await.unwrap();
let result = test_edition_marker1.create(&mut context).await.unwrap_err();
assert_custom_error!(result, MetadataError::AlreadyInitialized);
}

View File

@ -1,8 +1,18 @@
mod utils;
use num_traits::FromPrimitive;
use solana_program_test::*;
use solana_sdk::signature::Signer;
use solana_sdk::{
instruction::InstructionError,
pubkey::Pubkey,
signature::{Keypair, Signer},
transaction::{Transaction, TransactionError},
transport::TransportError,
};
use spl_token_metadata::error::MetadataError;
use spl_token_metadata::state::Key;
use spl_token_metadata::{id, instruction};
use spl_token_vault::state::PREFIX;
use utils::*;
#[tokio::test]
@ -73,3 +83,326 @@ async fn success() {
assert_eq!(edition_marker.ledger[1], 32);
assert_eq!(edition_marker.key, Key::EditionMarker);
}
#[tokio::test]
async fn fail_invalid_store_owner_pda() {
let mut program_test = program_test();
program_test.add_program("spl_token_vault", spl_token_vault::id(), None);
let mut context = program_test.start_with_context().await;
let test_metadata = Metadata::new();
let test_master_edition = MasterEditionV2::new(&test_metadata);
let test_external_price = ExternalPrice::new();
let test_vault = Vault::new();
let test_edition_marker = EditionMarker::new(&test_metadata, &test_master_edition, 10);
let fake_store = Keypair::new();
let payer_pubkey = context.payer.pubkey();
test_metadata
.create(
&mut context,
"Test".to_string(),
"TST".to_string(),
"uri".to_string(),
None,
10,
false,
)
.await
.unwrap();
test_master_edition
.create(&mut context, Some(10))
.await
.unwrap();
test_external_price.create(&mut context).await.unwrap();
test_external_price
.update(
&mut context,
1,
&test_external_price.price_mint.pubkey(),
true,
)
.await
.unwrap();
test_vault
.create(&mut context, &test_external_price)
.await
.unwrap();
let (safety_deposit_box, _) = test_vault
.add_token_to_inactive_vault(&mut context, 1, &test_metadata)
.await
.unwrap();
test_vault.activate(&mut context, 1).await.unwrap();
test_vault
.combine(&mut context, &test_external_price)
.await
.unwrap();
create_token_account(
&mut context,
&fake_store,
&test_vault.mint.pubkey(),
&payer_pubkey,
)
.await
.unwrap();
let tx = Transaction::new_signed_with_payer(
&[
instruction::mint_edition_from_master_edition_via_vault_proxy(
id(),
test_edition_marker.new_metadata_pubkey,
test_edition_marker.new_edition_pubkey,
test_edition_marker.master_edition_pubkey,
test_edition_marker.mint.pubkey(),
test_edition_marker.pubkey,
context.payer.pubkey(),
context.payer.pubkey(),
context.payer.pubkey(),
fake_store.pubkey(),
safety_deposit_box,
test_vault.keypair.pubkey(),
context.payer.pubkey(),
test_edition_marker.metadata_pubkey,
spl_token::id(),
spl_token_vault::id(),
test_edition_marker.edition,
),
],
Some(&context.payer.pubkey()),
&[&context.payer, &context.payer],
context.last_blockhash,
);
let result = context
.banks_client
.process_transaction(tx)
.await
.unwrap_err();
assert_custom_error!(result, MetadataError::InvalidOwner);
}
#[tokio::test]
async fn fail_invalid_vault_authority() {
let mut program_test = program_test();
program_test.add_program("spl_token_vault", spl_token_vault::id(), None);
let mut context = program_test.start_with_context().await;
let test_metadata = Metadata::new();
let test_master_edition = MasterEditionV2::new(&test_metadata);
let test_external_price = ExternalPrice::new();
let test_vault = Vault::new();
let test_edition_marker = EditionMarker::new(&test_metadata, &test_master_edition, 10);
let fake_vault_authority = Keypair::new();
test_metadata
.create(
&mut context,
"Test".to_string(),
"TST".to_string(),
"uri".to_string(),
None,
10,
false,
)
.await
.unwrap();
test_master_edition
.create(&mut context, Some(10))
.await
.unwrap();
test_external_price.create(&mut context).await.unwrap();
test_external_price
.update(
&mut context,
1,
&test_external_price.price_mint.pubkey(),
true,
)
.await
.unwrap();
test_vault
.create(&mut context, &test_external_price)
.await
.unwrap();
let (safety_deposit_box, store) = test_vault
.add_token_to_inactive_vault(&mut context, 1, &test_metadata)
.await
.unwrap();
test_vault.activate(&mut context, 1).await.unwrap();
test_vault
.combine(&mut context, &test_external_price)
.await
.unwrap();
let tx = Transaction::new_signed_with_payer(
&[
instruction::mint_edition_from_master_edition_via_vault_proxy(
id(),
test_edition_marker.new_metadata_pubkey,
test_edition_marker.new_edition_pubkey,
test_edition_marker.master_edition_pubkey,
test_edition_marker.mint.pubkey(),
test_edition_marker.pubkey,
context.payer.pubkey(),
context.payer.pubkey(),
fake_vault_authority.pubkey(),
store,
safety_deposit_box,
test_vault.keypair.pubkey(),
context.payer.pubkey(),
test_edition_marker.metadata_pubkey,
spl_token::id(),
spl_token_vault::id(),
test_edition_marker.edition,
),
],
Some(&context.payer.pubkey()),
&[&context.payer, &context.payer, &fake_vault_authority],
context.last_blockhash,
);
let result = context
.banks_client
.process_transaction(tx)
.await
.unwrap_err();
assert_custom_error!(
result,
spl_token_vault::error::VaultError::AuthorityDoesNotMatch
);
}
#[tokio::test]
async fn fail_store_account_mismatch() {
let mut program_test = program_test();
program_test.add_program("spl_token_vault", spl_token_vault::id(), None);
let mut context = program_test.start_with_context().await;
let test_metadata = Metadata::new();
let test_master_edition = MasterEditionV2::new(&test_metadata);
let test_external_price = ExternalPrice::new();
let test_vault = Vault::new();
let test_edition_marker = EditionMarker::new(&test_metadata, &test_master_edition, 10);
// TEST VAULT
test_metadata
.create(
&mut context,
"Test".to_string(),
"TST".to_string(),
"uri".to_string(),
None,
10,
false,
)
.await
.unwrap();
test_master_edition
.create(&mut context, Some(10))
.await
.unwrap();
test_external_price.create(&mut context).await.unwrap();
test_external_price
.update(
&mut context,
1,
&test_external_price.price_mint.pubkey(),
true,
)
.await
.unwrap();
test_vault
.create(&mut context, &test_external_price)
.await
.unwrap();
let (safety_deposit_box, _) = test_vault
.add_token_to_inactive_vault(&mut context, 1, &test_metadata)
.await
.unwrap();
test_vault.activate(&mut context, 1).await.unwrap();
test_vault
.combine(&mut context, &test_external_price)
.await
.unwrap();
// Generate fake store
let store = Keypair::new();
let token_mint_pubkey = test_metadata.mint.pubkey();
let spl_token_vault_id = spl_token_vault::id();
let vault_pubkey = test_vault.keypair.pubkey();
let seeds = &[
PREFIX.as_bytes(),
&vault_pubkey.as_ref(),
&token_mint_pubkey.as_ref(),
];
let (_, _) = Pubkey::find_program_address(seeds, &spl_token_vault_id);
let seeds = &[
PREFIX.as_bytes(),
&spl_token_vault_id.as_ref(),
&vault_pubkey.as_ref(),
];
let (authority, _) = Pubkey::find_program_address(seeds, &spl_token_vault_id);
create_token_account(&mut context, &store, &token_mint_pubkey, &authority)
.await
.unwrap();
let tx = Transaction::new_signed_with_payer(
&[
instruction::mint_edition_from_master_edition_via_vault_proxy(
id(),
test_edition_marker.new_metadata_pubkey,
test_edition_marker.new_edition_pubkey,
test_edition_marker.master_edition_pubkey,
test_edition_marker.mint.pubkey(),
test_edition_marker.pubkey,
context.payer.pubkey(),
context.payer.pubkey(),
context.payer.pubkey(),
store.pubkey(),
safety_deposit_box,
test_vault.keypair.pubkey(),
context.payer.pubkey(),
test_edition_marker.metadata_pubkey,
spl_token::id(),
spl_token_vault::id(),
test_edition_marker.edition,
),
],
Some(&context.payer.pubkey()),
&[&context.payer, &context.payer],
context.last_blockhash,
);
let result = context
.banks_client
.process_transaction(tx)
.await
.unwrap_err();
assert_custom_error!(
result,
spl_token_vault::error::VaultError::StoreDoesNotMatchSafetyDepositBox
);
}

View File

@ -1,8 +1,16 @@
mod utils;
use num_traits::FromPrimitive;
use solana_program_test::*;
use solana_sdk::signature::Signer;
use solana_sdk::{
instruction::InstructionError,
signature::{Keypair, Signer},
transaction::{Transaction, TransactionError},
transport::TransportError,
};
use spl_token_metadata::error::MetadataError;
use spl_token_metadata::state::Key;
use spl_token_metadata::{id, instruction};
use utils::*;
#[tokio::test]
@ -49,3 +57,45 @@ async fn success() {
assert_eq!(metadata.update_authority, context.payer.pubkey());
assert_eq!(metadata.key, Key::MetadataV1);
}
#[tokio::test]
async fn fail_invalid_update_authority() {
let mut context = program_test().start_with_context().await;
let test_metadata = Metadata::new();
let fake_update_authority = Keypair::new();
test_metadata
.create(
&mut context,
"Test".to_string(),
"TST".to_string(),
"uri".to_string(),
None,
10,
true,
)
.await
.unwrap();
let tx = Transaction::new_signed_with_payer(
&[instruction::update_metadata_accounts(
id(),
test_metadata.pubkey,
fake_update_authority.pubkey(),
None,
None,
None,
)],
Some(&context.payer.pubkey()),
&[&context.payer, &fake_update_authority],
context.last_blockhash,
);
let result = context
.banks_client
.process_transaction(tx)
.await
.unwrap_err();
assert_custom_error!(result, MetadataError::UpdateAuthorityIncorrect);
}

View File

@ -1,8 +1,16 @@
mod utils;
use num_traits::FromPrimitive;
use solana_program_test::*;
use solana_sdk::signature::Signer;
use solana_sdk::{
instruction::InstructionError,
signature::{Keypair, Signer},
transaction::{Transaction, TransactionError},
transport::TransportError,
};
use spl_token_metadata::error::MetadataError;
use spl_token_metadata::state::Key;
use spl_token_metadata::{id, instruction};
use utils::*;
#[tokio::test]
@ -42,3 +50,67 @@ async fn success() {
assert_eq!(metadata.update_authority, context.payer.pubkey());
assert_eq!(metadata.key, Key::MetadataV1);
}
#[tokio::test]
async fn fail_invalid_mint() {
let mut context = program_test().start_with_context().await;
let test_metadata = Metadata::new();
let fake_mint = Keypair::new();
let fake_token_account = Keypair::new();
let payer_pubkey = context.payer.pubkey();
create_mint(&mut context, &fake_mint, &payer_pubkey, None)
.await
.unwrap();
create_token_account(
&mut context,
&fake_token_account,
&fake_mint.pubkey(),
&payer_pubkey,
)
.await
.unwrap();
mint_tokens(
&mut context,
&fake_mint.pubkey(),
&fake_token_account.pubkey(),
10000000,
&payer_pubkey,
None,
)
.await
.unwrap();
test_metadata
.create(
&mut context,
"Test".to_string(),
"TST".to_string(),
"uri".to_string(),
None,
10,
true,
)
.await
.unwrap();
let tx = Transaction::new_signed_with_payer(
&[instruction::update_primary_sale_happened_via_token(
id(),
test_metadata.pubkey,
context.payer.pubkey(),
fake_token_account.pubkey(),
)],
Some(&context.payer.pubkey()),
&[&context.payer],
context.last_blockhash,
);
let result = context
.banks_client
.process_transaction(tx)
.await
.unwrap_err();
assert_custom_error!(result, MetadataError::MintMismatch);
}

View File

@ -0,0 +1,27 @@
#[macro_export]
macro_rules! assert_transport_error {
($error:expr, $matcher:pat) => {
match $error {
$matcher => {
assert!(true)
}
_ => assert!(false),
}
};
}
#[macro_export]
macro_rules! assert_custom_error {
($error:expr, $matcher:pat) => {
match $error {
TransportError::TransactionError(TransactionError::InstructionError(
0,
InstructionError::Custom(x),
)) => match FromPrimitive::from_i32(x as i32) {
Some($matcher) => assert!(true),
_ => assert!(false),
},
_ => assert!(false),
};
};
}

View File

@ -1,12 +1,18 @@
use crate::*;
use solana_program::borsh::try_from_slice_unchecked;
use borsh::BorshSerialize;
use solana_program::{
borsh::try_from_slice_unchecked,
instruction::{AccountMeta, Instruction},
sysvar,
};
use solana_program_test::*;
use solana_sdk::{
pubkey::Pubkey, signature::Signer, signer::keypair::Keypair, transaction::Transaction,
transport,
};
use spl_token_metadata::{
id, instruction,
id,
instruction::{self, MetadataInstruction, MintNewEditionFromMasterEditionViaTokenArgs},
state::{EDITION, EDITION_MARKER_BIT_SIZE, PREFIX},
};
@ -184,4 +190,63 @@ impl EditionMarker {
Ok(context.banks_client.process_transaction(tx).await?)
}
pub async fn create_with_invalid_token_program(
&self,
context: &mut ProgramTestContext,
) -> transport::Result<()> {
let fake_token_program = Keypair::new();
let program_id = spl_token_metadata::id();
let edition_number = self.edition.checked_div(EDITION_MARKER_BIT_SIZE).unwrap();
let as_string = edition_number.to_string();
let (edition_mark_pda, _) = Pubkey::find_program_address(
&[
PREFIX.as_bytes(),
program_id.as_ref(),
self.metadata_mint_pubkey.as_ref(),
EDITION.as_bytes(),
as_string.as_bytes(),
],
&program_id,
);
let accounts = vec![
AccountMeta::new(self.new_metadata_pubkey, false),
AccountMeta::new(self.new_edition_pubkey, false),
AccountMeta::new(self.master_edition_pubkey, false),
AccountMeta::new(self.mint.pubkey(), false),
AccountMeta::new(edition_mark_pda, false),
AccountMeta::new_readonly(context.payer.pubkey(), true),
AccountMeta::new(context.payer.pubkey(), true),
AccountMeta::new_readonly(context.payer.pubkey(), true),
AccountMeta::new_readonly(self.token.pubkey(), false),
AccountMeta::new_readonly(context.payer.pubkey(), false),
AccountMeta::new_readonly(self.metadata_pubkey, false),
AccountMeta::new_readonly(fake_token_program.pubkey(), false),
AccountMeta::new_readonly(solana_program::system_program::id(), false),
AccountMeta::new_readonly(sysvar::rent::id(), false),
];
let fake_instruction = Instruction {
program_id,
accounts,
data: MetadataInstruction::MintNewEditionFromMasterEditionViaToken(
MintNewEditionFromMasterEditionViaTokenArgs {
edition: self.edition,
},
)
.try_to_vec()
.unwrap(),
};
let tx = Transaction::new_signed_with_payer(
&[fake_instruction],
Some(&context.payer.pubkey()),
&[&context.payer],
context.last_blockhash,
);
Ok(context.banks_client.process_transaction(tx).await?)
}
}

View File

@ -1,9 +1,16 @@
use crate::*;
use borsh::ser::BorshSerialize;
use solana_program::borsh::try_from_slice_unchecked;
use solana_program::{
instruction::{AccountMeta, Instruction},
sysvar,
};
use solana_program_test::*;
use solana_sdk::signature::Keypair;
use solana_sdk::{pubkey::Pubkey, signature::Signer, transaction::Transaction, transport};
use spl_token_metadata::{
id, instruction,
id,
instruction::{self, CreateMasterEditionArgs, MetadataInstruction},
state::{EDITION, PREFIX},
};
@ -50,6 +57,41 @@ impl MasterEditionV2 {
try_from_slice_unchecked(&account.data).unwrap()
}
pub async fn create_with_invalid_token_program(
&self,
context: &mut ProgramTestContext,
max_supply: Option<u64>,
) -> transport::Result<()> {
let fake_token_program = Keypair::new();
let fake_instruction = Instruction {
program_id: spl_token_metadata::id(),
accounts: vec![
AccountMeta::new(self.pubkey, false),
AccountMeta::new(self.mint_pubkey, false),
AccountMeta::new_readonly(context.payer.pubkey(), true),
AccountMeta::new_readonly(context.payer.pubkey(), true),
AccountMeta::new_readonly(context.payer.pubkey(), true),
AccountMeta::new_readonly(self.metadata_pubkey, false),
AccountMeta::new_readonly(fake_token_program.pubkey(), false),
AccountMeta::new_readonly(solana_program::system_program::id(), false),
AccountMeta::new_readonly(sysvar::rent::id(), false),
],
data: MetadataInstruction::CreateMasterEdition(CreateMasterEditionArgs { max_supply })
.try_to_vec()
.unwrap(),
};
let tx = Transaction::new_signed_with_payer(
&[fake_instruction],
Some(&context.payer.pubkey()),
&[&context.payer],
context.last_blockhash,
);
Ok(context.banks_client.process_transaction(tx).await?)
}
pub async fn create(
&self,
context: &mut ProgramTestContext,

View File

@ -1,9 +1,11 @@
mod assert;
mod edition_marker;
mod external_price;
mod master_edition_v2;
mod metadata;
mod vault;
pub use assert::*;
pub use edition_marker::EditionMarker;
pub use external_price::ExternalPrice;
pub use master_edition_v2::MasterEditionV2;

View File

@ -1,4 +1,4 @@
use super::{create_mint, create_token_account, mint_tokens, ExternalPrice, Metadata};
use super::{create_mint, create_token_account, ExternalPrice, Metadata};
use solana_program::{pubkey::Pubkey, system_instruction};
use solana_program_test::*;
use solana_sdk::{