Crates.io | storage_encoded |
lib.rs | storage_encoded |
version | 0.1.1 |
created_at | 2025-09-18 15:04:12.731148+00 |
updated_at | 2025-09-18 17:12:09.566842+00 |
description | Direct off-chain storage access for Fuel smart contracts - no getters, no simulation, just read |
homepage | |
repository | https://github.com/IGI-111/storage_deque |
max_upload_size | |
id | 1844869 |
size | 122,561 |
A Sway library that enables direct storage access for encoded data in Fuel smart contracts, allowing off-chain reads without executing getter functions or simulating transactions.
StorageEncoded
provides a storage pattern for Sway smart contracts that allows direct off-chain reading of contract state. By storing ABI-encoded data in a predictable format, you can retrieve complex types directly from contract storage using the companion Rust library—no transaction simulation or FuelVM execution required.
AbiEncode
/AbiDecode
Add to your Forc.toml
:
[dependencies]
storage_encoded = "0.1.1"
Add to your Cargo.toml
:
[dependencies]
storage_encoded = "0.1.1"
fuel-core-client = "0.46.0"
fuels = "0.74.0"
contract;
use storage_encoded::*;
storage {
data in 0x0000000000000000000000000000000000000000000000000000000000000000: StorageEncoded = StorageEncoded {},
}
struct MyData {
count: u256,
items: Vec<u64>,
name: String,
}
impl Contract {
#[storage(read, write)]
fn store_data() {
let data = MyData {
count: 42,
items: vec![1, 2, 3],
name: String::from_ascii_str("example"),
};
storage.data.set::<MyData>(data);
}
#[storage(read)]
fn get_data() -> MyData {
storage.data.get::<MyData>()
}
}
use std::sync::Arc;
use fuel_core_client::client::FuelClient;
use fuel_types::{Bytes32, ContractId};
use fuels::types::{param_types::ParamType, Token};
use storage_encoded::decode_from_storage;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Arc::new(FuelClient::new("https://testnet.fuel.network")?);
let contract_id: ContractId = "0x...".parse()?;
// Define the type structure
let param_type = ParamType::Struct {
name: "MyData".into(),
fields: vec![
("count".into(), ParamType::U256),
("items".into(), ParamType::Vector(Box::new(ParamType::U64))),
("name".into(), ParamType::String),
],
generics: vec![],
};
// Read directly from storage slot
let storage_slot: Bytes32 = "0x0000000000000000000000000000000000000000000000000000000000000000".parse().unwrap(); // Your storage slot
let data = decode_from_storage(client, contract_id, ¶m_type, &storage_slot).await?;
println!("Data: {:?}", data);
Ok(())
}
For a given StorageEncoded
slot S
S
slot store the encoded data length (u64, big-endian)SHA256(S)
store the encoded data in 32-byte chunksOn Write (set()
):
On Read (get()
):
The Rust decoder replicates the storage layout logic to read and decode data directly from the blockchain state without executing any contract code.
The type system does not enforce encoding/decoding type consistency. You must use the exact same type for both set()
and get()
operations. Mismatched types will cause runtime failures.
// ❌ WRONG - Will fail at runtime
storage.data.set::<u64>(42);
let value = storage.data.get::<String>(); // Runtime error!
// ✅ CORRECT
storage.data.set::<u64>(42);
let value = storage.data.get::<u64>(); // Works!
AbiEncode
and AbiDecode
traits⚠️ Experimental: This library works but has not been thoroughly tested in production environments. Use with caution and test extensively before deploying to mainnet.