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:
parent
8fac1aca13
commit
bf95a0723b
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
};
|
||||
};
|
||||
}
|
|
@ -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?)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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::{
|
||||
|
|
Loading…
Reference in New Issue