Skip to main content

Introduction

NEXUS smart contracts are written in Rust and compiled to WebAssembly (WASM). They run in a deterministic VM with access to storage, events, cross-contract calls, and L1 chain data from Bitcoin, Zcash, and Dogecoin. The SDK provides Solidity-compatible types and patterns, making it familiar for EVM developers while leveraging Rust’s safety guarantees.

Getting Started

Prerequisites

# Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# Add WASM target
rustup target add wasm32-unknown-unknown

Create a Contract

nexus dev scaffold my_contract --template basic
cd my_contract

Build

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

Deploy

nexus contract deploy \
  --wasm ./target/wasm32-unknown-unknown/release/my_contract.wasm \
  --name my_contract \
  --from my-wallet

Contract Structure

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

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

// Initialize contract
nexus_fn! {
    fn init(initial_value: U256) {
        let sender = Blockchain::msg.sender();
        OWNER.set(&b"val".as_slice(), sender.clone());
        BALANCES.set(&sender, initial_value);
        ret::u32(1)
    }
}

// Public function with reentrancy protection
nexus_fn! {
    fn transfer(to: Address, amount: U256) {
        let _guard = ReentrancyGuard::new();
        let sender = Blockchain::msg.sender();
        
        let sender_bal = BALANCES.get(&sender);
        require!(sender_bal >= amount, "Insufficient balance");
        
        BALANCES.set(&sender, sender_bal.sub(amount));
        let to_bal = BALANCES.get(&to);
        BALANCES.set(&to, to_bal.add(amount));
        
        emit("Transfer", &[]);
        ret::u32(1)
    }
}

// View function
nexus_fn! {
    fn balanceOf(addr: Address) {
        let bal = BALANCES.get(&addr);
        let mut out = [0u8; 32];
        bal.to_little_endian(&mut out);
        ret::u256(&out)
    }
}

SDK Features

Solidity-Compatible Types

use nexus_sdk::solidity::{*, SafeMath};
use nexus_sdk::solidity::uint256 as U256;

// Single-key mapping
static BALANCES: Mapping<Address, U256> = Mapping::new(b"bal");

// Double-key mapping (like mapping(address => mapping(address => uint)))
static ALLOWANCES: DoubleMapping<Address, Address, U256> = DoubleMapping::new(b"allow");

// Usage
let balance = BALANCES.get(&addr);
BALANCES.set(&addr, new_balance);

let allowance = ALLOWANCES.get(&owner, &spender);
ALLOWANCES.set(&owner, &spender, amount);

SafeMath Operations

// Safe arithmetic that reverts on overflow
let sum = a.add(b);
let diff = a.sub(b);
let product = a.mul(b);
let quotient = a.div(b);

Reentrancy Protection

nexus_fn! {
    fn sensitive_operation() {
        let _guard = ReentrancyGuard::new();  // Auto-releases on drop
        // ... protected logic
    }
}

Cross-Contract Calls

use nexus_sdk::contract_api::xcc;

// Call another contract
let result = xcc::call(&token_address.0, "balanceOf", &args);

// Deploy a new contract
let new_addr = xcc::deploy(bytecode, init_args, salt);

Context Access

// Get caller address
let sender = Blockchain::msg.sender();

// Get sent value (for payable functions)
let value = Blockchain::msg.value();

// Get block info
let timestamp = Blockchain::block.timestamp();

Available Templates

TemplateDescription
basicMinimal contract with nexus_fn!
ownableWith owner management
pausableWith pause/unpause
nep20Fungible token (ERC-20 compatible)

Best Practices

  1. Use ReentrancyGuard - Protect state-changing functions
  2. Validate inputs - Use require! macro for assertions
  3. Use SafeMath - Prevent overflow/underflow
  4. Emit events - For indexing and off-chain tracking
  5. Modular design - Separate internal logic from ABI entry points