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_contract2. 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 testnetFull Documentation
For comprehensive smart contract documentation, see:
Smart Contracts Overview
Complete guide to TAKO smart contracts
Development GuideStep-by-step development tutorial
TAKO SDK ReferenceFull API documentation
Contract ExamplesERC20, VRF, Referrals, and more
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
| Operation | Cost |
|---|---|
| Token transfer | $0.001 |
| VRF random | $0.002 |
| Storage write | $0.0001/byte |
| Storage read | Free |
| Deploy contract | $0.01-$0.05 |
Next Steps
- Read the full development guide
- Explore contract examples
- Learn about native features
- Check the TAKO SDK reference
Last updated on