ownable-std
ownable-std is the shared Rust standard library for Ownables contracts.
It provides:
- common types/utilities used by Ownables contracts
- optional message-shaping proc macros (
ownable-std-macros) - a stable Host ABI v1 for wasm runtime calls that does not depend on
wasm-bindgenJS glue compatibility
Install
[]
= "0.4.0"
macros is enabled by default. To disable proc macros:
[]
= { = "0.4.0", = false }
ownable-std has no wasm-bindgen or js-sys dependency in runtime contract usage.
Host ABI v1
Constants:
ownable_std::abi::HOST_ABI_VERSION="1"ownable_std::abi::HOST_ABI_MANIFEST_FIELD="ownablesAbi"ownable_std::abi::HOST_ABI_WIRE_FORMAT="cbor"ownable_std::abi::HOST_ABI_WIRE_FORMAT_MANIFEST_FIELD="wireFormat"
Stable exports:
ownable_alloc(len: u32) -> u32ownable_free(ptr: u32, len: u32)ownable_instantiate(ptr: u32, len: u32) -> u64ownable_execute(ptr: u32, len: u32) -> u64ownable_query(ptr: u32, len: u32) -> u64ownable_external_event(ptr: u32, len: u32) -> u64
Return strategy:
- entrypoints return packed
u64 - low 32 bits = output pointer
- high 32 bits = output length
Wire format:
- input: CBOR bytes
- output: CBOR envelope bytes
Request Schemas (Per Call)
At the ABI transport layer, all four calls use the same schema:
instantiate: CBOR document bytesexecute: CBOR document bytesquery: CBOR document bytesexternal_event: CBOR document bytes
Required ABI-level keys:
- none (the full request shape is contract-defined)
Recommended convention for cross-contract consistency:
{
abi_version: "1",
payload: <contract-defined value>
}
If you use the convention above:
abi_version: required string, must be"1"payload: required contract-defined CBOR value
Response envelope schema (decoded structure):
{
success: bool,
payload: bytes,
error_code: string | null,
error_message: string | null
}
Contract Usage
Use the ownable_host_abi_v1! macro to export all required ABI symbols.
use HostAbiError;
use ownable_host_abi_v1;
ownable_host_abi_v1!;
Handler signature expected by the macro:
Host Runtime Call Flow
For each call (instantiate, execute, query, external_event):
- Serialize request object to CBOR bytes.
- Call
ownable_alloc(len). - Write bytes into wasm memory at the returned pointer.
- Call the selected
ownable_*entrypoint with(ptr, len). - Unpack
(out_ptr, out_len)from returnedu64. - Read
out_lenbytes atout_ptr. - Parse CBOR envelope and check
success. - Call
ownable_free(out_ptr, out_len).
Memory Ownership Rules
ownable_alloc(len)allocates wasm-side memory for host writes.- Host owns writing input bytes into this allocated buffer.
- Entrypoints consume input bytes immediately and copy them internally; host may treat input buffer as transient.
- Entrypoints allocate output envelope bytes and return
(ptr,len)packed inu64. - Host must call
ownable_free(out_ptr, out_len)exactly once for every non-zero output buffer. ptr=0,len=0means empty output.- Passing
ptr=0,len>0to entrypoints yields structured ABI error (INVALID_POINTER), not panic. - This crate does not enforce a hard max payload size; host/runtime should enforce practical limits.
Error Code Catalog
Current ABI-level error_code values:
INVALID_POINTER: null pointer with non-zero length inputINVALID_CBOR: request bytes failed CBOR parsing in contract handlerSERIALIZATION_FAILED: ABI envelope serialization failedHANDLER_PANIC: contract handler panicked; panic is converted to structured error
Handlers may return additional domain-specific error codes via HostAbiError::with_code.
Non-UTF8 Behavior
Non-UTF8 input must not panic.
Expected behavior:
- handler CBOR parse fails (
serde_cbor::from_slice) - error is mapped to structured ABI error envelope (
success=false,error_code=INVALID_CBOR)
Building Ownables
Build command:
This produces a wasm module consumable by a host/runtime that implements Host ABI v1.
Contract-side requirements:
- do not export runtime entrypoints with
#[wasm_bindgen] - do not rely on generated
*.jsglue for host calls - export only the stable
ownable_*ABI symbols (viaownable_host_abi_v1!)
End-to-End Test Vector
Example contract handler:
Host request bytes (CBOR, decoded form shown):
{ ping: "pong" }
Expected output envelope bytes decode to the same payload bytes.
{
success: true,
payload: <CBOR bytes for { ping: "pong" }>
}
Other Utilities in This Crate
MemoryStorage: in-memory storage implementation for testing/off-chain executioncreate_env/create_ownable_env: env builderspackage_title_from_name, color helpers, metadata/shared message structsownable-std-macros: attribute macros to extend execute/query/instantiate messages
Versioning Guidance
- set your package manifest field
ownablesAbito"1"for exported symbol/signature ABI compatibility - set your package manifest field
wireFormatto"cbor"for payload envelope encoding compatibility - host/runtime should reject incompatible versions
- non-interface dependency changes should not require runtime changes if ABI version stays the same