TAKO SDK Reference
The tako_sdk crate provides all the functions needed to build smart contracts on TOS Network.
Installation
Add to your Cargo.toml:
[dependencies]
tako-sdk = { git = "https://github.com/tos-network/tako", branch = "main" }Import in your contract:
use tako_sdk::*;Constants
/// Success return code
pub const SUCCESS: u64 = 0;
/// Generic error return code
pub const ERROR: u64 = 1;Core Functions
Environment
get_tx_sender
Get the address of the transaction sender.
pub fn get_tx_sender() -> [u8; 32];Example:
let sender = get_tx_sender();get_caller
Get the immediate caller (may differ from tx_sender in CPI).
pub fn get_caller() -> [u8; 32];get_contract_hash
Get the current contract’s address.
pub fn get_contract_hash() -> [u8; 32];get_call_value
Get the TOS amount sent with this call.
pub fn get_call_value() -> u64;Example:
let amount = get_call_value();
if amount == 0 {
return ERR_NO_VALUE;
}get_block_number
Get the current block number.
pub fn get_block_number() -> u64;get_block_hash
Get the current block hash.
pub fn get_block_hash() -> [u8; 32];get_timestamp
Get the current block timestamp.
pub fn get_timestamp() -> u64;Input/Output
get_input_data
Read the input data for this contract call.
pub fn get_input_data(buffer: &mut [u8]) -> u32;Returns: Number of bytes written to buffer.
Example:
let mut input = [0u8; 1024];
let len = get_input_data(&mut input);
// Parse opcode and parameters
let opcode = input[0];
let params = &input[1..len as usize];set_return_data
Set the return data for this call.
pub fn set_return_data(data: &[u8]) -> Result<(), u64>;Example:
let balance = get_balance(&account);
let result = balance.to_le_bytes();
set_return_data(&result)?;Storage
storage_read
Read data from contract storage.
pub fn storage_read(key: &[u8], buffer: &mut [u8]) -> u32;Returns: Number of bytes read (0 if key not found).
Example:
const COUNTER_KEY: &[u8] = b"counter";
let mut buffer = [0u8; 8];
let len = storage_read(COUNTER_KEY, &mut buffer);
let value = if len == 8 {
u64::from_le_bytes(buffer)
} else {
0 // Default value
};storage_write
Write data to contract storage.
pub fn storage_write(key: &[u8], value: &[u8]) -> Result<(), u64>;Cost: 20,000 compute units per write.
Example:
let value = 42u64;
storage_write(b"my_key", &value.to_le_bytes())?;Transfers
transfer
Transfer TOS to another address.
pub fn transfer(recipient: &[u8; 32], amount: u64) -> Result<(), u64>;Example:
let recipient = get_tx_sender();
let reward = 100_000000; // 1 TOS (8 decimals)
transfer(&recipient, reward)?;transfer_from_contract
Transfer TOS from contract balance.
pub fn transfer_from_contract(recipient: &[u8; 32], amount: u64) -> Result<(), u64>;Logging
log
Log a message (for debugging and events).
pub fn log(message: &str);Cost: 100 compute units.
Example:
log("Transfer successful");log_u64
Log up to 5 u64 values.
pub fn log_u64(a: u64, b: u64, c: u64, d: u64, e: u64);Example:
log_u64(amount, from_balance, to_balance, 0, 0);Hashing
blake3_hash
Compute Blake3 hash of data.
pub fn blake3_hash(data: &[u8]) -> [u8; 32];Example:
let data = b"hello world";
let hash = blake3_hash(data);keccak256
Compute Keccak256 hash (Ethereum compatible).
pub fn keccak256(data: &[u8]) -> [u8; 32];Cross-Program Invocation (CPI)
cpi_call
Call another contract.
pub fn cpi_call(
target: &[u8; 32],
input: &[u8],
return_buffer: &mut [u8],
) -> Result<u32, u64>;Returns: Number of bytes written to return_buffer.
Example:
let target_contract = [...]; // 32-byte contract address
let input = [OP_BALANCE_OF, ...]; // Call data
let mut return_data = [0u8; 8];
let len = cpi_call(&target_contract, &input, &mut return_data)?;
let balance = u64::from_le_bytes(return_data);VRF (Verifiable Random Function)
vrf_random
Generate a verifiable random number.
pub fn vrf_random(seed: &[u8]) -> Result<VRFOutput, u64>;Returns:
pub struct VRFOutput {
pub random: [u8; 32], // Random output
pub pre_output: [u8; 32], // Pre-output for verification
pub proof: [u8; 64], // VRF proof
}Cost: 10,000 compute units.
Example:
let seed = get_block_hash();
let output = vrf_random(&seed)?;
// Use first byte for game logic
let roll = output.random[0] % 100;vrf_verify
Verify a VRF proof.
pub fn vrf_verify(
public_key: &[u8; 32],
input: &[u8; 32],
pre_output: &[u8; 32],
proof: &[u8; 64],
) -> Result<(), u64>;vrf_public_key
Get the VRF public key for this block.
pub fn vrf_public_key() -> Result<[u8; 32], u64>;Referral System
tos_has_referrer
Check if user has bound a referrer.
pub fn tos_has_referrer(user: &[u8; 32]) -> Result<bool, u64>;Cost: 500 compute units.
tos_get_referrer
Get user’s direct referrer.
pub fn tos_get_referrer(user: &[u8; 32]) -> Result<[u8; 32], u64>;Cost: 500 compute units.
get_uplines
Get multiple levels of uplines.
pub fn get_uplines(
user: &[u8; 32],
levels: u8,
) -> Result<([[u8; 32]; 20], u8), u64>;Returns: Tuple of (uplines array, count of valid uplines).
Cost: 500 + 200×N compute units.
Example:
let (uplines, count) = get_uplines(&buyer, 3)?;
for i in 0..count as usize {
let upline = &uplines[i];
// Distribute reward to upline
}tos_get_team_size
Get total team size (cached).
pub fn tos_get_team_size(user: &[u8; 32]) -> Result<u64, u64>;Cost: 500 compute units.
Team Volume
add_team_volume
Add volume to upline chain.
pub fn add_team_volume(
user: &[u8; 32],
asset: &[u8; 32],
amount: u64,
levels: u8,
) -> Result<(), u64>;Cost: 1,000 + 500×levels compute units.
get_team_volume
Get total team volume for user-asset pair.
pub fn get_team_volume(
user: &[u8; 32],
asset: &[u8; 32],
) -> Result<u64, u64>;Cost: 500 compute units.
get_direct_volume
Get direct referral volume only.
pub fn get_direct_volume(
user: &[u8; 32],
asset: &[u8; 32],
) -> Result<u64, u64>;get_zone_volumes
Get each direct referral’s team volume.
pub fn get_zone_volumes(
user: &[u8; 32],
asset: &[u8; 32],
limit: u8,
) -> Result<ZoneVolumesResult, u64>;Error Codes
Common error codes returned by SDK functions:
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Generic error |
| 100 | Invalid argument |
| 101 | Buffer too small |
| 102 | Storage read failed |
| 103 | Storage write failed |
| 104 | Transfer failed |
| 105 | Insufficient balance |
| 106 | CPI call failed |
| 107 | VRF failed |
Complete Example
#![no_std]
#![no_main]
use tako_sdk::*;
const KEY_BALANCE: u8 = 0x10;
fn get_balance(account: &[u8; 32]) -> u64 {
let mut key = [0u8; 33];
key[0] = KEY_BALANCE;
key[1..33].copy_from_slice(account);
let mut buffer = [0u8; 8];
let len = storage_read(&key, &mut buffer);
if len == 8 {
u64::from_le_bytes(buffer)
} else {
0
}
}
fn set_balance(account: &[u8; 32], amount: u64) {
let mut key = [0u8; 33];
key[0] = KEY_BALANCE;
key[1..33].copy_from_slice(account);
let _ = storage_write(&key, &amount.to_le_bytes());
}
#[no_mangle]
pub extern "C" fn entrypoint() -> u64 {
let sender = get_tx_sender();
let deposit = get_call_value();
if deposit > 0 {
let current = get_balance(&sender);
let new_balance = current.saturating_add(deposit);
set_balance(&sender, new_balance);
log("Deposit successful");
}
SUCCESS
}
#[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! {
loop {}
}