pub trait Storable<const SLOTS: usize>: Sized + StorableType {
// Required methods
fn load<S: StorageOps>(
storage: &mut S,
base_slot: U256,
ctx: LayoutCtx,
) -> Result<Self>;
fn store<S: StorageOps>(
&self,
storage: &mut S,
base_slot: U256,
ctx: LayoutCtx,
) -> Result<()>;
fn to_evm_words(&self) -> Result<[U256; SLOTS]>;
fn from_evm_words(words: [U256; SLOTS]) -> Result<Self>;
// Provided methods
fn delete<S: StorageOps>(
storage: &mut S,
base_slot: U256,
ctx: LayoutCtx,
) -> Result<()> { ... }
fn validate_layout() { ... }
}Expand description
Trait for types that can be stored/loaded from EVM storage.
This trait provides a flexible abstraction for reading and writing Rust types to EVM storage. Types can occupy one or more consecutive storage slots, enabling support for both simple values (Address, U256, bool) and complex multi-slot types (structs, fixed arrays).
§Type Parameter
SLOTS: The number of consecutive storage slots this type occupies. For single-word types (Address, U256, bool), this is1. For fixed-size arrays, this equals the number of elements. For user-defined structs, this a number between1and the number of fields, which depends on slot packing.
§Storage Layout
For a type with SLOTS = 3 starting at base_slot:
- Slot 0:
base_slot + 0 - Slot 1:
base_slot + 1 - Slot 2:
base_slot + 2
§Safety
Implementations must ensure that:
- Round-trip conversions preserve data:
load(store(x)) == Ok(x) SLOTSaccurately reflects the number of slots usedstoreandloadaccess exactlySLOTSconsecutive slotsto_evm_wordsandfrom_evm_wordsproduce/consume exactlySLOTSwords
Required Methods§
Sourcefn load<S: StorageOps>(
storage: &mut S,
base_slot: U256,
ctx: LayoutCtx,
) -> Result<Self>
fn load<S: StorageOps>( storage: &mut S, base_slot: U256, ctx: LayoutCtx, ) -> Result<Self>
Load this type from storage starting at the given base slot.
Reads SLOTS consecutive slots starting from base_slot.
§Context
LayoutCtx::FULL: Load the entire value frombase_slot(and subsequent slots if multi-slot)LayoutCtx::packed(offset): Load a packed primitive from byteoffsetwithinbase_slot
§Errors
Returns an error if:
- Storage read fails
- Data cannot be decoded into this type
- Context is invalid for this type (e.g.,
Packedfor a multi-slot type)
Sourcefn store<S: StorageOps>(
&self,
storage: &mut S,
base_slot: U256,
ctx: LayoutCtx,
) -> Result<()>
fn store<S: StorageOps>( &self, storage: &mut S, base_slot: U256, ctx: LayoutCtx, ) -> Result<()>
Store this type to storage starting at the given base slot.
Writes SLOTS consecutive slots starting from base_slot.
§Context
LayoutCtx::FULL: Write the entire value tobase_slot(overwrites full slot)LayoutCtx::packed(offset): Write a packed primitive at byteoffset(read-modify-write)
§Errors
Returns an error if:
- Storage write fails
- Context is invalid for this type (e.g.,
Packedfor a multi-slot type)
Sourcefn to_evm_words(&self) -> Result<[U256; SLOTS]>
fn to_evm_words(&self) -> Result<[U256; SLOTS]>
Encode this type to an array of U256 words.
Returns exactly SLOTS words, where each word represents one storage slot.
For single-slot types (SLOTS = 1), returns a single-element array.
For multi-slot types, each array element corresponds to one slot’s data.
§Packed Storage
When multiple small fields are packed into a single slot, they are positioned and combined into a single U256 word according to their byte offsets. The derive macro handles this automatically.
Sourcefn from_evm_words(words: [U256; SLOTS]) -> Result<Self>
fn from_evm_words(words: [U256; SLOTS]) -> Result<Self>
Decode this type from an array of U256 words.
Accepts exactly N words, where each word represents one storage slot.
Constructs the complete type from all provided words.
§Packed Storage
When multiple small fields are packed into a single slot, they are extracted from the appropriate word using bit shifts and masks. The derive macro handles this automatically.
Provided Methods§
Sourcefn delete<S: StorageOps>(
storage: &mut S,
base_slot: U256,
ctx: LayoutCtx,
) -> Result<()>
fn delete<S: StorageOps>( storage: &mut S, base_slot: U256, ctx: LayoutCtx, ) -> Result<()>
Delete this type from storage (set all slots to zero).
Sets SLOTS consecutive slots to zero, starting from base_slot.
§Context
LayoutCtx::FULL: Clear entire slot(s) by writing zeroLayoutCtx::packed(offset): Clear only the bytes at the offset (read-modify-write)
The default implementation handles both contexts appropriately.
§Errors
Returns an error if:
- Storage write fails
- Context is invalid for this type
Sourcefn validate_layout()
fn validate_layout()
Test helper to ensure LAYOUT and SLOTS are in sync.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.