This document defines the naming conventions for storage keys used across all Remitwise smart contracts. These conventions ensure consistency, readability, and compatibility with Soroban's symbol_short! macro constraints.
Storage keys must not exceed 9 characters in length. This is a hard constraint imposed by Soroban's symbol_short! macro, which pre-computes short symbols at compile time for optimal performance.
Rationale:
symbol_short!generates compile-time constants for symbols up to 9 characters- Symbols exceeding 9 characters require
Symbol::new()at runtime, which is less efficient - Shorter keys reduce storage costs and improve contract performance
Examples:
✅ const KEY_PAUSE_ADM: Symbol = symbol_short!("PAUSE_ADM"); // 9 chars - OK
✅ const KEY_NEXT_ID: Symbol = symbol_short!("NEXT_ID"); // 7 chars - OK
❌ const KEY_PAUSE_ADMIN: Symbol = symbol_short!("PAUSE_ADMIN"); // 11 chars - TOO LONGAll storage keys must use UPPERCASE letters with underscores as word separators.
Rationale:
- Distinguishes storage keys from other identifiers
- Follows Rust constant naming conventions
- Improves code readability and maintainability
Valid characters:
- Uppercase letters:
A-Z - Underscores:
_ - Numbers:
0-9(not at the start)
Examples:
✅ "PAUSE_ADM" // Correct
✅ "NEXT_ID" // Correct
✅ "MS_WDRAW" // Correct
❌ "pause_adm" // Lowercase not allowed
❌ "PauseAdm" // Mixed case not allowed
❌ "PAUSE-ADM" // Hyphens not allowedStorage keys should not start or end with underscores.
Examples:
✅ "PAUSE_ADM" // Correct
❌ "_PAUSE_ADM" // Leading underscore
❌ "PAUSE_ADM_" // Trailing underscoreAvoid using multiple consecutive underscores.
Examples:
✅ "PAUSE_ADM" // Correct
❌ "PAUSE__ADM" // Consecutive underscoresKeys should be descriptive enough to understand their purpose while staying within the 9-character limit. Use common abbreviations when necessary.
Common Abbreviations:
ADM- AdminSCH- SchedulePREM- PremiumREM- RemittanceSAV- SavingsARCH- ArchiveSTOR- StorageSTAT- Statistics/StatusCONF- ConfigurationEM- EmergencyMS- MultiSigUNPD- UnpaidPEND- PendingEXEC- ExecutedUPG- UpgradeOWN- OwnerIDX- Index
The following keys are used consistently across multiple contracts:
| Key | Purpose | Used In |
|---|---|---|
PAUSE_ADM |
Pause admin address | remittance_split, savings_goals, bill_payments, insurance, family_wallet |
PAUSED |
Global pause flag | remittance_split, savings_goals, bill_payments, insurance, family_wallet |
UPG_ADM |
Upgrade admin address | remittance_split, savings_goals, bill_payments, insurance, family_wallet |
VERSION |
Contract version | remittance_split, savings_goals, bill_payments, insurance, family_wallet |
NEXT_ID |
Next entity ID counter | savings_goals, bill_payments, insurance |
AUDIT |
Audit log entries | remittance_split, savings_goals, orchestrator |
NONCES |
Replay protection nonces | remittance_split, savings_goals |
CONFIG- Owner + percentages + initialized flagSPLIT- Ordered percentagesREM_SCH- Remittance schedulesNEXT_RSCH- Next remittance schedule ID
GOALS- Primary goal recordsSAV_SCH- Recurring savings schedulesNEXT_SSCH- Next savings schedule IDPAUSED_FN- Per-function pause switchesUNP_AT- Optional time-locked unpause timestamp
BILLS- Active bill recordsARCH_BILL- Archived paid billsSTOR_STAT- Aggregated storage metricsUNPD_TOT- Unpaid totals by owner
POLICIES- Insurance policy recordsPREM_SCH- Premium schedulesNEXT_PSCH- Next premium schedule IDOWN_IDX- Owner index for policies
OWNER- Wallet ownerMEMBERS- Family members and rolesMS_WDRAW- Multisig config for large withdrawalsMS_SPLIT- Multisig config for split changesMS_ROLE- Multisig config for role changesMS_EMERG- Multisig config for emergency transferMS_POL- Multisig config for policy cancellationMS_REG- Config key for regular withdrawalsPEND_TXS- Pending multisig transactionsEXEC_TXS- Executed transaction markersNEXT_TX- Next pending tx IDEM_CONF- Emergency transfer constraintsEM_MODE- Emergency mode toggleEM_LAST- Last emergency transfer timestampARCH_TX- Archived executed transaction metadataROLE_EXP- Role expiry timestampsACC_AUDIT- Rolling access audit trailPROP_EXP- Proposal expiry duration
ADMIN- Reporting adminADDRS- Cross-contract address registryREPORTS- Active reportsARCH_RPT- Archived report summaries
STATS- Aggregate execution counters
Storage key naming conventions are automatically validated in CI through the storage_key_naming_test test suite located in testutils/tests/storage_key_naming_test.rs.
# Run all storage key validation tests
cargo test --package testutils storage_key_naming_test -- --nocapture
# Run specific test
cargo test --package testutils test_all_keys_within_max_length -- --nocaptureThe automated tests validate:
- Length Constraint - All keys are ≤ 9 characters
- Format Validation - All keys use UPPERCASE_WITH_UNDERSCORES
- No Duplicates - No duplicate keys within a contract
- Non-Empty - All keys are non-empty strings
- No Leading Underscores - Keys don't start with
_ - No Trailing Underscores - Keys don't end with
_ - No Consecutive Underscores - Keys don't contain
__ - Documentation Coverage - All keys have descriptions
- Consistency Check - Common keys are used consistently
The storage key validation runs automatically on every pull request and push to main through the GitHub Actions workflow defined in .github/workflows/ci.yml.
The storage-key-validation job will fail if any naming convention violations are detected, preventing non-compliant keys from being merged.
When adding a new storage key:
- Choose a descriptive name that clearly indicates the key's purpose
- Keep it under 9 characters using abbreviations if necessary
- Use UPPERCASE_WITH_UNDERSCORES format
- Check for consistency - if a similar key exists in other contracts, use the same name
- Update the test - add the new key to
testutils/tests/storage_key_naming_test.rs - Document it - add the key to
STORAGE_LAYOUT.mdand this document - Run tests - verify all validation tests pass before committing
// ✅ Good example
const KEY_RATE_LIM: Symbol = symbol_short!("RATE_LIM"); // 8 chars, clear purpose
// ❌ Bad examples
const KEY_RATE_LIMITER: Symbol = symbol_short!("RATE_LIMITER"); // 12 chars - too long
const KEY_RL: Symbol = symbol_short!("RL"); // 2 chars - too cryptic
const KEY_rate_lim: Symbol = symbol_short!("rate_lim"); // lowercase - wrong format- STORAGE_LAYOUT.md - Complete storage layout documentation
- Soroban Storage Documentation
- Soroban Symbol Documentation
- 2025-01-XX - Initial documentation created with automated validation tests