From a0dbfa7cfa0b1f1e64f85c482990ac84602a2b04 Mon Sep 17 00:00:00 2001 From: Csongor Kiss Date: Tue, 27 Feb 2024 21:28:15 -0500 Subject: [PATCH] solana: add two negative transfer tests --- .../tests/common/setup.rs | 60 ++++++++++- .../tests/sdk/instructions/admin.rs | 1 - .../tests/transfer.rs | 101 +++++++++++++++++- 3 files changed, 157 insertions(+), 5 deletions(-) diff --git a/solana/programs/example-native-token-transfers/tests/common/setup.rs b/solana/programs/example-native-token-transfers/tests/common/setup.rs index 3a18511aa..73b0883c0 100644 --- a/solana/programs/example-native-token-transfers/tests/common/setup.rs +++ b/solana/programs/example-native-token-transfers/tests/common/setup.rs @@ -42,18 +42,23 @@ pub const OUTBOUND_LIMIT: u64 = 10000; pub const INBOUND_LIMIT: u64 = 50000; pub const OTHER_TRANSCEIVER: [u8; 32] = [7u8; 32]; +pub const ANOTHER_TRANSCEIVER: [u8; 32] = [8u8; 32]; pub const OTHER_MANAGER: [u8; 32] = [9u8; 32]; +pub const ANOTHER_MANAGER: [u8; 32] = [5u8; 32]; pub const THIS_CHAIN: u16 = 1; pub const OTHER_CHAIN: u16 = 2; +pub const ANOTHER_CHAIN: u16 = 3; pub struct TestData { pub governance: Governance, pub program_owner: Keypair, pub mint_authority: Keypair, pub mint: Pubkey, + pub bad_mint: Pubkey, pub user: Keypair, pub user_token_account: Pubkey, + pub bad_user_token_account: Pubkey, } pub async fn setup_with_extra_accounts( @@ -197,7 +202,6 @@ pub async fn setup_ntt(ctx: &mut ProgramTestContext, test_data: &TestData, mode: SetPeer { payer: ctx.payer.pubkey(), owner: test_data.program_owner.pubkey(), - mint: test_data.mint, }, SetPeerArgs { chain_id: ChainId { id: OTHER_CHAIN }, @@ -209,6 +213,23 @@ pub async fn setup_ntt(ctx: &mut ProgramTestContext, test_data: &TestData, mode: .submit_with_signers(&[&test_data.program_owner], ctx) .await .unwrap(); + + set_peer( + &GoodNTT {}, + SetPeer { + payer: ctx.payer.pubkey(), + owner: test_data.program_owner.pubkey(), + }, + SetPeerArgs { + chain_id: ChainId { id: ANOTHER_CHAIN }, + address: ANOTHER_MANAGER, + limit: INBOUND_LIMIT, + token_decimals: 7, + }, + ) + .submit_with_signers(&[&test_data.program_owner], ctx) + .await + .unwrap(); } pub async fn setup_accounts(ctx: &mut ProgramTestContext, program_owner: Keypair) -> TestData { @@ -216,6 +237,8 @@ pub async fn setup_accounts(ctx: &mut ProgramTestContext, program_owner: Keypair let mint = Keypair::new(); let mint_authority = Keypair::new(); + let bad_mint = Keypair::new(); + let user = Keypair::new(); let payer = ctx.payer.pubkey(); @@ -225,6 +248,12 @@ pub async fn setup_accounts(ctx: &mut ProgramTestContext, program_owner: Keypair .await .unwrap(); + create_mint(ctx, &bad_mint, &mint_authority.pubkey(), 9) + .await + .submit(ctx) + .await + .unwrap(); + // create associated token account for user let user_token_account = get_associated_token_address_with_program_id(&user.pubkey(), &mint.pubkey(), &Token::id()); @@ -239,6 +268,20 @@ pub async fn setup_accounts(ctx: &mut ProgramTestContext, program_owner: Keypair .await .unwrap(); + let bad_user_token_account = + get_associated_token_address_with_program_id(&user.pubkey(), &bad_mint.pubkey(), &Token::id()); + + spl_associated_token_account::instruction::create_associated_token_account( + &payer, + &user.pubkey(), + &bad_mint.pubkey(), + &Token::id(), + ) + .submit(ctx) + .await + .unwrap(); + + spl_token::instruction::mint_to( &Token::id(), &mint.pubkey(), @@ -252,6 +295,19 @@ pub async fn setup_accounts(ctx: &mut ProgramTestContext, program_owner: Keypair .await .unwrap(); + spl_token::instruction::mint_to( + &Token::id(), + &bad_mint.pubkey(), + &bad_user_token_account, + &mint_authority.pubkey(), + &[], + MINT_AMOUNT, + ) + .unwrap() + .submit_with_signers(&[&mint_authority], ctx) + .await + .unwrap(); + TestData { governance: Governance { program: wormhole_governance::ID, @@ -259,8 +315,10 @@ pub async fn setup_accounts(ctx: &mut ProgramTestContext, program_owner: Keypair program_owner, mint_authority, mint: mint.pubkey(), + bad_mint: bad_mint.pubkey(), user, user_token_account, + bad_user_token_account, } } diff --git a/solana/programs/example-native-token-transfers/tests/sdk/instructions/admin.rs b/solana/programs/example-native-token-transfers/tests/sdk/instructions/admin.rs index 689f1d6a8..620450482 100644 --- a/solana/programs/example-native-token-transfers/tests/sdk/instructions/admin.rs +++ b/solana/programs/example-native-token-transfers/tests/sdk/instructions/admin.rs @@ -7,7 +7,6 @@ use crate::sdk::accounts::NTT; pub struct SetPeer { pub payer: Pubkey, pub owner: Pubkey, - pub mint: Pubkey, } pub fn set_peer(ntt: &NTT, accounts: SetPeer, args: SetPeerArgs) -> Instruction { diff --git a/solana/programs/example-native-token-transfers/tests/transfer.rs b/solana/programs/example-native-token-transfers/tests/transfer.rs index 06bd9c34b..874b8fb96 100644 --- a/solana/programs/example-native-token-transfers/tests/transfer.rs +++ b/solana/programs/example-native-token-transfers/tests/transfer.rs @@ -1,7 +1,7 @@ -#![cfg(feature = "test-sbf")] +// #![cfg(feature = "test-sbf")] #![feature(type_changing_struct_update)] -use anchor_lang::prelude::{Clock, Pubkey}; +use anchor_lang::prelude::{Clock, ErrorCode, Pubkey}; use anchor_spl::token::{Mint, TokenAccount}; use common::setup::{TestData, OTHER_CHAIN}; use example_native_token_transfers::{ @@ -25,7 +25,10 @@ use solana_sdk::{ use wormhole_anchor_sdk::wormhole::PostedVaa; use crate::{ - common::{query::GetAccountDataAnchor, setup::OUTBOUND_LIMIT}, + common::{ + query::GetAccountDataAnchor, + setup::{ANOTHER_CHAIN, OUTBOUND_LIMIT}, + }, sdk::{ accounts::{good_ntt, NTTAccounts}, instructions::transfer::Transfer, @@ -316,6 +319,98 @@ async fn locking_mode_locks_tokens() { assert_eq!(mint_before.supply, mint_after.supply); } +#[tokio::test] +async fn test_bad_mint() { + let (mut ctx, test_data) = setup(Mode::Locking).await; + + let outbox_item = Keypair::new(); + + let (mut accs, args) = init_accs_args( + &GoodNTT {}, + &mut ctx, + &test_data, + outbox_item.pubkey(), + 1050, + false, + ); + + // use the wrong mint here + accs.mint = test_data.bad_mint; + + approve_token_authority( + &GoodNTT {}, + &test_data.bad_user_token_account, + &test_data.user.pubkey(), + args.amount, + ) + .submit_with_signers(&[&test_data.user], &mut ctx) + .await + .unwrap(); + + let err = transfer(&GoodNTT {}, accs, args, Mode::Locking) + .submit_with_signers(&[&test_data.user, &outbox_item], &mut ctx) + .await + .unwrap_err(); + + assert_eq!( + err.unwrap(), + TransactionError::InstructionError( + 0, + InstructionError::Custom(ErrorCode::ConstraintAddress.into()) + ) + ); +} + +#[tokio::test] +async fn test_invalid_peer() { + // in this test we send to 'OTHER_CHAIN' but use the peer account for + // 'ANOTHER_CHAIN'. + struct BadNTT {} + + impl NTTAccounts for BadNTT { + fn peer(&self, _chain_id: u16) -> Pubkey { + // return 'ANOTHER_CHAIN' peer account + GoodNTT {}.peer(ANOTHER_CHAIN) + } + } + + let (mut ctx, test_data) = setup(Mode::Locking).await; + + let outbox_item = Keypair::new(); + + let (accs, args) = init_accs_args( + &BadNTT {}, + &mut ctx, + &test_data, + outbox_item.pubkey(), + 1050, + false, + ); + + approve_token_authority( + &GoodNTT {}, + &test_data.bad_user_token_account, + &test_data.user.pubkey(), + args.amount, + ) + .submit_with_signers(&[&test_data.user], &mut ctx) + .await + .unwrap(); + + let err = transfer(&BadNTT {}, accs, args, Mode::Locking) + .submit_with_signers(&[&test_data.user, &outbox_item], &mut ctx) + .await + .unwrap_err(); + + assert_eq!( + err.unwrap(), + TransactionError::InstructionError( + 0, + InstructionError::Custom(ErrorCode::ConstraintSeeds.into()) + ) + ); +} + #[tokio::test] async fn test_rate_limit() { let (mut ctx, test_data) = setup(Mode::Locking).await;