Skip to main content

Fungible Tokens

Besides the native NEAR token, NEAR accounts have access to a multitude of fungible tokens (e.g. these whitelisted tokens). Moreover, it is even possible for users to create their own fungible tokens.

In contrast with the NEAR native token, fungible token (FT) are not stored in the user's wallet. In fact, each FT lives in their own contract which is in charge of doing bookkeeping. This is, the contract keeps track of how many tokens each user has, and handles transfers internally.

In order for a contract to be considered a FT-contract it has to follow the NEP-141 and NEP-148 standards. The NEP-141 & NEP-148 standards explain the minimum interface required to be implemented, as well as the expected functionality.

Reference Implementation

We provide a FT reference implementation ready to be deployed and use.


Creating a Fungible Tokenโ€‹

Creating a new FT is as simple as deploying a new FT contract and initializing it. On initialization you will define the token's metadata such as its name (e.g. Ethereum), symbol (e.g. ETH) and total supply (e.g. 10M). You will also define an owner, which will own the tokens total supply.

# 1. Deploy the contract in a testnet account
near dev-deploy --wasmFile fungible_token.wasm

# 2. Initialize the contract with metadata
near call <ft-contract> new '{"owner_id": "<owner-account>", "total_supply": "1000000000000000", "metadata": { "spec": "ft-1.0.0", "name": "Example Token Name", "symbol": "EXLT", "decimals": 8 }}' --accountId <ft-contract>

info

On initialization you will define an owner, who will own ALL the tokens.


Querying Metadataโ€‹

You can query the FT's metadata by calling the ft_metadata.

near view <ft-contract> ft_metadata

Registering a Userโ€‹

In order for a user to own and transfer tokens they need to first register in the contract. This is done by calling storage_deposit and attaching 0.00125โ“ƒ. This method also allows to pay for other users to register them.

near call <ft-contract> storage_deposit '{"account_id": "<account-to-register>"}' --accountId <your-account> --amount 0.00125
info

You can make sure a user is registered by asserting they have a storage_balance_of greater than 0.00125 โ“ƒ.

tip

After you call the storage_deposit the FT will appear in the NEAR WALLET.


Getting Balanceโ€‹

To know how many coins a user has you will need to query the method ft_balance_of.

near view <ft-contract> ft_balance_of '{"account_id": "<users-account>"}'
caution

Keep in mind the decimals from the metadata. A balance of 150 FT for a token with 2 decimals actually represents 1.50 FT.


Transferringโ€‹

To send FT to another account you will use the ft_transfer method, indicating the receiver and the amount of FT you want to send.

near call <ft-contract> ft_transfer '{"receiver_id": "<receiver-account>", "amount": "<amount>"}' --accountId <your-account> --depositYocto 1
tip

Implement events to be able to track FT transfers in real time.

danger

In order to send a fungible token to an account, both the sender and receiver must be registered in the FT contract.


Attaching FTs to a Callโ€‹

Natively, only NEAR tokens (โ“ƒ) can be attached to a method calls. However, the FT standard enables to attach fungible tokens in a call by using the FT-contract as intermediary. This means that, instead of you attaching tokens directly to the call, you ask the FT-contract to do both a transfer and a method call in your name.

near call <ft-contract> ft_transfer_call '{"receiver_id": "<receiver-contract>", "amount": "<amount>", "msg": "<a-string-message>"}' --accountId <user_account_id> --depositYocto 1

Exampleโ€‹

Assume you want to attach some FT (๐Ÿช™) to a call on the receiver contract. The workflow is as follows:

  1. You call ft_transfer_call in the ๐Ÿช™-contract passing: the receiver, a message, and the amount.
  2. The FT contract transfers the amount to the receiver.
  3. The FT contract calls receiver.ft_on_transfer(sender, msg, amount).
  4. The FT contract handles errors in the ft_resolve_transfer callback.
  5. The FT contract returns you how much of the attached amount was actually used.

The ft_on_transfer methodโ€‹

From the workflow above it follows that the receiver we want to call needs to implement the ft_on_transfer method. When executed, such method will know:

  • Which FT was transferred, since it is the predecessor account.
  • Who is sending the FT, since it is a parameter
  • How many FT were transferred, since it is a parameter
  • If there are any parameters encoded as a message

The ft_on_transfer must return how many FT tokens it used, so the FT contract knows how many to transfer you back.


Eventsโ€‹

You can track real time events (such as transfers) by implementing the FT Event Standards. Events are simple to use, because they are just login messages formatted in a standardize way. Since these logged messages are public, a service can then be built to track them in real time.