Published on 22 Aug 2021
Accept an ERC20 token as payment in Smart Contract
How to allow user to pay in erc20 tokens along with native ethereum token in smart contract

Introduction

More often some DApp require to accept payments in the form of an ERC20 tokens. In this smartbook we will discuss how to accept erc20 token as payment in smart contract.

 

Deploy ERC20 token

If you haven't deployed erc20 token yet, then deploy it on any testnet. Use openzeppelin library to deploy tokens. If you have deployed tokens already and you have your token address then skip this step.

ERC20 token smart contract

// contracts/GLDToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract MyToken is ERC20 {

    constructor(uint256 initialSupply) ERC20("ERC20basic", "ABC") {
        _mint(msg.sender, initialSupply);
    }

   function decimals() public view virtual override returns (uint8) {
     return 18;  // eg. return 12;
   }
}

Deploy this smart contract and copy the contract address. the contract address itself will the token address.

 

Develope ECommerce contract

Step 1

define license and solidity version and import IERC20 solidity file from openzeppelin.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

Step 2

Define contract name and variables.

contract ECommerce {
    IERC20 token;
    address private owner;

Step 3

Adding construcor

constructor() public {
        token = IERC20(0x62D62D73C27E6240165ee3A97C6d1532c0dD0b42);
        // this token address is LINK token deployed on Rinkeby testnet
       // You can use any other ERC20 token smart contarct address here
        owner = msg.sender;
    }

Pass the token contract address , you have deployed earlier in IERC20 , we will store this instance in token. also define owner as contract deployer , i.e. msg.sender

Step 4

 modifier OnlyOwner() {
        require(msg.sender == owner);
        _;
    }

Adding modifier in case you want some functions to be executed by contract owner only. you can skip this steps.

Step 5

Defining function to get user balance

 function GetUserTokenBalance() public view returns(uint256){ 
       return token.balanceOf(msg.sender);// balancdOf function is already declared in ERC20 token function
   }

Step 6

Approve the user to transfer tokens from his wallet to this contract

 function Approvetokens(uint256 _tokenamount) public returns(bool){
       token.approve(address(this), _tokenamount);
       return true;
   }

Step 7

Get the user allowance , to check whether the allowed amount is equal to the tokens that are to bt transferred.

 function GetAllowance() public view returns(uint256){
       return token.allowance(msg.sender, address(this));
   }

Step 8

Accept ERC20 tokens from user wallet to this contract

 function AcceptPayment(uint256 _tokenamount) public returns(bool) {
       require(_tokenamount > GetAllowance(), "Please approve tokens before transferring");
       token.transfer(address(this), _tokenamount);
       return true;
   }

You can customize this function according to your dapp functionality

Step 9

Get the ERC20 token balance of this smart contract

 function GetContractTokenBalance() public OnlyOwner view returns(uint256){
       return token.balanceOf(address(this));
   }

 

Complete Code

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

contract ECommerce {
    IERC20 token;
    address private owner;

    constructor() public {
        token = IERC20(0x62D62D73C27E6240165ee3A97C6d1532c0dD0b42);
        // this token address is LINK token deployed on Rinkeby testnet
       // You can use any other ERC20 token smart contarct address here
        owner = msg.sender;
    }
    
    
    modifier OnlyOwner() {
        require(msg.sender == owner);
        _;
    }

  
   function GetUserTokenBalance() public view returns(uint256){ 
       return token.balanceOf(msg.sender);// balancdOf function is already declared in ERC20 token function
   }
   
   
   function Approvetokens(uint256 _tokenamount) public returns(bool){
       token.approve(address(this), _tokenamount);
       return true;
   }
   
   
   function GetAllowance() public view returns(uint256){
       return token.allowance(msg.sender, address(this));
   }
   
   function AcceptPayment(uint256 _tokenamount) public returns(bool) {
       require(_tokenamount > GetAllowance(), "Please approve tokens before transferring");
       token.transfer(address(this), _tokenamount);
       return true;
   }
   
   
   function GetContractTokenBalance() public OnlyOwner view returns(uint256){
       return token.balanceOf(address(this));
   }
   
}

------------------------------------------------------------------------------------------------------------------------------------------------------------

2302
1
1