Skip to main content

Fungible Token Interface (TIP-3.1)

Requires: TIP-6.1

Abstract

The following standard allows for the implementation of a standard API for tokens within smart contracts. General information about token is stored in the token root contract. Each token holder has its own instance of token wallet contract. Token transfers SHOULD be implemented in P2P fashion, between sender and receiver token wallets.

Motivation

A standard interface allows any tokens on Everscale to be re-used by other applications: from wallets to decentralized exchanges.

Specification

The keywords “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.

Notes

  • We choose Standard Interface Detection to expose the interfaces that a TIP3 smart contract supports.
  • This standard does not define the external methods to initiate transfer, mint or burn tokens. Though it defines the methods, which MUST be called on a recipient token wallet or token root during these operations.
  • The rules for a token wallet ownership MUST be defined in a child standards.
  • A -1 offset is added to some function IDs derivations, so the preimage of the hash cannot be known, further reducing the chances of a possible collisions.

Token root

Name

Returns the name of the token - e.g. "MyToken".

function name() public view responsible returns (string);

Symbol

Returns the symbol of the token. E.g. “HIX”.

function symbol() public view responsible returns (string);

Decimals

Returns the number of decimals the token uses - e.g. 8, means to divide the token amount by 100000000 to get its user representation.

function decimals() public view responsible returns (uint8);

Total supply

Returns the total token supply.

function totalSupply() public view responsible returns (uint128);

Token wallet code

Returns the token wallet code.

function walletCode() public view responsible returns (TvmCell);

Accept tokens burn

Does not have a standard signature, but has a standard function ID 0x192B51B1 obtained as tvm.functionId('acceptBurn(uint128)') - 1. The uint128 _value parameter MUST be first. The function name and the rest of the parameters are not fixed by this standard and can be reinvented for each substandard.

Decreases token total supply by _value. The contract MUST check that the sender is a correct token wallet. Before sending this message, caller token wallet MUST decrease its own balance by _value. If the mint can't be accepted (e.g. invalid sender), this message MUST be bounced.

Any function from the following snippet is a valid example:

interface TIP3AcceptBurn {
function acceptBurn(uint128 _value) functionID(0x192B51B1) public;
function acceptBurn2(uint128 _value, uint256 _publicKey, address _owner) functionID(0x192B51B1) public;
function acceptBurn3(uint128 _value, TvmCell _meta) functionID(0x192B51B1) public;
}

Standard interface detection

interface TIP3TokenRoot {
function acceptBurn(uint128 _value) functionID(0x192B51B1) public view responsible;

function name() public view responsible returns (string);
function symbol() public view responsible returns (string);
function decimals() public view responsible returns (uint8);
function totalSupply() public view responsible returns (uint128);
function walletCode() public view responsible returns (TvmCell);
}

The token root interface ID is 0x4371D8ED.

Token wallet

Root

Returns the token root address.

function root() public view responsible returns (address);

Balance

Returns the token wallet balance.

function balance() public view responsible returns (uint128);

Wallet code

Returns the token wallet code.

function walletCode() public view responsible returns (TvmCell);

Accept tokens transfer

Does not have a standard signature, but has a standard function ID 0x67A0B95F obtained as tvm.functionId('acceptTransfer(uint128)') - 1. The uint128 _value parameter MUST be first. The function name and the rest of the parameters are not fixed by this standard and can be reinvented for each substandard.

Increases token wallet balance by _value. The contract MUST check that the sender is a correct token wallet. Before sending this message, caller token wallet MUST decrease its own balance by _value. If the transfer can't be accepted (e.g. invalid sender), this message MUST be bounced.

Any function from the following snippet is a valid example:

interface TIP3AcceptTransfer {
function acceptTransfer(uint128 _value) functionID(0x67A0B95F) external;
function acceptTransfer2(uint128 _value, uint256 _publicKey, address _owner) functionID(0x67A0B95F) external;
function acceptTransfer3(uint128 _value, TvmCell _meta) functionID(0x67A0B95F) external;
}

Accept tokens mint

Does not have a standard signature, but has a standard function ID 0x4384F298 obtained as tvm.functionId('acceptMint(uint128)') - 1. The uint128 _value parameter MUST be first. The function name and the rest of the parameters are not fixed by this standard and can be reinvented for each substandard.

Increases token wallet balance by _value. The contract MUST check that the sender is a correct token root. Before sending this message, token root MUST increase the total supply by _value. If the mint can't be accepted (e.g. invalid sender), this message MUST be bounced.

Any function from the following snippet is a valid example:

interface TIP3AcceptMint {
function acceptMint(uint128 _value) functionID(0x4384F298) external;
function acceptMint2(uint128 _value, uint256 _publicKey, address _owner) functionID(0x4384F298) external;
function acceptMint3(uint128 _value, TvmCell _meta) functionID(0x4384F298) external;
}

On-bounce behaviour

The acceptTransfer or acceptBurn methods can be bounced, e.g. receiver token wallet has a different code or burning disabled. The token wallet behaviour in these cases should be implemented according to the following rules.

Handle acceptTransfer bounce

Increases token wallet balance according to the value, specified in the bounce body.

Handle acceptBurn bounce

Increases token wallet balance according to the value, specified in the bounce body.

Standard interface detection

interface TIP3TokenWallet {
function acceptTransfer(uint128 _value) functionID(0x67A0B95F) external;
function acceptMint(uint128 _value) functionID(0x4384F298) external;

function root() public view responsible returns (address);
function balance() public view responsible returns (uint128);
function walletCode() public view responsible returns (TvmCell);
}

The token wallet interface ID is 0x4F479FA3.