genie is the Rust SDK for building component-based contracts on the Grid Virtual Machine (GVM). It provides the high-level abstractions and tools needed to create composable, role-based contracts that run natively on RISC-V.
Genie enables the component-role architecture, where contracts are decomposed into logical roles (Root, Issuer, Holder, and so on) that can be installed independently and communicate through type-safe interfaces.
Genie is an early preview. The API surface will evolve.
Key architecture concepts
Components and roles
- Components are installable units that implement contract interfaces.
- Roles define specific capabilities within a contract (for example minting, holding balances).
- Contracts specify role-based contracts using declarative interfaces.
- Entities are independent units that own component instances.
- Component communication happens synchronously when components are on the same entity, or asynchronously when they are on different entities.
Benefits
- Composability. Mix and match components from different contracts.
- Sharded performance. Each entity runs independently with async cross-entity calls.
- Type safety. Generated clients ensure compile-time correctness.
- Upgradability. Components can be versioned and upgraded independently.
Feature snapshot (v0.1)
| Area | Components |
|---|---|
| Contract definition | #[contract], component-based modules |
| Implementation | Direct component implementation with automatic infrastructure generation |
| Installation | #[installation_request], component-based setup with auto-generated installers |
| Communication | Generated clients with local/remote routers, automatic async method generation |
| Storage | Storage::save(), Storage::load(), Storage::load_guarded(), type-safe persistence |
| Runtime | Async::spawn(), async task management, cross-component coordination |
| Attributes | #[installation_request], #[install], #[owner], #[private], #[view], #[public], #[entry] |
Quick start
1. Define a contract
2. Use the component
Macro reference
Genie uses procedural macros to define component boundaries, roles, and communication patterns.Contract definition
| Macro | Purpose |
|---|---|
#[contract] | Defines a contract module containing multiple components |
mod X | Declares a component module within a contract |
Component lifecycle
| Macro | Purpose | Example |
|---|---|---|
#[deploy] | Root deployment method called when deploying the root component (must be async) | #[deploy] pub async fn deploy() -> Result<()> |
#[install] | Internal component method called during component installation (must be async) | #[install] pub async fn install() -> Result<()> |
Access control
| Macro | Purpose | Example |
|---|---|---|
#[entry] | Public entry point accessible from external calls, generates async version | #[entry] fn transfer() -> Result<()> |
#[owner] | Restricts access to component owner, generates async version | #[owner] fn mint() -> Result<()> |
#[public] | Public entry point callable by any caller, generates async version | #[public] fn get_info() -> Result<Info> |
#[private] | Internal contract calls only, generates async version | #[private] fn internal_update() -> Result<()> |
Read-only methods
| Macro | Purpose | Example |
|---|---|---|
#[view] | Read-only method (no state changes), adds #[public] + #[read_only], generates async version | #[view] fn get_balance() -> Result<u64> |
#[read_only] | Marks method as read-only (no storage mutations) | #[read_only] fn calculate() -> Result<u64> |
Attribute usage patterns
Permission-based access control
Read-only versus mutable methods
Internal contract methods
Storage API
| Function | Purpose |
|---|---|
Storage::save<T>(value) | Persist value using type-derived key |
Storage::save_by_key<K, T>(key, value) | Persist with explicit key |
Storage::load<T>() | Load owned copy of stored value |
Storage::load_by_key<K, T>(key) | Load with explicit key |
Storage::load_zero_copy<T>() | Load by shared reference (Rc) without cloning payload |
Storage::load_zero_copy_by_key<K, T>(key) | Zero-copy load with explicit key |
Storage::load_guarded<T>() | Mutable reference that auto-saves on drop |
Storage::load_guarded_by_key<K, T>(key) | Keyed variant with auto-save |
Storage::delete<T>() | Remove value by type |
Storage::delete_by_key<K>(key) | Remove by explicit key |
Storage::exists<T>() | Check existence by type |
Storage::exists_by_key<K>(key) | Check existence by key |
Storage::save_self<T>(object) | Persist entire component struct (used by generated code) |
Storage::load_self<T>() | Load entire component struct (used by generated code) |
Member storage (automatic field persistence)
Components can define struct fields that are automatically persisted to storage. When a component struct has fields:- On load. The entire struct is loaded from storage using
Storage::load_self<T>(). - On save. After mutable method execution, the entire struct is saved using
Storage::save_self<T>(object).
_genie_reserved_key_self) to store the entire component struct atomically. This whole-struct approach ensures atomic state updates and avoids collisions with user-defined storage keys.
Runtime and communication API
| Function | Purpose |
|---|---|
Async::spawn(future) | Execute async task on runtime |
Async::spawn_to_sequence(future, sequence_id) | Execute async task in a specific sequence |
Async::join_sequence(future, sequence_id) | Join a future to an existing sequence |
Component::get_caller() | Get current call context information |
Component::is_same_entity(component_id) | Check if component is on same entity |
Component::get_owner_component() | Get the owner component of current context |
Component::create_new_entity() | Create a new entity on the blockchain |
Component::change_owner(component_id, new_owner) | Change component ownership |
Component::delete_component(component_id) | Delete a component from the system |
Component communication patterns
Local versus remote calls
Installation flow
Error handling
Generated infrastructure
The#[contract] macro automatically generates:
- Client with local/remote routers:
- Component installers:
- Contract traits for external implementations:
- Component traits for dynamic component creation:
See also
- Grid framework reference: the fungible-token contract and other primitives built on Genie.
- Cross-contract composition walkthrough: a 12-step worked example exercising every Genie feature above.
- Build and test a contract: the local build/test loop.
- Contract test tools reference: the test fixture you’ll use to exercise contracts.

