TZIP-12 Token Standard

Implemented by Stove Labs, proposed by the TQTezos.

TZIP-12 is a next generation token standard aiming to standardize integration & token data exchange between smart contracts and clients. It supports multiple token types, such as Fungible, Non-Fungible, Non-Transferrable or others.

Data Structure

(* token_id is a nat, following the TZIP-12 spec *)
type token_id is nat;
type token_owner is address;
(* token_balance is either 0 or positive, therefore it's a nat *)
type token_balance is nat;

(* 
    token_lookup_id is always a unique combination of a token_id and a token_owner, 
    representing a key in the big_map of token_balances
*)
type token_lookup_id is record
    token_id : token_id;
    token_owner : token_owner;
end;

type token_balances is big_map(token_lookup_id, token_balance);

(* 
    Total supply is persisted separately rather than computed at each request
    in order to optimise gas costs.
*)
type total_token_supply_count is nat;
type total_token_supply is big_map(token_id, total_token_supply_count);

type storage is record
    token_balances : token_balances;
    (* See https://www.wordhippo.com/what-is/the-plural-of/supply.html *)
    total_token_supply : total_token_supply;
end;
                    
                    

Available Entrypoints

type transfer is record
    token_id : token_id;
    amount : token_balance;
    from_ : token_owner;
    to_ : token_owner;
end;

type transfer_param is list(transfer);

type action is
| Transfer of transfer_param
| Balance_of of balance_of_param
| Total_supply of total_token_supply_param

(* Default function that represents our contract, it's sole purpose here is the entrypoint routing *)
function main (const action : action; var storage : storage) : (list(operation) * storage)
    is (case action of
    (* 
        Unwrap the `Transfer(...)` parameters and invoke the transfer function.
        The return value of `transfer(...)` is then returned as a result of `main(...)` as well.
     *)
    | Transfer(transfer_param) -> transfer(transfer_param, storage)
    | Balance_of(balance_of_param) -> balance_of(balance_of_param, storage)
    | Total_supply(total_token_supply_param) -> total_token_supply(total_token_supply_param, storage)
    end)
                
                

Token deployment

⚠️ Please see the full README for comprehensive usage instructions.

Set up the development environment

git clone https://github.com/stove-labs/tzip-12
cd tzip-12
npm i
                    

Configure the initial token storage state

// migrations/tzip_12.js
const tokenBalance = 10;
const tokenId = 0;
/**
* Generate lookup IDs for both alice & bob with tokenId = 0
*/
const tokenLookupIdAlice = getTokenLookupId(tokenId, alice.pkh);

/**
* Initialize the storage with Alice owning a certain token balance.
*/
const initialStorage = {
    token_balances: new MichelsonMap(),
    total_token_supply: new MichelsonMap()
};

initialStorage.token_balances.set(tokenLookupIdAlice, tokenBalance);

initialStorage.total_token_supply.set(
    tokenId, 
    calculateTotalTokenSupply(initialStorage)
);
                    

Migrate the contract

// Start a private sandbox network in Docker 🐳
npm run start-sandbox -- carthage
// Migrate the token contract
npm run migrate
                    

Partners & Projects