November 19th, 2015 an Ethereum Improvement Proposal (EIP) was published to standardize the structure to create tokens on the Ethereum blockchain. The authors were Fabian Vogelsteller and Vitalik Buterin, it was the 20th Ethereum Request For Comment (ERC) so it was given the name ERC-20: Token Standard.
The aim for creating this token standard was to provide basic functionality to transfer tokens, as well as allow tokens to be approved so they can be spent by another on-chain third party. It will also allow any tokens on Ethereum to be re-used by other applications: from wallets to decentralized exchanges.
First we need to create our constructor and state variables to set Name, Symbol, Decimal, and total supply on deployment.
State Variables
string private TokenName;
string private TokenSymbol;
uint8 private TokenDecimals;
uint256 private TokenSupply;
address public owner;
Constructor
constructor(
string memory _tokenName,
string memory _tokenSymbol,
uint8 _tokenDecimals,
uint256 _tokenSupply
) {
owner = msg.sender;
TokenName = _tokenName;
TokenSymbol = _tokenSymbol;
TokenDecimals = _tokenDecimals;
TokenSupply = _tokenSupply;
balance[owner] = TokenSupply;
}
There are 9 functions and 2 events specifications. I will list out the specifications and show you how I implemented it in my code.
Events
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value)
Functions
1. Name:
Specification:
Returns the name of the token - e.g. “My Token”
function name() public view returns (string)
Implementation:
function name() public view returns (string memory) {
return TokenName;
}
2. Symbol:
Specification:
Returns the symbol of the token - e.g. “MTK”
function symbol() public view returns (string)
Implementation:
function symbol() public view returns (string memory) {
return TokenSymbol;
}
3. Decimals:
Specification:
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 returns (uint8)
Implementation:
function decimals() public view returns (uint8) {
return TokenDecimals;
}
4. Total Supply:
Specification:
Returns the token total supply.
function totalSupply() public view returns (uint256)
Implementation:
function totalSupply() public view returns (uint256) {
return TokenSupply;
}
5. Balance Of:
Specification:
Returns the account balance of another account with address “_owner”.
function balanceOf(address _owner) public view returns (uint256 balance)
Implementation:
function balanceOf(address _owner) public view returns (uint256) {
return balance[_owner];
}
6. Transfer:
Specification:
Transfers “_value” amount of tokens to address “_to”, and MUST fire the “Transfer event”. The function SHOULD “throw” if the message caller’s account balance does not have enough tokens to spend.
function transfer(address _to, uint256 _value) public returns (bool success)
Implementation:
function transfer(
address payable _to,
uint256 _value
) public returns (bool) {
require(_to != address(0x0), "Wrong EOA");
require(_value <= balance[msg.sender], "You Don't have enough Token");
balance[msg.sender] = balance[msg.sender] - _value;
balance[_to] = balance[_to] + _value;
return true;
}
7. Transfer From:
Specification:
Transfers "_value" amount of tokens from address "_from" to address "_to", and MUST fire the "Transfer" event. The "transferFrom" method is used for a withdraw workflow, allowing contracts to transfer tokens on your behalf.
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success)
Implementation:
function transferFrom(
address _from,
address _to,
uint256 _value
) public returns (bool) {
require(_to != address(0x0), "Wrong EOA");
require(_value <= approval[_from][msg.sender]);
uint256 _burnAmount = _value / 10;
approval[_from][msg.sender] -= _value;
balance[_from] -= _value;
balance[_to] += _value;
burn(_from, _burnAmount); // You will see this function bellow
return true;
}
8. Approve:
Specification:
Allows "_spender" to withdraw from your account multiple times, up to the "_value" amount. If this function is called again it overwrites the current allowance with "_value".
function approve(address _spender, uint256 _value) public returns (bool success)
Implementation:
function approve(address _spender, uint256 _value) public returns (bool) {
approval[msg.sender][_spender] = _value;
return true;
}
9. Allowance:
Specification:
Returns the amount which "_spender" is still allowed to withdraw from "_owner".
function allowance(address _owner, address _spender) public view returns (uint256 remaining)
Implementation:
function allowance(
address _owner,
address _spender
) public view returns (uint256 approved) {
return approval[_owner][_spender];
}
Burn Feature.
I added a burn feature to the contract which was called in transferFrom function.
10. Burn
It burns 10% of the total supply.
Implementation:
function burn(address _from, uint256 _value) internal {
require(balance[_from] >= _value, "Insufficient balance to burn");
balance[_from] = balance[_from] - _value;
TokenSupply = TokenSupply - _value;
emit Transfer(_from, address(0), _value);
}
Top comments (0)