-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3911388
commit 747a208
Showing
1 changed file
with
52 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
# Dynamic types in storage | ||
|
||
## Description | ||
|
||
- Category: `Authorization` | ||
- Severity: `Critical` | ||
- Detectors: [`dynamic-instance-storage`](https://github.com/CoinFabrik/scout-soroban/tree/main/detectors/dynamic-instance-storage) | ||
- Test Cases: [`dynamic-instance-storage-1`](https://github.com/CoinFabrik/scout-soroban/tree/main/test-cases/dynamic-instance-storage/dynamic-instance-storage-1) [`dynamic-instance-storage-2`](https://github.com/CoinFabrik/scout-soroban/tree/main/test-cases/dynamic-instance-storage/dynamic-instance-storage-2) [`dynamic-instance-storage-3`](https://github.com/CoinFabrik/scout-soroban/tree/main/test-cases/dynamic-instance-storage/dynamic-instance-storage-3) | ||
|
||
In Rust, it is very useful to use `storage.persistent()` to store data that is shared among all users of the contract (e.g., a token administrator). However, using this macro with dynamic variables (such as vectors, maps, etc.) is not recommended. | ||
|
||
## Why is this bad? | ||
|
||
Using dynamic values with `storage.persistent()` can cause excessive storage use and may risk DoS attacks on the contract. | ||
|
||
## Issue example | ||
|
||
Consider the following `Soroban` contract: | ||
|
||
```rust | ||
|
||
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](https://github.com/CoinFabrik/scout-soroban/tree/main/test-cases/dynamic-instance-storage/dynamic-instance-storage-1/vulnerable-example). | ||
|
||
## Remediated example | ||
|
||
Consider the following `Soroban` contract: | ||
|
||
```rust | ||
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](https://github.com/CoinFabrik/scout-soroban/tree/main/test-cases/dynamic-instance-storage/dynamic-instance-storage-1/remediated-example). | ||
|
||
## How is it detected? | ||
|
||
Checks the usage of `storage().persistent()` with dynamic types. |