Fungible tokens (FTs) are digital assets that work on blockchain networks and have the same properties and values. These tokens can be swapped with each other because each unit of a fungible token is exactly the same as the others. This makes them very easy to trade and use for transactions within blockchain systems.
Indistinguishability: Each fungible token holds the same value and characteristics as any other token within the same batch or series. For example, every Bitcoin has the same value and properties as any other single Bitcoin.
Interchangeability: Fungible tokens are mutually interchangeable. This property enables seamless exchange and transfer between participants within a blockchain network. This interchangeability enables liquidity, facilitating their integration into various financial applications and systems.
Uniformity: Each fungible token is uniform in terms of value, divisibility, and utility. This uniformity simplifies transactions and allows for easy integration into smart contracts and decentralized applications (dApps).
Liquidity and market efficiency: Fungible tokens, being highly interchangeable, enhance liquidity and market efficiency within blockchain ecosystems. They facilitate the seamless exchange of assets and enable more efficient price discovery mechanisms.
Accessibility and inclusion: Fungible tokens offer increased access to financial services, allowing individuals with limited resources or restricted access to traditional banking systems to participate in financial activities. Fungible tokens can be easily acquired, traded, and stored using blockchain wallets, providing individuals with greater control over their assets and financial decisions.
Programmability and automation: Fungible tokens are programmable assets that can be integrated into smart contracts and decentralized applications. This programmability enables the automation of financial processes, such as automatic interest payments, decentralized exchanges, and yield farming strategies.
Transparency and security: Blockchain technology underlying fungible tokens ensures transparency and immutability of transactions. Each transaction recorded on the blockchain can be
Cryptocurrencies: Fungible tokens serve as the backbone of cryptocurrencies, enabling peer-to-peer transactions, a store of value, and a medium of exchange within blockchain networks.
DeFi and financial instruments: Fungible tokens play a crucial role in decentralized finance (DeFi) platforms by serving as collateral, governance tokens, or liquidity providers. They enable the creation of various financial instruments, including stablecoins, lending and borrowing protocols, and yield farming.
Gaming and virtual economies: Within the realm of gaming, fungible tokens power in-game currencies, enabling players to trade, purchase, and sell virtual assets. They foster the growth of virtual economies, where digital goods and services hold real economic value.
Fungible tokens are often created using specific token standards or protocols on a blockchain platform. The most common standard for fungible tokens is the ERC-20 standard on the Ethereum blockchain. This standard provides a set of rules and guidelines for the creation and implementation of fungible tokens.
Let's create a fungible token by implementing the ERC-20 interface. A fungible token should allow users to transfer tokens, check balances, approve allowances, and perform other common operations associated with ERC-20 tokens. The following code demonstrates how to create a fungible token using the ERC-20 standard.
// SPDX-License-Identifier: GPL-3.0pragma solidity ^0.8.0;interface ERC20 {function name() external view returns (string memory);function symbol() external view returns (string memory);function decimals() external view returns (uint8);function totalSupply() external view returns (uint256);function balanceOf(address _owner) external view returns (uint256);function transfer(address _to, uint256 _value) external returns (bool);function transferFrom(address _from, address _to, uint256 _value) external returns (bool);function approve(address _spender, uint256 _value) external returns (bool);function allowance(address _owner, address _spender) external view returns (uint256);event Transfer(address indexed _from, address indexed _to, uint256 _value);event Approval(address indexed _owner, address indexed _spender, uint256 _value);}contract FungibleToken is ERC20 {string private _name;string private _symbol;uint8 private _decimals;uint256 private _totalSupply;mapping(address => uint256) private _balances;mapping(address => mapping(address => uint256)) private _allowances;constructor(string memory name_,string memory symbol_,uint8 decimals_,uint256 totalSupply_) {_name = name_;_symbol = symbol_;_decimals = decimals_;_totalSupply = totalSupply_;_balances[msg.sender] = totalSupply_;}function name() external view override returns (string memory) {return _name;}function symbol() external view override returns (string memory) {return _symbol;}function decimals() external view override returns (uint8) {return _decimals;}function totalSupply() external view override returns (uint256) {return _totalSupply;}function balanceOf(address _owner) external view override returns (uint256) {return _balances[_owner];}function transfer(address _to, uint256 _value) external override returns (bool) {_transfer(msg.sender, _to, _value);return true;}function transferFrom(address _from,address _to,uint256 _value) external override returns (bool) {require(_allowances[_from][msg.sender] >= _value, "Insufficient allowance");_transfer(_from, _to, _value);_approve(_from, msg.sender, _allowances[_from][msg.sender] - _value);return true;}function approve(address _spender, uint256 _value) external override returns (bool) {_approve(msg.sender, _spender, _value);return true;}function allowance(address _owner, address _spender) external view override returns (uint256) {return _allowances[_owner][_spender];}function _transfer(address _from,address _to,uint256 _value) internal {require(_from != address(0), "Transfer from the zero address");require(_to != address(0), "Transfer to the zero address");require(_balances[_from] >= _value, "Insufficient balance");_balances[_from] -= _value;_balances[_to] += _value;emit Transfer(_from, _to, _value);}function _approve(address _owner,address _spender,uint256 _value) internal {require(_owner != address(0), "Approve from the zero address");require(_spender != address(0), "Approve to the zero address");_allowances[_owner][_spender] = _value;emit Approval(_owner, _spender, _value);}}
The code starts with a contract named FungibleToken
which implements the ERC20
interface. The ERC20
interface defines a set of functions and events that a token contract should have to be considered an ERC-20 token.
The contract has some state variables.
_name
: It stores the name of the token.
_symbol
: It stores the symbol of the token.
_decimals
: It stores the number of decimal places the token supports.
_totalSupply
: It stores the total supply of tokens in circulation.
There are two mapping variables.
_balances
: It maps addresses to their token balances.
_allowances
: It maps addresses to the allowances granted by token holders to spend their tokens on their behalf.
The constructor is a special function that is called only once during the deployment of the contract. It takes parameters such as the name, symbol, decimals, and total supply of the token. The constructor initializes the state variables with the provided values and assigns the total supply to the deployer’s address.
The next set of functions are the implementations of the functions defined in the ERC20 interface. Let’s go through them.
name()
, symbol()
, decimals()
, and totalSupply()
: These functions simply return the respective state variables.
balanceOf(address _owner)
: It returns the token balance of the specified address.
transfer(address _to, uint256 _value)
: It allows the sender to transfer tokens to another address.
transferFrom(address _from, address _to, uint256 _value)
: It allows a designated spender to transfer tokens on behalf of the token owner.
approve(address _spender, uint256 _value)
: It approves a designated address to spend a specified amount of tokens on behalf of the caller.
allowance(address _owner, address _spender)
: It returns the amount of tokens the spender is allowed to spend on behalf of the owner.
_transfer
and _approve
: Are helper functions used by other functions to perform the actual transfer of tokens and approval of allowances. They also emit events to notify listeners about the token transfers and approvals.
Fungible tokens have emerged as a vital component of the digital asset ecosystem, providing liquidity, efficiency, and programmability to blockchain networks. With their interchangeability, uniformity, and wide range of applications, fungible tokens have transformed the way we transact, invest, and participate in financial activities. As blockchain technology continues to advance, fungible tokens are expected to play a central role in shaping the future of finance, enabling greater accessibility, inclusivity, and innovation in the digital era.
Free Resources