diff --git a/contracts/settlement/src/test.rs b/contracts/settlement/src/test.rs index 08f19c5..aa71965 100644 --- a/contracts/settlement/src/test.rs +++ b/contracts/settlement/src/test.rs @@ -317,7 +317,7 @@ mod settlement_tests { assert_eq!(client.get_vault(), new_vault); } - // ── admin rotation edge cases ──────────────────────────────────────────── + // ── admin rotation edge cases ──────────────────────────────────────────── #[test] fn test_set_admin_to_same_address_succeeds() { @@ -463,7 +463,7 @@ mod settlement_tests { ); } - // ── event emission tests ──────────────────────────────────────────────── + // ── event emission tests ──────────────────────────────────────────────── #[test] fn test_set_admin_emits_nomination_event() { @@ -532,7 +532,7 @@ mod settlement_tests { assert_eq!(topic_new, new_admin); } - // ── panic / error paths ────────────────────────────────────────────────── + // ── panic / error paths ────────────────────────────────────────────────── #[test] #[should_panic(expected = "settlement contract already initialized")] @@ -654,7 +654,7 @@ mod settlement_tests { } } - // ── event shape tests ──────────────────────────────────────────────────── + // ── event shape tests ──────────────────────────────────────────────────── #[test] fn test_payment_received_event_to_pool() { @@ -777,7 +777,7 @@ mod settlement_tests { assert_eq!(bc_data.new_balance, 500i128); } - // ── regression tests: ensure settlement logic intact after rotation ───── + // ── regression tests: ensure settlement logic intact after rotation ───── #[test] fn test_receive_payment_works_after_admin_rotation() { @@ -913,4 +913,58 @@ mod settlement_tests { assert_eq!(pool_after.last_updated, 1_700_000_100); assert_eq!(pool_after.total_balance, 1500i128); } + + /// `last_updated` reflects the ledger timestamp at the moment of each pool credit. + #[test] + fn test_global_pool_last_updated_on_receive_payment() { + let env = Env::default(); + env.mock_all_auths(); + + let admin = Address::generate(&env); + let vault = Address::generate(&env); + let addr = env.register(CalloraSettlement, ()); + let client = CalloraSettlementClient::new(&env, &addr); + + env.ledger().set_timestamp(1_000); + client.init(&admin, &vault); + assert_eq!(client.get_global_pool().last_updated, 1_000); + + // Advance time and credit pool � last_updated must change + env.ledger().set_timestamp(2_000); + client.receive_payment(&vault, &100i128, &true, &None); + let pool = client.get_global_pool(); + assert_eq!(pool.last_updated, 2_000); + assert_eq!(pool.total_balance, 100i128); + + // Advance again � each credit stamps the new time + env.ledger().set_timestamp(3_000); + client.receive_payment(&vault, &50i128, &true, &None); + let pool2 = client.get_global_pool(); + assert_eq!(pool2.last_updated, 3_000); + assert_eq!(pool2.total_balance, 150i128); + } + + /// Routing to a developer does NOT update `last_updated` on the global pool. + #[test] + fn test_global_pool_last_updated_unchanged_for_developer_payment() { + let env = Env::default(); + env.mock_all_auths(); + + let admin = Address::generate(&env); + let vault = Address::generate(&env); + let developer = Address::generate(&env); + let addr = env.register(CalloraSettlement, ()); + let client = CalloraSettlementClient::new(&env, &addr); + + env.ledger().set_timestamp(1_000); + client.init(&admin, &vault); + + env.ledger().set_timestamp(5_000); + client.receive_payment(&vault, &200i128, &false, &Some(developer.clone())); + + // Pool timestamp must still be the init timestamp + assert_eq!(client.get_global_pool().last_updated, 1_000); + assert_eq!(client.get_global_pool().total_balance, 0); + assert_eq!(client.get_developer_balance(&developer), 200i128); + } } diff --git a/contracts/vault/src/lib.rs b/contracts/vault/src/lib.rs index f27769b..d8d94a7 100644 --- a/contracts/vault/src/lib.rs +++ b/contracts/vault/src/lib.rs @@ -606,4 +606,4 @@ impl CalloraVault { mod test; #[cfg(test)] -mod test_init_hardening; +mod test_init_hardening; \ No newline at end of file diff --git a/contracts/vault/src/test.rs b/contracts/vault/src/test.rs index e05f35a..c3f471b 100644 --- a/contracts/vault/src/test.rs +++ b/contracts/vault/src/test.rs @@ -424,7 +424,7 @@ fn set_allowed_depositor_duplicate_is_ignored() { client.init(&owner, &usdc, &Some(100), &None, &None, &None, &None); client.set_allowed_depositor(&owner, &Some(depositor.clone())); - client.set_allowed_depositor(&owner, &Some(depositor.clone())); // duplicate — should be a no-op + client.set_allowed_depositor(&owner, &Some(depositor.clone())); // duplicate — should be a no-op // depositor can still deposit exactly once (list not doubled) usdc_admin.mint(&depositor, &50); @@ -920,7 +920,7 @@ fn batch_deduct_too_large_fails() { #[test] fn batch_deduct_fail_mid_batch_leaves_balance_unchanged() { - // Second item exceeds balance — entire batch must revert. + // Second item exceeds balance — entire batch must revert. let env = Env::default(); let owner = Address::generate(&env); let (vault_address, client) = create_vault(&env); @@ -1996,7 +1996,7 @@ fn test_deduct_with_settlement_success() { } // --------------------------------------------------------------------------- -// Checked arithmetic — overflow / underflow boundary tests +// Checked arithmetic — overflow / underflow boundary tests // --------------------------------------------------------------------------- #[test] @@ -2067,7 +2067,7 @@ fn withdraw_to_zero_succeeds() { } // --------------------------------------------------------------------------- -// Issue #108 — set_allowed_depositor: duplicate add, clear, unauthorized +// Issue #108 — set_allowed_depositor: duplicate add, clear, unauthorized // --------------------------------------------------------------------------- #[test]