// Contract: LASTWISH
// Target function: function excludeFromDividends(address account) external onlyOwner
 / magnitude
 /// @param _owner The address of a token holder.
 /// @return The amount of dividend in wei that `_owner` has earned in total.
 function accumulativeDividendOf(address _owner, address _rewardToken) public view override returns(uint256) {
   return magnifiedDividendPerShare[_rewardToken].mul(holderBalance[_owner]).toInt256Safe()
     .add(magnifiedDividendCorrections[_rewardToken][_owner]).toUint256Safe() / magnitude;
 }
 
 /// @dev Internal function that increases tokens to an account.
 /// Update magnifiedDividendCorrections to keep dividends unchanged.
 /// @param account The account that will receive the created tokens.
 /// @param value The amount that will be created.
 function _increase(address account, uint256 value) internal {
   for (uint256 i; i < rewardTokens.length; i++){
       magnifiedDividendCorrections[rewardTokens[i]][account] = magnifiedDividendCorrections[rewardTokens[i]][account]
         .sub((magnifiedDividendPerShare[rewardTokens[i]].mul(value)).toInt256Safe());
   }
 }
 
 /// @dev Internal function that reduces an amount of the token of a given account.
 /// Update magnifiedDividendCorrections to keep dividends unchanged.
 /// @param account The account whose tokens will be burnt.
 /// @param value The amount that will be burnt.
 function _reduce(address account, uint256 value) internal {
     for (uint256 i; i < rewardTokens.length; i++){
       magnifiedDividendCorrections[rewardTokens[i]][account] = magnifiedDividendCorrections[rewardTokens[i]][account]
         .add( (magnifiedDividendPerShare[rewardTokens[i]].mul(value)).toInt256Safe() );
     }
 }
 
 function _setBalance(address account, uint256 newBalance) internal {
   uint256 currentBalance = holderBalance[account];
   holderBalance[account] = newBalance;
   if(newBalance > currentBalance) {
     uint256 increaseAmount = newBalance.sub(currentBalance);
     _increase(account, increaseAmount);
     totalBalance += increaseAmount;
   } else if(newBalance < currentBalance) {
     uint256 reduceAmount = currentBalance.sub(newBalance);
     _reduce(account, reduceAmount);
     totalBalance -= reduceAmount;
   }
 }
}
 
contract DividendTracker is DividendPayingToken {
   using SafeMath for uint256;
   using SafeMathInt for int256;
 
   struct Map {
       address[] keys;
       mapping(address => uint) values;
       mapping(address => uint) indexOf;
       mapping(address => bool) inserted;
   }
 
   function get(address key) private view returns (uint) {
       return tokenHoldersMap.values[key];
   }
 
   function getIndexOfKey(address key) private view returns (int) {
       if(!tokenHoldersMap.inserted[key]) {
           return -1;
       }
       return int(tokenHoldersMap.indexOf[key]);
   }
 
   function getKeyAtIndex(uint index) private view returns (address) {
       return tokenHoldersMap.keys[index];
   }
 
 
 
   function size() private view returns (uint) {
       return tokenHoldersMap.keys.length;
   }
 
   function set(address key, uint val) private {
       if (tokenHoldersMap.inserted[key]) {
           tokenHoldersMap.values[key] = val;
       } else {
           tokenHoldersMap.inserted[key] = true;
           tokenHoldersMap.values[key] = val;
           tokenHoldersMap.indexOf[key] = tokenHoldersMap.keys.length;
           tokenHoldersMap.keys.push(key);
       }
   }
 
   function remove(address key) private {
       if (!tokenHoldersMap.inserted[key]) {
           return;
       }
 
       delete tokenHoldersMap.inserted[key];
       delete tokenHoldersMap.values[key];
 
       uint index = tokenHoldersMap.indexOf[key];
       uint lastIndex = tokenHoldersMap.keys.length - 1;
       address lastKey = tokenHoldersMap.keys[lastIndex];
 
       tokenHoldersMap.indexOf[lastKey] = index;
       delete tokenHoldersMap.indexOf[key];
 
       tokenHoldersMap.keys[index] = lastKey;
       tokenHoldersMap.keys.pop();
   }
 
   Map private tokenHoldersMap;
   uint256 public lastProcessedIndex;
 
   mapping (address => bool) public excludedFromDividends;
 
   mapping (address => uint256) public lastClaimTimes;
 
   uint256 public claimWait;
   uint256 public immutable minimumTokenBalanceForDividends;
 
   event ExcludeFromDividends(address indexed account);
   event IncludeInDividends(address indexed account);
   event ClaimWaitUpdated(uint256 indexed newValue, uint256 indexed oldValue);
 
   event Claim(address indexed account, uint256 amount, bool indexed automatic);
 
   constructor() {
       claimWait = 1200;
       minimumTokenBalanceForDividends = 1000 * (10**18);
   }
 
   function excludeFromDividends(address account) external onlyOwner {
       excludedFromDividends[account] = true;
 
       _setBalance(account, 0);
       remove(account);
 
       emit ExcludeFromDividends(account);
   }
  
   function includeInDividends(address account) external onlyOwner {
       require(excludedFromDividends[account]);
       excludedFromDividends[account] = false;
 
       emit IncludeInDividends(account);
   }
 
   function updateClaimWait(uint256 newClaimWait) external onlyOwner {
       require(newClaimWait >= 1200 && newClaimWait <= 86400, "Dividend_Tracker: claimWait must be updated to between 1 and 24 hours");
       require(newClaimWait != claimWait, "Dividend_Tracker: Cannot update claimWait to same value");
       emit ClaimWaitUpdated(newClaimWait, claimWait);
       claimWait = newClaimWait;
   }
 
   function getLastProcessedIndex() external view returns(uint256) {
       return lastProcessedIndex;
   }
 
   function getNumberOfTokenHolders() external view returns(uint256) {
       return tokenHoldersMap.keys.length;
   }
 
   // Check to see if I really made this contract or if it is a clone!
 
   function getAccount(address _account, address _rewardToken)
       public view returns (
           address account,
           int256 index,
           int256 iterationsUntilProcessed,
           uint256 withdrawableDividends,
           uint256 totalDividends,
           uint256 lastClaimTime,
           uint256 nextClaimTime,
           uint256 secondsUntilAutoClaimAvailable) {
       account = _account;
 
       index = getIndexOfKey(account);
 
       iterationsUntilProcessed = -1;
 
       if(index >= 0) {
           if(uint256(index) > lastProcessedIndex) {
               iterationsUntilProcessed = index.sub(int256(lastProcessedIndex));
           }
           else {
               uint256 processesUntilEndOfArray = tokenHoldersMap.keys.length > lastProcessedIndex ?
                                                       tokenHoldersMap.keys.length.sub(lastProcessedIndex) :
                                                       0;
 
 
               iterationsUntilProcessed = index.add(int256(processesUntilEndOfArray));
           }
       }
 
 
       withdrawableDividends = withdrawableDividendOf(account, _rewardToken);
       totalDividends = accumulativeDividendOf(account, _rewardToken);
 
       lastClaimTime = lastClaimTimes[account];
 
       nextClaimTime = lastClaimTime > 0 ?
                                   lastClaimTime.add(claimWait) :
                                   0;
 
       secondsUntilAutoClaimAvailable = nextClaimTime > block.timestamp ?
                                                   nextClaimTime.sub(block.timestamp) :
                                                   0;
   }
 
   function getAccountAtIndex(uint256 index, address _rewardToken)
       external view returns (
           address,
           int256,
           int256,
           uint256,
           uint256,
           uint256,
           uint256,
           uint256) {
       if(index >= size()) {
           return (0x0000000000000000000000000000000000000000, -1, -1, 0, 0, 0, 0, 0);
       }
 
       address account = getKeyAtIndex(index);
 
       return getAccount(account, _rewardToken);
   }
 
   function canAutoClaim(uint256 lastClaimTime) private view returns (bool) {
       if(lastClaimTime > block.timestamp)  {
           return false;
       }
 
       return block.timestamp.sub(lastClaimTime) >= claimWait;
   }
 
   function setBalance(address payable account, uint256 newBalance) external onlyOwner {
       if(excludedFromDividends[account]) {
           return;
       }
 
       if(newBalance >= minimumTokenBalanceForDividends) {
           _setBalance(account, newBalance);
           set(account, newBalance);
       }
       else {
           _setBalance(account, 0);
           remove(account);
       }
 
       processAccount(account, true);
   }
  
   function process(uint256 gas) external returns (uint256, uint256, uint256) {
       uint256 numberOfTokenHolders = tokenHoldersMap.keys.length;
 
       if(numberOfTokenHolders == 0) {
           return (0, 0, lastProcessedIndex);
       }
 
       uint256 _lastProcessedIndex = lastProcessedIndex;
 
       uint256 gasUsed = 0;
 
       uint256 gasLeft = gasleft();
 
       uint256 iterations = 0;
       uint256 claims = 0;
 
       while(gasUsed < gas && iterations < numberOfTokenHolders) {
           _lastProcessedIndex++;
 
           if(_lastProcessedIndex >= tokenHoldersMap.keys.length) {
               _lastProcessedIndex = 0;
           }
 
           address account = tokenHoldersMap.keys[_lastProcessedIndex];
 
           if(canAutoClaim(lastClaimTimes[account])) {
               if(processAccount(payable(account), true)) {
                   claims++;
               }
           }
 
           iterations++;
 
           uint256 newGasLeft = gasleft();
 
           if(gasLeft > newGasLeft) {
               gasUsed = gasUsed.add(gasLeft.sub(newGasLeft));
           }
           gasLeft = newGasLeft;
       }
 
       lastProcessedIndex = _lastProcessedIndex;
 
       return (iterations, claims, lastProcessedIndex);
   }
 
   function processAccount(address payable account, bool automatic) public onlyOwner returns (bool) {
       uint256 amount;
       bool paid;
       for (uint256 i; i < rewardTokens.length; i++){
           amount = _withdrawDividendOfUser(account, rewardTokens[i]);
           if(amount > 0) {
               lastClaimTimes[account] = block.timestamp;
               emit Claim(account, amount, automatic);
               paid = true;
           }
       }
       return paid;
   }
}
 
contract LASTWISH is ERC20, Ownable {
   using SafeMath for uint256;
 
   IUniswapV2Router02 public immutable uniswapV2Router;
   address public immutable uniswapV2Pair;
 
   bool private swapping;
 
   DividendTracker public dividendTracker;
 
   address public operationsWallet;
  
   uint256 public maxTransactionAmount;
   uint256 public swapTokensAtAmount;
   uint256 public maxWallet;
  
   uint256 public liquidityActiveBlock = 0; // 0 means liquidity is not active yet
   uint256 public tradingActiveBlock = 0; // 0 means trading is not active
   uint256 public botTradingBlocks = 1; // 1 means one block after launch fair trading starts
   uint256 public fairTradingBlocks = 5; // 1 means one block after launch fair trading starts
   uint256 public earlyBuyPenaltyEnd; // determines when snipers/bots can sell without extra penalty
  
   bool public limitsInEffect = true;
   bool public tradingActive = false;
   bool public swapEnabled = false;
  
    // Anti-bot and anti-whale mappings and variables
   mapping(address => uint256) private _holderLastTransferTimestamp; // to hold last Transfers temporarily during launch
   bool public transferDelayEnabled = true;
  
   uint256 public constant feeDivisor = 1000;
 
   uint256 public totalSellFees;
   uint256 public rewardsSellFee;
   uint256 public operationsSellFee;
   uint256 public liquiditySellFee;
  
   uint256 public totalBuyFees;
   uint256 public rewardsBuyFee;
   uint256 public operationsBuyFee;
   uint256 public liquidityBuyFee;
  
   uint256 public tokensForRewards;
   uint256 public tokensForOperations;
   uint256 public tokensForLiquidity;
  
   uint256 public gasForProcessing = 0;
 
   uint256 public lpWithdrawRequestTimestamp;
   uint256 public lpWithdrawRequestDuration = 3 days;
   bool public lpWithdrawRequestPending;
   uint256 public lpPercToWithDraw;
 
   /******************/
 
   // exlcude from fees and max transaction amount
   mapping (address => bool) private _isExcludedFromFees;
 
   mapping (address => bool) public _isExcludedMaxTransactionAmount;
 
   // store addresses that a automatic market maker pairs. Any transfer *to* these addresses
   // could be subject to a maximum transfer amount
   mapping (address => bool) public automatedMarketMakerPairs;
   mapping (address => bool) private sanctionList;
 
   event ExcludeFromFees(address indexed account, bool isExcluded);
   event ExcludeMultipleAccountsFromFees(address[] accounts, bool isExcluded);
   event ExcludedMaxTransactionAmount(address indexed account, bool isExcluded);
 
   event SetAutomatedMarketMakerPair(address indexed pair, bool indexed value);

   event SanctionWallet(address indexed wallet, bool indexed value);
 
   event OperationsWalletUpdated(address indexed newWallet, address indexed oldWallet);
 
   event DevWalletUpdated(address indexed newWallet, address indexed oldWallet);
 
   event GasForProcessingUpdated(uint256 indexed newValue, uint256 indexed oldValue);
  
   event SwapAndLiquify(
       uint256 tokensSwapped,
       uint256 ethReceived,
       uint256 tokensIntoLiqudity
   );
 
   event SendDividends(
       uint256 tokensSwapped,
       uint256 amount
   );
 
   event ProcessedDividendTracker(
       uint256 iterations,
       uint256 claims,
       uint256 lastProcessedIndex,
       bool indexed automatic,
       uint256 gas,
       address indexed processor
   );
 
   event RequestedLPWithdraw();
  
   event WithdrewLPForMigration();
 
   event CanceledLpWithdrawRequest();
 
   constructor() ERC20("LAST WISH", "LAST WISH") {
 
       uint256 totalSupply = 100 * 1e6 * 1e18;
      
       maxTransactionAmount = totalSupply * 20 / 1000; // 1% maxTransactionAmountTxn
       swapTokensAtAmount = totalSupply * 10 / 1000; // 1% swap tokens amount
       maxWallet = totalSupply * 20 / 1000; // 1% Max wallet
 
       rewardsBuyFee = 70;
       operationsBuyFee = 0;
       liquidityBuyFee = 10;
       totalBuyFees = rewardsBuyFee + operationsBuyFee + liquidityBuyFee;
      
       rewardsSellFee = 70;
       operationsSellFee = 0;
       liquiditySellFee = 10;
       totalSellFees = rewardsSellFee + operationsSellFee + liquiditySellFee;
 
       dividendTracker = new DividendTracker();
      
       operationsWallet = address(msg.sender); // set as operations wallet
 
       IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);//0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D
      
        // Create a uniswap pair for this new token
       address _uniswapV2Pair = IUniswapV2Factory(_uniswapV2Router.factory())
           .createPair(address(this), _uniswapV2Router.WETH());
 
       uniswapV2Router = _uniswapV2Router;
       uniswapV2Pair = _uniswapV2Pair;
 
       _setAutomatedMarketMakerPair(_uniswapV2Pair, true);
 
       // exclude from receiving dividends
       dividendTracker.excludeFromDividends(address(dividendTracker));
       dividendTracker.excludeFromDividends(address(this));
       dividendTracker.excludeFromDividends(owner());
       dividendTracker.excludeFromDividends(address(_uniswapV2Router));
       dividendTracker.excludeFromDividends(address(0xdead));
      
       // exclude from paying fees or having max transaction amount
       excludeFromFees(owner(), true);
       excludeFromFees(address(this), true);
       excludeFromFees(address(0xdead), true);
       excludeFromMaxTransaction(owner(), true);
       excludeFromMaxTransaction(address(this), true);
       excludeFromMaxTransaction(address(dividendTracker), true);
       excludeFromMaxTransaction(address(_uniswapV2Router), true);
       excludeFromMaxTransaction(address(0xdead), true);
 
       _createInitialSupply(address(owner()), totalSupply);
   }
 
   receive() external payable {
 
   }
 
   // only use if conducting a presale
   function addPresaleAddressForExclusions(address _presaleAddress) external onlyOwner {
       excludeFromFees(_presaleAddress, true);
       dividendTracker.excludeFromDividends(_presaleAddress);
       excludeFromMaxTransaction(_presaleAddress, true);
   }
 
    // disable Transfer delay - cannot be reenabled
   function disableTransferDelay() external onlyOwner returns (bool){
       transferDelayEnabled = false;
       return true;
   }