0

I've tried almost every tutorial and help available online trying to accept BUSD or any ERC20 token in my solidity smart contract. I'm deploying the contract on Binance Testnet and I have 20 BUSD in testnet. When I call GetUserTokenBalance() it shows me my BUSD balance. but when I call Approvetokens(), even after a successful transaction the GetAllowance() shows 0. Hence, when I call the AcceptPayment() I get the below error. This forum is my last HOPE.

Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending? Internal JSON-RPC error. { "code": 3, "message": "execution reverted: insufficient funds", "data": "0x08c379a000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000012696e73756666696369656e742066756e64730000000000000000000000000000" }

// 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(0xeD24FC36d5Ee211Ea25A80239Fb8C4Cfd80f12Ee);
        // this token address is BUSD deployed on Binance 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));
   }
   
}

1 Answer 1

1

You're wrong in ApproveToken() function. In fact, a smart contract to deposit inside itself the user's token must to have permission from user access to his wallet. For to do this operation, a user have to interact with token contract and not with your contract. Try this: go into testnet.bscscan and seach token address that you want to deposit into smart contract. Then, go into Contract section and click on Write Contract. Connect your wallet clicking on Connect to web3 and then go into approve() function and set:

  • _spender: your smart contract address,
  • _amount: token quantity that smart contract can deposit from your wallet. At this point, go into your smart contract and call acceptPayment function (with amount you set into approve() function) and it'll work.

I changed and put some notes in your original smart contract:

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

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

contract ECommerce {
    IERC20 token;
    address private owner;

    constructor() {
        token = IERC20(0xeD24FC36d5Ee211Ea25A80239Fb8C4Cfd80f12Ee);
        // this token address is BUSD deployed on Binance 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);// balanceOf function is already declared in ERC20 token function
   }
   
   function GetAllowance() public view returns(uint256){
       return token.allowance(msg.sender, address(this));
   }
   
   function AcceptPayment(uint256 _tokenamount) public returns(bool) {
       // _tokenAmount cannot exceed allowance. In this case I put equals symbol to prevent require error
       require(_tokenamount >= GetAllowance(), "Please approve tokens before transferring");
       // Use transferFrom() function if you want to transfer from user to smart contract a specific amount of tokens.
       token.transferFrom(msg.sender, address(this), _tokenamount);
       return true;
   }
   
   function GetContractTokenBalance() public OnlyOwner view returns(uint256){
       return token.balanceOf(address(this));
   }
   
}
1
  • Works fine when using contract on bsc testnet scan, but why cant set allowance from my contract?
    – Wraith
    Jun 12 at 15:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.