- Category: storage_keys
- Severity: Medium
- Rule name:
storage_collision
S005 walks storage accesses and tracks the literal keys used per storage tier (instance, persistent, temporary). When the same key value is reused for different data types within the same tier, it reports a potential collision. It distinguishes keys by their (storage_type, key_value) pair and flags reuse across distinct value types or distinct data domains.
A storage key uniquely identifies a ledger entry within a tier. If two unrelated pieces of data are written under the same key, one write silently overwrites the other, and a later read deserializes bytes that were never meant for it. The result is cross-feature data corruption that is hard to reproduce and easy to miss in review.
#![no_std]
use soroban_sdk::{contract, contractimpl, symbol_short, Address, Env};
#[contract]
pub struct Vault;
#[contractimpl]
impl Vault {
pub fn set_owner(env: Env, owner: Address) {
// S005: "data" reused for an Address ...
env.storage().instance().set(&symbol_short!("data"), &owner);
}
pub fn set_total(env: Env, total: i128) {
// ... and here reused for an i128 — same key, different type.
env.storage().instance().set(&symbol_short!("data"), &total);
}
}#![no_std]
use soroban_sdk::{contract, contractimpl, contracttype, Address, Env};
#[contracttype]
pub enum DataKey {
Owner,
Total,
}
#[contract]
pub struct Vault;
#[contractimpl]
impl Vault {
pub fn set_owner(env: Env, owner: Address) {
// Distinct, typed key variant per data domain.
env.storage().instance().set(&DataKey::Owner, &owner);
}
pub fn set_total(env: Env, total: i128) {
env.storage().instance().set(&DataKey::Total, &total);
}
}- Vector:
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:H/A:L - Base score: 5.9
- Rating: Medium
Triggering a meaningful collision generally requires a specific call ordering (higher complexity), but the consequence — silent overwrite of unrelated state — is a high integrity impact.
- Use a single typed key enum (
#[contracttype] enum DataKey { ... }) so each data domain has its own variant. - Give each domain a unique prefix; avoid reusing the same
symbol_short!/Symbolfor different value types. - Never key two different types off the same literal within one storage tier.