diff --git a/.gitignore b/.gitignore index cf08208..6228458 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,4 @@ target/ # Docs plan.md -CLAUDE.md \ No newline at end of file +CLAUDE.md diff --git a/loan_manager/src/lib.rs b/loan_manager/src/lib.rs index 80d5aef..29ff847 100644 --- a/loan_manager/src/lib.rs +++ b/loan_manager/src/lib.rs @@ -1576,17 +1576,20 @@ impl LoanManager { }; Self::apply_debt_recovery(&mut loan, debt_repaid); - loan.status = LoanStatus::Liquidated; - loan.collateral_amount = 0; - env.storage().persistent().set(&loan_key, &loan); - Self::bump_persistent_ttl(&env, &loan_key); - Self::decrement_borrower_loan_count(&env, &loan.borrower); let token: Address = env .storage() .instance() .get(&DataKey::Token) .expect("token not set"); + Self::adjust_total_outstanding(&env, &token, -loan.amount); + + loan.status = LoanStatus::Liquidated; + loan.collateral_amount = 0; + env.storage().persistent().set(&loan_key, &loan); + Self::bump_persistent_ttl(&env, &loan_key); + Self::decrement_borrower_loan_count(&env, &loan.borrower); + let lending_pool: Address = env .storage() .instance() diff --git a/loan_manager/src/test.rs b/loan_manager/src/test.rs index 2561fa0..80390cc 100644 --- a/loan_manager/src/test.rs +++ b/loan_manager/src/test.rs @@ -1572,6 +1572,56 @@ fn test_liquidate_under_threshold_transfers_bonus_and_refund() { ); } +#[test] +fn test_liquidation_frees_outstanding_for_approve_loan() { + let env = Env::default(); + env.mock_all_auths_allowing_non_root_auth(); + + let (manager, nft_client, pool_client, token_id, _token_admin) = setup_test(&env); + let borrower_one = Address::generate(&env); + let borrower_two = Address::generate(&env); + let liquidator = Address::generate(&env); + + let history_hash = soroban_sdk::BytesN::from_array(&env, &[0u8; 32]); + nft_client.mint( + &borrower_one, + &650, + &history_hash, + &String::from_str(&env, "ipfs://QmTest"), + &None, + ); + nft_client.mint( + &borrower_two, + &650, + &history_hash, + &String::from_str(&env, "ipfs://QmTest"), + &None, + ); + + let stellar_token = StellarAssetClient::new(&env, &token_id); + stellar_token.mint(&pool_client, &10_000); + stellar_token.mint(&borrower_one, &20_000); + + manager.set_liquidation_threshold(&14_500); + + let first_loan = manager.request_loan(&borrower_one, &6_000, &17_280); + let second_loan = manager.request_loan(&borrower_two, &6_000, &17_280); + manager.approve_loan(&first_loan); + manager.deposit_collateral(&first_loan, &8_500); + + let blocked_before_liquidation = manager.try_approve_loan(&second_loan); + assert_eq!( + blocked_before_liquidation, + Err(Ok(LoanError::InsufficientPoolLiquidity)) + ); + + manager.liquidate(&liquidator, &first_loan); + + assert_eq!(manager.get_loan(&first_loan).status, LoanStatus::Liquidated); + manager.approve_loan(&second_loan); + assert_eq!(manager.get_loan(&second_loan).status, LoanStatus::Approved); +} + #[test] fn test_liquidate_rejects_healthy_collateral_ratio() { let env = Env::default();