From 49edffee976265bae73d14d511b01291d2ae0b60 Mon Sep 17 00:00:00 2001 From: hj Date: Tue, 27 Oct 2026 11:38:27 +0800 Subject: [PATCH] fix(ttl): extend instance storage TTL in keep_alive across all contracts (#566) --- contracts/escrow/src/lib.rs | 2 ++ contracts/escrow/src/test.rs | 30 ++++++++++++++++++++++++++ contracts/maintenance-pool/src/lib.rs | 2 ++ contracts/maintenance-pool/src/test.rs | 30 ++++++++++++++++++++++++++ contracts/milestones/src/lib.rs | 2 ++ contracts/milestones/src/test.rs | 30 ++++++++++++++++++++++++++ 6 files changed, 96 insertions(+) diff --git a/contracts/escrow/src/lib.rs b/contracts/escrow/src/lib.rs index d5c83c5b..d6e95730 100644 --- a/contracts/escrow/src/lib.rs +++ b/contracts/escrow/src/lib.rs @@ -786,6 +786,8 @@ mod contract { extend_ttl_for_target(&env, &contribution_key, target); } + extend_instance_ttl(&env); + Ok(()) } diff --git a/contracts/escrow/src/test.rs b/contracts/escrow/src/test.rs index 87a014a7..ed4d509c 100644 --- a/contracts/escrow/src/test.rs +++ b/contracts/escrow/src/test.rs @@ -3346,3 +3346,33 @@ fn test_set_admin_requires_current_and_new_admin_auth() { client.set_admin(&third_admin); assert_eq!(client.get_admin(), third_admin); } + +// ── Regression: issue #566 ──────────────────────────────────────────────────── + +#[test] +fn test_keep_alive_refreshes_instance_ttl() { + use soroban_sdk::testutils::storage::Instance as _; + let env = Env::default(); + env.mock_all_auths(); + let (contract_id, _admin, _treasury, client) = setup(&env); + + 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, &10_000i128); + + client.fund(&566u64, &sponsor, &token_addr, &10_000i128, &10_000_000u64, &None); + + // Advance ledger past the instance threshold (500_000 - 450_000 = 50_000 < 100_000). + env.ledger().set_sequence_number(450_000); + let ttl_before = env.as_contract(&contract_id, || env.storage().instance().get_ttl()); + assert_eq!(ttl_before, 50_000); + + // Calling only keep_alive must extend instance storage back to 500_000 ledgers. + env.set_auths(&[]); + client.keep_alive(&566u64); + + let ttl_after = env.as_contract(&contract_id, || env.storage().instance().get_ttl()); + assert_eq!(ttl_after, 500_000); +} + diff --git a/contracts/maintenance-pool/src/lib.rs b/contracts/maintenance-pool/src/lib.rs index a17cbe54..8fb2bf29 100644 --- a/contracts/maintenance-pool/src/lib.rs +++ b/contracts/maintenance-pool/src/lib.rs @@ -614,6 +614,8 @@ mod contract { extend_ttl(&env, &DataKey::Deposit(pool_id, i)); } + extend_instance_ttl(&env); + PoolKeptAlive { pool_id }.publish(&env); Ok(()) } diff --git a/contracts/maintenance-pool/src/test.rs b/contracts/maintenance-pool/src/test.rs index 155ee2c9..45b3222a 100644 --- a/contracts/maintenance-pool/src/test.rs +++ b/contracts/maintenance-pool/src/test.rs @@ -1683,3 +1683,33 @@ fn test_deposit_rejects_zero_received_with_fee_on_transfer_token() { let err = client.try_deposit(&101u64, &sponsor, &token_addr, &500i128); assert_eq!(err, Err(Ok(Error::InvalidAmount))); } + +// ── Regression: issue #566 ──────────────────────────────────────────────────── + +#[test] +fn test_keep_alive_refreshes_instance_ttl() { + use soroban_sdk::testutils::storage::Instance as _; + let env = Env::default(); + env.mock_all_auths(); + let (_admin, _treasury, client) = setup(&env); + + let token_admin = Address::generate(&env); + let (token_addr, asset_client, _) = create_token(&env, &token_admin); + let sponsor = Address::generate(&env); + asset_client.mint(&sponsor, &10_000i128); + + client.deposit(&566u64, &sponsor, &token_addr, &10_000i128); + + // Advance ledger past the instance threshold (500_000 - 450_000 = 50_000 < 100_000). + env.ledger().set_sequence_number(450_000); + let ttl_before = env.as_contract(&client.address, || env.storage().instance().get_ttl()); + assert_eq!(ttl_before, 50_000); + + // Calling only keep_alive must extend instance storage back to 500_000 ledgers. + env.set_auths(&[]); + client.keep_alive(&566u64); + + let ttl_after = env.as_contract(&client.address, || env.storage().instance().get_ttl()); + assert_eq!(ttl_after, 500_000); +} + diff --git a/contracts/milestones/src/lib.rs b/contracts/milestones/src/lib.rs index 5e3d8347..4a60c12b 100644 --- a/contracts/milestones/src/lib.rs +++ b/contracts/milestones/src/lib.rs @@ -999,6 +999,8 @@ mod contract { extend_ttl(&env, &DataKey::IssueStatus(milestone_id, issue_id)); } + extend_instance_ttl(&env); + MilestoneKeptAlive { milestone_id }.publish(&env); Ok(()) } diff --git a/contracts/milestones/src/test.rs b/contracts/milestones/src/test.rs index 7ab259b6..2e5f99a6 100644 --- a/contracts/milestones/src/test.rs +++ b/contracts/milestones/src/test.rs @@ -2770,3 +2770,33 @@ fn test_create_milestone_accepts_future_deadline() { // deadline = 501 > 500: must succeed client.create_milestone(&1u64, &sponsor, &token_addr, &1_000i128, &501u64); } + +// ── Regression: issue #566 ──────────────────────────────────────────────────── + +#[test] +fn test_keep_alive_refreshes_instance_ttl() { + use soroban_sdk::testutils::storage::Instance as _; + let env = Env::default(); + env.mock_all_auths(); + let (_admin, _treasury, client) = setup(&env); + + let token_admin = Address::generate(&env); + let (token_addr, asset_client, _) = create_token(&env, &token_admin); + let sponsor = Address::generate(&env); + asset_client.mint(&sponsor, &10_000i128); + + client.create_milestone(&566u64, &sponsor, &token_addr, &10_000i128, &10_000_000u64); + + // Advance ledger past the instance threshold (500_000 - 450_000 = 50_000 < 100_000). + env.ledger().set_sequence_number(450_000); + let ttl_before = env.as_contract(&client.address, || env.storage().instance().get_ttl()); + assert_eq!(ttl_before, 50_000); + + // Calling only keep_alive must extend instance storage back to 500_000 ledgers. + env.set_auths(&[]); + client.keep_alive(&566u64); + + let ttl_after = env.as_contract(&client.address, || env.storage().instance().get_ttl()); + assert_eq!(ttl_after, 500_000); +} +