From 03fbd69ad0eaec33b141b7189d35c74575e292db Mon Sep 17 00:00:00 2001 From: Ricardo Guilherme Schmidt <3esmit@gmail.com> Date: Mon, 1 Jun 2026 12:18:35 -0300 Subject: [PATCH] test(stablecoin): cover deposit collateral edge cases --- programs/stablecoin/src/deposit_collateral.rs | 2 + programs/stablecoin/src/tests.rs | 70 +++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/programs/stablecoin/src/deposit_collateral.rs b/programs/stablecoin/src/deposit_collateral.rs index f4983ba..973d1c8 100644 --- a/programs/stablecoin/src/deposit_collateral.rs +++ b/programs/stablecoin/src/deposit_collateral.rs @@ -177,6 +177,8 @@ pub fn deposit_collateral( let mut position_post = position.account.clone(); position_post.data = Data::from(&updated_position); + // Framework zips declared inputs with returned post-states and truncates to the shorter + // length, so these must stay positionally aligned with the first two inputs: owner, position. let post_states = vec![ AccountPostState::new(owner.account), AccountPostState::new(position_post), diff --git a/programs/stablecoin/src/tests.rs b/programs/stablecoin/src/tests.rs index 43c97c5..10c059d 100644 --- a/programs/stablecoin/src/tests.rs +++ b/programs/stablecoin/src/tests.rs @@ -689,6 +689,50 @@ fn deposit_collateral_updates_position_and_emits_transfer() { assert_eq!(chained_calls[0], expected_transfer); } +#[test] +fn deposit_collateral_allows_exact_user_balance() { + let initial_collateral: u128 = 500; + let amount: u128 = 100; + let position_account = init_position_account(initial_collateral, 0); + let vault = init_vault_account(); + let user_holding = user_holding_account(amount); + + let (post_states, chained_calls) = crate::deposit_collateral::deposit_collateral( + owner_account(), + position_account.clone(), + vault.clone(), + user_holding.clone(), + collateral_definition_account(), + STABLECOIN_PROGRAM_ID, + amount, + ); + + let expected_position = Position { + collateral_vault_id: vault_id(), + collateral_definition_id: collateral_definition_id(), + collateral_amount: initial_collateral + amount, + debt_amount: 0, + }; + let post_state_account_ids = [owner_id(), position_account.account_id]; + let position_post = position_post_state( + &post_states, + &post_state_account_ids, + position_account.account_id, + &expected_position, + ); + let position = Position::try_from(&position_post.account().data).expect("valid Position"); + assert_eq!(position, expected_position); + + let expected_transfer = ChainedCall::new( + TOKEN_PROGRAM_ID, + vec![user_holding, vault], + &token_core::Instruction::Transfer { + amount_to_transfer: amount, + }, + ); + assert_eq!(chained_calls, vec![expected_transfer]); +} + #[test] fn deposit_collateral_allows_zero_amount() { let initial: u128 = 500; @@ -907,6 +951,17 @@ fn deposit_collateral_rejects_nonfungible_vault() { assert_deposit_collateral_panics(fixture, crate::deposit_collateral::ERR_VAULT_NOT_FUNGIBLE); } +#[test] +fn deposit_collateral_rejects_master_nft_vault() { + let mut fixture = deposit_fixture(); + fixture.vault.account.data = Data::from(&TokenHolding::NftMaster { + definition_id: collateral_definition_id(), + print_balance: 0, + }); + + assert_deposit_collateral_panics(fixture, crate::deposit_collateral::ERR_VAULT_NOT_FUNGIBLE); +} + #[test] fn deposit_collateral_rejects_vault_definition_owner_mismatch() { let mut fixture = deposit_fixture(); @@ -995,6 +1050,21 @@ fn deposit_collateral_rejects_nonfungible_user_holding() { ); } +#[test] +fn deposit_collateral_rejects_master_nft_user_holding() { + let mut fixture = deposit_fixture(); + fixture.amount = 1; + fixture.user_holding.account.data = Data::from(&TokenHolding::NftMaster { + definition_id: collateral_definition_id(), + print_balance: 0, + }); + + assert_deposit_collateral_panics( + fixture, + crate::deposit_collateral::ERR_USER_HOLDING_NOT_FUNGIBLE, + ); +} + #[test] fn deposit_collateral_rejects_other_token_definition() { let mut fixture = deposit_fixture();