Skip to Content
TutorialsSmart Contract Tutorial

Smart Contract Tutorial

This tutorial has been updated. TOS Network uses Rust smart contracts with the TAKO runtime.

Learn to build smart contracts on TOS Network using Rust. This tutorial will guide you through creating your first contract with native features like VRF randomness and referral rewards.

Quick Start

1. Setup Development Environment

# Install Rust curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh # Add WebAssembly target rustup target add wasm32-unknown-unknown # Create new project cargo new --lib my_contract cd my_contract

2. Configure Cargo.toml

[package] name = "my_contract" version = "0.1.0" edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] tako_sdk = "0.1" [profile.release] opt-level = "z" lto = true panic = "abort"

3. Write Your Contract

#![no_std] #![no_main] use tako_sdk::*; #[no_mangle] pub extern "C" fn entrypoint() -> u64 { let method = get_method(); match method.as_str() { "greet" => greet(), "set_message" => set_message(), "get_message" => get_message(), _ => ERROR_INVALID_METHOD } } fn greet() -> u64 { log("Hello from TOS Network!"); SUCCESS } fn set_message() -> u64 { let message = get_args(); storage_write(b"message", &message); SUCCESS } fn get_message() -> u64 { let mut buffer = [0u8; 256]; let len = storage_read(b"message", &mut buffer); set_return_data(&buffer[..len as usize]); SUCCESS }

4. Build and Deploy

# Build cargo build --release --target wasm32-unknown-unknown # Deploy to testnet tos deploy \ --contract target/wasm32-unknown-unknown/release/my_contract.wasm \ --network testnet

Full Documentation

For comprehensive smart contract documentation, see:

Example Contracts

Token Contract

#![no_std] #![no_main] use tako_sdk::*; #[no_mangle] pub extern "C" fn entrypoint() -> u64 { match get_method().as_str() { "transfer" => transfer(), "balance_of" => balance_of(), _ => ERROR_INVALID_METHOD } } fn transfer() -> u64 { let args = get_args(); let to = &args[0..32]; let amount = u64::from_le_bytes(args[32..40].try_into().unwrap()); let from = get_caller(); let from_key = [b"balance:", &from[..]].concat(); // Read balance let mut balance_bytes = [0u8; 8]; storage_read(&from_key, &mut balance_bytes); let from_balance = u64::from_le_bytes(balance_bytes); if from_balance < amount { return ERROR_INSUFFICIENT_BALANCE; } // Update sender balance storage_write(&from_key, &(from_balance - amount).to_le_bytes()); // Update recipient balance let to_key = [b"balance:", to].concat(); let mut to_balance_bytes = [0u8; 8]; storage_read(&to_key, &mut to_balance_bytes); let to_balance = u64::from_le_bytes(to_balance_bytes); storage_write(&to_key, &(to_balance + amount).to_le_bytes()); emit_event("Transfer", &[&from, to, &amount.to_le_bytes()]); SUCCESS } fn balance_of() -> u64 { let account = &get_args()[0..32]; let key = [b"balance:", account].concat(); let mut balance_bytes = [0u8; 8]; storage_read(&key, &mut balance_bytes); set_return_data(&balance_bytes); SUCCESS }

VRF Lottery Contract

#![no_std] #![no_main] use tako_sdk::*; #[no_mangle] pub extern "C" fn entrypoint() -> u64 { match get_method().as_str() { "enter" => enter_lottery(), "draw" => draw_winner(), _ => ERROR_INVALID_METHOD } } fn enter_lottery() -> u64 { let player = get_caller(); let entry_fee = get_value(); if entry_fee < 1_00000000 { // 1 TOS minimum return ERROR_INSUFFICIENT_VALUE; } // Add to participants let mut count_bytes = [0u8; 8]; storage_read(b"count", &mut count_bytes); let count = u64::from_le_bytes(count_bytes); let key = [b"player:", &count.to_le_bytes()].concat(); storage_write(&key, &player); storage_write(b"count", &(count + 1).to_le_bytes()); SUCCESS } fn draw_winner() -> u64 { // Get participant count let mut count_bytes = [0u8; 8]; storage_read(b"count", &mut count_bytes); let count = u64::from_le_bytes(count_bytes); if count == 0 { return ERROR_NO_PARTICIPANTS; } // Get VRF random number let random = vrf_random(&get_timestamp().to_le_bytes()); // Select winner let winner_index = random % count; let key = [b"player:", &winner_index.to_le_bytes()].concat(); let mut winner = [0u8; 32]; storage_read(&key, &mut winner); // Transfer prize pool to winner let prize = get_balance(); native_transfer(&winner, prize); // Reset lottery storage_write(b"count", &0u64.to_le_bytes()); emit_event("Winner", &[&winner, &prize.to_le_bytes()]); SUCCESS }

Key Concepts

Storage

// Write to storage storage_write(b"key", &value_bytes); // Read from storage let mut buffer = [0u8; 32]; storage_read(b"key", &mut buffer); // Delete from storage storage_delete(b"key");

Events

// Emit event with indexed parameters emit_event("Transfer", &[&from, &to, &amount.to_le_bytes()]); // Emit simple log log("Operation completed");

Native Features

// VRF random number let random = vrf_random(&seed); // Referral system referral_set(&user, &referrer); referral_distribute(&user, amount); // Batch transfer batch_transfer(&recipients, &amounts);

Gas Costs

OperationCost
Token transfer$0.001
VRF random$0.002
Storage write$0.0001/byte
Storage readFree
Deploy contract$0.01-$0.05

Next Steps

Last updated on