Priority: High · Area: Soroban contract / state archival · Est. effort: 8–12 h
📌 Problem
Soroban archives ledger entries whose TTL lapses. An archived persistent entry is unreadable until explicitly restored; an archived instance entry takes the contract instance with it.
This contract does manage TTL — grep -rn 'extend_ttl\|extend_instance' src/ returns 27 sites, which is a genuinely better starting point than many Soroban codebases. But the storage surface is larger:
env.storage().persistent() — 37 uses
env.storage().instance() — 13 uses
The gap between 27 and 50 is what this issue asks you to characterise. It is not automatically a defect: a single extend_ttl may correctly cover several reads of the same key, and some entries may be intentionally short-lived. The deliverable is establishing which of the 50 sites are covered, which are deliberately not, and which are genuine gaps.
The failure mode if there are gaps: an anchor, liquidity entry or settlement record created and left for longer than the default TTL — an ordinary lifecycle for a settlement awaiting execution — can be archived out from under the contract. The next operation then fails against a record that logically still exists.
🎯 Design decision required
State and defend:
- Coverage model. After the audit, decide how coverage should be guaranteed going forward: typed accessors in
storage.rs that bump internally, entrypoint-boundary bumps, or an explicit keeper entrypoint. Argue which, and how it prevents new code from silently bypassing it.
- Instance TTL. Establish whether instance storage is extended and where. Instance archival is the most severe failure mode, so it warrants an explicit answer even if the audit shows it is already handled.
- Rent and abuse. Who pays for extensions, and can an attacker drive the contract into paying to keep adversarial entries alive? State the answer for your chosen model.
🧩 Requirements and context
- The audit table is the primary deliverable: every persistent and instance storage site, whether its key's TTL is extended, and where.
- Thresholds must have a single source of truth. If constants already exist in
src/storage.rs, use them; do not introduce a second set.
- Soroban test utilities can advance ledger sequence, so TTL behaviour is testable in-crate. "Untestable" is not an accepted reason to skip tests.
- Report the wasm byte delta; the contract's size is currently unmeasured (tracked separately).
- Do not change storage keys or the data model.
🛠️ Suggested execution
- Produce the 50-site audit table; post it in the PR before writing code.
- For any gap, write a failing test — create the record, advance the ledger past the threshold, show the read fails.
- Implement the coverage model.
- Show the tests passing.
- Add an instance-storage survival test.
✅ Acceptance criteria
🚫 Out of scope
- Restoring already-archived entries (
RestoreFootprint) — this is prevention only.
- Changing storage keys or the data model.
- The wasm size guard — separate issue.
🧪 Verification
cargo test
cargo build --target wasm32-unknown-unknown --release
grep -rn "storage()\.persistent()\|storage()\.instance()" src/ | wc -l
cargo fmt --all -- --check
📤 What your PR must include
- The 50-site audit table with coverage before and after.
- Your coverage model and how it prevents future bypass.
- The rent/abuse analysis.
- Failing-then-passing test output for each gap.
Closes #<n>.
🔒 Security notes
This is a funds-and-records availability issue. If an entry backing a settlement or a liquidity position archives while the position is still live, the operation that depends on it fails against a record that logically exists, and recovery needs an explicit restore that nothing in the contract or its documentation currently describes. The longer the gap between creating a record and acting on it, the more likely this becomes — and settlements awaiting execution are exactly that case.
📋 Guidelines
- Minimum 95% test coverage on changed lines
- Clear documentation
- Timeframe: 96 hours from assignment
- One logical change per commit; no merge commits
💬 Join our community
Working on this, or want to sanity-check your approach before you start? Come and ask — the maintainers are there and happy to help.
Telegram: https://t.me/Grainlify
Priority: High · Area: Soroban contract / state archival · Est. effort: 8–12 h
📌 Problem
Soroban archives ledger entries whose TTL lapses. An archived persistent entry is unreadable until explicitly restored; an archived instance entry takes the contract instance with it.
This contract does manage TTL —
grep -rn 'extend_ttl\|extend_instance' src/returns 27 sites, which is a genuinely better starting point than many Soroban codebases. But the storage surface is larger:env.storage().persistent()— 37 usesenv.storage().instance()— 13 usesThe gap between 27 and 50 is what this issue asks you to characterise. It is not automatically a defect: a single
extend_ttlmay correctly cover several reads of the same key, and some entries may be intentionally short-lived. The deliverable is establishing which of the 50 sites are covered, which are deliberately not, and which are genuine gaps.The failure mode if there are gaps: an anchor, liquidity entry or settlement record created and left for longer than the default TTL — an ordinary lifecycle for a settlement awaiting execution — can be archived out from under the contract. The next operation then fails against a record that logically still exists.
🎯 Design decision required
State and defend:
storage.rsthat bump internally, entrypoint-boundary bumps, or an explicit keeper entrypoint. Argue which, and how it prevents new code from silently bypassing it.🧩 Requirements and context
src/storage.rs, use them; do not introduce a second set.🛠️ Suggested execution
✅ Acceptance criteria
cargo testpasses; wasm byte delta reported.🚫 Out of scope
RestoreFootprint) — this is prevention only.🧪 Verification
📤 What your PR must include
Closes #<n>.🔒 Security notes
This is a funds-and-records availability issue. If an entry backing a settlement or a liquidity position archives while the position is still live, the operation that depends on it fails against a record that logically exists, and recovery needs an explicit restore that nothing in the contract or its documentation currently describes. The longer the gap between creating a record and acting on it, the more likely this becomes — and settlements awaiting execution are exactly that case.
📋 Guidelines
💬 Join our community
Working on this, or want to sanity-check your approach before you start? Come and ask — the maintainers are there and happy to help.
Telegram: https://t.me/Grainlify