Problem
The creditline contract tracks user_active_debt, loan counters, and per-user loan indexes in instance storage (see contracts/creditline-contract/src/storage.rs). Instance entries have a hard ledger footprint ceiling and a shared budget per contract instance. Every create_loan() appends to the borrower's paginated loan index and mutates debt counters; repay_loan() and repay_installment() mutate the same entries plus the loan body on every payment.
As a borrower's loan count grows, the instance entry holding their index grows linearly: read cost grows, and eventually the entry approaches Soroban's max instance size — at which point create_loan() (which writes the index) and repay_installment() (which writes loan + counters) start failing outright. A borrower who cannot repay is frozen mid-loan; a malicious actor can deliberately fragment many loans to hit the ceiling, and because mark_defaulted() also writes these entries, default handling can be made to fail — leaving defaulted principal locked in the pool forever with absorb_loss() unreachable.
TTL handling compounds it: verify whether every instance/persistent write in the repay/create paths extends TTL appropriately; an expired index entry mid-flow yields silent index loss (loan exists, invisible in listings, unreachable by the indexer).
Ground Rules
- Read context/architecture-context.md, context/code-standards.md, context/progress-tracker.md in full
- Read
contracts/creditline-contract/src/storage.rs in full and map every key to its storage class (instance vs persistent)
- Compare with
liquidity-pool-contract/src/storage.rs:123–139 which demonstrates the correct persistent-key + extend_ttl pattern
What To Build
- Move per-user loan indexes and debt counters from instance storage to persistent per-borrower keys with
extend_ttl after every write, mirroring the LP-shares pattern.
- Cap or chunk the index (e.g. fixed-size pages keyed
(borrower, page)) so no single entry can grow unbounded; document the pagination contract for consumers.
- Audit every write site in lib.rs for a paired
extend_ttl.
- Add a storage-layout regression test asserting entry classes and that a 200-loan borrower can still create and repay loans within footprint budgets.
Files To Touch
contracts/creditline-contract/src/storage.rs
contracts/creditline-contract/src/lib.rs
contracts/creditline-contract/src/tests.rs
context/progress-tracker.md
Acceptance Criteria
Mandatory Checks Before Opening PR
Standard Grantfox checklist applies.
Problem
The creditline contract tracks
user_active_debt, loan counters, and per-user loan indexes in instance storage (seecontracts/creditline-contract/src/storage.rs). Instance entries have a hard ledger footprint ceiling and a shared budget per contract instance. Everycreate_loan()appends to the borrower's paginated loan index and mutates debt counters;repay_loan()andrepay_installment()mutate the same entries plus the loan body on every payment.As a borrower's loan count grows, the instance entry holding their index grows linearly: read cost grows, and eventually the entry approaches Soroban's max instance size — at which point
create_loan()(which writes the index) andrepay_installment()(which writes loan + counters) start failing outright. A borrower who cannot repay is frozen mid-loan; a malicious actor can deliberately fragment many loans to hit the ceiling, and becausemark_defaulted()also writes these entries, default handling can be made to fail — leaving defaulted principal locked in the pool forever withabsorb_loss()unreachable.TTL handling compounds it: verify whether every instance/persistent write in the repay/create paths extends TTL appropriately; an expired index entry mid-flow yields silent index loss (loan exists, invisible in listings, unreachable by the indexer).
Ground Rules
contracts/creditline-contract/src/storage.rsin full and map every key to its storage class (instance vs persistent)liquidity-pool-contract/src/storage.rs:123–139which demonstrates the correct persistent-key +extend_ttlpatternWhat To Build
extend_ttlafter every write, mirroring the LP-shares pattern.(borrower, page)) so no single entry can grow unbounded; document the pagination contract for consumers.extend_ttl.Files To Touch
contracts/creditline-contract/src/storage.rscontracts/creditline-contract/src/lib.rscontracts/creditline-contract/src/tests.rscontext/progress-tracker.mdAcceptance Criteria
extend_ttlMandatory Checks Before Opening PR
Standard Grantfox checklist applies.