Help for my ERC20 token

Hi guys, I create this token, honestly i couldn’t tested properly locally because of the router i’m setting as i couldn’t create a mock router locally using Foundry. However, i was able to deploy the contract on BSC Testnet and verify the contract.

Here is my challenge after deploying this contract… Using pancakeswap

  1. I can add liquidity successfully.
  2. I can buy/sell when the wallet is add to excluded wallets
  3. I can buy/sell if i toggle tax fee off

But

  1. I can’t buy/sell if i toggle tax on
  2. I can’t buy/sell if the wallet is not included in isExcludedFromFee mapping
    Debug:
    When i check the event logs on bsc scan, i noticed that the _update() is not called at all and no event was logged. So when fee is enabled and i’m transacting from a wallet not added to isExcludedFromFee, my metamask did not pop out for me to confirm transaction and then the transaction timed out with error “Unknown error: “Failed to fetch”. Try increasing your slippage tolerance.”
    image

:1234: Code to reproduce

/*
* Tokenomics
*
*  Name  - CocoToken
*  Symbol - COCO
*  MAX Supply -  2.1 Million
*  Tax 5%  - only applicable for the first 1 year from the time liquidity is provided (0% thereafter)
*  5% tax distribution
    - 1% to liquidity pool
    - 1% to marketing wallet (sent as BNB)
    - 1% to ‘buyback’ wallet (sent as BNB)
    - 2% to RewardHolderNFT Contract (sent as COCO)
*   Other features
    - Anti-dump Max Sell no more than 0.5% of supply (105k) over 72 hours – only applicable for 6 months (0% thereafter)
*/

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

import {SafeMath} from "./library/SafeMath.sol";
import {ERC20Capped} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Capped.sol";
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import {IUniswapV2Factory} from "./interface/IUniswapV2Factory.sol";
import {IUniswapV2Router02} from "./interface/IUniswapV2Router02.sol";
// import {RewardHolderNFT} from "./RewardHolderNFT.sol";

contract CocoToken is ERC20Capped, Ownable, ReentrancyGuard {
    using SafeMath for uint256;

    // Errors
    error CocoToken__InvalidAddress();
    error CocoToken__TransferFromZeroAddress();
    error CocoToken__AddressCannotBeZeroAddress();
    error CocoToken__AmountMustBeGreaterThanZero();
    error CocoToken__AntiDumpLimitExceeded();

    // State variables
    address private uniswapV2Pair;
    IUniswapV2Router02 private uniswapV2Router;

    // State constants and immutables
    uint256 private constant MAX_SUPPLY = 2100000 * 10 ** 4;
    uint256 private constant ANTI_DUMP_DURATION = 72 hours;
    uint256 private constant ANTI_DUMP_PERIOD = 6 * 30 days;
    uint256 private constant TAX_PERIOD = 365 days;
    uint256 private constant MAX_SELL_PERCENT = 5; // 0.5% (5/1000)
    address payable public immutable nftRewardContract;

    uint256 public taxFee = 500; // 5%
    uint256 public deployTime;
    address payable public marketingWallet;
    address payable public buyBackWallet;

    // State mappings
    mapping(address => bool) private isExcludedFromFee;
    mapping(address => uint256) private soldAmounts;
    mapping(address => uint256) private sellTimestamps;

    // Events
    event DebugEvent(string message);
    event DebugEvent2(string message, bytes data);
    event AccountExcludedFromFee(address account);
    event AccountIncludedInFee(address account);
    event MarketingWalletUpdated(address newMarketingWallet);
    event BuybackWalletUpdated(address newBuybackWallet);
    event FeeStateUpdated(bool enabled);
    event SwapAttempted(uint256 tokenAmount, uint256 minETHExpected, uint256 ethReceived);
    event LiquidityAdded(uint256 tokenAmount, uint256 ethAmount, bool success);
    event AntiDumpChecked(address indexed seller, uint256 sellAmount, bool allowed);
    event FeesDistributed(uint256 marketingETH, uint256 buybackETH, uint256 liquidityETH, uint256 nftTokens);
    event TaxCalculated(
        address indexed sender,
        address indexed recipient,
        uint256 amount,
        uint256 taxAmount,
        bool isSell,
        bool isExcluded
    );

    /**
     * @notice Constructor that initializes the token, mints the max supply, and assigns wallets.
     * @param _marketingWallet The wallet address to receive the marketing fee.
     * @param _buyBackWallet This wallet address to receive buy back and burn CORE.
     */
    constructor(address _marketingWallet, address _buyBackWallet)
        ERC20("CocoToken", "COCO")
        ERC20Capped(MAX_SUPPLY)
        Ownable(msg.sender)
    {
        if (_marketingWallet == address(0) || _buyBackWallet == address(0)) {
            revert CocoToken__InvalidAddress();
        }

        deployTime = block.timestamp;

        marketingWallet = payable(_marketingWallet);
        buyBackWallet = payable(_buyBackWallet);

        // Deploy reward nft contract
        // RewardHolderNFT claimContract = new RewardHolderNFT(address(this));
        // nftRewardContract = payable(claimContract);

        IUniswapV2Router02 _router = IUniswapV2Router02(0xD99D1c33F9fC3444f8101754aBC46c52416550D1);
        uniswapV2Pair = IUniswapV2Factory(_router.factory()).createPair(address(this), _router.WETH());
        uniswapV2Router = _router;

        isExcludedFromFee[msg.sender] = true;
        isExcludedFromFee[address(this)] = true;
        isExcludedFromFee[buyBackWallet] = true;
        isExcludedFromFee[marketingWallet] = true;
        isExcludedFromFee[nftRewardContract] = true;

        // Mint max supply
        _mint(msg.sender, MAX_SUPPLY);
    }

    receive() external payable {}

    /**
     * @param sender The sender's address.
     * @param recipient The recipient's address.
     * @param amount The amount of tokens to transfer.
     * @dev Internal function to handle token transfers.
     * @notice Only buy and sell transactions are subject to fees.
     */
    function _update(address sender, address recipient, uint256 amount) internal override {
        if (amount <= 0) {
            revert CocoToken__AmountMustBeGreaterThanZero();
        }

        uint256 tax = _calculateTax(sender, recipient, amount);
        uint256 transferAmount = amount.sub(tax);

        if (tax > 0) {
            super._update(sender, address(this), tax);

            _distributeFees(tax);
        }

        if (transferAmount > 0) {
            super._update(sender, recipient, transferAmount);
        }
    }

    function _calculateTax(address sender, address recipient, uint256 amount) private returns (uint256) {
        uint256 taxAmount;
        bool isSell = recipient == uniswapV2Pair;
        bool excluded = isExcludedFromFee[sender] || isExcludedFromFee[recipient];

        if (excluded) {
            taxAmount = 0;
            emit TaxCalculated(sender, recipient, amount, taxAmount, isSell, excluded);
            return taxAmount;
        }

        if (block.timestamp <= deployTime + TAX_PERIOD) {
            taxAmount = amount.mul(taxFee).div(10000);
            emit TaxCalculated(sender, recipient, amount, taxAmount, isSell, excluded);
            return taxAmount;
        }

        if (isSell && block.timestamp <= deployTime + ANTI_DUMP_PERIOD) {
            if (!_checkAntiDump(sender, amount)) {
                revert CocoToken__AntiDumpLimitExceeded();
            }
        }

        taxAmount = 0;
        emit TaxCalculated(sender, recipient, amount, taxAmount, isSell, excluded);
        return taxAmount;
    }

    function _checkAntiDump(address seller, uint256 amount) private returns (bool) {
        // Reset if last sell was beyond the anti-dump duration
        if (block.timestamp > sellTimestamps[seller] + ANTI_DUMP_DURATION) {
            soldAmounts[seller] = 0;
            sellTimestamps[seller] = block.timestamp;
        }

        uint256 maxSell = totalSupply().mul(MAX_SELL_PERCENT).div(1000);
        uint256 newSoldAmount = soldAmounts[seller] + amount;

        if (newSoldAmount > maxSell) {
            emit AntiDumpChecked(seller, amount, false);
            return false; // Not allowed
        }

        // Update tracking
        soldAmounts[seller] = newSoldAmount;
        sellTimestamps[seller] = block.timestamp;

        emit AntiDumpChecked(seller, amount, true);
        return true; // Allowed
    }

    function _distributeFees(uint256 taxAmount) private {
        uint256 liquidity = taxAmount.mul(1).div(5); // 1%
        uint256 marketing = taxAmount.mul(1).div(5); // 1%
        uint256 buyback = taxAmount.mul(1).div(5); // 1%
        uint256 nftTokens = taxAmount.mul(2).div(5); // 2%

        // Send tokens to NFT contract
        super._update(address(this), nftRewardContract, nftTokens);

        // Process CORE conversions
        uint256 totalCOREConversion = marketing.add(buyback).add(liquidity.div(2));
        uint256 initialBalance = address(this).balance;

        _swapTokensForEth(totalCOREConversion);

        uint256 newBalance = address(this).balance.sub(initialBalance);

        // Calculate proportional CORE amounts
        uint256 marketingCORE = newBalance.mul(marketing).div(totalCOREConversion);
        uint256 buybackCORE = newBalance.mul(buyback).div(totalCOREConversion);
        uint256 liquidityCORE = newBalance.mul(liquidity.div(2)).div(totalCOREConversion);

        // Send CORE to destinations

        payable(marketingWallet).transfer(marketingCORE);
        payable(buyBackWallet).transfer(buybackCORE);

        // Add liquidity with remaining tokens and CORE
        if (liquidityCORE > 0) {
            _addLiquidity(liquidity.div(2), liquidityCORE);
        }

        emit FeesDistributed(marketingCORE, buybackCORE, liquidityCORE, nftTokens);
    }

    function _addLiquidity(uint256 tokenAmount, uint256 COREAmount) private {
        _approve(address(this), address(uniswapV2Router), tokenAmount);

        try uniswapV2Router.addLiquidityETH{value: COREAmount}(
            address(this), tokenAmount, 0, 0, owner(), block.timestamp
        ) {
            emit LiquidityAdded(tokenAmount, COREAmount, true);
        } catch {
            emit LiquidityAdded(tokenAmount, COREAmount, false);
        }
    }

    function _swapTokensForEth(uint256 tokenAmount) private {
        address[] memory path = new address[](2);
        path[0] = address(this);
        path[1] = uniswapV2Router.WETH();

        _approve(address(this), address(uniswapV2Router), tokenAmount);

        // Adjust for tax fee to calculate expected received tokens
        uint256 adjustedAmount = tokenAmount.mul(10000 - taxFee).div(10000);
        uint256 minETH = uniswapV2Router.getAmountsOut(adjustedAmount, path)[1].mul(99).div(100);

        uint256 ethBefore = address(this).balance;
        uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(
            tokenAmount, minETH, path, address(this), block.timestamp
        );

        uint256 ethReceived = address(this).balance - ethBefore;

        emit SwapAttempted(tokenAmount, minETH, ethReceived);
    }

    function contractBalanceSwap() external onlyOwner {
        uint256 contractBalance = balanceOf(address(this));
        _swapTokensForEth(contractBalance);
    }

    // Administrative Functions
    function excludeFromFee(address account) external onlyOwner {
        isExcludedFromFee[account] = true;
        emit AccountExcludedFromFee(account);
    }

    function includeInFee(address account) external onlyOwner {
        isExcludedFromFee[account] = false;
        emit AccountIncludedInFee(account);
    }

    function setBuybackWallet(address _buybackWalletAddr) external onlyOwner {
        if (_buybackWalletAddr == address(0)) revert CocoToken__AddressCannotBeZeroAddress();
        buyBackWallet = payable(_buybackWalletAddr);
        emit BuybackWalletUpdated(_buybackWalletAddr);
    }

    function setMarketingWallet(address _marketingWalletAddr) external onlyOwner {
        if (_marketingWalletAddr == address(0)) revert CocoToken__AddressCannotBeZeroAddress();
        marketingWallet = payable(_marketingWalletAddr);
        emit MarketingWalletUpdated(_marketingWalletAddr);
    }

    function setFeeState(bool enabled) external onlyOwner {
        taxFee = enabled ? 500 : 0;
        emit FeeStateUpdated(enabled);
    }

    function decimals() public view virtual override returns (uint8) {
        return 4;
    }

    function verifyPairCreation() external view returns (bool exists, address pairAddress) {
        address token0 = address(this);
        address token1 = uniswapV2Router.WETH();

        address computedPair = IUniswapV2Factory(uniswapV2Router.factory()).getPair(token0, token1);
        return (computedPair != address(0), computedPair);
    }
}

:computer: Environment

Contract complied and deployed successfully on Remix

Are you a bot?
I’m sorry if you are not, just trying to understand who is replying me.

Thanks a lot. Really appreciate you taking time to reply but i don’t know why i need to go to live support to resolve an issue when i post on platform here.

The website https://decentralizedhelp.com/ even looks somehow and has nothing to do with Coredao. The website is not even secure and the first thing i’m being asked to do is to connect wallet. How?

Ok, thanks but since my issue is with my smart contract, i don’t see the point in connect wallet. I was hoping someone can take a look for me

Lol. you must think you are speaking to novice lol. You have to narrow what to wallet. watin concern my wallet with the contract. if you want to debug, they can do that with their own wallet. Have a nice day