In this tutorial, we’ll explore how data is stored on Stellar’s Soroban smart contract platform, focusing on Soroban’s state management and the types of storage available.
Understanding these concepts will allow you to manage data optimally and keep your decentralized applications efficient.
Introduction to Soroban State Management
Blockchain technology has evolved significantly since Bitcoin’s initial design, which featured simple data storage with 10-minute block times. Today, web3 developers often write code that resembles backend server-side logic, demanding faster confirmations and efficient data storage.
However, on many smart contract platforms, all on-chain data, every transaction, token swap, or NFT purchase, is stored permanently by each node on the network. This accumulation of data, called state bloat, can increase costs for validators and reduce network efficiency and scalability.
Soroban addresses this by introducing a rental model for persistent storage. Here’s an overview of how Soroban manages data storage and mitigates state bloat.
Soroban’s Storage Rental Model
Soroban tackles state bloat by making persistent storage subject to a rental fee. Here’s how the model works:
- Prepaid Rent Developers prepay rent in XLM for their contract’s code and data storage.
- Extend TTL As time passes, developers can extend the “time to live” (TTL) by topping up the rent.
- Data Archival If rent expires, the data moves to an off-chain archive. To retrieve archived data, simply pay the rent again, and it’s restored on-chain.
The state archival system uses a Merkle tree structure for verification, ensuring that data restoration is secure and reliable. By allowing developers to restore archived contracts and data to their original locations, Soroban effectively prevents stale data from clogging the network and promotes sustainable blockchain operations.
Soroban Data Locations
Soroban provides three primary storage types within env.storage, each tailored to different use cases. Let’s go over these storage types:
Persistent Storage
Persistent storage is designed for data that needs to remain accessible over extended periods. Persistent entries may expire if their rent balance depletes, but they can be restored without being recreated. This makes persistent storage ideal for critical information that requires long-term retention.
Temporary Storage
Temporary storage is best for short-lived data or data that can be easily recreated. More cost-effective than persistent storage, entries in temporary storage are automatically removed from the ledger after their designated lifetime.
Instance Storage
Instance storage is directly associated with the contract instance and is suitable for small amounts of data closely tied to the contract, like configuration settings. This storage type is limited to around 100 KB per entry.
Soroban Storage Methods
Soroban provides several methods for each storage location to manage data across these storage types.
has() | Checks if a key exists in storage, returning true or false |
get() | Fetches a value by passing in a key, returning an option |
set() | Sets a value to a key |
update() | Updates the value associated with a key |
try_update() | Similar to update, but for cases where you’re unsure about the data state |
extend_ttl() | Extends the time-to-live for data stored under a specified key |
remove() | Deletes a key-value pair from storage |
Full details here: https://docs.rs/soroban-sdk/latest/soroban_sdk/storage/struct.Persistent.html
Now, let’s walk through an example where we store persistent data on Soroban. This example will help you understand how to write, retrieve, and extend data on-chain using Soroban’s storage methods.
Full code for this is available here: https://github.com/jamesbachini/Soroban-Data/
#![no_std]
use soroban_sdk::{contract, contractimpl, Env, Symbol};
#[contract]
pub struct SorobanData;
#[contractimpl]
impl SorobanData{
pub fn set(env: &Env, key: Symbol, value: Symbol) {
env.storage().persistent().set(&key, &value);
env.storage().instance().set(&key, &value);
env.storage().temporary().set(&key, &value);
}
pub fn get(env: &Env, key: Symbol) -> Option<Symbol> {
env.storage().persistent().get(&key)
}
pub fn extend(env: Env, key: Symbol) {
let max_ttl = env.storage().max_ttl();
env.storage().persistent().extend_ttl(&key, max_ttl, max_ttl);
env.storage().instance().extend_ttl(max_ttl, max_ttl);
}
}
mod test;
This code defines a basic Soroban smart contract that demonstrates how to store and retrieve data across different storage types on the Soroban platform.
The contract defines three main methods: set, get, and extend, each serving distinct purposes related to data management within the blockchain’s storage.
The set function takes a key-value pair and stores it across three storage types persistent, instance, and temporary storage. This allows the data to be accessible for various use cases.
The get function retrieves a value from persistent storage using a given key, returning an option type, which will contain Some(value) if the key exists or None if it does not.
The extend function allows extending TTL of a stored key, helping to ensure that the data remains available in persistent and instance storage for a maximum duration by setting the TTL to the highest possible value.
This approach provides a way to manage the lifespan of stored data dynamically, ensuring that critical information remains accessible while minimizing storage costs and potential state bloat.
Restoring Archived Data
If the TTL expires, data moves to an off-chain archive. You can restore this data at any time by paying the rent again. Soroban’s state archival system uses a Merkle tree structure for verification, ensuring that restoration is secure and reliable. This prevents stale data from overloading the network and enables a sustainable, scalable blockchain experience.
For more information on restoring archived data, refer to Stellar’s developer documentation:
- https://developers.stellar.org/docs/build/guides/cli/restore-contract-instance
- https://developers.stellar.org/docs/learn/encyclopedia/storage/state-archival#restorefootprintop
This concludes the guide to Soroban data locations and state management. I hope you found this tutorial helpful and I’m excited to see what you build on Soroban!