Description
Soroban persistent storage entries expire after a network-defined number of ledgers unless their TTL is explicitly extended via bump calls; without proactive TTL management, invoice state can silently disappear mid-campaign and make escrowed funds irrecoverable. The contract needs a systematic bump strategy tied to every write path, plus a public entry point allowing anyone to extend a live invoice's TTL.
Technical Context
contracts/split/src/storage.rs — centralize all persistent writes in save_invoice(), save_recipients(), and save_contributor() helper functions; each helper calls env.storage().persistent().bump(key, MIN_INVOICE_TTL_LEDGERS, MAX_INVOICE_TTL_LEDGERS) immediately after set(); contracts/split/src/constants.rs — define MIN_INVOICE_TTL_LEDGERS: u32 and MAX_INVOICE_TTL_LEDGERS: u32 with inline comments documenting the rationale; contracts/split/src/lib.rs — add bump_invoice_ttl(invoice_id: u64) entry point callable by any address.
Acceptance Criteria
Description
Soroban persistent storage entries expire after a network-defined number of ledgers unless their TTL is explicitly extended via
bumpcalls; without proactive TTL management, invoice state can silently disappear mid-campaign and make escrowed funds irrecoverable. The contract needs a systematic bump strategy tied to every write path, plus a public entry point allowing anyone to extend a live invoice's TTL.Technical Context
contracts/split/src/storage.rs— centralize all persistent writes insave_invoice(),save_recipients(), andsave_contributor()helper functions; each helper callsenv.storage().persistent().bump(key, MIN_INVOICE_TTL_LEDGERS, MAX_INVOICE_TTL_LEDGERS)immediately afterset();contracts/split/src/constants.rs— defineMIN_INVOICE_TTL_LEDGERS: u32andMAX_INVOICE_TTL_LEDGERS: u32with inline comments documenting the rationale;contracts/split/src/lib.rs— addbump_invoice_ttl(invoice_id: u64)entry point callable by any address.Acceptance Criteria
env.storage().persistent().set()call insave_invoice(),save_recipients(), andsave_contributor()is immediately followed by abump()call using the constants fromconstants.rsMIN_INVOICE_TTL_LEDGERSandMAX_INVOICE_TTL_LEDGERSare defined incontracts/split/src/constants.rswith documented rationale for the chosen ledger countsbump_invoice_ttl(invoice_id)bumps allDataKeyentries associated with the given invoice and returnsError::InvoiceNotFoundfor unknown IDsenv.storage().persistent().set()calls exist outside of the centralized storage helper functions (enforced by agrep-based CI check in the Makefile or CI script)contracts/split/src/tests/ttl_tests.rsconfirms thatbump()is invoked with the correct key and minimum TTL value after each storage write