Subscribe to our free newsletter

To make sure you won't miss any valuable content we share with our community.

ERC-20 Event and Function + Sample Smart Contract

In this article, we are going to analyze the ERC-20 event and function deeper and get familiar with the building blocks of any ERC-20 smart contract. Learning these methods and events will help us write the smart contract of our desired token. Throughout this article, you will see the functionalities of all the smart contracts that we wrote for creating an ERC20 token in the last article.

Functions and Event of all ERC-20 contracts:

In general, every ERC-20 token has the below functions and events:

function name() public view returns (string)
function symbol() public view returns (string)
function decimals() public view returns (uint8)
function totalSupply() public view returns (uint256)
function balanceOf(address _owner) public view returns (uint256 balance)
function transfer(address _to, uint256 _value) public returns (bool success)
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success)
function approve(address _spender, uint256 _value) public returns (bool success)
function allowance(address _owner, address _spender) public view returns (uint256 remaining)


ERC-20 Event


event Transfer(address indexed _from, address indexed _to, uint256 _value)
event Approval(address indexed _owner, address indexed _spender, uint256 _value)


A Sample ERC-20 Smart Contract: Method & Event

For the following contract, we are going to explain more about the ERC-20 method and event (TokenERC20.sol):

pragma solidity ^0.6.0;

interface tokenRecipient {
	function receiveApproval(address _from, uint256 _value, address _token, bytes calldata 
                _extraData) external;
}

contract TokenERC20 {
	string public name;
	string public symbol;
	uint8 public decimals = 18;
	uint256 public totalSupply;
}

Name, symbol, decimals, and total supply are the main variables of every ERC-20 smart contract.

mapping (address => uint256) public balanceOf;
mapping (address => mapping (address => uint256)) public allowance;


Created a mapping between the addresses and balances (array of addresses and balances).

event Transfer(address indexed from, address indexed to, uint256 value);

A public event that will inform the clients about the transfer (sender, receiver, and value sent)

event Approval(address indexed _owner, address indexed _spender, uint256 _value);

A public event that will inform the clients about the transfer (sender, receiver, and value sent).

event Burn(address indexed from, uint256 value);

The burn event will inform the clients about the amount that has been burnt.

constructor(uint256 initialSupply,
		string memory tokenName,
		string memory tokenSymbol
		) public {
	totalSupply = initialSupply * 10 ** uint256(decimals);
	balanceOf[msg.sender] = totalSupply;
	name = tokenName;
	symbol = tokenSymbol;
}


The above constructor determines the total supply according to the decimals. And transfers all of it to the balance of the owner of the contract. In end, the name and the symbol of the token are determined for display.

function _transfer(address _from, address _to, uint _value) internal {
	require(_to != address(0x0));
}

The receiver should not be addressed as 0x0 or the owner of the contract.

require(balanceOf[_from] >= _value);

The sender must have enough balance to send the desired value.

require(balanceOf[_to] + _value >= balanceOf[_to]);

After the transaction, the receiver’s balance must increase. In other words, the value must be greater or equal to zero.

uint previousBalances = balanceOf[_from] + balanceOf[_to];

Before the transfer, the balance of the sender and receiver is calculated for the later tests.

balanceOf[_from] -= _value;

After the transfer, the balance of the sender is subtracted by the value.

balanceOf[_to] += _value;

After the transfer, the balance of the receiver is added to the value of the transfer.

emit Transfer(_from, _to, _value);

The event is emitted to notify the clients about the transaction.

assert(balanceOf[_from] + balanceOf[_to] == previousBalances);

We test whether, after the transfer, the sum of the balances equals the previous sum of balances.The following function uses the data of the _transfer to verify the success of the transaction.

function transfer(address _to, uint256 _value) public returns (bool success) {
	_transfer(msg.sender, _to, _value);
	return true;
}


The following function will allow the sender to send just the value to the receiver.

function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
	require(_value <= allowance[_from][msg.sender]);
	allowance[_from][msg.sender] -= _value;
	_transfer(_from, _to, _value);
	return true;
}


The function below checks the output of the above function if it has returned true and will let the contract know.

function approveAndCall(address _spender, uint256 _value, bytes memory 					 
	_extraData) public returns (bool success) {
	tokenRecipient spender = tokenRecipient(_spender);
	if (approve(_spender, _value)) {
		spender.receiveApproval(msg.sender, _value, address(this), _extraData);							
		return true;
	}
}

The function below burns the amount of transfer value, or in other words, it will decrease the amount that has been transferred from the total supply.

function burn(uint256 _value) public returns (bool success) {
	require(balanceOf[msg.sender] >= _value);
	balanceOf[msg.sender] -= _value; // Subtract from the sender
	totalSupply -= _value;
	emit Burn(msg.sender, _value);
	return true;
}


The following function is the same as above with the difference that it will ask for the allowance of the sender for the burning.


function burnFrom(address _from, uint256 _value) public returns (bool success) {
	require(balanceOf[_from] >= _value);
	require(_value <= allowance[_from][msg.sender]);
	balanceOf[_from] -= _value
	allowance[_from][msg.sender] -= _value; 						
	totalSupply -= _value;
	emit Burn(_from, _value);
	return true;	
}


Final Word

In this article, we have studied an ERC-20 smart contract. We have analyzed the necessary functions, methods, and events that every ERC-20 token smart contract must have. Furthermore, we have taken a look at how a sample token contract has been written in solidity with the consideration of all the events, methods, and necessary functions. Notice, that you can write an ERC-20 smart contract in a very different way as long as you include the necessary method and event in it.

Download this Article in PDF format

metaverse

Care to Know About Metaverse?

In Arashtad, we are providing custom services on 3d developments such as 3d websites, 3d models, metaverses and all 3d applications.

Arashtad Serivces
Tell us about your ideas
Fill in the Form
Blockchain Development

How to Interact with the ERC-20 Smart Contract

In this tutorial we are going to run the ERC-20 smart contract deployment on the Rinkeby chain and see the actual token created in our Metamask wallet. After you create and deploy your ERC-20 smart contract, you will be able to see that this token is added on the Rinkeby Etherscan, and by adding the address and specifications of the token, you can add it to your wallet and also you will be able to do the same on Uniswap afterward to be able to swap your token with other tokens.

ERC-20 Smart Contract

In our last related article on how to create an ERC-20 token, we learned how to create a token with the ERC-20 standard. Moreover, we showed how to run it via Ganache-CLI. In this tutorial, we are going to run the very same deployment on the Rinkeby network, and see the actual token created in our Metamask wallet. After you create and deploy your ERC-20 smart contract, you will be able to see that this token is added to the Rinkeby Etherscan. Then, by adding the address and specifications of the token, you can add it to your wallet. Also, you will be able to do the same on Uniswap afterward to be able to swap your token with other tokens (notice that swapping your token is only possible on Mainnet but not on the Rinkeby test network).

Deploying on Rinkeby Testnet:

To begin with the deployment of our ERC-20 token, type the following command in the terminal:

brownie run scripts/1_deploy_token.py --network rinkeby

Result:

Brownie v1.18.1 - Python development framework for Ethereum Compiling contracts... Solc version: 0.6.12 Optimizer: Enabled Runs: 200 EVM Version: Istanbul Generating build data... - TokenERC20 - tokenRecipient Compiling contracts... Solc version: 0.8.13 Optimizer: Enabled Runs: 200 EVM Version: Istanbul Generating build data... - OpenZeppelin/[email protected]/ERC20 - OpenZeppelin/[email protected]/IERC20 - OpenZeppelin/[email protected]/IERC20Metadata - OpenZeppelin/[email protected]/Context - OurToken MytokenProject is the active project. Running 'scripts/1_deploy_token.py::main'... Transaction sent: 0xa85a8d1595d290657f726f1533d105c2d2b6604e051409dc0c2e4d9a74bf547e Gas price: 1.000000019 gwei Gas limit: 745852 Nonce: 62 TokenERC20.constructor confirmed Block: 10468341 Gas used: 678048 (90.91%) TokenERC20 deployed at: 0xDD7f08A04c3d66beD75aFFA5f0e70e46de4567eb

Finding the token on Rinkeby Etherscan:

By copying and pasting the “0xDD7f08A04c3d66beD75aFFA5f0e70e46de4567eb” into the Rinkeby Etherscan, you will be able to see that we have indeed created a token called Token:

Adding the token to the Metamask:

Now, let’s head over to our Metamask, and in the Rinkeby network, import our new token by entering the address of the contract deployment:

ERC-20 smart contract

Adding the token to the Metamask:

Now, let’s head over to our Metamask, and in the Rinkeby network, import our new token by entering the address of the contract deployment:

ERC-20 smart contract ERC-20 smart contract

And you will see that our initial supply which was 1000 has been multiplied by 10 to power our decimals (which was 18). As a result, you can see 21 zeros after one as the total supply (All of which are in our account).

Transferring the tokens:

Now, we can send these tokens to other accounts. For example, here we transfer our TKN token to account 2.

ERC-20 smart contract

Importing the token in Uniswap:

We can also go to Uniswap and see if we can add our token to it.

ERC

let’s first connect to our Metamask wallet:

ERC

Then, press the “Select A Token” button. And in order to add your token in Uniswap, you should first enter your address in the box and you should be able to find the TKN token. Press import:

ERC

And we have our token in Uniswap!

ERC

Last Thought on ERC-20 Smart Contract

In this article, we have managed to run the deployment of the ERC-20 smart contract on the Rinkeby chain test network. Then, we copied the address of the deployed contract in the Rinkeby Etherscan and found our created token there. Afterward, we entered the specifications of the token in the add token section of the Metamask wallet and added the created token to it. Finally, we imported our token into the Uniswap Rinkeby Testnet.

Download this Article in PDF format

3d websites

Care to Know Us More?

In Arashtad, we have gathered a professional team of developers who are working in fields such as 3D websites, 3D games, metaverses, and other types of WebGL and 3D applications.

Arashtad Serivces
Drop us a message and tell us about your ideas.
Request a Quote
ThreeJS Development