Add domain-separated storage namespace to prevent key collisions acro… - #38
Merged
Conversation
…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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 aSoroban instance, identical discriminant values cause key collisions — e.g.,
DataKey::Adminin resource-token (discriminant 1) collides withDataKey::Pricein 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:
RESO0x5245534fCOMM0x434f4d4dTARI0x54415249SETL0x5345544cWhat changed
New crate:
contracts/common/— containsStorageNamespacetrait withscoped_key()and tests ensuring all prefixes are unique and keys stayunder 64 bytes.
resource-token (
storage.rs):DataKey::encode()prependsNAMESPACE_PREFIXto XDR-serialized keymigrate_namespace()rewrites 3 singleton + N per-address keysprice_oracle (
lib.rs):DataKey::encode()prependsNAMESPACE_PREFIXto XDR-serialized keymigrate_namespace()rewrites Admin, Updater, Price keysutility_contracts (
lib.rs):DataKey::encode()dispatches tariff variants → TARIFF, others → COMMONencode_raw_key()utility for non-DataKey keys (u64 settlement IDs)settlement_key()helper using SETTLEMENT prefixmigrate_namespace()rewrites tariff oracle + common singleton keysBug fix
price_oraclexlm_to_usd_centswas dividing by10^decimals, but theprice field is already in cents. Removed the erroneous division. The
existing test was never compiled (test module wasn't declared in lib.rs).
Testing
utility_contractshas ~30 pre-existing compilation errors (unrelated)