Skip to content

feat(v2): implement TTL policy for all v2 record types - #119

Merged
collinsezedike merged 1 commit into
mainfrom
feat/v2-ttl-policy
Aug 28, 2026
Merged

feat(v2): implement TTL policy for all v2 record types#119
collinsezedike merged 1 commit into
mainfrom
feat/v2-ttl-policy

Conversation

@collinsezedike

Copy link
Copy Markdown
Collaborator

Closes #72

Summary

Implements TTL policy for all four of v2's long-lived record types (AssertionV2, Resolution, Position, Credit), per #72's scope.

Every write already re-extended TTL via a flat 30-day bump (INSTANCE_BUMP_AMOUNT), matching v1's constant. That's a hardcoded margin, not one sized from the deployment's actual policy: anti_snipe_hard_max_secs isn't capped today (that's #114/#116, still in review), and even once bounded at 29 days, anti_snipe_hard_max_secs + reveal_duration_secs can exceed 30 days on its own for a deployment configured with a long anti-snipe window and a long reveal window. A record whose TTL is sized independently of the round it belongs to can expire mid-round.

What changed

  • New record_bump(policy) helper computes the TTL bump (threshold, amount) in ledgers from that specific assertion's own pinned PolicySnapshotV2: anti_snipe_hard_max_secs + reveal_duration_secs + SETTLEMENT_GRACE_SECS (a fixed 7-day settlement/withdrawal grace period), floored at INSTANCE_BUMP_AMOUNT so this never shrinks the existing margin, only ever matches or exceeds it.
  • set_assertion, set_resolution, set_position, and add_credit all now compute their bump from this instead of the flat constant.
  • New permissionless bump_ttl(id, address). Position/Credit keys aren't enumerable on-chain (the design deliberately avoids an unbounded voter vector), so a record nobody happens to touch again before its own next write, a registered voter who never reveals, or unclaimed credit sitting past settlement, previously only got its TTL renewed if that address's own owner called reveal/settle/withdraw. Anyone who knows the (id, address) key can now renew it directly. A no-op (not an error) for any of the four entries that don't exist for a given id/address; fails only with AssertionNotFound if id itself doesn't exist.

On the issue's other requirements

  • Restoration path: Soroban's archival-restoration mechanic (a client-submitted RestoreFootprintOp) is transaction-level, not something contract code can trigger internally. Nothing in settle/withdraw/get_* assumes non-restorability, so a restored entry works normally once the client includes it in a transaction's footprint. bump_ttl reduces how often restoration is even needed by making proactive renewal permissionless.
  • Indexable events for key discovery: checked against [Feature] V2: implement reveal phase and commitment verification #67-[Feature] V2: implement credit accrual and owner-authorized withdrawal #70's events rather than assumed. Every Position/Credit key is already derivable without on-chain enumeration: fixed positions' keys come from Asserted+Disputed (both carry the address), external positions' from PositionFunded, and credit's from Settled/DustCredited (both carry the address). No new event needed for this requirement.

Test plan

  • cargo fmt --check, cargo clippy --workspace --all-targets -- -D warnings, and cargo test --workspace pass locally (104 tests in tholos-v2, all 100 pre-existing ones unchanged and passing, confirming the floor keeps default-policy behavior identical to before)
  • CONTRACT_V2.md updated: the TTL section now describes the sized calculation, and bump_ttl has its own function reference entry
  • Not applicable: scripts/testnet-smoke.sh covers v1 only
  • New tests: test_dispute_sizes_resolution_and_position_ttl_from_policy_when_larger_than_instance_bump (confirms a large anti_snipe_hard_max_secs produces a TTL bump exceeding the flat floor, with the exact expected ledger count), test_bump_ttl_extends_assertion_resolution_position_and_credit (full flow to all four record types populated, confirms bump_ttl restores every one to a full bump after partial decay), test_bump_ttl_on_nonexistent_assertion_fails, test_bump_ttl_is_noop_when_position_and_credit_do_not_exist_for_address

@collinsezedike
collinsezedike force-pushed the feat/v2-ttl-policy branch 2 times, most recently from 21f39d7 to c072dfc Compare August 28, 2026 00:25
@collinsezedike
collinsezedike merged commit e970055 into main Aug 28, 2026
4 checks passed
@collinsezedike
collinsezedike deleted the feat/v2-ttl-policy branch August 28, 2026 09:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] V2: implement TTL policy for all v2 record types

1 participant