//SPDX-License-Identifier: MIT
pragma solidity ^0.8.5;
 
/**
* Standard SafeMath, stripped down to just add/sub/mul/div
*/
library SafeMath {
   function add(uint256 a, uint256 b) internal pure returns (uint256) {
       uint256 c = a + b;
       require(c >= a, "SafeMath: addition overflow");
 
       return c;
   }
   function sub(uint256 a, uint256 b) internal pure returns (uint256) {
       return sub(a, b, "SafeMath: subtraction overflow");
   }
   function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
       require(b <= a, errorMessage);
       uint256 c = a - b;
 
       return c;
   }
   function mul(uint256 a, uint256 b) internal pure returns (uint256) {
       if (a == 0) {
           return 0;
       }
 
       uint256 c = a * b;
       require(c / a == b, "SafeMath: multiplication overflow");
 
       return c;
   }
   function div(uint256 a, uint256 b) internal pure returns (uint256) {
       return div(a, b, "SafeMath: division by zero");
   }
   function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
       // Solidity only automatically asserts when dividing by 0
       require(b > 0, errorMessage);
       uint256 c = a / b;
       // assert(a == b * c + a % b); // There is no case in which this doesn't hold
 
       return c;
   }
}
 
/**
* BEP20 standard interface.
*/
interface IBEP20 {
   function totalSupply() external view returns (uint256);
   function decimals() external view returns (uint8);
   function symbol() external view returns (string memory);
   function name() external view returns (string memory);
   function getOwner() external view returns (address);
   function balanceOf(address account) external view returns (uint256);
   function transfer(address recipient, uint256 amount) external returns (bool);
   function allowance(address _owner, address spender) external view returns (uint256);
   function approve(address spender, uint256 amount) external returns (bool);
   function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
   event Transfer(address indexed from, address indexed to, uint256 value);
   event Approval(address indexed owner, address indexed spender, uint256 value);
}
 
/**
* Allows for contract ownership along with multi-address authorization
*/
abstract contract Auth {
   address internal owner;
   mapping (address => bool) internal authorizations;
 
   constructor(address _owner) {
       owner = _owner;
       authorizations[_owner] = true;
   }
 
   /**
    * Function modifier to require caller to be contract owner
    */
   modifier onlyOwner() {
       require(isOwner(msg.sender), "!OWNER"); _;
   }
 
   /**
    * Function modifier to require caller to be authorized
    */
   modifier authorized() {
       require(isAuthorized(msg.sender), "!AUTHORIZED"); _;
   }
 
   /**
    * Authorize address. Owner only
    */
   function authorize(address adr) public onlyOwner {
       authorizations[adr] = true;
   }
 
   /**
    * Remove address' authorization. Owner only
    */
   function unauthorize(address adr) public onlyOwner {
       authorizations[adr] = false;
   }
 
   /**
    * Check if address is owner
    */
   function isOwner(address account) public view returns (bool) {
       return account == owner;
   }
 
   /**
    * Return address' authorization status
    */
   function isAuthorized(address adr) public view returns (bool) {
       return authorizations[adr];
   }
 
   /**
    * Transfer ownership to new address. Caller must be owner. Leaves old owner authorized
    */
   function transferOwnership(address payable adr) public onlyOwner {
       owner = adr;
       authorizations[adr] = true;
       emit OwnershipTransferred(adr);
   }
 
   event OwnershipTransferred(address owner);
}
 
interface IDEXFactory {
   function createPair(address tokenA, address tokenB) external returns (address pair);
}
 
interface IDEXRouter {
   function factory() external pure returns (address);
   function WETH() external pure returns (address);
 
   function addLiquidity(
       address tokenA,
       address tokenB,
       uint amountADesired,
       uint amountBDesired,
       uint amountAMin,
       uint amountBMin,
       address to,
       uint deadline
   ) external returns (uint amountA, uint amountB, uint liquidity);
 
   function addLiquidityETH(
       address token,
       uint amountTokenDesired,
       uint amountTokenMin,
       uint amountETHMin,
       address to,
       uint deadline
   ) external payable returns (uint amountToken, uint amountETH, uint liquidity);
 
   function swapExactTokensForTokensSupportingFeeOnTransferTokens(
       uint amountIn,
       uint amountOutMin,
       address[] calldata path,
       address to,
       uint deadline
   ) external;
 
   function swapExactETHForTokensSupportingFeeOnTransferTokens(
       uint amountOutMin,
       address[] calldata path,
       address to,
       uint deadline
   ) external payable;
 
   function swapExactTokensForETHSupportingFeeOnTransferTokens(
       uint amountIn,
       uint amountOutMin,
       address[] calldata path,
       address to,
       uint deadline
   ) external;
}
 
interface IDividendDistributor {
   function setDistributionCriteria(uint256 _minPeriod, uint256 _minDistribution) external;
   function setShare(address shareholder, uint256 amount) external;
   function deposit() external payable;
   function process(uint256 gas) external;
}
 
contract DividendDistributor is IDividendDistributor {
   using SafeMath for uint256;
 
   address _token;
 
   struct Share {
       uint256 amount;
       uint256 totalExcluded;
       uint256 totalRealised;
   }
 
   IBEP20 USDC = IBEP20(0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8);
   address WETH = 0x82aF49447D8a07e3bd95BD0d56f35241523fBab1;
   IDEXRouter router;
 
   address[] shareholders;
   mapping (address => uint256) shareholderIndexes;
   mapping (address => uint256) shareholderClaims;
 
   mapping (address => Share) public shares;
 
   uint256 public totalShares;
   uint256 public totalDividends;
   uint256 public totalDistributed;
   uint256 public dividendsPerShare;
   uint256 public dividendsPerShareAccuracyFactor = 10 ** 36;
 
   uint256 public minPeriod = 1 hours;
   uint256 public minDistribution = 1 * (10 ** 8);
 
   uint256 currentIndex;
 
   bool initialized;
   modifier initialization() {
       require(!initialized);
       _;
       initialized = true;
   }
 
   modifier onlyToken() {
       require(msg.sender == _token); _;
   }
 
   constructor (address _router) {
       router = _router != address(0)
           ? IDEXRouter(_router)
           : IDEXRouter(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);
       _token = msg.sender;
   }
 
   function setDistributionCriteria(uint256 _minPeriod, uint256 _minDistribution) external override onlyToken {
       minPeriod = _minPeriod;
       minDistribution = _minDistribution;
   }
 
   function setShare(address shareholder, uint256 amount) external override onlyToken {
       if(shares[shareholder].amount > 0){
           distributeDividend(shareholder);
       }
 
       if(amount > 0 && shares[shareholder].amount == 0){
           addShareholder(shareholder);
       }else if(amount == 0 && shares[shareholder].amount > 0){
           removeShareholder(shareholder);
       }
 
       totalShares = totalShares.sub(shares[shareholder].amount).add(amount);
       shares[shareholder].amount = amount;
       shares[shareholder].totalExcluded = getCumulativeDividends(shares[shareholder].amount);
   }
 
   function deposit() external payable override onlyToken {
       uint256 balanceBefore = USDC.balanceOf(address(this));
 
       address[] memory path = new address[](2);
       path[0] = WETH;
       path[1] = address(USDC);
 
       router.
 
swapExactETHForTokensSupportingFeeOnTransferTokens{value: msg.value}(
           0,
           path,
           address(this),
           block.timestamp
       );
 
       uint256 amount = USDC.balanceOf(address(this)).sub(balanceBefore);
 
       totalDividends = totalDividends.add(amount);
       dividendsPerShare = dividendsPerShare.add(dividendsPerShareAccuracyFactor.mul(amount).div(totalShares));
   }
 
   function process(uint256 gas) external override onlyToken {
       uint256 shareholderCount = shareholders.length;
 
       if(shareholderCount == 0) { return; }
 
       uint256 gasUsed = 0;
       uint256 gasLeft = gasleft();
 
       uint256 iterations = 0;
 
       while(gasUsed < gas && iterations < shareholderCount) {
           if(currentIndex >= shareholderCount){
               currentIndex = 0;
           }
 
           if(shouldDistribute(shareholders[currentIndex])){
               distributeDividend(shareholders[currentIndex]);
           }
 
           gasUsed = gasUsed.add(gasLeft.sub(gasleft()));
           gasLeft = gasleft();
           currentIndex++;
           iterations++;
       }
   }
   
   function shouldDistribute(address shareholder) internal view returns (bool) {
       return shareholderClaims[shareholder] + minPeriod < block.timestamp
               && getUnpaidEarnings(shareholder) > minDistribution;
   }
 
   function distributeDividend(address shareholder) internal {
       if(shares[shareholder].amount == 0){ return; }
 
       uint256 amount = getUnpaidEarnings(shareholder);
       if(amount > 0){
           totalDistributed = totalDistributed.add(amount);
           USDC.transfer(shareholder, amount);
           shareholderClaims[shareholder] = block.timestamp;
           shares[shareholder].totalRealised = shares[shareholder].totalRealised.add(amount);
           shares[shareholder].totalExcluded = getCumulativeDividends(shares[shareholder].amount);
       }
   }
   
   function claimDividend(address shareholder) external onlyToken{
       distributeDividend(shareholder);
   }
 
   function getUnpaidEarnings(address shareholder) public view returns (uint256) {
       if(shares[shareholder].amount == 0){ return 0; }
 
       uint256 shareholderTotalDividends = getCumulativeDividends(shares[shareholder].amount);
       uint256 shareholderTotalExcluded = shares[shareholder].totalExcluded;
 
       if(shareholderTotalDividends <= shareholderTotalExcluded){ return 0; }
 
       return shareholderTotalDividends.sub(shareholderTotalExcluded);
   }
 
   function getCumulativeDividends(uint256 share) internal view returns (uint256) {
       return share.mul(dividendsPerShare).div(dividendsPerShareAccuracyFactor);
   }
 
   function addShareholder(address shareholder) internal {
       shareholderIndexes[shareholder] = shareholders.length;
       shareholders.push(shareholder);
   }
 
   function removeShareholder(address shareholder) internal {
       shareholders[shareholderIndexes[shareholder]] = shareholders[shareholders.length-1];
       shareholderIndexes[shareholders[shareholders.length-1]] = shareholderIndexes[shareholder];
       shareholders.pop();
   }
}
 
contract ArbZilla is IBEP20, Auth {
   using SafeMath for uint256;
 
   address USDC = 0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8;
   address WETH = 0x82aF49447D8a07e3bd95BD0d56f35241523fBab1;
   address DEAD = 0x000000000000000000000000000000000000dEaD; 
   address ZERO = 0x0000000000000000000000000000000000000000;
 
   string constant _name = "ArbZilla";
   string constant _symbol = "ZILLA";
   uint8 constant _decimals = 9;
 
   uint256 _totalSupply = 69000000000000000000000 * (10 ** _decimals);
   uint256 public _maxTxAmount = ( _totalSupply * 1 ) / 100 ;
   
   //max wallet holding  
    uint256 public _maxWalletToken = ( _totalSupply * 2 ) / 100;
 
   mapping (address => uint256) _balances;
   mapping (address => mapping (address => uint256)) _allowances;
 
   mapping (address => bool) isFeeExempt;
   mapping (address => bool) isTxLimitExempt;
   mapping (address => bool) isDividendExempt;
   mapping (address => bool) public isBlacklisted;

   // Buy Fees
    uint256 liquidityFeeBuy = 100; 
    uint256 buybackFeeBuy = 0; 
    uint256 reflectionFeeBuy = 0;
    uint256 marketingFeeBuy = 200;
    uint256 totalFeeBuy = 300;

    // Sell fees
    uint256 liquidityFeeSell = 500;
    uint256 buybackFeeSell = 0; 
    uint256 reflectionFeeSell = 0;
    uint256 marketingFeeSell = 1500; 
    uint256 totalFeeSell = 2000;
 
   uint256 liquidityFee;
   uint256 buybackFee;
 
uint256 reflectionFee;
   uint256 marketingFee;
   uint256 totalFee;
   uint256 feeDenominator = 10000;
 
   address public autoLiquidityReceiver;
   address public marketingFeeReceiver;
 
   uint256 targetLiquidity = 20;
   uint256 targetLiquidityDenominator = 100;

   bool public tradingOpen = false;
 
   IDEXRouter public router;
   address public pair;
 
   uint256 public deadBlocks = 0;
   uint256 public launchedAt = 0;
 
   uint256 buybackMultiplierNumerator = 200;
   uint256 buybackMultiplierDenominator = 100;
   uint256 buybackMultiplierTriggeredAt;
   uint256 buybackMultiplierLength = 30 minutes;
 
   bool public autoBuybackEnabled = false;
   bool public autoBuybackMultiplier = true;
   uint256 autoBuybackCap;
   uint256 autoBuybackAccumulator;
   uint256 autoBuybackAmount;
   uint256 autoBuybackBlockPeriod;
   uint256 autoBuybackBlockLast;
 
   DividendDistributor distributor;
   uint256 distributorGas = 500000;
 
   bool public swapEnabled = true;
   uint256 public swapThreshold = _totalSupply / 200; // %
   bool inSwap;
   modifier swapping() { inSwap = true; _; inSwap = false; }
 
   constructor () Auth(msg.sender) {
       router = IDEXRouter(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);
       pair = IDEXFactory(router.factory()).createPair(WETH, address(this));
       _allowances[address(this)][address(router)] = type(uint256).max;
 
       distributor = new DividendDistributor(address(router));
       
       address _presaler = msg.sender;
       isFeeExempt[_presaler] = true;
       isTxLimitExempt[_presaler] = true;
       isDividendExempt[pair] = true;
       isDividendExempt[address(this)] = true;
       isDividendExempt[DEAD] = true;
 
       autoLiquidityReceiver = msg.sender;
       marketingFeeReceiver = msg.sender;
 
       _balances[_presaler] = _totalSupply;
       emit Transfer(address(0), _presaler, _totalSupply);
   }
 
   receive() external payable { }
 
   function totalSupply() external view override returns (uint256) { return _totalSupply; }
   function decimals() external pure override returns (uint8) { return _decimals; }
   function symbol() external pure override returns (string memory) { return _symbol; }
   function name() external pure override returns (string memory) { return _name; }
   function getOwner() external view override returns (address) { return owner; }
   function balanceOf(address account) public view override returns (uint256) { return _balances[account]; }
   function allowance(address holder, address spender) external view override returns (uint256) { return _allowances[holder][spender]; }
 
   function approve(address spender, uint256 amount) public override returns (bool) {
       _allowances[msg.sender][spender] = amount;
       emit Approval(msg.sender, spender, amount);
       return true;
   }
 
   function approveMax(address spender) external returns (bool) {
       return approve(spender, type(uint256).max);
   }
 
   function transfer(address recipient, uint256 amount) external override returns (bool) {
       return _transferFrom(msg.sender, recipient, amount);
   }
 
   function transferFrom(address sender, address recipient, uint256 amount) external override returns (bool) {
       if(_allowances[sender][msg.sender] != type(uint256).max){
           _allowances[sender][msg.sender] = _allowances[sender][msg.sender].sub(amount, "Insufficient Allowance");
       }
 
       return _transferFrom(sender, recipient, amount);
   }
   
   //settting the maximum permitted wallet holding (percent of total supply)
     function setMaxWalletPercent(uint256 maxWallPercent) external onlyOwner() {
        _maxWalletToken = (_totalSupply * maxWallPercent ) / 100;
    }
 
   function _transferFrom(address sender, address recipient, uint256 amount) internal returns (bool) {
       if(inSwap){ return _basicTransfer(sender, recipient, amount); }
       
        if(!authorizations[sender] && !authorizations[recipient]){
            require(tradingOpen,"Trading not open yet");
        }

        require(!isBlacklisted[recipient] && !isBlacklisted[sender], 'Address is blacklisted');

        bool isSell = recipient == pair;

        setCorrectFees(isSell);
       
       // max wallet code
        if (!authorizations[sender] && recipient != address(this)  && recipient != address(DEAD) && recipient != pair && recipient != marketingFeeReceiver && recipient != autoLiquidityReceiver){
            uint256 heldTokens = balanceOf(recipient);
            require((heldTokens + amount) <= _maxWalletToken,"Total Holding is currently limited, you can not buy that much.");}
       
       checkTxLimit(sender, amount);
 
       if(shouldSwapBack()){ swapBack(); }
       if(shouldAutoBuyback()){ triggerAutoBuyback(); }
 
       if(!launched() && recipient == pair){ require(_balances[sender] > 0); launch(); }
 
       _balances[sender] = _balances[sender].sub(amount, "Insufficient Balance");
 
       uint256 amountReceived = shouldTakeFee(sender) ? takeFee(sender, recipient, amount) : amount;
 
_balances[recipient] = _balances[recipient].add(amountReceived);
 
       if(!isDividendExempt[sender]){ try distributor.setShare(sender, _balances[sender]) {} catch {} }
       if(!isDividendExempt[recipient]){ try distributor.setShare(recipient, _balances[recipient]) {} catch {} }
 
       try distributor.process(distributorGas) {} catch {}
 
       emit Transfer(sender, recipient, amountReceived);
       return true;
   }

   // Set the correct fees for buying or selling
    function setCorrectFees(bool isSell) internal {
        if(isSell){
            liquidityFee = liquidityFeeSell;
            buybackFee = buybackFeeSell;
            reflectionFee = reflectionFeeSell;
            marketingFee = marketingFeeSell;
            totalFee = totalFeeSell;
        } else {
            liquidityFee = liquidityFeeBuy;
            buybackFee = buybackFeeBuy;
            reflectionFee = reflectionFeeBuy;
            marketingFee = marketingFeeBuy;
            totalFee = totalFeeBuy;
        }
    }

   function blacklistAddress(address _address, bool _value) public authorized{
        isBlacklisted[_address] = _value;
    }
   
   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 checkTxLimit(address sender, uint256 amount) internal view {
       require(amount <= _maxTxAmount || isTxLimitExempt[sender], "TX Limit Exceeded");
   }
 
   function shouldTakeFee(address sender) internal view returns (bool) {
       return !isFeeExempt[sender];
   }
 
   function getTotalFee(bool selling) public view returns (uint256) {
       if(launchedAt + 1 >= block.number){ return feeDenominator.sub(1); }
       if(selling && buybackMultiplierTriggeredAt.add(buybackMultiplierLength) > block.timestamp){ return getMultipliedFee(); }
       return totalFee;
   }
 
   function getMultipliedFee() public view returns (uint256) {
       uint256 remainingTime = buybackMultiplierTriggeredAt.add(buybackMultiplierLength).sub(block.timestamp);
       uint256 feeIncrease = totalFee.mul(buybackMultiplierNumerator).div(buybackMultiplierDenominator).sub(totalFee);
       return totalFee.add(feeIncrease.mul(remainingTime).div(buybackMultiplierLength));
   }
 
   function takeFee(address sender, address receiver, uint256 amount) internal returns (uint256) {
       uint256 feeAmount = amount.mul(getTotalFee(receiver == pair)).div(feeDenominator);
       
       if((launchedAt + deadBlocks) > block.number){
            feeAmount = amount.div(100).mul(99);
        }
 
       _balances[address(this)] = _balances[address(this)].add(feeAmount);
       emit Transfer(sender, address(this), feeAmount);
 
       return amount.sub(feeAmount);
   }
 
   function shouldSwapBack() internal view returns (bool) {
       return msg.sender != pair
       && !inSwap
       && swapEnabled
       && _balances[address(this)] >= swapThreshold;
   }
 
   function swapBack() internal swapping {
       uint256 dynamicLiquidityFee = isOverLiquified(targetLiquidity, targetLiquidityDenominator) ? 0 : liquidityFee;
       uint256 amountToLiquify = swapThreshold.mul(dynamicLiquidityFee).div(totalFee).div(2);
       uint256 amountToSwap = swapThreshold.sub(amountToLiquify);
 
       address[] memory path = new address[](2);
       path[0] = address(this);
       path[1] = WETH;
 
       uint256 balanceBefore = address(this).balance;
 
       router.swapExactTokensForETHSupportingFeeOnTransferTokens(
           amountToSwap,
           0,
           path,
           address(this),
           block.timestamp
       );
       uint256 amountETH = address(this).balance.sub(balanceBefore);
       uint256 totalETHFee = totalFee.sub(dynamicLiquidityFee.div(2));
       uint256 amountETHLiquidity = amountETH.mul(dynamicLiquidityFee).div(totalETHFee).div(2);
       uint256 amountETHReflection = amountETH.mul(reflectionFee).div(totalETHFee);
       uint256 amountETHMarketing = amountETH.mul(marketingFee).div(totalETHFee);
 
       try distributor.deposit{value: amountETHReflection}() {} catch {}
       (bool success, /* bytes memory data */) = payable(marketingFeeReceiver).call{value: amountETHMarketing, gas: 30000}("");
       require(success, "receiver rejected ETH transfer");
 
       if(amountToLiquify > 0){
           router.addLiquidityETH{value: amountETHLiquidity}(
               address(this),
               amountToLiquify,
               0,
               0,
               autoLiquidityReceiver,
               block.timestamp
           );
           emit AutoLiquify(amountETHLiquidity, amountToLiquify);
       }
   }
 
function shouldAutoBuyback() internal view returns (bool) {
       return msg.sender != pair
           && !inSwap
           && autoBuybackEnabled
           && autoBuybackBlockLast + autoBuybackBlockPeriod <= block.number
           && address(this).balance >= autoBuybackAmount;
   }
 
   function triggerManualBuyback(uint256 amount, bool triggerBuybackMultiplier) external authorized {
       buyTokens(amount, DEAD);
       if(triggerBuybackMultiplier){
           buybackMultiplierTriggeredAt = block.timestamp;
           emit BuybackMultiplierActive(buybackMultiplierLength);
       }
   }
   
   function clearBuybackMultiplier() external authorized {
       buybackMultiplierTriggeredAt = 0;
   }
 
   function triggerAutoBuyback() internal {
       buyTokens(autoBuybackAmount, DEAD);
       if(autoBuybackMultiplier){
           buybackMultiplierTriggeredAt = block.timestamp;
           emit BuybackMultiplierActive(buybackMultiplierLength);
       }
       autoBuybackBlockLast = block.number;
       autoBuybackAccumulator = autoBuybackAccumulator.add(autoBuybackAmount);
       if(autoBuybackAccumulator > autoBuybackCap){ autoBuybackEnabled = false; }
   }
 
   function buyTokens(uint256 amount, address to) internal swapping {
       address[] memory path = new address[](2);
       path[0] = WETH;
       path[1] = address(this);
 
       router.swapExactETHForTokensSupportingFeeOnTransferTokens{value: amount}(
           0,
           path,
           to,
           block.timestamp
       );
   }
 
   function setAutoBuybackSettings(bool _enabled, uint256 _cap, uint256 _amount, uint256 _period, bool _autoBuybackMultiplier) external authorized {
       autoBuybackEnabled = _enabled;
       autoBuybackCap = _cap;
       autoBuybackAccumulator = 0;
       autoBuybackAmount = _amount;
       autoBuybackBlockPeriod = _period;
       autoBuybackBlockLast = block.number;
       autoBuybackMultiplier = _autoBuybackMultiplier;
   }
 
   function setBuybackMultiplierSettings(uint256 numerator, uint256 denominator, uint256 length) external authorized {
       require(numerator / denominator <= 2 && numerator > denominator);
       buybackMultiplierNumerator = numerator;
       buybackMultiplierDenominator = denominator;
       buybackMultiplierLength = length;
   }
 
   function launched() internal view returns (bool) {
       return launchedAt != 0;
   }
 
    function tradingStatus(bool _status, uint256 _deadBlocks) public onlyOwner {
        tradingOpen = _status;
        if(tradingOpen && launchedAt == 0){
            launchedAt = block.number;
            deadBlocks = _deadBlocks;
        }
    }
 
   function launch() internal {
       launchedAt = block.number;
   }

   function setTxLimit(uint256 percent) external onlyOwner {
       _maxTxAmount = _totalSupply.mul(percent).div(100);
   }
 
   function setIsDividendExempt(address holder, bool exempt) external authorized {
       require(holder != address(this) && holder != pair);
       isDividendExempt[holder] = exempt;
       if(exempt){
           distributor.setShare(holder, 0);
       }else{
           distributor.setShare(holder, _balances[holder]);
       }
   }
 
   function setIsFeeExempt(address holder, bool exempt) external authorized {
       isFeeExempt[holder] = exempt;
   }
 
   function setIsTxLimitExempt(address holder, bool exempt) external authorized {
       isTxLimitExempt[holder] = exempt;
   }
 
   // Set our buy fees
    function setBuyFees(uint256 _liquidityFeeBuy, uint256 _buybackFeeBuy, uint256 _reflectionFeeBuy, uint256 _marketingFeeBuy, uint256 _feeDenominator) external authorized {
        liquidityFeeBuy = _liquidityFeeBuy;
        buybackFeeBuy = _buybackFeeBuy;
        reflectionFeeBuy = _reflectionFeeBuy;
        marketingFeeBuy = _marketingFeeBuy;
        totalFeeBuy = _liquidityFeeBuy.add(_buybackFeeBuy).add(_reflectionFeeBuy).add(_marketingFeeBuy);
        feeDenominator = _feeDenominator;
    }

    // Set our sell fees
    function setSellFees(uint256 _liquidityFeeSell, uint256 _buybackFeeSell, uint256 _reflectionFeeSell, uint256 _marketingFeeSell, uint256 _feeDenominator) external authorized {
        liquidityFeeSell = _liquidityFeeSell;
        buybackFeeSell = _buybackFeeSell;
        reflectionFeeSell = _reflectionFeeSell;
        marketingFeeSell = _marketingFeeSell;
        totalFeeSell = _liquidityFeeSell.add(_buybackFeeSell).add(_reflectionFeeSell).add(_marketingFeeSell);
        feeDenominator = _feeDenominator;
    }
 
   function setFeeReceivers(address _autoLiquidityReceiver, address _marketingFeeReceiver) external authorized {
       autoLiquidityReceiver = _autoLiquidityReceiver;
       marketingFeeReceiver = _marketingFeeReceiver;
   }
 
   function setSwapBackSettings(bool _enabled, uint256 _amount) external authorized {
       swapEnabled = _enabled;
       swapThreshold = _amount;
 
}
 
   function setTargetLiquidity(uint256 _target, uint256 _denominator) external authorized {
       targetLiquidity = _target;
       targetLiquidityDenominator = _denominator;
   }
 
   function manualSend() external authorized {
       uint256 contractETHBalance = address(this).balance;
       payable(marketingFeeReceiver).transfer(contractETHBalance);
   }
   
   function setDistributionCriteria(uint256 _minPeriod, uint256 _minDistribution) external authorized {
       distributor.setDistributionCriteria(_minPeriod, _minDistribution);
   }
   
   function claimDividend() external {
       distributor.claimDividend(msg.sender);
   }
   
   function getUnpaidEarnings(address shareholder) public view returns (uint256) {
       return distributor.getUnpaidEarnings(shareholder);
   }
 
   function setDistributorSettings(uint256 gas) external authorized {
       require(gas < 750000);
       distributorGas = gas;
   }
   
   function getCirculatingSupply() public view returns (uint256) {
       return _totalSupply.sub(balanceOf(DEAD)).sub(balanceOf(ZERO));
   }
 
   function getLiquidityBacking(uint256 accuracy) public view returns (uint256) {
       return accuracy.mul(balanceOf(pair).mul(2)).div(getCirculatingSupply());
   }
 
   function isOverLiquified(uint256 target, uint256 accuracy) public view returns (bool) {
       return getLiquidityBacking(accuracy) > target;
   }
   
   event AutoLiquify(uint256 amountETH, uint256 amountBOG);
   event BuybackMultiplierActive(uint256 duration);
}