Skip to main content
The Contract API provides host functions and utilities for writing WASM smart contracts that run on NEXUS.

Installation

For smart contracts, use the contract feature:
[dependencies]
nexus-sdk = { version = "0.1", features = ["contract"] }

Basic Contract Structure

NEXUS contracts use the nexus_fn! macro for ABI-compatible function exports:
use nexus_sdk::{
    solidity::{*, SafeMath},
    contract_api::ez::ret,
    require,
};
use nexus_sdk::solidity::uint256 as U256;

// State variables using Solidity-compatible Mappings
static VALUE: Mapping<&[u8], U256> = Mapping::new(b"value");
static OWNER: Mapping<&[u8], Address> = Mapping::new(b"owner");

nexus_fn! {
    fn init() {
        let sender = Blockchain::msg.sender();
        OWNER.set(&b"val".as_slice(), sender);
        VALUE.set(&b"val".as_slice(), U256::from(0));
        ret::u32(1)
    }
}

nexus_fn! {
    fn my_function(amount: U256) {
        let _guard = ReentrancyGuard::new();
        let current = VALUE.get(&b"val".as_slice());
        VALUE.set(&b"val".as_slice(), current.add(amount));
        
        let mut out = [0u8; 32];
        current.to_little_endian(&mut out);
        ret::u256(&out)
    }
}

Storage Module

Persistent key-value storage for contract state.

storage::get(key)

Read a value from storage.
use nexus_sdk::contract_api::storage;

let value = storage::get(b"my_key");
// Returns: Vec<u8> (empty if not found)

storage::set(key, value)

Write a value to storage.
storage::set(b"my_key", b"my_value");

storage::remove(key)

Delete a key from storage.
storage::remove(b"my_key");

storage::has(key)

Check if a key exists.
if storage::has(b"my_key") {
    // Key exists
}

Context Module

Access execution context information.

context::caller()

Get the immediate caller address.
use nexus_sdk::contract_api::context;

let caller = context::caller();
// Returns: Vec<u8> (caller's public key)

context::self_address()

Get the contract’s own address.
let self_addr = context::self_address();
// Returns: Vec<u8> (contract ID)

context::block_height()

Get current block height.
let height = context::block_height();
// Returns: u64

context::block_timestamp()

Get current block timestamp.
let timestamp = context::block_timestamp();
// Returns: u64 (Unix timestamp)

context::origin()

Get the original transaction sender.
let origin = context::origin();
// Returns: Vec<u8> (original sender's public key)

Crypto Module

Cryptographic hash functions.

crypto::sha256(data)

Compute SHA-256 hash.
use nexus_sdk::contract_api::crypto;

let hash = crypto::sha256(b"hello");
// Returns: [u8; 32]

crypto::keccak256(data)

Compute Keccak-256 hash.
let hash = crypto::keccak256(b"hello");
// Returns: [u8; 32]

crypto::blake3(data)

Compute BLAKE3 hash.
let hash = crypto::blake3(b"hello");
// Returns: [u8; 32]

Events Module

Emit events for off-chain indexing.

events::emit(name, data)

Emit a named event.
use nexus_sdk::contract_api::events;

events::emit("Transfer", &transfer_data);

Cross-Contract Calls (XCC)

Call other contracts.

xcc::call(address, function, data)

Call another contract.
use nexus_sdk::contract_api::xcc;

let result = xcc::call(&contract_address, "get_balance", &args);
// Returns: Vec<u8>

xcc::call_value(address, function, data, value)

Call another contract with value transfer.
let result = xcc::call_value(&contract_address, "deposit", &args, 1000);

xcc::deploy(code, args, salt)

Deploy a new contract.
let new_contract_id = xcc::deploy(&wasm_code, &init_args, &salt);
// Returns: Vec<u8> (new contract ID)

xcc::deploy_template(template_name, args, salt)

Deploy from a registered template.
let new_contract_id = xcc::deploy_template("nep20", &init_args, &salt);

Bitcoin Module

Access Bitcoin L1 data.

bitcoin::height()

Get current Bitcoin block height.
use nexus_sdk::contract_api::bitcoin;

let btc_height = bitcoin::height();
// Returns: i64

bitcoin::hash_at(height)

Get Bitcoin block hash at height.
let block_hash = bitcoin::hash_at(100);
// Returns: [u8; 32]

bitcoin::request_spend(amount, script_hash, vault_pubkey)

Request a Bitcoin spend from vault.
let success = bitcoin::request_spend(
    10000,           // amount in sats
    &script_hash,    // destination script hash
    Some(&vault_pk)  // optional vault pubkey
);
// Returns: bool

bitcoin::verify_inclusion(height, txid, path, index)

Verify Bitcoin transaction inclusion (SPV proof).
let valid = bitcoin::verify_inclusion(
    100,        // block height
    &txid,      // transaction ID
    &proof,     // merkle proof
    0           // tx index
);
// Returns: i32 (0 = valid)

Gas Module

Gas metering utilities.

gas::remaining()

Get remaining gas.
use nexus_sdk::contract_api::gas;

let remaining = gas::remaining();
// Returns: u64

Logger Module

Debug logging (development only).

logger::log(msg)

Log a debug message.
use nexus_sdk::contract_api::logger;

logger::log("Debug message");

Result Helpers

Return values from contract functions.

result_bytes(data)

Return raw bytes.
use nexus_sdk::contract_api::result_bytes;

return result_bytes(&my_data);

result_u32(value)

Return a u32 value.
use nexus_sdk::contract_api::result_u32;

return result_u32(42);

result_u64(value)

Return a u64 value.
use nexus_sdk::contract_api::result_u64;

return result_u64(1000000);

EZ Module (High-Level API)

Simplified API for common patterns.

ez::env

Environment shortcuts.
use nexus_sdk::contract_api::ez;

let sender = ez::env::sender();      // Same as context::caller()
let addr = ez::env::address();       // Same as context::self_address()
let height = ez::env::height();      // Same as context::block_height()
let time = ez::env::timestamp();     // Same as context::block_timestamp()
let value = ez::env::value();        // Get msg.value (transferred sats)

ez::store

Typed storage helpers.
use nexus_sdk::contract_api::ez::store;

// Integers
store::set_u64(b"counter", 100);
let counter = store::get_u64(b"counter").unwrap_or(0);

store::set_u32(b"version", 1);
let version = store::get_u32(b"version");

// Strings
store::set_string(b"name", "MyToken");
let name = store::get_string(b"name");

// Bytes
store::set_bytes(b"data", &my_bytes);
let data = store::get_bytes(b"data");

// Check existence
if store::exists(b"key") { /* ... */ }

ez::ret

Return value helpers.
use nexus_sdk::contract_api::ez::ret;

return ret::u64(balance);
return ret::u32(count);
return ret::string("success");
return ret::bytes(&data);

ez::abi

ABI encoding/decoding helpers.
use nexus_sdk::contract_api::ez::abi;

// Parse JSON arguments
let args = abi::parse_args_json(data);
let arg0 = abi::arg_string(ptr, len, 0);
let arg1 = abi::arg_uint64(ptr, len, 1);
let addr = abi::arg_address_hex(ptr, len, 2);

// Hex conversion
let bytes = abi::hex_to_bytes("0x1234");

// Number encoding
let bytes = abi::u64_bytes(1000);
let value = abi::u64_from_bytes(&bytes);

NEP-20 Standard Helpers

Helpers for implementing NEP-20 tokens.
use nexus_sdk::contract_api::ez::standards::nep20;

// Generate storage keys
let balance_key = nep20::balance_key(&address);
let allowance_key = nep20::allowance_key(&owner, &spender);

// Emit standard events
nep20::emit_transfer(&from, &to, amount);
nep20::emit_approval(&owner, &spender, amount);

NEP-20 Macro

Auto-generate standard NEP-20 exports:
use nexus_sdk::nexus_nep20_exports;

nexus_nep20_exports!();

// This generates:
// - init_token(name, symbol, decimals, supply)
// - name()
// - symbol()
// - decimals()
// - total_supply() / totalSupply()
// - balance_of(address) / balanceOf(address)
// - transfer(to, amount)
// - approve(spender, amount)
// - allowance(owner, spender)
// - transfer_from(from, to, amount)

Complete Example: Counter Contract

use nexus_sdk::{
    solidity::{*, SafeMath},
    contract_api::{ez::ret, events},
    require,
};
use nexus_sdk::solidity::uint256 as U256;

// State variables
static COUNTER: Mapping<&[u8], U256> = Mapping::new(b"counter");
static OWNER: Mapping<&[u8], Address> = Mapping::new(b"owner");

nexus_fn! {
    fn init() {
        let sender = Blockchain::msg.sender();
        OWNER.set(&b"val".as_slice(), sender);
        COUNTER.set(&b"val".as_slice(), U256::from(0));
        
        emit("Initialized", &[]);
        ret::u32(1)
    }
}

nexus_fn! {
    fn increment() {
        let current = COUNTER.get(&b"val".as_slice());
        let new_value = current.add(U256::from(1));
        COUNTER.set(&b"val".as_slice(), new_value);
        
        emit("Incremented", &[]);
        
        let mut out = [0u8; 32];
        new_value.to_little_endian(&mut out);
        ret::u256(&out)
    }
}

nexus_fn! {
    fn get_count() {
        let current = COUNTER.get(&b"val".as_slice());
        let mut out = [0u8; 32];
        current.to_little_endian(&mut out);
        ret::u256(&out)
    }
}

nexus_fn! {
    fn reset() {
        let caller = Blockchain::msg.sender();
        let owner = OWNER.get(&b"val".as_slice());
        
        require!(caller == owner, "Unauthorized");
        
        COUNTER.set(&b"val".as_slice(), U256::from(0));
        emit("Reset", &[]);
        ret::u32(1)
    }
}

---

## Compilation

```bash
# Build for WASM
cargo build --target wasm32-unknown-unknown --release

# Optimize (optional but recommended)
wasm-opt -O3 target/wasm32-unknown-unknown/release/my_contract.wasm \
  -o my_contract_optimized.wasm