Skip to main content

Dynamic types in storage

Description​

In Rust, storage.persistent() is useful for storing data shared among all users of a contract (e.g., a token administrator). However, using this macro with dynamic data structures (such as vectors, maps, etc.) is not recommended.

Why is this bad?​

Storing dynamic data with storage.persistent() can lead to excessive storage consumption and increase the risk of DoS attacks on the contract.

Issue example​

Consider the following function:


pub fn store_vector(e: Env, data: Vec<i32>) {
e.storage()
.persistent()
.set(&Symbol::new(&e, "vector_data"), &data);
}

In this example, the function is storing a vector using storage.persistent().

The code example can be found here.

Remediated example​

Consider the following function:

 pub fn store_vector(e: Env, data: Vec<i32>) {
for (i, value) in data.iter().enumerate() {
let key = DataKey::VecElement(i as u32);
e.storage().persistent().set(&key, &value);
}
}

Instead of using storage.persistent() to store a vector in the storage, the data belonging to the vector can be stored directly in the storage.

The remediated code example can be found here.

How is it detected?​

Checks the usage of storage().persistent() with dynamic types.