From 0ecb8dca70ebf5e6a20962f79ae1e9cd14548f62 Mon Sep 17 00:00:00 2001 From: Obiajulu-gif Date: Wed, 26 Aug 2026 20:19:16 +0100 Subject: [PATCH] test: cover mergefi edge cases --- contracts/escrow/src/error.rs | 1 + contracts/maintenance-pool/src/error.rs | 1 + contracts/maintenance-pool/src/lib.rs | 5 +-- contracts/maintenance-pool/src/test.rs | 14 ++++++++ contracts/milestones/src/error.rs | 1 + contracts/milestones/src/lib.rs | 3 +- contracts/milestones/src/test.rs | 43 +++++++++++++++++++++++++ 7 files changed, 65 insertions(+), 3 deletions(-) diff --git a/contracts/escrow/src/error.rs b/contracts/escrow/src/error.rs index a0c8535..23eebbc 100644 --- a/contracts/escrow/src/error.rs +++ b/contracts/escrow/src/error.rs @@ -3,6 +3,7 @@ use soroban_sdk::contracterror; #[contracterror] #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[repr(u32)] +#[non_exhaustive] pub enum Error { AlreadyInitialized = 1, NotInitialized = 2, diff --git a/contracts/maintenance-pool/src/error.rs b/contracts/maintenance-pool/src/error.rs index 95d6b2e..52c4c34 100644 --- a/contracts/maintenance-pool/src/error.rs +++ b/contracts/maintenance-pool/src/error.rs @@ -3,6 +3,7 @@ use soroban_sdk::contracterror; #[contracterror] #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[repr(u32)] +#[non_exhaustive] pub enum Error { AlreadyInitialized = 1, NotInitialized = 2, diff --git a/contracts/maintenance-pool/src/lib.rs b/contracts/maintenance-pool/src/lib.rs index 46ed5d1..2d86133 100644 --- a/contracts/maintenance-pool/src/lib.rs +++ b/contracts/maintenance-pool/src/lib.rs @@ -210,7 +210,8 @@ impl MaintenancePoolContract { Ok(()) } - pub fn get_pool(env: Env, pool_id: u64) -> Result { env.storage() + pub fn get_pool(env: Env, pool_id: u64) -> Result { + env.storage() .persistent() .get(&DataKey::Pool(pool_id)) .ok_or(Error::PoolNotFound) @@ -230,4 +231,4 @@ fn require_admin(env: &Env) -> Result { fn extend_ttl(env: &Env, key: &DataKey) { mergefi_common::extend_ttl(env, key); -} \ No newline at end of file +} diff --git a/contracts/maintenance-pool/src/test.rs b/contracts/maintenance-pool/src/test.rs index af8a4fc..0ce11c4 100644 --- a/contracts/maintenance-pool/src/test.rs +++ b/contracts/maintenance-pool/src/test.rs @@ -25,6 +25,20 @@ fn setup(env: &Env) -> (Address, Address, MaintenancePoolContractClient<'_>) { (admin, treasury, client) } +#[test] +fn test_get_pool_and_withdraw_reject_nonexistent_pool() { + let env = Env::default(); + env.mock_all_auths(); + let (_admin, _treasury, client) = setup(&env); + let maintainer = Address::generate(&env); + + let get_err = client.try_get_pool(&404u64); + assert_eq!(get_err, Err(Ok(Error::PoolNotFound))); + + let withdraw_err = client.try_withdraw(&404u64, &maintainer, &1i128); + assert_eq!(withdraw_err, Err(Ok(Error::PoolNotFound))); +} + #[test] fn test_deposit_accumulates_balance_and_history() { let env = Env::default(); diff --git a/contracts/milestones/src/error.rs b/contracts/milestones/src/error.rs index e0d7d45..46793bd 100644 --- a/contracts/milestones/src/error.rs +++ b/contracts/milestones/src/error.rs @@ -3,6 +3,7 @@ use soroban_sdk::contracterror; #[contracterror] #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[repr(u32)] +#[non_exhaustive] pub enum Error { AlreadyInitialized = 1, NotInitialized = 2, diff --git a/contracts/milestones/src/lib.rs b/contracts/milestones/src/lib.rs index 6cac2de..d6e17ce 100644 --- a/contracts/milestones/src/lib.rs +++ b/contracts/milestones/src/lib.rs @@ -360,7 +360,8 @@ impl MilestonesContract { Ok(()) } - pub fn get_milestone(env: Env, milestone_id: u64) -> Result { env.storage() + pub fn get_milestone(env: Env, milestone_id: u64) -> Result { + env.storage() .persistent() .get(&DataKey::Milestone(milestone_id)) .ok_or(Error::MilestoneNotFound) diff --git a/contracts/milestones/src/test.rs b/contracts/milestones/src/test.rs index 84f8d17..0d0243f 100644 --- a/contracts/milestones/src/test.rs +++ b/contracts/milestones/src/test.rs @@ -25,6 +25,19 @@ fn setup(env: &Env) -> (Address, Address, MilestonesContractClient<'_>) { (admin, treasury, client) } +#[test] +fn test_initialize_rejects_fee_bps_above_10000() { + let env = Env::default(); + env.mock_all_auths(); + let admin = Address::generate(&env); + let treasury = Address::generate(&env); + let contract_id = env.register(MilestonesContract, ()); + let client = MilestonesContractClient::new(&env, &contract_id); + + let err = client.try_initialize(&admin, &treasury, &10_001u32); + assert_eq!(err, Err(Ok(Error::InvalidFee))); +} + #[test] fn test_create_milestone_allocate_and_release_per_issue() { let env = Env::default(); @@ -68,6 +81,36 @@ fn test_create_milestone_allocate_and_release_per_issue() { ); } +#[test] +fn test_release_issue_with_zero_fee_pays_full_allocation() { + let env = Env::default(); + env.mock_all_auths(); + + let admin = Address::generate(&env); + let treasury = Address::generate(&env); + let contract_id = env.register(MilestonesContract, ()); + let client = MilestonesContractClient::new(&env, &contract_id); + client.initialize(&admin, &treasury, &0u32); + + let token_admin = Address::generate(&env); + let (token_addr, asset_client, token_client) = create_token(&env, &token_admin); + let sponsor = Address::generate(&env); + asset_client.mint(&sponsor, &1_000_0000000i128); + + client.create_milestone(&10u64, &sponsor, &token_addr, &1_000_0000000i128); + client.allocate(&10u64, &1001u64, &1_000_0000000i128); + + let maintainer = Address::generate(&env); + client.release_issue( + &10u64, + &1001u64, + &vec![&env, (maintainer.clone(), 10_000u32)], + ); + + assert_eq!(token_client.balance(&maintainer), 1_000_0000000i128); + assert_eq!(token_client.balance(&treasury), 0i128); +} + #[test] fn test_release_issue_distributes_rounding_dust_by_largest_remainder() { let env = Env::default();