Error in contract withdrawal function:“ALERT: Transaction Error. Exception thrown in contract code.”

I wrote a BSC contract, which realized the function of adding token and depositing and withdrawing money. But when I tried to withdraw money after the deployment of the test network, I found that it could not be done. It showed “Alert: transaction error. Exception throw in contract code”. Can you tell me how to modify it?
This is the contract address I deployed in BSC test network:https://testnet.bscscan.com/address/0xE1eEd11c9172f09E5dbD7AFc07D37F494349EB78

// SPDX-License-Identifier: MIT

pragma solidity ^0.6.12;

interface IERC20{
function balanceOf(address _owner) view external returns (uint256 balance);
function transfer(address _to, uint256 _value) external returns (bool success);
function transferFrom(address _from, address _to, uint256 _value) external returns (bool success);
function approve(address _spender, uint256 _value) external returns (bool success);
function allowance(address _owner, address _spender) view external returns (uint256 remaining);
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}

contract myContract{

IERC20 public token;
address public owner;

struct Token{
    bool isExist;
    string name;
    uint8 decimals;
    mapping(address => uint256) balances;
}

mapping(address => Token) public tokenInfo;
mapping(string => address) public nameToadr;

modifier onlyOwner(){
    require(msg.sender == owner,"not an owner.");
    _;
}

constructor(
    address _owner

) public {
    owner = _owner;
}

function addToken(address _tokenadr, string memory _name, uint8 _decimals) public onlyOwner {
    
    tokenInfo[_tokenadr].isExist = true;
    tokenInfo[_tokenadr].name = _name;
    tokenInfo[_tokenadr].decimals = _decimals;
    
    nameToadr[_name] = _tokenadr;
}

function deposit(address _tokenadr, uint256 _amount) public {
    require(tokenInfo[_tokenadr].isExist,"token not exist.");
    token = IERC20(_tokenadr);
    
    token.transferFrom(msg.sender, address(this), _amount);
    tokenInfo[_tokenadr].balances[msg.sender] += _amount;
    
}

function withdraw(address _tokenadr, uint256 _amount) public {
    require(tokenInfo[_tokenadr].isExist,"token not exist.");
    require(tokenInfo[_tokenadr].balances[msg.sender] >= _amount,"incorrect amount");
    token = IERC20(_tokenadr);
    
    token.transferFrom(msg.sender, address(this), _amount);
    tokenInfo[_tokenadr].balances[msg.sender] -= _amount;
}

function isTokenExist(address _tokenadr) public view returns(bool){
    return tokenInfo[_tokenadr].isExist;
}

function getTokenInfo(address _tokenadr) public view returns(bool, string memory, uint8){
    return (tokenInfo[_tokenadr].isExist, tokenInfo[_tokenadr].name, tokenInfo[_tokenadr].decimals);
}

}

Please tell me how to modify it. I’ve tried many ways, but I still can’t

It's because of this line.
tokenInfo[_tokenadr].balances[msg.sender]
This gets the balance of the withdrawer. Meaning when you go to withdraw the Token, it's checking the withdrawer's balance, not the contract address's balance.

msg.sender - is the address of the withdrawer. (the address of the person calling the function).

Instead you should check the balance of the contract itself using
address(this)

Below are my two functions that I use to withdraw funds from my contract. Developers have their own preferences when it comes to these things, and there are many implementations you can use. I choose to withdraw by BNB, or by a specific token address.

// withdraw from contract functions

    function withdrawBNBSentToContractAddress() external onlyOwner()  {

        _msgSender().transfer(address(this).balance);

    }

    using SafeBEP20 for IBEP20; 

    function withdrawBEP20SentToContractAddress(IBEP20 tokenToWithdraw) external onlyOwner()  {

        tokenToWithdraw.safeTransfer(_msgSender(), tokenToWithdraw.balanceOf(address(this)));

    }

You should use SafeERC20, I've just renamed it to BEP20.

3 Likes

Thank you. I used your method. It worked

2 Likes