Problem with transfer function.. exceed allowance? it must not be checked!

Hi!

I've been struggling with transfer function, where approval is not needed on ERC20 tokens where the caller is msg.sender as it's a public function, but I'm always getting same error.. Indeed I am on truffle debugger seeing that is also checking allowance, and that's the runtime error I get

image of the error

Could you please help me to identify the problem? it must be easy.. but i've been hours without results. Thanks in advance!

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

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";


/// @custom:security-contact ealcober85@gmail.com
contract Ancestry is ERC20, ERC20Burnable, Pausable, Ownable {

    using SafeMath for *;

    mapping(address => uint256) private _balances;

    address payable[] teamMembers = [
    payable(0xE76dfad0a129CD7B72E3E6aD172F98865998c1aB), // same as deployer
    payable(0x58d299cf28e508704646A95d78AEA4EFddd6B7c8),
    payable(0xFe76F9F0aF1F8250CB30767461921e81871d9037),
    payable(0xEaEEB732b67169F3Bc24DAA6271e95fc104e0FC0),
    payable(0x631bB0244071aC67663241657c8312eCDb23A665),
    payable(0xE8DD32180803095A57b4Ff1B475753ea5D1c3b8d),
    payable(0x3C9E6083E2Db441843c9d6678f1E54cC9bb5B719),
    payable(0xdDfACfD8B9dA4c15f61beB43B41Db12c33c6898F)
    ];

    address payable rewardsWallet = payable(0x9f5094675526898e4260a411241d374232021183);

    // Team distribution
    uint256 teamTokensTotal        = 3900000 * 10 ** decimals();
    uint256 tokensPerMember        = teamTokensTotal.div(8);
    uint256 privateSaleTokens      = 2600000  * 10 ** decimals();
    uint256 otherTokens            = 16900000 * 10 ** decimals();



    constructor() ERC20("Ancestry", "ANC") {
        _mint(msg.sender   , privateSaleTokens); // Private Sale Tokens
        _mint(rewardsWallet, otherTokens); // Marketing + Rewards + Airdrop + Reward Bag Tokens
        for (uint i = 0 ; i < teamMembers.length ; i++)
            _mint(teamMembers[i], tokensPerMember); // Tokens per member in locked wallets by DXSale


    }

    function pause() public onlyOwner {
        _pause();
    }

    function unpause() public onlyOwner {
        _unpause();
    }

    function mint(address to, uint256 amount) public onlyOwner {
        _mint(to, amount);
    }

        /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `recipient` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address recipient, uint256 amount) public override returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

    function _beforeTokenTransfer(address from, address to, uint256 amount)
        internal
        whenNotPaused
        override
    {
        super._beforeTokenTransfer(from, to, amount);

    }

    // the token transfer function with the addition of a 5% share that
    // goes to the rewardsWallet address specified above
    function _transfer(
        address sender,
        address recipient,
        uint256 amount
    ) internal override {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        uint256 fee = amount.mul(5) / 100;
        uint256 senderBalance = _balances[sender];

        _beforeTokenTransfer(sender, recipient, amount);
        
        require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
        unchecked {
            _balances[sender] = senderBalance - amount;
        }
        _balances[recipient] += amount - fee;
        _balances[rewardsWallet] += fee;

        emit Transfer(sender, recipient, amount - fee);
        emit Transfer(sender, rewardsWallet, fee);

        _afterTokenTransfer(sender, recipient, amount);
    }
    
}

1 Like

your mapping _balance is not stored any value, change the public, so that it checks

since the mint function is being performed in the erc20 contract and therefore saves the data in the _balance variable of that contract

I recommend that instead of editing the Ancestry contract you modify the erc20 contract

At first thanks for your answer but literally there's "nothing" performed on ERC20 contract. BTW adding unimplemented functions and variables to my source code just made it work. I've seen that inheritance is a bit different in solidity...

If it is a little different, the inheritance, I recommend that if you plan to make any change to the standard functions of the erc20 contract, do it directly in the erc20 contract

Thats the only NOT recommended thing... why do you suggest that? modifying interfaces would drive to security issues.. for sure.... so please, explain

oppenzeppelin contracts are templates to speed up the development of contracts, you are free to modify them to your needs, as long as you have the necessary knowledge, at no time am I saying to modify the interface, I am recommended that you modify the actions they execute the functions in the erc20 contract directly