Skip to Content
Native FeaturesBatch Transfer

Native Batch Transfer

TOS allows sending to up to 500 recipients in a single transaction, with a 50% gas discount compared to individual transfers.

Implementation Status

FeatureStatus
Transfers transaction (multi-target)Implemented
Max 500 recipients per transactionImplemented
50% gas discountImplemented

Why Batch Transfer?

ScenarioIndividual (TRON)TOS BatchSavings
10 transfers$1.00$0.00599.5%
100 transfers$10.00$0.0599.5%
500 transfers$50.00$0.2599.5%

Use Cases

  • Referral distributions - Pay multiple uplines at once
  • Airdrops - Distribute tokens to hundreds of addresses
  • Payroll - Batch salary payments
  • Gaming - Settle multiple players simultaneously
  • Dividends - Distribute rewards to holders

Transaction Format

pub struct BatchTransfer { /// Asset type (TOS or token) pub asset: Hash, /// List of (recipient, amount) pairs pub transfers: Vec<(Address, u64)>, } pub mod BatchLimits { /// Maximum recipients per transaction pub const MAX_BATCH_SIZE: usize = 500; /// Gas discount percentage pub const BATCH_GAS_DISCOUNT: u64 = 50; }

CLI Usage

# Batch transfer from file tos_wallet batch_transfer --asset TOS --file recipients.csv # recipients.csv format: # address,amount # tos1abc123...,1000000000 # tos1def456...,500000000

SDK Usage

// JavaScript const recipients = [ { address: 'tos1abc...', amount: 1000_00000000 }, { address: 'tos1def...', amount: 500_00000000 }, { address: 'tos1ghi...', amount: 250_00000000 }, ]; const tx = await tos.batchTransfer({ asset: 'TOS', transfers: recipients });

Smart Contract Usage

use tako_sdk::*; /// Distribute referral rewards using batch transfer fn distribute_to_uplines(investor: &[u8; 32], amount: u64) { // Get uplines let (uplines, count) = get_uplines(investor, 10).unwrap_or_default(); let rates = [10, 5, 3, 2, 1, 1, 1, 1, 1, 1]; // percentages let mut transfers = Vec::new(); for i in 0..(count as usize).min(10) { let reward = amount * rates[i] / 100; if reward > 0 { transfers.push((uplines[i], reward)); } } // Execute all transfers in one syscall batch_transfer(TOS_ASSET, transfers).ok(); }

Gas Calculation

/// Gas for batch transfer fn calculate_batch_gas(count: usize) -> u64 { let base = 1_000; // Base transfer cost let per_recipient = 500; // Discounted per-recipient cost base + (per_recipient * count as u64) } // Examples: // 10 recipients: 1,000 + 5,000 = 6,000 gas (~$0.006) // 100 recipients: 1,000 + 50,000 = 51,000 gas (~$0.05) // 500 recipients: 1,000 + 250,000 = 251,000 gas (~$0.25)

Atomicity

Batch transfers are atomic - all succeed or all fail:

pub enum BatchResult { /// All transfers succeeded Success { count: usize }, /// Batch failed (none executed) Failed { reason: BatchError }, } pub enum BatchError { /// Insufficient balance for total InsufficientBalance, /// Too many recipients (>500) TooManyRecipients, /// Invalid recipient address InvalidAddress { index: usize }, /// Zero amount ZeroAmount { index: usize }, }

Airdrop Example

/// Airdrop tokens to multiple addresses fn airdrop(recipients: Vec<[u8; 32]>, amount_each: u64) { let transfers: Vec<_> = recipients .into_iter() .map(|addr| (addr, amount_each)) .collect(); // Split into chunks of 500 if needed for chunk in transfers.chunks(500) { batch_transfer(TOKEN_ASSET, chunk.to_vec()).ok(); } }

Comparison

FeatureTOS BatchTRONBSCSolana
Native supportYesNoNoYes
Max recipients500N/AN/A~20
Gas discount50%N/AN/AMinimal
AtomicityYesN/AN/AYes

Limits

LimitValue
Max recipients500
Min amount per recipient1 (smallest unit)
Max total amountSender’s balance
Gas limit per batch1,000,000

Error Handling

try { const result = await tos.batchTransfer({ asset: 'TOS', transfers: recipients }); console.log(`Transferred to ${result.count} recipients`); } catch (error) { if (error.code === 'INSUFFICIENT_BALANCE') { console.log('Not enough balance for batch'); } else if (error.code === 'TOO_MANY_RECIPIENTS') { // Split into multiple batches await batchInChunks(recipients, 500); } }
Last updated on