You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This document describes on-chain storage keys and value shapes for every workspace contract:
remittance_split
savings_goals
bill_payments
insurance
family_wallet
reporting
orchestrator
data_migration
Scope: current implementation in this repository, focused on auditability and migration planning.
Storage Key Naming Conventions
All storage keys follow strict naming conventions to ensure consistency and compatibility with Soroban's symbol_short! macro:
Maximum length: 9 characters (enforced by symbol_short!)
Format: UPPERCASE_WITH_UNDERSCORES
Valid characters: A-Z, 0-9, _ (underscore)
These conventions are automatically validated in CI by three complementary test suites: a hand-maintained catalogue check (storage_key_naming_test.rs), a live source scan (storage_key_source_scan_test.rs) that parses each contract's src/lib.rs directly so a key added or renamed in code can't silently drift out of sync with the documented conventions, and a reserved-key check (reserved_storage_keys_test.rs) that fails the build if a contract reuses a key set aside for a future roadmap feature. See Storage Key Naming Conventions for detailed guidelines, Reserved Storage Keys for the list of keys not yet available for reuse, and testutils/tests/README.md for information about the automated validation tests.
Run validation tests:
# Catalogue check + live source scan
cargo test --package testutils storage_key -- --nocapture
Common Patterns
Storage scope
Most contracts use env.storage().instance().
savings_goals additionally writes NEXT_ID and GOALS to persistent() in init (legacy bootstrap path), while runtime operations use instance keys.
TTL bump strategy
Most contracts define:
INSTANCE_LIFETIME_THRESHOLD = 17280 (~1 day)
INSTANCE_BUMP_AMOUNT = 518400 (~30 days)
Archive-enabled contracts also define:
ARCHIVE_LIFETIME_THRESHOLD = 17280
ARCHIVE_BUMP_AMOUNT = 2592000 (~180 days)
Important implementation detail:
Archive bump helpers still call instance().extend_ttl(...); they extend the contract instance entry TTL, not a separate archive namespace.
Shared TTL-bump helpers (remitwise-common)
remitwise-common exports three helpers that centralise the canonical TTL policy:
Helper
Threshold
Bump
Purpose
bump_instance(env)
INSTANCE_LIFETIME_THRESHOLD (1 day)
INSTANCE_BUMP_AMOUNT (30 days)
Active instance data
bump_persistent(env, key)
PERSISTENT_LIFETIME_THRESHOLD (15 days)
PERSISTENT_BUMP_AMOUNT (60 days)
Persistent storage entries
bump_archive(env)
ARCHIVE_LIFETIME_THRESHOLD (1 day)
ARCHIVE_BUMP_AMOUNT (150 days)
Archive instance window
Using these helpers prevents the common mistake of swapping threshold and bump arguments. See docs/ttl-bump-helpers.md for usage guidance.
ID allocation patterns
Monotonic counters via NEXT_* keys:
NEXT_ID, NEXT_SSCH, NEXT_PSCH, NEXT_RSCH, NEXT_TX
Pattern is generally:
read current counter with default 0 (or 1 for family_wallet init),
Replay protection for owner-authorized mutating calls
AUDIT
Vec<AuditEntry>
Rotating audit log, max MAX_AUDIT_ENTRIES (100)
REM_SCH
Map<u32, RemittanceSchedule>
Remittance schedules
NEXT_RSCH
u32
Next remittance schedule ID
PAUSE_ADM
Address
Pause admin
PAUSED
bool
Global pause flag
PAUSED_AT
u64
Timestamp when contract was paused
UPG_ADM
Address
Upgrade admin
VERSION
u32
Contract version
Keys and value types (persistent storage)
Key
Type
Notes
Schedule(u32)
RemittanceSchedule
Individual remittance schedule
OwnerSchedules
Vec<u32>
Per-owner index of schedule IDs, ordered by ID ascending
TTL and IDs
Instance TTL: CONFIG, SPLIT, and other administrative keys are bumped on every access (read/write) using INSTANCE_BUMP_AMOUNT / INSTANCE_LIFETIME_THRESHOLD.
Persistent TTL: RemittanceSchedule and the OwnerSchedules index are bumped on every access using PERSISTENT_BUMP_AMOUNT / PERSISTENT_LIFETIME_THRESHOLD.