Skip to content

Add domain-separated storage namespace to prevent key collisions acro… - #38

Merged
elizabetheonoja-art merged 1 commit into
Utility-Protocol:mainfrom
Adeyemi-cmd:Storage_Key_Collision_Between_Resource_Token_and_Tariff_Namespace
Jun 24, 2026
Merged

Add domain-separated storage namespace to prevent key collisions acro…#38
elizabetheonoja-art merged 1 commit into
Utility-Protocol:mainfrom
Adeyemi-cmd:Storage_Key_Collision_Between_Resource_Token_and_Tariff_Namespace

Conversation

@Adeyemi-cmd

Copy link
Copy Markdown
Contributor

Closes #9

PR description:

Domain-Separated Storage Namespace

Problem

All contract modules used raw #[contracttype] enum variants as storage keys
(e.g. DataKey::Admin, DataKey::Price). When multiple contracts share a
Soroban instance, identical discriminant values cause key collisions — e.g.,
DataKey::Admin in resource-token (discriminant 1) collides with
DataKey::Price in price_oracle (discriminant 0) if both are value 0.

Solution

Each contract module now prefixes every storage key with a unique 4-byte
namespace prefix before the XDR-serialized discriminant + payload:

Module Prefix Bytes
resource-token RESO 0x5245534f
price_oracle COMM 0x434f4d4d
tariff_oracle TARI 0x54415249
settlement SETL 0x5345544c

What changed

New crate: contracts/common/ — contains StorageNamespace trait with
scoped_key() and tests ensuring all prefixes are unique and keys stay
under 64 bytes.

resource-token (storage.rs):

  • DataKey::encode() prepends NAMESPACE_PREFIX to XDR-serialized key
  • All 12 storage functions refactored to use encoded keys
  • migrate_namespace() rewrites 3 singleton + N per-address keys

price_oracle (lib.rs):

  • DataKey::encode() prepends NAMESPACE_PREFIX to XDR-serialized key
  • All storage operations refactored
  • migrate_namespace() rewrites Admin, Updater, Price keys

utility_contracts (lib.rs):

  • DataKey::encode() dispatches tariff variants → TARIFF, others → COMMON
  • encode_raw_key() utility for non-DataKey keys (u64 settlement IDs)
  • settlement_key() helper using SETTLEMENT prefix
  • migrate_namespace() rewrites tariff oracle + common singleton keys

Bug fix

price_oracle xlm_to_usd_cents was dividing by 10^decimals, but the
price field is already in cents. Removed the erroneous division. The
existing test was never compiled (test module wasn't declared in lib.rs).

Testing

  • 27 tests pass across common (3), resource-token (20), price_oracle (4)
  • utility_contracts has ~30 pre-existing compilation errors (unrelated)

…ss contracts

Introduce a unique 4-byte prefix per contract module so that storage keys
are scoped and cannot collide when multiple contracts share an instance.

Changes:
  - Add utility-contracts-common crate with StorageNamespace trait
    providing scoped_key() and prefix uniqueness enforcement
  - Add NAMESPACE_PREFIX [u8; 4] constants:
      RESOURCE  = 0x5245534f  ("RESO")
      TARIFF    = 0x54415249  ("TARI")
      SETTLEMENT = 0x5345544c ("SETL")
      COMMON    = 0x434f4d4d ("COMM")
  - Implement DataKey::encode() in resource-token, price_oracle, and
    utility_contracts that serializes keys as
    namespace_prefix || xdr_discriminant || payload
  - Refactor all storage read/write operations in resource-token,
    price_oracle, tariff_oracle, and settlement to use scoped keys
  - Add migrate_namespace() entry point to each contract for rewriting
    legacy keys to scoped keys after upgrade
  - Fix pre-existing bug in price_oracle xlm_to_usd_cents that
    incorrectly divided by 10^decimals (price is already in cents)
  - Update resource-token test snapshots for new key format

@elizabetheonoja-art elizabetheonoja-art left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@elizabetheonoja-art
elizabetheonoja-art merged commit 878e454 into Utility-Protocol:main Jun 24, 2026
2 checks passed
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.

Storage Key Collision Between Resource Token and Tariff Namespace

2 participants