Skip to main content

Vara Multi-Token (VMT) Standard and Extended Implementation

note

The Vara Multi-Token (VMT) Standard is the analogue of ERC-1155 on Ethereum.

The VMT Standard outlines a unified API for implementing multi-token functionality in programs. The initial section provides an in-depth exploration of the core VMT service, covering operations like batch token transfers and token balance queries, detailing the contract state, interface, and key methods. The source code of the standard-service is avaiable on the GitHub.

The following section expands on extending this core service to develop a fully functional multi-token application. This part illustrates how to incorporate minting and burning capabilities and advanced management features, building upon the core VMT service to create a robust and flexible token system. The source code of the extended version is avaiable on the GitHub.

tip

The project code is developed using the Sails framework.

Core VMT Service

Functions

The VMT service includes the following functions:

  • Approve(to)
  • TransferFrom(from, to, id, amount)
  • BatchTransferFrom(from, to, ids, amounts)
  • BalanceOf(account, id)
  • BalanceOfBatch(accounts, ids)
  • IsApproved(account, operator)
  • Name()
  • Symbol()
  • Decimals()
  • TotalSupply()

Events

The core service also defines the following events:

  • Approval(from, to)
  • Transfer(from, to, ids, amounts)

Key Methods

Approve

pub fn approve(&mut self, to: ActorId) -> bool

Allows an account to approve another actor (to) to manage all of its tokens. This function sets the approval status of the operator and returns a boolean indicating success. When approved, the Approval event is triggered.

TransferFrom

pub fn transfer_from(&mut self, from: ActorId, to: ActorId, id: TokenId, amount: U256)

Transfers amount of token with ID id from the from account to the to account. The caller must be approved to manage the from account's tokens. The Transfer event is triggered upon successful execution.

BatchTransferFrom

pub fn batch_transfer_from(
&mut self,
from: ActorId,
to: ActorId,
ids: Vec<TokenId>,
amounts: Vec<U256>,
)

Transfers multiple token types from one account to another. The ids array contains token IDs, and the amounts array specifies how many of each token type to transfer. This method triggers the Transfer event for each token ID and amount.

Query methods

BalanceOf

Returns the balance of tokens for a given account and token ID.

pub fn balance_of(&self, account: ActorId, id: TokenId) -> U256

BalanceOfBatch

Returns the balances of tokens for the specified accounts and token IDs.

pub fn balance_of_batch(&self, accounts: Vec<ActorId>, id: Vec<TokenId>) -> Vec<U256>

IsApproved

Checks if a specific operator is approved to manage the tokens of the account.

pub fn is_approved(&self, account: ActorId, operator: ActorId) -> bool

Name

Returns the name of the multi-token collection.

pub fn name(&self) -> &'static str

Symbol

Returns the symbol of the token collection.

pub fn symbol(&self) -> &'static str

Decimals

Returns the number of decimal places for the tokens.

pub fn decimals(&self) -> u8

TotalSupply

Returns the total supply of each token ID.

pub fn total_supply(&self) -> Vec<(TokenId, U256)>
note

The core VMT service serves as a foundational framework for multi-token contracts. It can be extended to introduce more complex functionality such as minting, burning, and role management. The code for the core service is available on GitHub.

Extended VMT Implementation

Additional Features

The extended implementation adds new functionality to the core VMT service, including:

Functions

  • Mint(to, id, amount, token_metadata)
  • MintBatch(to, ids, amounts, token_metadata)
  • Burn(from, id, amount)
  • BurnBatch(from, ids, amounts)
  • GrantAdminRole(to)
  • GrantMinterRole(to)
  • GrantBurnerRole(to)
  • RevokeAdminRole(from)
  • RevokeMinterRole(from)
  • RevokeBurnerRole(from)
  • Admins()
  • Minters()
  • Burners()

Events

  • Minted(to, ids, amounts)
  • Burned(from, ids, amounts)

Implementation Details

The VMT core service is imported and extended:

use vmt_service::Service as VmtService;

pub struct ExtendedVmtService {
vmt: VmtService,
}

The #[service(extends = VmtService, events = Event)] attribute ensures inheritance from VmtService.

Key Methods

Mint

pub fn mint(
&mut self,
to: ActorId,
id: TokenId,
amount: U256,
token_metadata: Option<TokenMetadata>,
)

Mints a new token with a specified ID and amount, assigning it to the to account. The optional token_metadata field allows storing additional information about the token (like title, description, media and reference). This function triggers the Minted event.

MintBatch

pub fn mint_batch(
&mut self,
to: ActorId,
ids: Vec<TokenId>,
amounts: Vec<U256>,
token_metadata: Vec<Option<TokenMetadata>>,
)

Mints multiple types of tokens and assigns them to the to account. The function accepts arrays of token IDs and amounts, along with corresponding metadata. It triggers the Minted event for all tokens in the batch.

Burn

pub fn burn(&mut self, from: ActorId, id: TokenId, amount: U256)

Burns a specified amount of tokens with a specific ID from the from account. This reduces the total supply of the burned tokens and triggers the Burned event.

BurnBatch

pub fn burn_batch(&mut self, from: ActorId, ids: Vec<TokenId>, amounts: Vec<U256>) 

Burns multiple types of tokens from the from account. This method reduces the total supply for each token in the batch and triggers the Burned event.

Role Management

  • grant_admin_role(&mut self, to: ActorId)
  • grant_minter_role(&mut self, to: ActorId)
  • grant_burner_role(&mut self, to: ActorId)
  • revoke_admin_role(&mut self, from: ActorId)
  • revoke_minter_role(&mut self, from: ActorId)
  • revoke_burner_role(&mut self, from: ActorId)

These methods manage the assignment and revocation of administrative, minting, and burning roles, ensuring that only authorized actors can perform sensitive operations.

Query methods

minters

Returns a list of all actors who have the minter role.

pub fn minters(&self) -> Vec<ActorId> 

burners

Returns a list of all actors who have the burner role.

pub fn burners(&self) -> Vec<ActorId> 

admins

Returns a list of all actors who have the admin role.

pub fn admins(&self) -> Vec<ActorId> 

Contract Interface

The extended VMT service includes the following interface:

type TokenMetadata = struct {
title: opt str,
description: opt str,
media: opt str,
reference: opt str,
};

constructor {
New : (name: str, symbol: str, decimals: u8);
};

service Vmt {
Burn : (from: actor_id, id: u256, amount: u256) -> null;
BurnBatch : (from: actor_id, ids: vec u256, amounts: vec u256) -> null;
GrantAdminRole : (to: actor_id) -> null;
GrantBurnerRole : (to: actor_id) -> null;
GrantMinterRole : (to: actor_id) -> null;
Mint : (to: actor_id, id: u256, amount: u256, token_metadata: opt TokenMetadata) -> null;
MintBatch : (to: actor_id, ids: vec u256, amounts: vec u256, token_metadata: vec opt TokenMetadata) -> null;
RevokeAdminRole : (from: actor_id) -> null;
RevokeBurnerRole : (from: actor_id) -> null;
RevokeMinterRole : (from: actor_id) -> null;
Approve : (to: actor_id) -> bool;
BatchTransferFrom : (from: actor_id, to: actor_id, ids: vec u256, amounts: vec u256) -> null;
TransferFrom : (from: actor_id, to: actor_id, id: u256, amount: u256) -> null;

query Admins : () -> vec actor_id;
query Burners : () -> vec actor_id;
query Minters : () -> vec actor_id;
query BalanceOf : (account: actor_id, id: u256) -> u256;
query BalanceOfBatch : (accounts: vec actor_id, ids: vec u256) -> vec u256;
query Decimals : () -> u8;


query IsApproved : (account: actor_id, operator: actor_id) -> bool;
query Name : () -> str;
query Symbol : () -> str;
query TotalSupply : () -> vec struct { u256, u256 };

events {
Minted: struct { to: actor_id, ids: vec u256, amounts: vec u256 };
Burned: struct { from: actor_id, ids: vec u256, amounts: vec u256 };
Approval: struct { from: actor_id, to: actor_id };
Transfer: struct { from: actor_id, to: actor_id, ids: vec u256, amounts: vec u256 };
}
};


note

This extended VMT service demonstrates how the core functionality can be built upon to include features like minting, burning, and URI management. The complete implementation is available on GitHub.

Conclusion

The core VMT service establishes a solid foundation for implementing multi-token systems within the Vara ecosystem, encompassing essential functionalities that align with recognized token standards. This service acts as a fundamental core, while the Extended VMT implementation demonstrates how it can be expanded to include advanced features such as minting, burning, and role management. Together, these implementations offer a comprehensive framework for developers, enabling the creation of versatile and feature-rich token systems. By leveraging both the core service and its extended capabilities, developers are equipped to design flexible, secure, and scalable token solutions that meet specific needs and enhance overall system functionality.