Programmable SSUs
A Smart Storage Unit (SSU) is a programmable storage structure. It can hold items and expose custom rules through Move extensions.
The SSU is one of the most useful Frontier builder targets because storage can become:
- a vending machine
- a public deposit box
- a field reward dispenser
- a small trade hub
- a mission terminal
- a logistics hand-off point
- a route-service payment receiver
Inventory Model
Section titled “Inventory Model”SSU interactions usually involve two inventory ideas:
| Inventory | Purpose |
|---|---|
| Primary inventory | Owner-controlled storage for the SSU. |
| Ephemeral inventory | Temporary per-character inventory for non-owner interactions. |
Ephemeral inventories make it possible for other players to interact with the SSU without giving them direct owner access.
Extension Authority
Section titled “Extension Authority”Custom SSU contracts usually use the typed-witness pattern. The extension defines a witness type and the owner authorises that exact type on the storage unit.
public struct VendingAuth has drop {}After authorisation, the extension can call the world storage-unit module through the authorised path. That is different from giving every user owner access. Your extension remains responsible for its own payment, eligibility and rate-limit rules before it calls the storage-unit function.
Builder rule:
extension checks policy -> extension calls storage unit with witness -> world module enforces authorised pathItem Bridge
Section titled “Item Bridge”Items may need to move between in-game state and chain state before a contract can handle them.
game item -> chain item -> contract interaction -> game itemDo not assume every item visible in the game is already available to your contract. If a workflow requires a deposit, model the bridge step explicitly and display clear state to the user.
Deposit And Withdraw Design
Section titled “Deposit And Withdraw Design”Design every item movement as an explicit state transition:
| Step | User-Facing Question |
|---|---|
| Item visible in game | Is it in the player inventory or already represented on-chain? |
| Bridge to chain | What item type id and quantity will be bridged? |
| Deposit into SSU or owned inventory | Which storage unit receives it and under what rule? |
| Withdraw from SSU | What type id and quantity leave stock? |
| Delivery to player | Does it return to game inventory, owned inventory or an intermediate object? |
If the UI cannot explain the current state, do not ask for a signature yet.
Extension Design Pattern
Section titled “Extension Design Pattern”A useful SSU extension usually has these parts:
| Part | Responsibility |
|---|---|
| Configuration | Owner sets price, allowed types, limits or recipient rules. |
| Authorisation | Owner registers the extension with the SSU. |
| User entry point | Player calls a clean function such as buy, deposit, claim or redeem. |
| SSU call | Extension calls the SSU using its witness or authorised path. |
| Event output | Contract emits enough data for explorers and indexers. |
Keep the user entry point small. The more logic you put into one transaction, the harder it is to explain failure and recover user assets safely.
Vending Unit Design
Section titled “Vending Unit Design”A vending SSU needs at least:
| Field | Reason |
|---|---|
| Output type id | Contract logic must not compare only display names. |
| Output quantity | Prevent ambiguous stock movement. |
| Payment type id | Avoid accepting the wrong asset. |
| Price | Show exact cost before signing. |
| Recipient character | Prevent accidental delivery. |
| Stock check | Fail before payment where possible. |
| Event output | Let explorers and operators audit purchases. |
UI should show both the display name and the stable type id for anything being paid, deposited or withdrawn.
Deposit Box Design
Section titled “Deposit Box Design”A deposit SSU needs at least:
| Field | Reason |
|---|---|
| Allowed type ids | Prevent arbitrary deposits. |
| Quantity limits | Prevent accidental over-deposit. |
| Recipient or owner policy | Clarify who can later withdraw. |
| Refund or failure handling | Avoid trapping user assets on malformed input. |
| Event output | Make deposits auditable. |
Avoid unbounded public deposit flows unless the owner explicitly wants that behaviour.
Example Workflows
Section titled “Example Workflows”Vending Unit
Section titled “Vending Unit”player selects itemplayer bridges payment/item if requiredextension checks price and stockextension withdraws from SSUextension sends item to player or player inventoryevent records purchaseDeposit Box
Section titled “Deposit Box”player bridges item to chainextension checks allowed type and quantityextension deposits into SSU or owner-controlled inventoryevent records depositField Reward
Section titled “Field Reward”player proves conditionextension checks claim stateextension withdraws rewardextension marks claim consumedevent records rewardPublic Data A Tool Needs
Section titled “Public Data A Tool Needs”Use Black Relay for display and discovery:
| UI Field | API Starting Point |
|---|---|
| SSU list | /v1/current/storage |
| Owner or operator context | /v1/current/ownership, entity relations |
| Item names | /v1/types/{typeID}, /v1/current/items |
| Source evidence | /v1/entities/{idOrSlug}/sources |
| Related events | /v1/events?module=storage_unit |
Use direct Sui reads for final object versions, ownership, inventory state and transaction building.
Example API Flow
Section titled “Example API Flow”For an SSU dApp UI:
- read
tenantanditemIdfrom the dApp context - fetch
/v1/current/storage?q=<itemId>&cycles=current - fetch
/v1/entities/{storageId}/sourcesfor evidence display - fetch
/v1/types/{typeID}for item labels - fetch live object state through direct Sui or dApp Kit before building the transaction
- submit only after the user sees the exact item movement
Black Relay can make the UI readable. It should not be the final authority for stock, object version or capability ownership.
SSU Build Checklist
Section titled “SSU Build Checklist”- Decide whether the extension is owner-only, public, tribe-gated or payment-gated.
- Decide which item type IDs are allowed.
- Decide whether the SSU should accept deposits, withdrawals or both.
- Define the failure states before writing code.
- Keep all quantities explicit.
- Emit events that can be indexed later.
- Never trust only a display name for type checks.
- Use type IDs, object IDs and capabilities for contract logic.
- Use names only for UI.
- Re-read source and package IDs before deploying to a live environment.
- Emit events for successful deposits, withdrawals or claims.
- Fail safely when stock, payment or bridge state is not what the UI expected.
- Document who can recover stuck stock or misconfigured settings.
Common Mistakes
Section titled “Common Mistakes”| Mistake | Safer Approach |
|---|---|
| Comparing only item names. | Compare stable type IDs and display names separately. |
| Assuming an SSU inventory is public truth. | Check the latest chain object before mutation. |
| Hiding pending bridge state. | Show whether an item is in-game, on-chain or in an ephemeral inventory. |
| Allowing unlimited public calls. | Add limits, caps or explicit owner-controlled configuration. |
| Treating Registry export freshness as transaction authority. | Use Registry for discovery then direct Sui for signing. |