storage_unit.move
Overview
This report provides a comprehensive technical analysis of the storage_unit.move module. As a specialized implementation of the Assembly architecture, the Storage Unit serves as the primary persistence layer for items within the EVE Frontier universe, facilitating the secure bridging of assets between the game server and the blockchain.
Learning Objectives
By the end of this article, you will be able to:
- Analyze the
StorageUnitdata structure and its use of Dynamic Fields for multi-tenant inventory management. - Explain the dependency between
StorageUnitlifecycle states andNetworkNodeenergy handling. - Trace the execution flow of item bridging (Game-to-Chain and Chain-to-Game).
- Evaluate the security model governing access control and sponsorship requirements.
1. Core Component Architecture
The StorageUnit is a shared object that acts as a container for operational primitives and user inventories. Unlike simple assemblies, it must handle storage for multiple users (Character inventories) and the structure itself (Output inventory).
classDiagram
class StorageUnit {
+UID id
+TenantItemId key
+AssemblyStatus status
+Location location
+Metadata metadata
+vector<ID> inventory_keys
+Option<ID> energy_source_id
+ID owner_cap_id
+u64 type_id
}
class Inventory {
+Dynamic Field
}
class NetworkNode {
+EnergySource
}
StorageUnit *-- AssemblyStatus : contains
StorageUnit *-- Location : contains
StorageUnit *-- Metadata : contains
StorageUnit "1" *-- "*" Inventory : manages via Dynamic Fields
StorageUnit ..> NetworkNode : connects to
Key Components
inventory_keys: A vector tracking the IDs of all inventories attached to this unit. This allows the contract to iterate through and manage all stored assets during destruction.- Dynamic Field Inventories: Instead of a single flat inventory, the Storage Unit uses Sui’s Dynamic Fields to attach separate
Inventoryobjects.- Structure Inventory: Attached using the
StorageUnit’s ownOwnerCapID. - Character Inventories: Attached using the Character’s
OwnerCapID (ephemeral inventories created on demand).
- Structure Inventory: Attached using the
energy_source_id: Stores the ID of theNetworkNodecurrently powering the unit. This enforces the requirement that storage must be powered to function.
2. Functional Lifecycle
The Storage Unit’s lifecycle is tightly coupled with the energy grid. It cannot operate (allow item transfers) without an active connection to a NetworkNode providing energy.
stateDiagram-v2
[*] --> Created: create_and_share
Created --> Online: set_online (Requires NetworkNode + OwnerCap)
Online --> Offline: set_offline (Releases Energy)
Online --> Offline: Network Energy Depletion
Online --> [*]: destroy (Must be Offline first?)
Offline --> Online: set_online
Offline --> [*]: destroy (Releases resources)
Lifecycle Hooks
- Initialization (
create_and_share): Sets up theStorageUnitand creates its primary “Structure Inventory” (the default storage bin for the unit itself). - Activation (
set_online):- Verifies the
NetworkNodehas sufficient energy capacity. - Reserves Energy: Calls
reserve_energyon the node, locking a portion of the grid’s capacity for this unit. - Updates
LocationandAssemblyStatusto active.
- Verifies the
- Deactivation (
set_offline):- Releases Energy: Calls
release_energyon the node, freeing up capacity on the grid. - Disconnects the
StorageUnitfrom theNetworkNode. - Sets state to inactive.
- Releases Energy: Calls
- Destruction (
destroy):- Iterates through
inventory_keysto destroy all attached inventories (both structure and character). - Cleans up metadata, unanchors the unit, and deletes the
UID.
- Iterates through
3. Logic Deep Dive: Item Bridging
The primary “physics” of this module is the movement of items between the off-chain game state and on-chain ownership.
Game-to-Chain (Minting)
This process “imports” items from the game world into the blockchain inventory.
sequenceDiagram
participant Admin as Game Server (Sponsor)
participant User
participant StorageUnit
participant Inventory
User->>StorageUnit: game_item_to_chain_inventory(Item Data, Quantity)
activate StorageUnit
StorageUnit->>Admin: check is_authorized_sponsor(ctx)
StorageUnit->>StorageUnit: check status.is_online()
alt User Inventory Missing
StorageUnit->>Inventory: create new Inventory
StorageUnit->>StorageUnit: bound as Dynamic Field
end
StorageUnit->>Inventory: mint_items(Item Data)
Inventory-->>User: Items Added
deactivate StorageUnit
Critical Check: The transaction must be sponsored by an address authorized in the AdminACL. This prevents users from arbitrarily minting items without the game server verifying they actually found those items in-game.
Chain-to-Game (Burning)
This process “exports” items back to the game, effectively burning them on-chain to credit the player in the database.
- Function:
chain_item_to_game_inventory - Mechanism: Calls
inventory.burn_items_with_proof. - Verification: Requires the
StorageUnitto be Online. This ensures players can’t extract items from a “powered down” or “destroyed” station (simulating game mechanics where looting a destroyed station might work differently).
4. Security & Access Patterns
Access control is enforced through a combination of Capabilities (OwnerCap) and Access Control Lists (AdminACL).
| Function | Required Authority | Scope |
|---|---|---|
create_and_share |
Private (Package) | Called by game logic / initialization scripts. |
set_online |
OwnerCap<T> |
Only the owner can activate the unit. |
set_offline |
OwnerCap<T> |
Only the owner can deactivate the unit. |
game_item_to_chain_inventory |
OwnerCap + AdminACL |
Hybrid: Owner requests, Game Server (Admin) allows via sponsorship. |
chain_item_to_game_inventory |
OwnerCap |
Owner can burn their own items to move them in-game. |
The AdminACL Role
The AdminACL is crucial specifically for minting (Game -> Chain). It acts as a bridge of trust. The Move contract cannot verify game events (like “Player looted Item X”), so it trusts transactions signed/sponsored by the Game Server logic.
Dynamic Field Security
The helper function check_inventory_authorization performs a type check on the OwnerCap:
- If
OwnerCapisStorageUnit: Checks ifaccess::is_authorizedfor the storage unit ID. - If
OwnerCapisCharacter: Checks ifaccess::is_authorizedfor the character ID.
This distinction ensures that a user can only interact with their own ephemeral inventory within the storage unit, or the unit’s main inventory if they own the unit.