Skip to main content

SAVITRI-1155: Multi-Asset Token Standard

SAVITRI-1155 (SMA -- Savitri Multi Asset) is the multi-asset token standard for the Savitri Network, equivalent to Ethereum's ERC-1155. It supports both fungible and non-fungible tokens in a single contract with efficient batch operations.

Interface

FunctionParamsReturnsDescription
balance_ofowner, idu128Balance of a specific token for an owner
balance_of_batchowners[], ids[]u128[]Batch balance query
safe_transfer_fromfrom, to, id, amount, dataResultTransfer tokens
safe_batch_transfer_fromfrom, to, ids[], amounts[], dataResultBatch transfer
set_approval_for_alloperator, approvedResultApprove operator for all tokens
is_approved_for_allowner, operatorboolCheck operator approval

Storage Layout

Balance Storage (Slot 100+)

Nested mapping: balances[owner][id]

hash1 = keccak256(owner || 100)
hash2 = keccak256(id || hash1)
slot = first 8 bytes of hash2 as u64

Operator Approval Storage (Slot 200+)

Nested mapping: operator_approvals[owner][operator]

hash1 = keccak256(owner || 200)
hash2 = keccak256(operator || hash1)
slot = first 8 bytes of hash2 as u64

This layout provides:

  • Uniform distribution: Keccak256 ensures uniform slot distribution
  • No collisions: Negligible collision probability
  • Efficient batch queries: Each slot is calculated independently
  • Cache-friendly: ContractStorage caches reads

Usage

Single Transfer

use savitri_contracts::contracts::standards::savitri1155::SAVITRI1155;

SAVITRI1155::safe_transfer_from(
&mut contract_storage,
&storage,
&from, // [u8; 32]
&to, // [u8; 32]
1, // token id
100, // amount
&[], // data
&mut event_system,
Some(&mut gas_meter),
)?;

Batch Transfer

SAVITRI1155::safe_batch_transfer_from(
&mut contract_storage,
&storage,
&from,
&to,
&[1, 2, 3], // token ids
&[100, 50, 1], // amounts
&[], // data
&mut event_system,
Some(&mut gas_meter),
)?;

Batch Balance Query

let balances = SAVITRI1155::balance_of_batch(
&contract_storage,
&storage,
&[owner1, owner2, owner3],
&[token_id_1, token_id_2, token_id_3],
)?;

Operator Approval

// Approve an operator for all tokens
SAVITRI1155::set_approval_for_all(
&mut contract_storage,
&storage,
&owner,
&operator,
true, // approved
&mut event_system,
Some(&mut gas_meter),
)?;

// Check approval
let approved = SAVITRI1155::is_approved_for_all(
&contract_storage,
&storage,
&owner,
&operator,
)?;

Events

EventFieldsDescription
TransferSingleoperator, from, to, id, amountSingle token transfer
TransferBatchoperator, from, to, ids[], amounts[]Batch transfer
ApprovalForAllowner, operator, approvedOperator approval changed

Use Cases

ScenarioToken TypeExample
In-game currencyFungible (id=1)1000 gold coins
Unique itemsNon-fungible (amount=1)Legendary sword #42
Semi-fungibleLimited supply50 copies of a rare card
RewardsFungiblePoU reward tokens
CertificatesNon-fungibleValidator certification

Batch Optimization

The SAVITRI-1155 implementation optimizes batch operations by:

  1. Pre-calculating all slots before reading storage
  2. Leveraging ContractStorage cache to avoid repeated DB reads
  3. Independent slot calculation enabling future parallel reads
  4. Minimizing address decoding by reusing decoded addresses across operations