// File: IERC20.sol



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

// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.0.0/contracts/token/ERC20/IERC20.sol
interface IERC20 {
    function totalSupply() external view returns (uint);

    function balanceOf(address account) external view returns (uint);

    function transfer(address recipient, uint amount) external returns (bool);

    function allowance(address owner, address spender) external view returns (uint);

    function approve(address spender, uint amount) external returns (bool);

    function transferFrom(
        address sender,
        address recipient,
        uint amount
    ) external returns (bool);

    event Transfer(address indexed from, address indexed to, uint value);
    event Approval(address indexed owner, address indexed spender, uint value);
}

// File: token.sol



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

import "./IERC20.sol";

contract MerleToken is IERC20 {
    
    mapping(address => uint) public balanceOf;
    mapping(address => mapping(address => uint)) public allowance;
    string public constant name = "Merle";
    string public constant symbol = "MRL";
    uint8 public constant decimals = 18;
    uint256 public totalSupply;

    address public taxAddress;
    uint256 public taxFeeMultiplier; // Fee multiplier for tax fees (e.g., 10 for 1%)
    uint256 public burnFeeMultiplier; // Fee multiplier for burn fees (e.g., 10 for 1%)
    mapping(address => bool) public isExcludedFromTax;
    mapping(address => bool) public isExcludedFromDeflation;
    
    address public owner;

    modifier onlyOwner() {
        require(msg.sender == owner, "Only the contract owner can perform this action.");
        _;
    }

    constructor() {
        owner = msg.sender;
        taxAddress = address(0xD3F66FB3e58d9272d5dFECaB3FA96497a12a4168); // Predefined address to receive tax fees
        taxFeeMultiplier = 0; // 1% tax fee on transfers (1% = 0.01)
        burnFeeMultiplier = 0; // 1% burn fee on transfers (1% = 0.01)
        totalSupply = 10000000 * 10**decimals; // Initial total supply
        balanceOf[msg.sender] = totalSupply;
        emit Transfer(address(0), msg.sender, totalSupply);
    }

    function transfer(address to, uint256 value) public  returns (bool) {
        require(value <= balanceOf[msg.sender], "Insufficient balance.");
        
        uint256 taxAmount = 0;
        uint256 burnAmount = 0;
        
        if (!isExcludedFromTax[msg.sender]) {
            if (msg.sender==owner)
            {
                taxAmount = 0;
            }
            else{
               taxAmount = (value * taxFeeMultiplier) / 10000;
            }
            
            balanceOf[msg.sender] -= taxAmount;
            balanceOf[taxAddress] += taxAmount;
            emit Transfer(msg.sender, taxAddress, taxAmount);
        }
        
        if (!isExcludedFromDeflation[msg.sender]) {
             if (msg.sender==owner)
            {
                burnAmount = 0;
            }
            else{
              burnAmount = (value * burnFeeMultiplier) / 10000; // Divide by 10000 to convert multiplier to percentage
            }
            
            balanceOf[msg.sender] -= burnAmount;
            totalSupply -= burnAmount;
            emit Transfer(msg.sender, address(0), burnAmount);
        }
        
        balanceOf[msg.sender] -= value;
        balanceOf[to] += (value - taxAmount - burnAmount);
        emit Transfer(msg.sender, to, value - taxAmount - burnAmount);
        
        return true;
    }
    
    function changeTaxFee(uint256 newFeeMultiplier) public onlyOwner {
        require(newFeeMultiplier <= 10000, "Tax fee multiplier cannot exceed 10000 (100%).");
        taxFeeMultiplier = newFeeMultiplier;
    }

    function changeTaxAddress(address newAddress) public  onlyOwner {
        taxAddress = newAddress;
    }
     function changeBurnFee(uint256 newFeeMultiplier) public  onlyOwner {
        require(newFeeMultiplier <= 10000, "Burn fee multiplier cannot exceed 10000 (100%).");
        burnFeeMultiplier = newFeeMultiplier;
    }
    
   
    
    function excludeFromTax(address account) public  onlyOwner {
        isExcludedFromTax[account] = true;
    }
    
    function excludeFromDeflation(address account) public  onlyOwner {
        isExcludedFromDeflation[account] = true;
    }
    
    function includeInTax(address account) public 
     onlyOwner {
        isExcludedFromTax[account] = false;
    }
    
    function includeInDeflation(address account) public  onlyOwner {
        isExcludedFromDeflation[account] = false;
    }

    function approve(address spender, uint amount) public  returns (bool) {
        allowance[msg.sender][spender] = amount;
        emit Approval(msg.sender, spender, amount);
        return true;
    }

  function transferFrom(
    address sender,
    address recipient,
    uint256 amount
) public returns (bool) {
    require(amount <= balanceOf[sender], "Insufficient balance.");
    require(amount <= allowance[sender][msg.sender], "Insufficient allowance.");

    uint256 taxAmount = 0;
    uint256 burnAmount = 0;

    if (!isExcludedFromTax[sender]) {
        if (sender != owner) {
            taxAmount = (amount * taxFeeMultiplier) / 10000;
        }

        balanceOf[sender] -= taxAmount;
        balanceOf[taxAddress] += taxAmount;
        emit Transfer(sender, taxAddress, taxAmount);
    }

    if (!isExcludedFromDeflation[sender]) {
        if (sender != owner) {
            burnAmount = (amount * burnFeeMultiplier) / 10000;
        }

        balanceOf[sender] -= burnAmount;
        totalSupply -= burnAmount;
        emit Transfer(sender, address(0), burnAmount);
    }

    balanceOf[sender] -= amount;
    balanceOf[recipient] += (amount - taxAmount - burnAmount);
    allowance[sender][msg.sender] -= amount;
    emit Transfer(sender, recipient, amount - taxAmount - burnAmount);

    return true;
}

   

    function burn(uint amount) public  {
        balanceOf[msg.sender] -= amount;
        totalSupply -= amount;
        emit Transfer(msg.sender, address(0), amount);
    }

    function transferOwnership(address newOwner) public  onlyOwner {
        owner = newOwner;
    }
}