NeuroWASM overview
NeuroWASM is the contract runtime of NeuroChain: WebAssembly run by the wasmi interpreter, metered in fuel, with host functions imported from the module env. Its semantics follow CosmWasm and NEAR, plus native AI host functions.
It is not binary-compatible with wasmd or nearcore — the same ideas, a different interface.
Execution model
- Synchronous calls. A contract calling another runs it to completion before continuing (like the EVM).
- One journal per transaction. All storage writes, balance changes and transfers of the whole call tree commit together — or, if anything traps, none of them do.
- Read-your-writes. A nested call sees the caller's uncommitted writes.
- Depth limit of 8 nested calls (
MAX_CALL_DEPTH). - Deterministic. Every validator runs the same bytecode on the same state and gets the same result; there is no clock, randomness or network access.
Planned later: asynchronous sub-messages with a reply entry point, then NEAR-style promises and IBC v2 packets.
Host functions
All imports come from env. Pointers and lengths are i32 offsets into the contract's exported memory.
| Area | Live | Planned |
|---|---|---|
| Memory | allocate, deallocate, abort | — |
| Storage | get_storage, set_storage | remove_storage, storage_has, storage_usage |
| Context | get_caller, get_block_height, get_balance, get_stake, get_stake_at | get_self_addr, get_signer, get_block_time, get_shard_id, get_attached_deposit, gas_remaining |
| Bank & events | transfer, emit_event, set_return | log |
| Cross-contract | call_contract | call_contract_with_value |
| Crypto | — | sha3_256, verify_mldsa65, addr_validate |
| AI host | — | Model, certificate, Sentinel, trust-list and account-abstraction reads |
Entry points the contract exports are described in Guest exports; limits and fuel prices in Gas & limits.
A minimal contract
A counter in no_std Rust. It reads the call, keeps a number in storage and returns it.
#![no_std]
#[link(wasm_import_module = "env")]
extern "C" {
fn get_storage(key_ptr: i32, key_len: i32, val_ptr: i32, val_max: i32) -> i32;
fn set_storage(key_ptr: i32, key_len: i32, val_ptr: i32, val_len: i32);
fn set_return(ptr: i32, len: i32);
}
#[panic_handler]
fn panic(_: &core::panic::PanicInfo) -> ! { core::arch::wasm32::unreachable() }
const KEY: &[u8] = b"count";
fn read_count() -> u64 {
let mut buf = [0u8; 20];
let n = unsafe { get_storage(KEY.as_ptr() as i32, KEY.len() as i32, buf.as_mut_ptr() as i32, 20) };
if n <= 0 { return 0; }
core::str::from_utf8(&buf[..n as usize]).ok().and_then(|s| s.parse().ok()).unwrap_or(0)
}
#[no_mangle]
pub extern "C" fn call(input_ptr: i32, input_len: i32) {
let input = unsafe { core::slice::from_raw_parts(input_ptr as *const u8, input_len as usize) };
let mut n = read_count();
if input.windows(11).any(|w| w == b"\"increment\"") {
n += 1;
let mut out = [0u8; 20];
let s = fmt_u64(n, &mut out);
unsafe { set_storage(KEY.as_ptr() as i32, KEY.len() as i32, s.as_ptr() as i32, s.len() as i32) };
}
let mut out = [0u8; 20];
let s = fmt_u64(n, &mut out);
unsafe { set_return(s.as_ptr() as i32, s.len() as i32) };
}
fn fmt_u64(mut v: u64, buf: &mut [u8; 20]) -> &[u8] {
let mut i = 20;
loop { i -= 1; buf[i] = b'0' + (v % 10) as u8; v /= 10; if v == 0 { break; } }
&buf[i..]
}Call it with {"function":"increment"} to add one, or anything else to read. Build and deploy as in Deploy contracts. The NRC-20 token in neurochain/contracts/nrc20 is a complete, larger example.
The design document behind this interface is docs/neuro-wasm-spec.md in the repository.