From 72903bde44502e5e72ae809bbc79d3a04f6d2dfc Mon Sep 17 00:00:00 2001 From: Lucas-FManager <265058144+Lucas-FManager@users.noreply.github.com> Date: Thu, 28 May 2026 01:15:44 +0700 Subject: [PATCH] Validate loan manager min score bounds --- contracts/loan_manager/src/lib.rs | 8 +++++- contracts/loan_manager/src/test.rs | 40 ++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/contracts/loan_manager/src/lib.rs b/contracts/loan_manager/src/lib.rs index c330c7f4..70ebe16b 100644 --- a/contracts/loan_manager/src/lib.rs +++ b/contracts/loan_manager/src/lib.rs @@ -165,6 +165,7 @@ impl LoanManager { const MIN_RATE_BPS: u32 = 1; // Minimum 0.01% interest rate /// Default maximum interest rate (configurable via set_rate_bounds). #631 const MAX_RATE_BPS: u32 = 100_000; // Maximum 1000% interest rate + const MAX_CREDIT_SCORE: u32 = 850; const MAX_PENALTY_MULTIPLIER: i128 = 2; // Total debt cannot exceed 2x original principal fn bump_instance_ttl(env: &Env) { @@ -1935,7 +1936,11 @@ impl LoanManager { Self::default_window_ledgers(&env) } - pub fn set_min_score(env: Env, min_score: u32) { + pub fn set_min_score(env: Env, min_score: u32) -> Result<(), LoanError> { + if min_score == 0 || min_score > Self::MAX_CREDIT_SCORE { + return Err(LoanError::InvalidConfiguration); + } + Self::admin(&env).require_auth(); let old_score: u32 = env @@ -1946,6 +1951,7 @@ impl LoanManager { env.storage().instance().set(&DataKey::MinScore, &min_score); Self::bump_instance_ttl(&env); events::min_score_updated(&env, old_score, min_score); + Ok(()) } pub fn set_max_loan_amount(env: Env, amount: i128) -> Result<(), LoanError> { diff --git a/contracts/loan_manager/src/test.rs b/contracts/loan_manager/src/test.rs index 06e4d952..dc86eb7e 100644 --- a/contracts/loan_manager/src/test.rs +++ b/contracts/loan_manager/src/test.rs @@ -629,6 +629,46 @@ fn test_set_interest_rate_zero_rejected() { assert_eq!(result, Err(Ok(LoanError::InvalidRate))); } +#[test] +fn test_set_min_score_updates_value() { + let env = Env::default(); + env.mock_all_auths_allowing_non_root_auth(); + + let (manager, _nft_client, _pool, _token, _token_admin) = setup_test(&env); + + manager.set_min_score(&700); + + assert_eq!(manager.get_min_score(), 700); +} + +#[test] +fn test_set_min_score_accepts_max_score_boundary() { + let env = Env::default(); + env.mock_all_auths_allowing_non_root_auth(); + + let (manager, _nft_client, _pool, _token, _token_admin) = setup_test(&env); + + manager.set_min_score(&850); + + assert_eq!(manager.get_min_score(), 850); +} + +#[test] +fn test_set_min_score_rejects_out_of_bounds_values() { + let env = Env::default(); + env.mock_all_auths_allowing_non_root_auth(); + + let (manager, _nft_client, _pool, _token, _token_admin) = setup_test(&env); + + let above_max = manager.try_set_min_score(&851); + assert_eq!(above_max, Err(Ok(LoanError::InvalidConfiguration))); + assert_eq!(manager.get_min_score(), 500); + + let zero = manager.try_set_min_score(&0); + assert_eq!(zero, Err(Ok(LoanError::InvalidConfiguration))); + assert_eq!(manager.get_min_score(), 500); +} + #[test] fn test_legacy_zero_interest_config_falls_back_to_default() { let env = Env::default();