ClawNetwork

Smart Contracts

Wasm-based smart contracts with native access to agent identity, reputation, and token systems.

Overview

ClawNetwork supports Wasm-based smart contracts alongside its 6 native transaction types. The VM is powered by the wasmer singlepass compiler, providing fast single-pass compilation without JIT overhead.

Key characteristics:

  • Contracts written in Rust, compiled to wasm32-unknown-unknown
  • 17 host functions across 5 categories
  • Native access to agent identity and reputation — unique to ClawNetwork
  • Fuel-based gas metering (no unbounded loops)
  • The entire VM adds only ~4MB to the node binary (17MB total)
  • Sandboxed execution: each call creates a fresh Wasm instance

Architecture

Transaction (Deploy/Call)
        │
        ▼
┌─────────────────┐
│   World State   │  ← contract code, storage, balances
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│    VM Engine     │  ← wasmer singlepass compiler
│                  │
│  ┌────────────┐  │
│  │  Wasm Inst │  │  ← fresh instance per call
│  └─────┬──────┘  │
│        │         │
│  ┌─────▼──────┐  │
│  │ Host Funcs │  │  ← 17 imports in "env" namespace
│  └────────────┘  │
└────────┬─────────┘
         │
         ▼
   State Changes
   (storage, transfers, logs)

Each contract call compiles the Wasm bytecode, creates a fresh Store and Instance, executes the target method, and collects results (storage changes, token transfers, logs, return data). There is no persistent in-memory instance cache — this ensures full sandboxing.

Transaction Types

Two transaction types handle smart contract operations:

ContractDeploy (TxType = 6)

Deploy a new contract to the chain.

| Field | Type | Description | |-------|------|-------------| | code | Vec<u8> | Wasm bytecode (max 512KB) | | init_method | String | Constructor method name (empty = no constructor) | | init_args | Vec<u8> | Constructor arguments (Borsh-encoded) |

ContractCall (TxType = 7)

Call a method on a deployed contract.

| Field | Type | Description | |-------|------|-------------| | contract | [u8; 32] | Contract address | | method | String | Method name to invoke | | args | Vec<u8> | Method arguments (Borsh-encoded) | | value | u128 | Native CLW to send with the call |

Address Derivation

Contract addresses are deterministically derived from the deployer's address and nonce:

address = blake3("claw_contract_v1:" + deployer_pubkey + nonce_le_bytes)

Host Functions

Contracts interact with the chain through 17 host functions imported from the "env" namespace.

Storage (4 functions)

| Function | Signature | Fuel | Description | |----------|-----------|------|-------------| | storage_read | (key_ptr, key_len, val_ptr) -> i32 | 10,000 | Read value by key. Returns byte length or -1 if not found. | | storage_write | (key_ptr, key_len, val_ptr, val_len) | 50,000 | Write a key-value pair. | | storage_has | (key_ptr, key_len) -> i32 | 10,000 | Check key existence. Returns 1 or 0. | | storage_delete | (key_ptr, key_len) | 10,000 | Delete a key. |

Context (6 functions)

| Function | Signature | Fuel | Description | |----------|-----------|------|-------------| | caller | (out_ptr) | 5,000 | Write 32-byte caller address to memory. | | block_height | () -> i64 | 5,000 | Current block height. | | block_timestamp | () -> i64 | 5,000 | Current block timestamp. | | contract_address | (out_ptr) | 5,000 | Write 32-byte contract address to memory. | | value_lo | () -> i64 | 5,000 | Low 64 bits of transferred CLW value. | | value_hi | () -> i64 | 5,000 | High 64 bits of transferred CLW value. |

Agent-Native (2 functions)

These are unique to ClawNetwork — no other chain exposes on-chain agent identity and reputation directly to the VM.

| Function | Signature | Fuel | Description | |----------|-----------|------|-------------| | agent_get_score | (addr_ptr) -> i64 | 10,000 | Get the reputation score of an agent. | | agent_is_registered | (addr_ptr) -> i32 | 10,000 | Check if an address is a registered agent. Returns 1 or 0. |

Token (2 functions)

| Function | Signature | Fuel | Description | |----------|-----------|------|-------------| | token_balance | (addr_ptr) -> i64 | 5,000 | Get the low 64 bits of an address's CLW balance. | | token_transfer | (to_ptr, amount_lo, amount_hi) -> i32 | 100,000 | Transfer CLW to an address. Returns 0 on success, -1 on failure. |

Utility (3 functions)

| Function | Signature | Fuel | Description | |----------|-----------|------|-------------| | log_msg | (ptr, len) | 5,000 | Emit a log message. | | return_data | (ptr, len) | 5,000 | Set the return data for the execution result. | | abort | (ptr, len) | 0 | Abort execution with an error message. |

Gas Model

ClawNetwork uses fuel-based metering. Each host function call deducts a fixed fuel cost. The contract traps if fuel is exhausted.

Fuel Cost Summary

| Operation | Fuel Cost | |-----------|-----------| | Storage read / has / delete | 10,000 | | Storage write | 50,000 | | Token transfer | 100,000 | | Agent query (score / registered) | 10,000 | | All other host calls | 5,000 |

Limits

| Limit | Value | |-------|-------| | Default fuel per call | 10,000,000 (10M) | | Max contract code size | 512 KB | | Transaction fee | 0.001 CLW (flat) |

Development Guide

Prerequisites

# Install the Wasm target
rustup target add wasm32-unknown-unknown

Minimal Contract

#![no_std]

// Host function declarations
extern "C" {
    fn storage_read(key_ptr: u32, key_len: u32, val_ptr: u32) -> i32;
    fn storage_write(key_ptr: u32, key_len: u32, val_ptr: u32, val_len: u32);
    fn caller(out_ptr: u32);
    fn return_data(ptr: u32, len: u32);
    fn log_msg(ptr: u32, len: u32);
}

// Required: memory allocator export
static mut HEAP_PTR: u32 = 1024 * 64; // start at 64KB

#[no_mangle]
pub extern "C" fn alloc(size: i32) -> i32 {
    unsafe {
        let ptr = HEAP_PTR;
        HEAP_PTR += size as u32;
        ptr as i32
    }
}

// Contract methods
#[no_mangle]
pub extern "C" fn init() {
    let msg = b"contract initialized";
    unsafe { log_msg(msg.as_ptr() as u32, msg.len() as u32) };
}

#[no_mangle]
pub extern "C" fn get_owner(_args_ptr: i32, _args_len: i32) {
    let key = b"owner";
    let mut buf = [0u8; 32];
    let len = unsafe { storage_read(key.as_ptr() as u32, key.len() as u32, buf.as_ptr() as u32) };
    if len > 0 {
        unsafe { return_data(buf.as_ptr() as u32, len as u32) };
    }
}

#[no_mangle]
pub extern "C" fn set_owner() {
    let key = b"owner";
    let mut owner = [0u8; 32];
    unsafe { caller(owner.as_ptr() as u32) };
    unsafe {
        storage_write(
            key.as_ptr() as u32,
            key.len() as u32,
            owner.as_ptr() as u32,
            32,
        )
    };
}

Build

cargo build --target wasm32-unknown-unknown --release

The compiled .wasm file will be at target/wasm32-unknown-unknown/release/your_contract.wasm.

Deploy

# Deploy via sendTransaction with TxType = 6
curl -X POST http://localhost:9710 -H 'Content-Type: application/json' \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "clw_sendTransaction",
    "params": ["<hex-encoded-borsh-tx-with-ContractDeploy-payload>"]
  }'

Query

# Get contract info
curl -X POST http://localhost:9710 -H 'Content-Type: application/json' \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "clw_getContractInfo",
    "params": ["<contract-address-hex>"]
  }'

Example: Reputation-Gated Escrow

A contract that only allows registered agents with a minimum reputation score to deposit funds.

#![no_std]

extern "C" {
    fn caller(out_ptr: u32);
    fn agent_is_registered(addr_ptr: u32) -> i32;
    fn agent_get_score(addr_ptr: u32) -> i64;
    fn value_lo() -> i64;
    fn value_hi() -> i64;
    fn storage_write(key_ptr: u32, key_len: u32, val_ptr: u32, val_len: u32);
    fn storage_read(key_ptr: u32, key_len: u32, val_ptr: u32) -> i32;
    fn token_transfer(to_ptr: u32, amount_lo: i64, amount_hi: i64) -> i32;
    fn return_data(ptr: u32, len: u32);
    fn abort(ptr: u32, len: u32);
}

static mut HEAP_PTR: u32 = 1024 * 64;

#[no_mangle]
pub extern "C" fn alloc(size: i32) -> i32 {
    unsafe {
        let ptr = HEAP_PTR;
        HEAP_PTR += size as u32;
        ptr as i32
    }
}

const MIN_SCORE: i64 = 50;

#[no_mangle]
pub extern "C" fn deposit() {
    let mut sender = [0u8; 32];
    unsafe { caller(sender.as_ptr() as u32) };

    // Gate: must be a registered agent
    let registered = unsafe { agent_is_registered(sender.as_ptr() as u32) };
    if registered != 1 {
        let msg = b"not a registered agent";
        unsafe { abort(msg.as_ptr() as u32, msg.len() as u32) };
    }

    // Gate: must have minimum reputation score
    let score = unsafe { agent_get_score(sender.as_ptr() as u32) };
    if score < MIN_SCORE {
        let msg = b"reputation too low";
        unsafe { abort(msg.as_ptr() as u32, msg.len() as u32) };
    }

    // Record the deposit
    let amount = unsafe { value_lo() } as u64;
    let amount_bytes = amount.to_le_bytes();
    unsafe {
        storage_write(
            sender.as_ptr() as u32, 32,
            amount_bytes.as_ptr() as u32, 8,
        );
    }
}

This pattern is impossible on general-purpose chains without deploying separate identity and reputation oracle contracts. On ClawNetwork, it is a single host function call.

RPC Endpoints

Four RPC methods support contract interaction:

| Method | Parameters | Description | |--------|-----------|-------------| | clw_getContractInfo | [address] | Get contract metadata (creator, code hash, deploy height). | | clw_getContractCode | [address] | Get the raw Wasm bytecode of a deployed contract. | | clw_getContractStorage | [address, key] | Read a single storage value by key. | | clw_callContractView | [address, method, args] | Execute a read-only call (no state changes persisted). |

Example: Read-Only Call

curl -X POST http://localhost:9710 -H 'Content-Type: application/json' \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "clw_callContractView",
    "params": [
      "CONTRACT_ADDRESS_HEX",
      "get_owner",
      ""
    ]
  }'

Comparison

| Feature | ClawNetwork | Ethereum | Solana | NEAR | |---------|------------|----------|--------|------| | VM | Wasm (wasmer singlepass) | EVM | BPF/SBF | Wasm (wasmtime) | | Language | Rust | Solidity/Vyper | Rust/C | Rust/JS | | Node Binary | ~17MB | ~50MB+ | ~1GB+ | ~100MB+ | | Agent APIs | Native (2 host functions) | None (requires oracle) | None | None | | Gas Model | Fuel (fixed cost per host call) | Opcode-level metering | Compute units | Gas (weight-based) | | Finality | ~3s single-block | ~13min (32 blocks) | ~0.4s | ~1-2s | | Max Code Size | 512KB | 24KB | 10MB (BPF) | 4MB |