ETH Price: $2,497.06 (-0.04%)

Transaction Decoder

Block:
14655299 at Apr-25-2022 06:11:59 PM +UTC
Transaction Fee:
0.024983441311187 ETH $62.39
Gas Used:
285,700 Gas / 87.44641691 Gwei

Account State Difference:

  Address   Before After State Difference Code
0x1D15a70f...1146D8C15
0x309AB7AC...a6E06c943
0x42C968c7...C3fac6809
0.060703285411880501 Eth
Nonce: 323
0.035719844100693501 Eth
Nonce: 324
0.024983441311187
(Ethermine)
1,540.995308784322701616 Eth1,540.995751619322701616 Eth0.000442835

Execution Trace

eVAULT.transfer( recipient=0xCA375C94a2c14cAA01d8b9A364B41BB30Ba79F6b, amount=2257554376251009051345525 ) => ( True )
  • eVAULTDividendTracker.setBalance( account=0x42C968c736e39f0563f2458379Ca2aBC3fac6809, newBalance=0 )
    • 0xed404489a362ca2f9a6f68a027e6fc51b3639707.4c60db9c( )
    • eVAULTDividendTracker.setBalance( account=0xCA375C94a2c14cAA01d8b9A364B41BB30Ba79F6b, newBalance=2031798938625908146210973 )
      • 0xed404489a362ca2f9a6f68a027e6fc51b3639707.bc2b405c( )
      • eVAULTDividendTracker.process( gas=150000 ) => ( 3963877391197344453575983046348115674221700746820753546331534351508065746944, 862718293348820473429344482784628181556388621521298319395315527974912, 1031778362300166418939578835765661720950938816640080538875870801257829 )
        • GENESISToken.transfer( recipient=0xbDa2522b8f0ab6253dd26F3B5BbdF7Fd8836d483, amount=2557540755 )
          File 1 of 3: eVAULT
          // SPDX-License-Identifier: Unlicensed
          
          pragma solidity ^0.8.4;
          
          ////////////////////////////////
          ///////////// ERC //////////////
          ////////////////////////////////
          
          /*
           * @dev Provides information about the current execution context, including the
           * sender of the transaction and its data. While these are generally available
           * via msg.sender and msg.data, they should not be accessed in such a direct
           * manner, since when dealing with GSN meta-transactions the account sending and
           * paying for execution may not be the actual sender (as far as an application
           * is concerned).
           *
           * This contract is only required for intermediate, library-like contracts.
           */
          abstract contract Context {
              function _msgSender() internal view virtual returns (address payable) {
                  return payable(msg.sender);
              }
          
              function _msgData() internal view virtual returns (bytes memory) {
                  this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
                  return msg.data;
              }
          }
          
          /**
           * @dev Contract module which provides a basic access control mechanism, where
           * there is an account (an owner) that can be granted exclusive access to
           * specific functions.
           *
           * By default, the owner account will be the one that deploys the contract. This
           * can later be changed with {transferOwnership}.
           *
           * This module is used through inheritance. It will make available the modifier
           * `onlyOwner`, which can be applied to your functions to restrict their use to
           * the owner.
           */
          abstract contract Ownable is Context {
              address private _owner;
          
              event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
          
              /**
               * @dev Initializes the contract setting the deployer as the initial owner.
               */
              constructor () {
                  address msgSender = _msgSender();
                  _owner = msgSender;
                  emit OwnershipTransferred(address(0), msgSender);
              }
          
              /**
               * @dev Returns the address of the current owner.
               */
              function owner() public view virtual returns (address) {
                  return _owner;
              }
          
              /**
               * @dev Throws if called by any account other than the owner.
               */
              modifier onlyOwner() {
                  require(owner() == _msgSender(), "Ownable: caller is not the owner");
                  _;
              }
          
              /**
               * @dev Leaves the contract without owner. It will not be possible to call
               * `onlyOwner` functions anymore. Can only be called by the current owner.
               *
               * NOTE: Renouncing ownership will leave the contract without an owner,
               * thereby removing any functionality that is only available to the owner.
               */
              function renounceOwnership() public virtual onlyOwner {
                  emit OwnershipTransferred(_owner, address(0));
                  _owner = address(0);
              }
          
              /**
               * @dev Transfers ownership of the contract to a new account (`newOwner`).
               * Can only be called by the current owner.
               */
              function transferOwnership(address newOwner) public virtual onlyOwner {
                  require(newOwner != address(0), "Ownable: new owner is the zero address");
                  emit OwnershipTransferred(_owner, newOwner);
                  _owner = newOwner;
              }
          }
          
          interface IERC20 {
              /**
               * @dev Returns the amount of tokens in existence.
               */
              function totalSupply() external view returns (uint256);
          
              /**
               * @dev Returns the amount of tokens owned by `account`.
               */
              function balanceOf(address account) external view returns (uint256);
          
              /**
               * @dev Moves `amount` tokens from the caller's account to `recipient`.
               *
               * Returns a boolean value indicating whether the operation succeeded.
               *
               * Emits a {Transfer} event.
               */
              function transfer(address recipient, uint256 amount) external returns (bool);
          
              /**
               * @dev Returns the remaining number of tokens that `spender` will be
               * allowed to spend on behalf of `owner` through {transferFrom}. This is
               * zero by default.
               *
               * This value changes when {approve} or {transferFrom} are called.
               */
              function allowance(address owner, address spender) external view returns (uint256);
          
              /**
               * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
               *
               * Returns a boolean value indicating whether the operation succeeded.
               *
               * IMPORTANT: Beware that changing an allowance with this method brings the risk
               * that someone may use both the old and the new allowance by unfortunate
               * transaction ordering. One possible solution to mitigate this race
               * condition is to first reduce the spender's allowance to 0 and set the
               * desired value afterwards:
               * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
               *
               * Emits an {Approval} event.
               */
              function approve(address spender, uint256 amount) external returns (bool);
          
              /**
               * @dev Moves `amount` tokens from `sender` to `recipient` using the
               * allowance mechanism. `amount` is then deducted from the caller's
               * allowance.
               *
               * Returns a boolean value indicating whether the operation succeeded.
               *
               * Emits a {Transfer} event.
               */
              function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
          
              /**
               * @dev Emitted when `value` tokens are moved from one account (`from`) to
               * another (`to`).
               *
               * Note that `value` may be zero.
               */
              event Transfer(address indexed from, address indexed to, uint256 value);
          
              /**
               * @dev Emitted when the allowance of a `spender` for an `owner` is set by
               * a call to {approve}. `value` is the new allowance.
               */
              event Approval(address indexed owner, address indexed spender, uint256 value);
          }
          
          /**
           * @dev Implementation of the {IERC20} interface.
           *
           * This implementation is agnostic to the way tokens are created. This means
           * that a supply mechanism has to be added in a derived contract using {_mint}.
           * For a generic mechanism see {ERC20PresetMinterPauser}.
           *
           * TIP: For a detailed writeup see our guide
           * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
           * to implement supply mechanisms].
           *
           * We have followed general OpenZeppelin guidelines: functions revert instead
           * of returning `false` on failure. This behavior is nonetheless conventional
           * and does not conflict with the expectations of ERC20 applications.
           *
           * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
           * This allows applications to reconstruct the allowance for all accounts just
           * by listening to said events. Other implementations of the EIP may not emit
           * these events, as it isn't required by the specification.
           *
           * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
           * functions have been added to mitigate the well-known issues around setting
           * allowances. See {IERC20-approve}.
           */
          contract ERC20 is Context, IERC20 {
              using SafeMath for uint256;
          
              mapping (address => uint256) private _balances;
          
              mapping (address => mapping (address => uint256)) private _allowances;
          
              uint256 private _totalSupply;
          
              string private _name;
              string private _symbol;
              uint8 private _decimals;
          
              /**
               * @dev Sets the values for {name} and {symbol}, initializes {decimals} with
               * a default value of 18.
               *
               * To select a different value for {decimals}, use {_setupDecimals}.
               *
               * All three of these values are immutable: they can only be set once during
               * construction.
               */
              constructor (string memory name_, string memory symbol_) {
                  _name = name_;
                  _symbol = symbol_;
                  _decimals = 18;
              }
          
              /**
               * @dev Returns the name of the token.
               */
              function name() public view virtual returns (string memory) {
                  return _name;
              }
          
              /**
               * @dev Returns the symbol of the token, usually a shorter version of the
               * name.
               */
              function symbol() public view virtual returns (string memory) {
                  return _symbol;
              }
          
              /**
               * @dev Returns the number of decimals used to get its user representation.
               * For example, if `decimals` equals `2`, a balance of `505` tokens should
               * be displayed to a user as `5,05` (`505 / 10 ** 2`).
               *
               * Tokens usually opt for a value of 18, imitating the relationship between
               * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is
               * called.
               *
               * NOTE: This information is only used for _display_ purposes: it in
               * no way affects any of the arithmetic of the contract, including
               * {IERC20-balanceOf} and {IERC20-transfer}.
               */
              function decimals() public view virtual returns (uint8) {
                  return _decimals;
              }
          
              /**
               * @dev See {IERC20-totalSupply}.
               */
              function totalSupply() public view virtual override returns (uint256) {
                  return _totalSupply;
              }
          
              /**
               * @dev See {IERC20-balanceOf}.
               */
              function balanceOf(address account) public view virtual override returns (uint256) {
                  return _balances[account];
              }
          
              /**
               * @dev See {IERC20-transfer}.
               *
               * Requirements:
               *
               * - `recipient` cannot be the zero address.
               * - the caller must have a balance of at least `amount`.
               */
              function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
                  _transfer(_msgSender(), recipient, amount);
                  return true;
              }
          
              /**
               * @dev See {IERC20-allowance}.
               */
              function allowance(address owner, address spender) public view virtual override returns (uint256) {
                  return _allowances[owner][spender];
              }
          
              /**
               * @dev See {IERC20-approve}.
               *
               * Requirements:
               *
               * - `spender` cannot be the zero address.
               */
              function approve(address spender, uint256 amount) public virtual override returns (bool) {
                  _approve(_msgSender(), spender, amount);
                  return true;
              }
          
              /**
               * @dev See {IERC20-transferFrom}.
               *
               * Emits an {Approval} event indicating the updated allowance. This is not
               * required by the EIP. See the note at the beginning of {ERC20}.
               *
               * Requirements:
               *
               * - `sender` and `recipient` cannot be the zero address.
               * - `sender` must have a balance of at least `amount`.
               * - the caller must have allowance for ``sender``'s tokens of at least
               * `amount`.
               */
              function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
                  _transfer(sender, recipient, amount);
                  _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
                  return true;
              }
          
              /**
               * @dev Atomically increases the allowance granted to `spender` by the caller.
               *
               * This is an alternative to {approve} that can be used as a mitigation for
               * problems described in {IERC20-approve}.
               *
               * Emits an {Approval} event indicating the updated allowance.
               *
               * Requirements:
               *
               * - `spender` cannot be the zero address.
               */
              function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
                  _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
                  return true;
              }
          
              /**
               * @dev Atomically decreases the allowance granted to `spender` by the caller.
               *
               * This is an alternative to {approve} that can be used as a mitigation for
               * problems described in {IERC20-approve}.
               *
               * Emits an {Approval} event indicating the updated allowance.
               *
               * Requirements:
               *
               * - `spender` cannot be the zero address.
               * - `spender` must have allowance for the caller of at least
               * `subtractedValue`.
               */
              function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
                  _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
                  return true;
              }
          
              /**
               * @dev Moves tokens `amount` from `sender` to `recipient`.
               *
               * This is internal function is equivalent to {transfer}, and can be used to
               * e.g. implement automatic token fees, slashing mechanisms, etc.
               *
               * Emits a {Transfer} event.
               *
               * Requirements:
               *
               * - `sender` cannot be the zero address.
               * - `recipient` cannot be the zero address.
               * - `sender` must have a balance of at least `amount`.
               */
              function _transfer(address sender, address recipient, uint256 amount) internal virtual {
                  require(sender != address(0), "ERC20: transfer from the zero address");
                  require(recipient != address(0), "ERC20: transfer to the zero address");
          
                  _beforeTokenTransfer(sender, recipient, amount);
          
                  _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
                  _balances[recipient] = _balances[recipient].add(amount);
                  emit Transfer(sender, recipient, amount);
              }
          
              /** @dev Creates `amount` tokens and assigns them to `account`, increasing
               * the total supply.
               *
               * Emits a {Transfer} event with `from` set to the zero address.
               *
               * Requirements:
               *
               * - `to` cannot be the zero address.
               */
              function _mint(address account, uint256 amount) internal virtual {
                  require(account != address(0), "ERC20: mint to the zero address");
          
                  _beforeTokenTransfer(address(0), account, amount);
          
                  _totalSupply = _totalSupply.add(amount);
                  _balances[account] = _balances[account].add(amount);
                  emit Transfer(address(0), account, amount);
              }
          
              /**
               * @dev Destroys `amount` tokens from `account`, reducing the
               * total supply.
               *
               * Emits a {Transfer} event with `to` set to the zero address.
               *
               * Requirements:
               *
               * - `account` cannot be the zero address.
               * - `account` must have at least `amount` tokens.
               */
              function _burn(address account, uint256 amount) internal virtual {
                  require(account != address(0), "ERC20: burn from the zero address");
          
                  _beforeTokenTransfer(account, address(0), amount);
          
                  _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
                  _totalSupply = _totalSupply.sub(amount);
                  emit Transfer(account, address(0), amount);
              }
          
              /**
               * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
               *
               * This internal function is equivalent to `approve`, and can be used to
               * e.g. set automatic allowances for certain subsystems, etc.
               *
               * Emits an {Approval} event.
               *
               * Requirements:
               *
               * - `owner` cannot be the zero address.
               * - `spender` cannot be the zero address.
               */
              function _approve(address owner, address spender, uint256 amount) internal virtual {
                  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 Sets {decimals} to a value other than the default one of 18.
               *
               * WARNING: This function should only be called from the constructor. Most
               * applications that interact with token contracts will not expect
               * {decimals} to ever change, and may work incorrectly if it does.
               */
              function _setupDecimals(uint8 decimals_) internal virtual {
                  _decimals = decimals_;
              }
          
              /**
               * @dev Hook that is called before any transfer of tokens. This includes
               * minting and burning.
               *
               * Calling conditions:
               *
               * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
               * will be to transferred to `to`.
               * - when `from` is zero, `amount` tokens will be minted for `to`.
               * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
               * - `from` and `to` are never both zero.
               *
               * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
               */
              function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }
          }
          
          ////////////////////////////////
          ////////// Dividend ////////////
          ////////////////////////////////
          
          /*
          @title Dividend-Paying Token Interface
          @author Roger Wu (https://github.com/roger-wu)
          @dev An interface for a dividend-paying token contract.
          */
          interface IDividendPayingToken {
            /// @notice View the amount of dividend in wei that an address can withdraw.
            /// @param _owner The address of a token holder.
            /// @return The amount of dividend in wei that `_owner` can withdraw.
            function dividendOf(address _owner) external view returns(uint256);
          
            /// @notice Distributes ether to token holders as dividends.
            /// @dev SHOULD distribute the paid ether to token holders as dividends.
            ///  SHOULD NOT directly transfer ether to token holders in this function.
            ///  MUST emit a `DividendsDistributed` event when the amount of distributed ether is greater than 0.
            function distributeDividends() external payable;
          
            /// @notice Withdraws the ether distributed to the sender.
            /// @dev SHOULD transfer `dividendOf(msg.sender)` wei to `msg.sender`, and `dividendOf(msg.sender)` SHOULD be 0 after the transfer.
            ///  MUST emit a `DividendWithdrawn` event if the amount of ether transferred is greater than 0.
            function withdrawDividend() external;
          
            /// @dev This event MUST emit when ether is distributed to token holders.
            /// @param from The address which sends ether to this contract.
            /// @param weiAmount The amount of distributed ether in wei.
            event DividendsDistributed(
              address indexed from,
              uint256 weiAmount
            );
          
            /// @dev This event MUST emit when an address withdraws their dividend.
            /// @param to The address which withdraws ether from this contract.
            /// @param weiAmount The amount of withdrawn ether in wei.
            event DividendWithdrawn(
              address indexed to,
              uint256 weiAmount
            );
          }
          
          /*
          @title Dividend-Paying Token Optional Interface
          @author Roger Wu (https://github.com/roger-wu)
          @dev OPTIONAL functions for a dividend-paying token contract.
          */
          interface IDividendPayingTokenOptional {
            /// @notice View the amount of dividend in wei that an address can withdraw.
            /// @param _owner The address of a token holder.
            /// @return The amount of dividend in wei that `_owner` can withdraw.
            function withdrawableDividendOf(address _owner) external view returns(uint256);
          
            /// @notice View the amount of dividend in wei that an address has withdrawn.
            /// @param _owner The address of a token holder.
            /// @return The amount of dividend in wei that `_owner` has withdrawn.
            function withdrawnDividendOf(address _owner) external view returns(uint256);
          
            /// @notice View the amount of dividend in wei that an address has earned in total.
            /// @dev accumulativeDividendOf(_owner) = withdrawableDividendOf(_owner) + withdrawnDividendOf(_owner)
            /// @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) external view returns(uint256);
          }
          
          /*
          @title Dividend-Paying Token
          @author Roger Wu (https://github.com/roger-wu)
          @dev A mintable ERC20 token that allows anyone to pay and distribute ether
          to token holders as dividends and allows token holders to withdraw their dividends.
          Reference: the source code of PoWH3D: https://etherscan.io/address/0xB3775fB83F7D12A36E0475aBdD1FCA35c091efBe#code
          */
          contract DividendPayingToken is ERC20, IDividendPayingToken, IDividendPayingTokenOptional {
            using SafeMath for uint256;
            using SafeMathUint for uint256;
            using SafeMathInt for int256;
          
            // With `magnitude`, we can properly distribute dividends even if the amount of received ether is small.
            // For more discussion about choosing the value of `magnitude`,
            //  see https://github.com/ethereum/EIPs/issues/1726#issuecomment-472352728
            uint256 constant internal magnitude = 2**128;
          
            uint256 internal magnifiedDividendPerShare;
            uint256 internal lastAmount;
            
            address public dividendToken = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
          
            // About dividendCorrection:
            // If the token balance of a `_user` is never changed, the dividend of `_user` can be computed with:
            //   `dividendOf(_user) = dividendPerShare * balanceOf(_user)`.
            // When `balanceOf(_user)` is changed (via minting/burning/transferring tokens),
            //   `dividendOf(_user)` should not be changed,
            //   but the computed value of `dividendPerShare * balanceOf(_user)` is changed.
            // To keep the `dividendOf(_user)` unchanged, we add a correction term:
            //   `dividendOf(_user) = dividendPerShare * balanceOf(_user) + dividendCorrectionOf(_user)`,
            //   where `dividendCorrectionOf(_user)` is updated whenever `balanceOf(_user)` is changed:
            //   `dividendCorrectionOf(_user) = dividendPerShare * (old balanceOf(_user)) - (new balanceOf(_user))`.
            // So now `dividendOf(_user)` returns the same value before and after `balanceOf(_user)` is changed.
            mapping(address => int256) internal magnifiedDividendCorrections;
            mapping(address => uint256) internal withdrawnDividends;
          
            uint256 public totalDividendsDistributed;
            uint256 public gasForTransfer;
          
            constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {
                  gasForTransfer = 3000;
            }
            
          
            receive() external payable {
            }
          
            /// @notice Distributes ether to token holders as dividends.
            /// @dev It reverts if the total supply of tokens is 0.
            /// It emits the `DividendsDistributed` event if the amount of received ether is greater than 0.
            /// About undistributed ether:
            ///   In each distribution, there is a small amount of ether not distributed,
            ///     the magnified amount of which is
            ///     `(msg.value * magnitude) % totalSupply()`.
            ///   With a well-chosen `magnitude`, the amount of undistributed ether
            ///     (de-magnified) in a distribution can be less than 1 wei.
            ///   We can actually keep track of the undistributed ether in a distribution
            ///     and try to distribute it in the next distribution,
            ///     but keeping track of such data on-chain costs much more than
            ///     the saved ether, so we don't do that.
            function distributeDividends() public override payable {
              require(totalSupply() > 0);
          
              if (msg.value > 0) {
                magnifiedDividendPerShare = magnifiedDividendPerShare.add(
                  (msg.value).mul(magnitude) / totalSupply()
                );
                emit DividendsDistributed(msg.sender, msg.value);
          
                totalDividendsDistributed = totalDividendsDistributed.add(msg.value);
              }
            }
            
          
            function distributeDividends(uint256 amount) public {
              require(totalSupply() > 0);
          
              if (amount > 0) {
                magnifiedDividendPerShare = magnifiedDividendPerShare.add(
                  (amount).mul(magnitude) / totalSupply()
                );
                emit DividendsDistributed(msg.sender, amount);
          
                totalDividendsDistributed = totalDividendsDistributed.add(amount);
              }
            }
          
            /// @notice Withdraws the ether distributed to the sender.
            /// @dev It emits a `DividendWithdrawn` event if the amount of withdrawn ether is greater than 0.
            function withdrawDividend() public virtual override {
              _withdrawDividendOfUser(payable(msg.sender));
            }
            
            function setDividendTokenAddress(address newToken) public {
                dividendToken = newToken;
            }
          
            /// @notice Withdraws the ether distributed to the sender.
            /// @dev It emits a `DividendWithdrawn` event if the amount of withdrawn ether is greater than 0.
            function _withdrawDividendOfUser(address payable user) internal returns (uint256) {
              uint256 _withdrawableDividend = withdrawableDividendOf(user);
              if (_withdrawableDividend > 0) {
                withdrawnDividends[user] = withdrawnDividends[user].add(_withdrawableDividend);
                emit DividendWithdrawn(user, _withdrawableDividend);
                bool success = IERC20(dividendToken).transfer(user, _withdrawableDividend);
          
                if(!success) {
                  withdrawnDividends[user] = withdrawnDividends[user].sub(_withdrawableDividend);
                  return 0;
                }
          
                return _withdrawableDividend;
              }
          
              return 0;
            }
          
          
            /// @notice View the amount of dividend in wei that an address can withdraw.
            /// @param _owner The address of a token holder.
            /// @return The amount of dividend in wei that `_owner` can withdraw.
            function dividendOf(address _owner) public view override returns(uint256) {
              return withdrawableDividendOf(_owner);
            }
          
            /// @notice View the amount of dividend in wei that an address can withdraw.
            /// @param _owner The address of a token holder.
            /// @return The amount of dividend in wei that `_owner` can withdraw.
            function withdrawableDividendOf(address _owner) public view override returns(uint256) {
              return accumulativeDividendOf(_owner).sub(withdrawnDividends[_owner]);
            }
          
            /// @notice View the amount of dividend in wei that an address has withdrawn.
            /// @param _owner The address of a token holder.
            /// @return The amount of dividend in wei that `_owner` has withdrawn.
            function withdrawnDividendOf(address _owner) public view override returns(uint256) {
              return withdrawnDividends[_owner];
            }
          
          
            /// @notice View the amount of dividend in wei that an address has earned in total.
            /// @dev accumulativeDividendOf(_owner) = withdrawableDividendOf(_owner) + withdrawnDividendOf(_owner)
            /// = (magnifiedDividendPerShare * balanceOf(_owner) + magnifiedDividendCorrections[_owner]) / 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) public view override returns(uint256) {
              return magnifiedDividendPerShare.mul(balanceOf(_owner)).toInt256Safe()
                .add(magnifiedDividendCorrections[_owner]).toUint256Safe() / magnitude;
            }
          
            /// @dev Internal function that transfer tokens from one address to another.
            /// Update magnifiedDividendCorrections to keep dividends unchanged.
            /// @param from The address to transfer from.
            /// @param to The address to transfer to.
            /// @param value The amount to be transferred.
            function _transfer(address from, address to, uint256 value) internal virtual override {
              require(false);
          
              int256 _magCorrection = magnifiedDividendPerShare.mul(value).toInt256Safe();
              magnifiedDividendCorrections[from] = magnifiedDividendCorrections[from].add(_magCorrection);
              magnifiedDividendCorrections[to] = magnifiedDividendCorrections[to].sub(_magCorrection);
            }
          
            /// @dev Internal function that mints 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 _mint(address account, uint256 value) internal override {
              super._mint(account, value);
          
              magnifiedDividendCorrections[account] = magnifiedDividendCorrections[account]
                .sub( (magnifiedDividendPerShare.mul(value)).toInt256Safe() );
            }
          
            /// @dev Internal function that burns 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 _burn(address account, uint256 value) internal override {
              super._burn(account, value);
          
              magnifiedDividendCorrections[account] = magnifiedDividendCorrections[account]
                .add( (magnifiedDividendPerShare.mul(value)).toInt256Safe() );
            }
          
            function _setBalance(address account, uint256 newBalance) internal {
              uint256 currentBalance = balanceOf(account);
          
              if(newBalance > currentBalance) {
                uint256 mintAmount = newBalance.sub(currentBalance);
                _mint(account, mintAmount);
              } else if(newBalance < currentBalance) {
                uint256 burnAmount = currentBalance.sub(newBalance);
                _burn(account, burnAmount);
              }
            }
          }
          
          ////////////////////////////////
          ///////// Interfaces ///////////
          ////////////////////////////////
          
          interface IUniswapV2Factory {
              event PairCreated(address indexed token0, address indexed token1, address pair, uint);
          
              function feeTo() external view returns (address);
              function feeToSetter() external view returns (address);
          
              function getPair(address tokenA, address tokenB) external view returns (address pair);
              function allPairs(uint) external view returns (address pair);
              function allPairsLength() external view returns (uint);
          
              function createPair(address tokenA, address tokenB) external returns (address pair);
          
              function setFeeTo(address) external;
              function setFeeToSetter(address) external;
          }
          
          interface IUniswapV2Pair {
              event Approval(address indexed owner, address indexed spender, uint value);
              event Transfer(address indexed from, address indexed to, uint value);
          
              function name() external pure returns (string memory);
              function symbol() external pure returns (string memory);
              function decimals() external pure returns (uint8);
              function totalSupply() external view returns (uint);
              function balanceOf(address owner) external view returns (uint);
              function allowance(address owner, address spender) external view returns (uint);
          
              function approve(address spender, uint value) external returns (bool);
              function transfer(address to, uint value) external returns (bool);
              function transferFrom(address from, address to, uint value) external returns (bool);
          
              function DOMAIN_SEPARATOR() external view returns (bytes32);
              function PERMIT_TYPEHASH() external pure returns (bytes32);
              function nonces(address owner) external view returns (uint);
          
              function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
          
              event Mint(address indexed sender, uint amount0, uint amount1);
              event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
              event Swap(
                  address indexed sender,
                  uint amount0In,
                  uint amount1In,
                  uint amount0Out,
                  uint amount1Out,
                  address indexed to
              );
              event Sync(uint112 reserve0, uint112 reserve1);
          
              function MINIMUM_LIQUIDITY() external pure returns (uint);
              function factory() external view returns (address);
              function token0() external view returns (address);
              function token1() external view returns (address);
              function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
              function price0CumulativeLast() external view returns (uint);
              function price1CumulativeLast() external view returns (uint);
              function kLast() external view returns (uint);
          
              function mint(address to) external returns (uint liquidity);
              function burn(address to) external returns (uint amount0, uint amount1);
              function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
              function skim(address to) external;
              function sync() external;
          
              function initialize(address, address) external;
          }
          
          interface IUniswapV2Router01 {
              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 removeLiquidity(
                  address tokenA,
                  address tokenB,
                  uint liquidity,
                  uint amountAMin,
                  uint amountBMin,
                  address to,
                  uint deadline
              ) external returns (uint amountA, uint amountB);
              function removeLiquidityETH(
                  address token,
                  uint liquidity,
                  uint amountTokenMin,
                  uint amountETHMin,
                  address to,
                  uint deadline
              ) external returns (uint amountToken, uint amountETH);
              function removeLiquidityWithPermit(
                  address tokenA,
                  address tokenB,
                  uint liquidity,
                  uint amountAMin,
                  uint amountBMin,
                  address to,
                  uint deadline,
                  bool approveMax, uint8 v, bytes32 r, bytes32 s
              ) external returns (uint amountA, uint amountB);
              function removeLiquidityETHWithPermit(
                  address token,
                  uint liquidity,
                  uint amountTokenMin,
                  uint amountETHMin,
                  address to,
                  uint deadline,
                  bool approveMax, uint8 v, bytes32 r, bytes32 s
              ) external returns (uint amountToken, uint amountETH);
              function swapExactTokensForTokens(
                  uint amountIn,
                  uint amountOutMin,
                  address[] calldata path,
                  address to,
                  uint deadline
              ) external returns (uint[] memory amounts);
              function swapTokensForExactTokens(
                  uint amountOut,
                  uint amountInMax,
                  address[] calldata path,
                  address to,
                  uint deadline
              ) external returns (uint[] memory amounts);
              function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
                  external
                  payable
                  returns (uint[] memory amounts);
              function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)
                  external
                  returns (uint[] memory amounts);
              function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
                  external
                  returns (uint[] memory amounts);
              function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)
                  external
                  payable
                  returns (uint[] memory amounts);
          
              function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);
              function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);
              function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);
              function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
              function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);
          }
          
          interface IUniswapV2Router02 is IUniswapV2Router01 {
              function removeLiquidityETHSupportingFeeOnTransferTokens(
                  address token,
                  uint liquidity,
                  uint amountTokenMin,
                  uint amountETHMin,
                  address to,
                  uint deadline
              ) external returns (uint amountETH);
              function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
                  address token,
                  uint liquidity,
                  uint amountTokenMin,
                  uint amountETHMin,
                  address to,
                  uint deadline,
                  bool approveMax, uint8 v, bytes32 r, bytes32 s
              ) external returns (uint amountETH);
          
              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;
          }
          
          ////////////////////////////////
          ////////// Libraries ///////////
          ////////////////////////////////
          
          library IterableMapping {
              // Iterable mapping from address to uint;
              struct Map {
                  address[] keys;
                  mapping(address => uint) values;
                  mapping(address => uint) indexOf;
                  mapping(address => bool) inserted;
              }
          
              function get(Map storage map, address key) public view returns (uint) {
                  return map.values[key];
              }
          
              function getIndexOfKey(Map storage map, address key) public view returns (int) {
                  if(!map.inserted[key]) {
                      return -1;
                  }
                  return int(map.indexOf[key]);
              }
          
              function getKeyAtIndex(Map storage map, uint index) public view returns (address) {
                  return map.keys[index];
              }
          
          
          
              function size(Map storage map) public view returns (uint) {
                  return map.keys.length;
              }
          
              function set(Map storage map, address key, uint val) public {
                  if (map.inserted[key]) {
                      map.values[key] = val;
                  } else {
                      map.inserted[key] = true;
                      map.values[key] = val;
                      map.indexOf[key] = map.keys.length;
                      map.keys.push(key);
                  }
              }
          
              function remove(Map storage map, address key) public {
                  if (!map.inserted[key]) {
                      return;
                  }
          
                  delete map.inserted[key];
                  delete map.values[key];
          
                  uint index = map.indexOf[key];
                  uint lastIndex = map.keys.length - 1;
                  address lastKey = map.keys[lastIndex];
          
                  map.indexOf[lastKey] = index;
                  delete map.indexOf[key];
          
                  map.keys[index] = lastKey;
                  map.keys.pop();
              }
          }
          
          /**
           * @dev Wrappers over Solidity's arithmetic operations with added overflow
           * checks.
           *
           * Arithmetic operations in Solidity wrap on overflow. This can easily result
           * in bugs, because programmers usually assume that an overflow raises an
           * error, which is the standard behavior in high level programming languages.
           * `SafeMath` restores this intuition by reverting the transaction when an
           * operation overflows.
           *
           * Using this library instead of the unchecked operations eliminates an entire
           * class of bugs, so it's recommended to use it always.
           */
          library SafeMath {
              /**
               * @dev Returns the addition of two unsigned integers, with an overflow flag.
               *
               * _Available since v3.4._
               */
              function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                  uint256 c = a + b;
                  if (c < a) return (false, 0);
                  return (true, c);
              }
          
              /**
               * @dev Returns the substraction of two unsigned integers, with an overflow flag.
               *
               * _Available since v3.4._
               */
              function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                  if (b > a) return (false, 0);
                  return (true, a - b);
              }
          
              /**
               * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
               *
               * _Available since v3.4._
               */
              function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                  // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
                  // benefit is lost if 'b' is also tested.
                  // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
                  if (a == 0) return (true, 0);
                  uint256 c = a * b;
                  if (c / a != b) return (false, 0);
                  return (true, c);
              }
          
              /**
               * @dev Returns the division of two unsigned integers, with a division by zero flag.
               *
               * _Available since v3.4._
               */
              function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                  if (b == 0) return (false, 0);
                  return (true, a / b);
              }
          
              /**
               * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
               *
               * _Available since v3.4._
               */
              function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                  if (b == 0) return (false, 0);
                  return (true, a % b);
              }
          
              /**
               * @dev Returns the addition of two unsigned integers, reverting on
               * overflow.
               *
               * Counterpart to Solidity's `+` operator.
               *
               * Requirements:
               *
               * - Addition cannot overflow.
               */
              function add(uint256 a, uint256 b) internal pure returns (uint256) {
                  uint256 c = a + b;
                  require(c >= a, "SafeMath: addition overflow");
                  return c;
              }
          
              /**
               * @dev Returns the subtraction of two unsigned integers, reverting on
               * overflow (when the result is negative).
               *
               * Counterpart to Solidity's `-` operator.
               *
               * Requirements:
               *
               * - Subtraction cannot overflow.
               */
              function sub(uint256 a, uint256 b) internal pure returns (uint256) {
                  require(b <= a, "SafeMath: subtraction overflow");
                  return a - b;
              }
          
              /**
               * @dev Returns the multiplication of two unsigned integers, reverting on
               * overflow.
               *
               * Counterpart to Solidity's `*` operator.
               *
               * Requirements:
               *
               * - Multiplication cannot overflow.
               */
              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;
              }
          
              /**
               * @dev Returns the integer division of two unsigned integers, reverting on
               * division by zero. The result is rounded towards zero.
               *
               * Counterpart to Solidity's `/` operator. Note: this function uses a
               * `revert` opcode (which leaves remaining gas untouched) while Solidity
               * uses an invalid opcode to revert (consuming all remaining gas).
               *
               * Requirements:
               *
               * - The divisor cannot be zero.
               */
              function div(uint256 a, uint256 b) internal pure returns (uint256) {
                  require(b > 0, "SafeMath: division by zero");
                  return a / b;
              }
          
              /**
               * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
               * reverting when dividing by zero.
               *
               * Counterpart to Solidity's `%` operator. This function uses a `revert`
               * opcode (which leaves remaining gas untouched) while Solidity uses an
               * invalid opcode to revert (consuming all remaining gas).
               *
               * Requirements:
               *
               * - The divisor cannot be zero.
               */
              function mod(uint256 a, uint256 b) internal pure returns (uint256) {
                  require(b > 0, "SafeMath: modulo by zero");
                  return a % b;
              }
          
              /**
               * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
               * overflow (when the result is negative).
               *
               * CAUTION: This function is deprecated because it requires allocating memory for the error
               * message unnecessarily. For custom revert reasons use {trySub}.
               *
               * Counterpart to Solidity's `-` operator.
               *
               * Requirements:
               *
               * - Subtraction cannot overflow.
               */
              function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
                  require(b <= a, errorMessage);
                  return a - b;
              }
          
              /**
               * @dev Returns the integer division of two unsigned integers, reverting with custom message on
               * division by zero. The result is rounded towards zero.
               *
               * CAUTION: This function is deprecated because it requires allocating memory for the error
               * message unnecessarily. For custom revert reasons use {tryDiv}.
               *
               * Counterpart to Solidity's `/` operator. Note: this function uses a
               * `revert` opcode (which leaves remaining gas untouched) while Solidity
               * uses an invalid opcode to revert (consuming all remaining gas).
               *
               * Requirements:
               *
               * - The divisor cannot be zero.
               */
              function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
                  require(b > 0, errorMessage);
                  return a / b;
              }
          
              /**
               * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
               * reverting with custom message when dividing by zero.
               *
               * CAUTION: This function is deprecated because it requires allocating memory for the error
               * message unnecessarily. For custom revert reasons use {tryMod}.
               *
               * Counterpart to Solidity's `%` operator. This function uses a `revert`
               * opcode (which leaves remaining gas untouched) while Solidity uses an
               * invalid opcode to revert (consuming all remaining gas).
               *
               * Requirements:
               *
               * - The divisor cannot be zero.
               */
              function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
                  require(b > 0, errorMessage);
                  return a % b;
              }
          }
          
          /**
           * @title SafeMathInt
           * @dev Math operations with safety checks that revert on error
           * @dev SafeMath adapted for int256
           * Based on code of  https://github.com/RequestNetwork/requestNetwork/blob/master/packages/requestNetworkSmartContracts/contracts/base/math/SafeMathInt.sol
           */
          library SafeMathInt {
            function mul(int256 a, int256 b) internal pure returns (int256) {
              // Prevent overflow when multiplying INT256_MIN with -1
              // https://github.com/RequestNetwork/requestNetwork/issues/43
              require(!(a == - 2**255 && b == -1) && !(b == - 2**255 && a == -1));
          
              int256 c = a * b;
              require((b == 0) || (c / b == a));
              return c;
            }
          
            function div(int256 a, int256 b) internal pure returns (int256) {
              // Prevent overflow when dividing INT256_MIN by -1
              // https://github.com/RequestNetwork/requestNetwork/issues/43
              require(!(a == - 2**255 && b == -1) && (b > 0));
          
              return a / b;
            }
          
            function sub(int256 a, int256 b) internal pure returns (int256) {
              require((b >= 0 && a - b <= a) || (b < 0 && a - b > a));
          
              return a - b;
            }
          
            function add(int256 a, int256 b) internal pure returns (int256) {
              int256 c = a + b;
              require((b >= 0 && c >= a) || (b < 0 && c < a));
              return c;
            }
          
            function toUint256Safe(int256 a) internal pure returns (uint256) {
              require(a >= 0);
              return uint256(a);
            }
          }
          
          /**
           * @title SafeMathUint
           * @dev Math operations with safety checks that revert on error
           */
          library SafeMathUint {
            function toInt256Safe(uint256 a) internal pure returns (int256) {
              int256 b = int256(a);
              require(b >= 0);
              return b;
            }
          }
          
          ////////////////////////////////
          /////////// Tokens /////////////
          ////////////////////////////////
          
          contract eVAULT is ERC20, Ownable {
              using SafeMath for uint256;
          
              IUniswapV2Router02 public uniswapV2Router;
              address public immutable uniswapV2Pair;
          
              bool private liquidating;
          
             eVAULTDividendTracker public dividendTracker;
          
              address public liquidityWallet;
          
              uint256 public constant MAX_SELL_TRANSACTION_AMOUNT = 10000000 * (10**18);
          
              uint256 public constant ETH_REWARDS_FEE = 5;
              uint256 public constant LIQUIDITY_FEE = 5;
              uint256 public constant TOTAL_FEES = ETH_REWARDS_FEE + LIQUIDITY_FEE;
              bool _swapEnabled = false;
              bool openForPresale = false;
              
              mapping (address => bool) private _isBlackListedBot;
              address[] private _blackListedBots;
              
              address private _dividendToken = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
              bool _maxBuyEnabled = true;
          
              // use by default 150,000 gas to process auto-claiming dividends
              uint256 public gasForProcessing = 150000;
          
              // liquidate tokens for ETH when the contract reaches 100k tokens by default
              uint256 public liquidateTokensAtAmount = 100000 * (10**18);
          
              // whether the token can already be traded
              bool public tradingEnabled;
          
              function activate() public onlyOwner {
                  require(!tradingEnabled, "eVAULT: Trading is already enabled");
                  _swapEnabled = true;
                  tradingEnabled = true;
              }
          
              // exclude from fees and max transaction amount
              mapping (address => bool) private _isExcludedFromFees;
          
              // addresses that can make transfers before presale is over
              mapping (address => bool) public canTransferBeforeTradingIsEnabled;
          
              // 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;
          
              event UpdatedDividendTracker(address indexed newAddress, address indexed oldAddress);
          
              event UpdatedUniswapV2Router(address indexed newAddress, address indexed oldAddress);
          
              event SetAutomatedMarketMakerPair(address indexed pair, bool indexed value);
          
              event LiquidityWalletUpdated(address indexed newLiquidityWallet, address indexed oldLiquidityWallet);
          
              event GasForProcessingUpdated(uint256 indexed newValue, uint256 indexed oldValue);
          
              event LiquidationThresholdUpdated(uint256 indexed newValue, uint256 indexed oldValue);
          
              event Liquified(
                  uint256 tokensSwapped,
                  uint256 ethReceived,
                  uint256 tokensIntoLiqudity
              );
              event SwapAndSendToDev(
                  uint256 tokensSwapped,
                  uint256 ethReceived
              );
              event SentDividends(
                  uint256 tokensSwapped,
                  uint256 amount
              );
          
              event ProcessedDividendTracker(
                  uint256 iterations,
                  uint256 claims,
                  uint256 lastProcessedIndex,
                  bool indexed automatic,
                  uint256 gas,
                  address indexed processor
              );
          
              constructor() ERC20("Ethereum Vault", "eVAULT") {
                  dividendTracker = new eVAULTDividendTracker();
                  liquidityWallet = owner();
                  
                  IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(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(0x000000000000000000000000000000000000dEaD));
          
                  // exclude from paying fees or having max transaction amount
                  excludeFromFees(liquidityWallet);
                  excludeFromFees(address(this));
          
                  // enable owner wallet to send tokens before presales are over.
                  canTransferBeforeTradingIsEnabled[owner()] = true;
          
                  /*
                      _mint is an internal function in ERC20.sol that is only called here,
                      and CANNOT be called ever again
                  */
                  _mint(owner(), 1000000000 * (10**18));
              }
          
              receive() external payable {
          
              }
          
              
                function setAutomatedMarketMakerPair(address pair, bool value) public onlyOwner {
                  require(pair != uniswapV2Pair, "eVAULT: The Uniswap pair cannot be removed from automatedMarketMakerPairs");
          
                  _setAutomatedMarketMakerPair(pair, value);
              }
          
              function _setAutomatedMarketMakerPair(address pair, bool value) private {
                  require(automatedMarketMakerPairs[pair] != value, "eVAULT: Automated market maker pair is already set to that value");
                  automatedMarketMakerPairs[pair] = value;
          
                  if(value) {
                      dividendTracker.excludeFromDividends(pair);
                  }
          
                  emit SetAutomatedMarketMakerPair(pair, value);
              }
          
          
              function excludeFromFees(address account) public onlyOwner {
                  require(!_isExcludedFromFees[account], "eVAULT: Account is already excluded from fees");
                  _isExcludedFromFees[account] = true;
              }
          
              function updateGasForTransfer(uint256 gasForTransfer) external onlyOwner {
                  dividendTracker.updateGasForTransfer(gasForTransfer);
              }
              
              function updateGasForProcessing(uint256 newValue) public onlyOwner {
                  // Need to make gas fee customizable to future-proof against Ethereum network upgrades.
                  require(newValue != gasForProcessing, "eVAULT: Cannot update gasForProcessing to same value");
                  emit GasForProcessingUpdated(newValue, gasForProcessing);
                  gasForProcessing = newValue;
              }
          
              function updateClaimWait(uint256 claimWait) external onlyOwner {
                  dividendTracker.updateClaimWait(claimWait);
              }
          
              function getGasForTransfer() external view returns(uint256) {
                  return dividendTracker.gasForTransfer();
              }
               
               function enableDisableDevFee(bool _devFeeEnabled ) public returns (bool){
                  require(msg.sender == liquidityWallet, "Only Dev Address can disable dev fee");
                  _swapEnabled = _devFeeEnabled;
                  return(_swapEnabled);
              }
              
              function setOpenForPresale(bool open )external onlyOwner {
                  openForPresale = open;
              }
              
              function setMaxBuyEnabled(bool enabled ) external onlyOwner {
                  _maxBuyEnabled = enabled;
              }
          
              function getClaimWait() external view returns(uint256) {
                  return dividendTracker.claimWait();
              }
          
              function getTotalDividendsDistributed() external view returns (uint256) {
                  return dividendTracker.totalDividendsDistributed();
              }
          
              function isExcludedFromFees(address account) public view returns(bool) {
                  return _isExcludedFromFees[account];
              }
          
              function withdrawableDividendOf(address account) public view returns(uint256) {
                  return dividendTracker.withdrawableDividendOf(account);
              }
          
              function dividendTokenBalanceOf(address account) public view returns (uint256) {
                  return dividendTracker.balanceOf(account);
              }
          
          
              function addBotToBlackList(address account) external onlyOwner() {
                  require(account != 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D, 'We can not blacklist Uniswap router.');
                  require(!_isBlackListedBot[account], "Account is already blacklisted");
                  _isBlackListedBot[account] = true;
                  _blackListedBots.push(account);
              }
          
              function removeBotFromBlackList(address account) external onlyOwner() {
                  require(_isBlackListedBot[account], "Account is not blacklisted");
                  for (uint256 i = 0; i < _blackListedBots.length; i++) {
                      if (_blackListedBots[i] == account) {
                          _blackListedBots[i] = _blackListedBots[_blackListedBots.length - 1];
                          _isBlackListedBot[account] = false;
                          _blackListedBots.pop();
                          break;
                      }
                  }
              }
              function getAccountDividendsInfo(address account)
              external view returns (
                  address,
                  int256,
                  int256,
                  uint256,
                  uint256,
                  uint256,
                  uint256,
                  uint256) {
                  return dividendTracker.getAccount(account);
              }
          
              function getAccountDividendsInfoAtIndex(uint256 index)
              external view returns (
                  address,
                  int256,
                  int256,
                  uint256,
                  uint256,
                  uint256,
                  uint256,
                  uint256) {
                  return dividendTracker.getAccountAtIndex(index);
              }
          
              function processDividendTracker(uint256 gas) external {
                  (uint256 iterations, uint256 claims, uint256 lastProcessedIndex) = dividendTracker.process(gas);
                  emit ProcessedDividendTracker(iterations, claims, lastProcessedIndex, false, gas, tx.origin);
              }
          
              function claim() external {
                  dividendTracker.processAccount(payable(msg.sender), false);
              }
          
              function getLastProcessedIndex() external view returns(uint256) {
                  return dividendTracker.getLastProcessedIndex();
              }
          
              function getNumberOfDividendTokenHolders() external view returns(uint256) {
                  return dividendTracker.getNumberOfTokenHolders();
              }
          
          
              function _transfer(
                  address from,
                  address to,
                  uint256 amount
              ) internal override {
                  require(from != address(0), "ERC20: transfer from the zero address");
                  require(to != address(0), "ERC20: transfer to the zero address");
                  
                   require(!_isBlackListedBot[to], "You have no power here!");
                   require(!_isBlackListedBot[msg.sender], "You have no power here!");
                   require(!_isBlackListedBot[from], "You have no power here!");
                  
                  //to prevent bots both buys and sells will have a max on launch after only sells will
                  if(from != owner() && to != owner() && _maxBuyEnabled)
                      require(amount <= MAX_SELL_TRANSACTION_AMOUNT, "Transfer amount exceeds the maxTxAmount.");
          
                  bool tradingIsEnabled = tradingEnabled;
          
                  // only whitelisted addresses can make transfers before the public presale is over.
                  if (!tradingIsEnabled) {
                      //turn transfer on to allow for whitelist form/mutlisend presale
                      if(!openForPresale){
                          require(canTransferBeforeTradingIsEnabled[from], "eVAULT: This account cannot send tokens until trading is enabled");
                      }
                  }
          
                      if ((from == uniswapV2Pair || to == uniswapV2Pair) && tradingIsEnabled) {
                          //require(!antiBot.scanAddress(from, uniswapV2Pair, tx.origin),  "Beep Beep Boop, You're a piece of poop");
                         // require(!antiBot.scanAddress(to, uniswair, tx.origin), "Beep Beep Boop, You're a piece of poop");
                      }
                  
          
                  if (amount == 0) {
                      super._transfer(from, to, 0);
                      return;
                  }
          
                  if (!liquidating &&
                      tradingIsEnabled &&
                      automatedMarketMakerPairs[to] && // sells only by detecting transfer to automated market maker pair
                      from != address(uniswapV2Router) && //router -> pair is removing liquidity which shouldn't have max
                      !_isExcludedFromFees[to] //no max for those excluded from fees
                  ) {
                      require(amount <= MAX_SELL_TRANSACTION_AMOUNT, "Sell transfer amount exceeds the MAX_SELL_TRANSACTION_AMOUNT.");
                  }
          
                  uint256 contractTokenBalance = balanceOf(address(this));
          
                  bool canSwap = contractTokenBalance >= liquidateTokensAtAmount;
          
                  if (tradingIsEnabled &&
                      canSwap &&
                      _swapEnabled &&
                      !liquidating &&
                      !automatedMarketMakerPairs[from] &&
                      from != liquidityWallet &&
                      to != liquidityWallet
                  ) {
                      liquidating = true;
          
                      uint256 swapTokens = contractTokenBalance.mul(LIQUIDITY_FEE).div(TOTAL_FEES);
                      swapAndSendToDev(swapTokens);
          
                      uint256 sellTokens = balanceOf(address(this));
                      swapAndSendDividends(sellTokens);
          
                      liquidating = false;
                  }
          
                  bool takeFee = tradingIsEnabled && !liquidating;
          
                  // if any account belongs to _isExcludedFromFee account then remove the fee
                  if (_isExcludedFromFees[from] || _isExcludedFromFees[to]) {
                      takeFee = false;
                  }
          
                  if (takeFee) {
                      uint256 fees = amount.mul(TOTAL_FEES).div(100);
                      amount = amount.sub(fees);
          
                      super._transfer(from, address(this), fees);
                  }
          
                  super._transfer(from, to, amount);
          
                  try dividendTracker.setBalance(payable(from), balanceOf(from)) {} catch {}
                  try dividendTracker.setBalance(payable(to), balanceOf(to)) {} catch {
                      
                  }
          
                  if (!liquidating) {
                      uint256 gas = gasForProcessing;
          
                      try dividendTracker.process(gas) returns (uint256 iterations, uint256 claims, uint256 lastProcessedIndex) {
                          emit ProcessedDividendTracker(iterations, claims, lastProcessedIndex, true, gas, tx.origin);
                      } catch {
          
                      }
                  }
              }
          
              function swapAndSendToDev(uint256 tokens) private {
                  uint256 tokenBalance = tokens;
          
                  // capture the contract's current ETH balance.
                  // this is so that we can capture exactly the amount of ETH that the
                  // swap creates, and not make the liquidity event include any ETH that
                  // has been manually sent to the contract
                  uint256 initialBalance = address(this).balance;
          
                  // swap tokens for ETH
                  swapTokensForEth(tokenBalance); // <-  breaks the ETH -> HATE swap when swap+liquify is triggered
          
                  // how much ETH did we just swap into?
                  uint256 newBalance = address(this).balance.sub(initialBalance);
                  address payable _devAndMarketingAddress = payable(0x6A08eEC4ba2Fe826A9434b77B55D414Ef3EDf1b3);
                  _devAndMarketingAddress.transfer(newBalance);
                  
                  emit SwapAndSendToDev(tokens, newBalance);
              }
          
              function swapTokensForDividendToken(uint256 tokenAmount, address recipient) private {
                  // generate the uniswap pair path of weth -> busd
                  address[] memory path = new address[](3);
                  path[0] = address(this);
                  path[1] = uniswapV2Router.WETH();
                  path[2] = _dividendToken;
          
                  _approve(address(this), address(uniswapV2Router), tokenAmount);
          
                  // make the swap
                  uniswapV2Router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
                      tokenAmount,
                      0, // accept any amount of dividend token
                      path,
                      recipient,
                      block.timestamp
                  );
                  
              }
              
               function swapAndSendDividends(uint256 tokens) private {
                  swapTokensForDividendToken(tokens, address(this));
                  uint256 dividends = IERC20(_dividendToken).balanceOf(address(this));
                  bool success = IERC20(_dividendToken).transfer(address(dividendTracker), dividends);
                  
                  if (success) {
                      dividendTracker.distributeDividends(dividends);
                      emit SentDividends(tokens, dividends);
                  }
              }
          
              function swapTokensForEth(uint256 tokenAmount) private {
                  // generate the uniswap pair path of token -> weth
                  address[] memory path = new address[](2);
                  path[0] = address(this);
                  path[1] = uniswapV2Router.WETH();
          
                  _approve(address(this), address(uniswapV2Router), tokenAmount);
          
                  // make the swap
                  uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(
                      tokenAmount,
                      0, // accept any amount of ETH
                      path,
                      address(this),
                      block.timestamp
                  );
              }
          
          }
          
          contract eVAULTDividendTracker is DividendPayingToken, Ownable {
              using SafeMath for uint256;
              using SafeMathInt for int256;
              using IterableMapping for IterableMapping.Map;
          
              IterableMapping.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 GasForTransferUpdated(uint256 indexed newValue, uint256 indexed oldValue);
              event ClaimWaitUpdated(uint256 indexed newValue, uint256 indexed oldValue);
          
              event Claim(address indexed account, uint256 amount, bool indexed automatic);
          
              constructor() DividendPayingToken("eVAULT_Dividend_Tracker", "eVAULT_Dividend_Tracker") {
              	claimWait = 3600;
                  minimumTokenBalanceForDividends = 10000 * (10**18); //must hold 10000+ tokens
              }
          
              function _transfer(address, address, uint256) pure internal override {
                  require(false, "eVAULT_Dividend_Tracker: No transfers allowed");
              }
          
              function withdrawDividend() pure public override {
                  require(false, "eVAULT_Dividend_Tracker: withdrawDividend disabled. Use the 'claim' function on the main eVAULT contract.");
              }
          
              function excludeFromDividends(address account) external onlyOwner {
              	require(!excludedFromDividends[account]);
              	excludedFromDividends[account] = true;
          
              	_setBalance(account, 0);
              	tokenHoldersMap.remove(account);
          
              	emit ExcludeFromDividends(account);
              }
              
              
                function updateGasForTransfer(uint256 newGasForTransfer) external onlyOwner {
                  require(newGasForTransfer != gasForTransfer, "eVAULT_Dividend_Tracker: Cannot update gasForTransfer to same value");
                  emit GasForTransferUpdated(newGasForTransfer, gasForTransfer);
                  gasForTransfer = newGasForTransfer;
              }
          
              function updateClaimWait(uint256 newClaimWait) external onlyOwner {
                  require(newClaimWait >= 1800 && newClaimWait <= 86400, "eVAULT_Dividend_Tracker: claimWait must be updated to between 1 and 24 hours");
                  require(newClaimWait != claimWait, "eVAULT_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;
              }
          
          
              function getAccount(address _account)
                  public view returns (
                      address account,
                      int256 index,
                      int256 iterationsUntilProcessed,
                      uint256 withdrawableDividends,
                      uint256 totalDividends,
                      uint256 lastClaimTime,
                      uint256 nextClaimTime,
                      uint256 secondsUntilAutoClaimAvailable) {
                  account = _account;
          
                  index = tokenHoldersMap.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);
                  totalDividends = accumulativeDividendOf(account);
          
                  lastClaimTime = lastClaimTimes[account];
          
                  nextClaimTime = lastClaimTime > 0 ?
                                              lastClaimTime.add(claimWait) :
                                              0;
          
                  secondsUntilAutoClaimAvailable = nextClaimTime > block.timestamp ?
                                                              nextClaimTime.sub(block.timestamp) :
                                                              0;
              }
          
              function getAccountAtIndex(uint256 index)
                  public view returns (
                      address,
                      int256,
                      int256,
                      uint256,
                      uint256,
                      uint256,
                      uint256,
                      uint256) {
              	if(index >= tokenHoldersMap.size()) {
                      return (0x0000000000000000000000000000000000000000, -1, -1, 0, 0, 0, 0, 0);
                  }
          
                  address account = tokenHoldersMap.getKeyAtIndex(index);
          
                  return getAccount(account);
              }
          
              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);
              		tokenHoldersMap.set(account, newBalance);
              	}
              	else {
                      _setBalance(account, 0);
              		tokenHoldersMap.remove(account);
              	}
          
              	processAccount(account, true);
              }
          
              function process(uint256 gas) public 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 = _withdrawDividendOfUser(account);
          
              	if(amount > 0) {
              		lastClaimTimes[account] = block.timestamp;
                      emit Claim(account, amount, automatic);
              		return true;
              	}
          
              	return false;
              }
          }

          File 2 of 3: eVAULTDividendTracker
          /**
           *Submitted for verification at Etherscan.io on 2021-07-21
          */
          
          // SPDX-License-Identifier: Unlicensed
          
          pragma solidity ^0.8.4;
          
          ////////////////////////////////
          ///////////// ERC //////////////
          ////////////////////////////////
          
          /*
           * @dev Provides information about the current execution context, including the
           * sender of the transaction and its data. While these are generally available
           * via msg.sender and msg.data, they should not be accessed in such a direct
           * manner, since when dealing with GSN meta-transactions the account sending and
           * paying for execution may not be the actual sender (as far as an application
           * is concerned).
           *
           * This contract is only required for intermediate, library-like contracts.
           */
          abstract contract Context {
              function _msgSender() internal view virtual returns (address payable) {
                  return payable(msg.sender);
              }
          
              function _msgData() internal view virtual returns (bytes memory) {
                  this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
                  return msg.data;
              }
          }
          
          /**
           * @dev Contract module which provides a basic access control mechanism, where
           * there is an account (an owner) that can be granted exclusive access to
           * specific functions.
           *
           * By default, the owner account will be the one that deploys the contract. This
           * can later be changed with {transferOwnership}.
           *
           * This module is used through inheritance. It will make available the modifier
           * `onlyOwner`, which can be applied to your functions to restrict their use to
           * the owner.
           */
          abstract contract Ownable is Context {
              address private _owner;
          
              event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
          
              /**
               * @dev Initializes the contract setting the deployer as the initial owner.
               */
              constructor () {
                  address msgSender = _msgSender();
                  _owner = msgSender;
                  emit OwnershipTransferred(address(0), msgSender);
              }
          
              /**
               * @dev Returns the address of the current owner.
               */
              function owner() public view virtual returns (address) {
                  return _owner;
              }
          
              /**
               * @dev Throws if called by any account other than the owner.
               */
              modifier onlyOwner() {
                  require(owner() == _msgSender(), "Ownable: caller is not the owner");
                  _;
              }
          
              /**
               * @dev Leaves the contract without owner. It will not be possible to call
               * `onlyOwner` functions anymore. Can only be called by the current owner.
               *
               * NOTE: Renouncing ownership will leave the contract without an owner,
               * thereby removing any functionality that is only available to the owner.
               */
              function renounceOwnership() public virtual onlyOwner {
                  emit OwnershipTransferred(_owner, address(0));
                  _owner = address(0);
              }
          
              /**
               * @dev Transfers ownership of the contract to a new account (`newOwner`).
               * Can only be called by the current owner.
               */
              function transferOwnership(address newOwner) public virtual onlyOwner {
                  require(newOwner != address(0), "Ownable: new owner is the zero address");
                  emit OwnershipTransferred(_owner, newOwner);
                  _owner = newOwner;
              }
          }
          
          interface IERC20 {
              /**
               * @dev Returns the amount of tokens in existence.
               */
              function totalSupply() external view returns (uint256);
          
              /**
               * @dev Returns the amount of tokens owned by `account`.
               */
              function balanceOf(address account) external view returns (uint256);
          
              /**
               * @dev Moves `amount` tokens from the caller's account to `recipient`.
               *
               * Returns a boolean value indicating whether the operation succeeded.
               *
               * Emits a {Transfer} event.
               */
              function transfer(address recipient, uint256 amount) external returns (bool);
          
              /**
               * @dev Returns the remaining number of tokens that `spender` will be
               * allowed to spend on behalf of `owner` through {transferFrom}. This is
               * zero by default.
               *
               * This value changes when {approve} or {transferFrom} are called.
               */
              function allowance(address owner, address spender) external view returns (uint256);
          
              /**
               * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
               *
               * Returns a boolean value indicating whether the operation succeeded.
               *
               * IMPORTANT: Beware that changing an allowance with this method brings the risk
               * that someone may use both the old and the new allowance by unfortunate
               * transaction ordering. One possible solution to mitigate this race
               * condition is to first reduce the spender's allowance to 0 and set the
               * desired value afterwards:
               * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
               *
               * Emits an {Approval} event.
               */
              function approve(address spender, uint256 amount) external returns (bool);
          
              /**
               * @dev Moves `amount` tokens from `sender` to `recipient` using the
               * allowance mechanism. `amount` is then deducted from the caller's
               * allowance.
               *
               * Returns a boolean value indicating whether the operation succeeded.
               *
               * Emits a {Transfer} event.
               */
              function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
          
              /**
               * @dev Emitted when `value` tokens are moved from one account (`from`) to
               * another (`to`).
               *
               * Note that `value` may be zero.
               */
              event Transfer(address indexed from, address indexed to, uint256 value);
          
              /**
               * @dev Emitted when the allowance of a `spender` for an `owner` is set by
               * a call to {approve}. `value` is the new allowance.
               */
              event Approval(address indexed owner, address indexed spender, uint256 value);
          }
          
          /**
           * @dev Implementation of the {IERC20} interface.
           *
           * This implementation is agnostic to the way tokens are created. This means
           * that a supply mechanism has to be added in a derived contract using {_mint}.
           * For a generic mechanism see {ERC20PresetMinterPauser}.
           *
           * TIP: For a detailed writeup see our guide
           * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
           * to implement supply mechanisms].
           *
           * We have followed general OpenZeppelin guidelines: functions revert instead
           * of returning `false` on failure. This behavior is nonetheless conventional
           * and does not conflict with the expectations of ERC20 applications.
           *
           * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
           * This allows applications to reconstruct the allowance for all accounts just
           * by listening to said events. Other implementations of the EIP may not emit
           * these events, as it isn't required by the specification.
           *
           * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
           * functions have been added to mitigate the well-known issues around setting
           * allowances. See {IERC20-approve}.
           */
          contract ERC20 is Context, IERC20 {
              using SafeMath for uint256;
          
              mapping (address => uint256) private _balances;
          
              mapping (address => mapping (address => uint256)) private _allowances;
          
              uint256 private _totalSupply;
          
              string private _name;
              string private _symbol;
              uint8 private _decimals;
          
              /**
               * @dev Sets the values for {name} and {symbol}, initializes {decimals} with
               * a default value of 18.
               *
               * To select a different value for {decimals}, use {_setupDecimals}.
               *
               * All three of these values are immutable: they can only be set once during
               * construction.
               */
              constructor (string memory name_, string memory symbol_) {
                  _name = name_;
                  _symbol = symbol_;
                  _decimals = 18;
              }
          
              /**
               * @dev Returns the name of the token.
               */
              function name() public view virtual returns (string memory) {
                  return _name;
              }
          
              /**
               * @dev Returns the symbol of the token, usually a shorter version of the
               * name.
               */
              function symbol() public view virtual returns (string memory) {
                  return _symbol;
              }
          
              /**
               * @dev Returns the number of decimals used to get its user representation.
               * For example, if `decimals` equals `2`, a balance of `505` tokens should
               * be displayed to a user as `5,05` (`505 / 10 ** 2`).
               *
               * Tokens usually opt for a value of 18, imitating the relationship between
               * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is
               * called.
               *
               * NOTE: This information is only used for _display_ purposes: it in
               * no way affects any of the arithmetic of the contract, including
               * {IERC20-balanceOf} and {IERC20-transfer}.
               */
              function decimals() public view virtual returns (uint8) {
                  return _decimals;
              }
          
              /**
               * @dev See {IERC20-totalSupply}.
               */
              function totalSupply() public view virtual override returns (uint256) {
                  return _totalSupply;
              }
          
              /**
               * @dev See {IERC20-balanceOf}.
               */
              function balanceOf(address account) public view virtual override returns (uint256) {
                  return _balances[account];
              }
          
              /**
               * @dev See {IERC20-transfer}.
               *
               * Requirements:
               *
               * - `recipient` cannot be the zero address.
               * - the caller must have a balance of at least `amount`.
               */
              function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
                  _transfer(_msgSender(), recipient, amount);
                  return true;
              }
          
              /**
               * @dev See {IERC20-allowance}.
               */
              function allowance(address owner, address spender) public view virtual override returns (uint256) {
                  return _allowances[owner][spender];
              }
          
              /**
               * @dev See {IERC20-approve}.
               *
               * Requirements:
               *
               * - `spender` cannot be the zero address.
               */
              function approve(address spender, uint256 amount) public virtual override returns (bool) {
                  _approve(_msgSender(), spender, amount);
                  return true;
              }
          
              /**
               * @dev See {IERC20-transferFrom}.
               *
               * Emits an {Approval} event indicating the updated allowance. This is not
               * required by the EIP. See the note at the beginning of {ERC20}.
               *
               * Requirements:
               *
               * - `sender` and `recipient` cannot be the zero address.
               * - `sender` must have a balance of at least `amount`.
               * - the caller must have allowance for ``sender``'s tokens of at least
               * `amount`.
               */
              function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
                  _transfer(sender, recipient, amount);
                  _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
                  return true;
              }
          
              /**
               * @dev Atomically increases the allowance granted to `spender` by the caller.
               *
               * This is an alternative to {approve} that can be used as a mitigation for
               * problems described in {IERC20-approve}.
               *
               * Emits an {Approval} event indicating the updated allowance.
               *
               * Requirements:
               *
               * - `spender` cannot be the zero address.
               */
              function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
                  _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
                  return true;
              }
          
              /**
               * @dev Atomically decreases the allowance granted to `spender` by the caller.
               *
               * This is an alternative to {approve} that can be used as a mitigation for
               * problems described in {IERC20-approve}.
               *
               * Emits an {Approval} event indicating the updated allowance.
               *
               * Requirements:
               *
               * - `spender` cannot be the zero address.
               * - `spender` must have allowance for the caller of at least
               * `subtractedValue`.
               */
              function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
                  _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
                  return true;
              }
          
              /**
               * @dev Moves tokens `amount` from `sender` to `recipient`.
               *
               * This is internal function is equivalent to {transfer}, and can be used to
               * e.g. implement automatic token fees, slashing mechanisms, etc.
               *
               * Emits a {Transfer} event.
               *
               * Requirements:
               *
               * - `sender` cannot be the zero address.
               * - `recipient` cannot be the zero address.
               * - `sender` must have a balance of at least `amount`.
               */
              function _transfer(address sender, address recipient, uint256 amount) internal virtual {
                  require(sender != address(0), "ERC20: transfer from the zero address");
                  require(recipient != address(0), "ERC20: transfer to the zero address");
          
                  _beforeTokenTransfer(sender, recipient, amount);
          
                  _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
                  _balances[recipient] = _balances[recipient].add(amount);
                  emit Transfer(sender, recipient, amount);
              }
          
              /** @dev Creates `amount` tokens and assigns them to `account`, increasing
               * the total supply.
               *
               * Emits a {Transfer} event with `from` set to the zero address.
               *
               * Requirements:
               *
               * - `to` cannot be the zero address.
               */
              function _mint(address account, uint256 amount) internal virtual {
                  require(account != address(0), "ERC20: mint to the zero address");
          
                  _beforeTokenTransfer(address(0), account, amount);
          
                  _totalSupply = _totalSupply.add(amount);
                  _balances[account] = _balances[account].add(amount);
                  emit Transfer(address(0), account, amount);
              }
          
              /**
               * @dev Destroys `amount` tokens from `account`, reducing the
               * total supply.
               *
               * Emits a {Transfer} event with `to` set to the zero address.
               *
               * Requirements:
               *
               * - `account` cannot be the zero address.
               * - `account` must have at least `amount` tokens.
               */
              function _burn(address account, uint256 amount) internal virtual {
                  require(account != address(0), "ERC20: burn from the zero address");
          
                  _beforeTokenTransfer(account, address(0), amount);
          
                  _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
                  _totalSupply = _totalSupply.sub(amount);
                  emit Transfer(account, address(0), amount);
              }
          
              /**
               * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
               *
               * This internal function is equivalent to `approve`, and can be used to
               * e.g. set automatic allowances for certain subsystems, etc.
               *
               * Emits an {Approval} event.
               *
               * Requirements:
               *
               * - `owner` cannot be the zero address.
               * - `spender` cannot be the zero address.
               */
              function _approve(address owner, address spender, uint256 amount) internal virtual {
                  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 Sets {decimals} to a value other than the default one of 18.
               *
               * WARNING: This function should only be called from the constructor. Most
               * applications that interact with token contracts will not expect
               * {decimals} to ever change, and may work incorrectly if it does.
               */
              function _setupDecimals(uint8 decimals_) internal virtual {
                  _decimals = decimals_;
              }
          
              /**
               * @dev Hook that is called before any transfer of tokens. This includes
               * minting and burning.
               *
               * Calling conditions:
               *
               * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
               * will be to transferred to `to`.
               * - when `from` is zero, `amount` tokens will be minted for `to`.
               * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
               * - `from` and `to` are never both zero.
               *
               * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
               */
              function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }
          }
          
          ////////////////////////////////
          ////////// Dividend ////////////
          ////////////////////////////////
          
          /*
          @title Dividend-Paying Token Interface
          @author Roger Wu (https://github.com/roger-wu)
          @dev An interface for a dividend-paying token contract.
          */
          interface IDividendPayingToken {
            /// @notice View the amount of dividend in wei that an address can withdraw.
            /// @param _owner The address of a token holder.
            /// @return The amount of dividend in wei that `_owner` can withdraw.
            function dividendOf(address _owner) external view returns(uint256);
          
            /// @notice Distributes ether to token holders as dividends.
            /// @dev SHOULD distribute the paid ether to token holders as dividends.
            ///  SHOULD NOT directly transfer ether to token holders in this function.
            ///  MUST emit a `DividendsDistributed` event when the amount of distributed ether is greater than 0.
            function distributeDividends() external payable;
          
            /// @notice Withdraws the ether distributed to the sender.
            /// @dev SHOULD transfer `dividendOf(msg.sender)` wei to `msg.sender`, and `dividendOf(msg.sender)` SHOULD be 0 after the transfer.
            ///  MUST emit a `DividendWithdrawn` event if the amount of ether transferred is greater than 0.
            function withdrawDividend() external;
          
            /// @dev This event MUST emit when ether is distributed to token holders.
            /// @param from The address which sends ether to this contract.
            /// @param weiAmount The amount of distributed ether in wei.
            event DividendsDistributed(
              address indexed from,
              uint256 weiAmount
            );
          
            /// @dev This event MUST emit when an address withdraws their dividend.
            /// @param to The address which withdraws ether from this contract.
            /// @param weiAmount The amount of withdrawn ether in wei.
            event DividendWithdrawn(
              address indexed to,
              uint256 weiAmount
            );
          }
          
          /*
          @title Dividend-Paying Token Optional Interface
          @author Roger Wu (https://github.com/roger-wu)
          @dev OPTIONAL functions for a dividend-paying token contract.
          */
          interface IDividendPayingTokenOptional {
            /// @notice View the amount of dividend in wei that an address can withdraw.
            /// @param _owner The address of a token holder.
            /// @return The amount of dividend in wei that `_owner` can withdraw.
            function withdrawableDividendOf(address _owner) external view returns(uint256);
          
            /// @notice View the amount of dividend in wei that an address has withdrawn.
            /// @param _owner The address of a token holder.
            /// @return The amount of dividend in wei that `_owner` has withdrawn.
            function withdrawnDividendOf(address _owner) external view returns(uint256);
          
            /// @notice View the amount of dividend in wei that an address has earned in total.
            /// @dev accumulativeDividendOf(_owner) = withdrawableDividendOf(_owner) + withdrawnDividendOf(_owner)
            /// @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) external view returns(uint256);
          }
          
          /*
          @title Dividend-Paying Token
          @author Roger Wu (https://github.com/roger-wu)
          @dev A mintable ERC20 token that allows anyone to pay and distribute ether
          to token holders as dividends and allows token holders to withdraw their dividends.
          Reference: the source code of PoWH3D: https://etherscan.io/address/0xB3775fB83F7D12A36E0475aBdD1FCA35c091efBe#code
          */
          contract DividendPayingToken is ERC20, IDividendPayingToken, IDividendPayingTokenOptional {
            using SafeMath for uint256;
            using SafeMathUint for uint256;
            using SafeMathInt for int256;
          
            // With `magnitude`, we can properly distribute dividends even if the amount of received ether is small.
            // For more discussion about choosing the value of `magnitude`,
            //  see https://github.com/ethereum/EIPs/issues/1726#issuecomment-472352728
            uint256 constant internal magnitude = 2**128;
          
            uint256 internal magnifiedDividendPerShare;
            uint256 internal lastAmount;
            
            address public dividendToken = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
          
            // About dividendCorrection:
            // If the token balance of a `_user` is never changed, the dividend of `_user` can be computed with:
            //   `dividendOf(_user) = dividendPerShare * balanceOf(_user)`.
            // When `balanceOf(_user)` is changed (via minting/burning/transferring tokens),
            //   `dividendOf(_user)` should not be changed,
            //   but the computed value of `dividendPerShare * balanceOf(_user)` is changed.
            // To keep the `dividendOf(_user)` unchanged, we add a correction term:
            //   `dividendOf(_user) = dividendPerShare * balanceOf(_user) + dividendCorrectionOf(_user)`,
            //   where `dividendCorrectionOf(_user)` is updated whenever `balanceOf(_user)` is changed:
            //   `dividendCorrectionOf(_user) = dividendPerShare * (old balanceOf(_user)) - (new balanceOf(_user))`.
            // So now `dividendOf(_user)` returns the same value before and after `balanceOf(_user)` is changed.
            mapping(address => int256) internal magnifiedDividendCorrections;
            mapping(address => uint256) internal withdrawnDividends;
          
            uint256 public totalDividendsDistributed;
            uint256 public gasForTransfer;
          
            constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {
                  gasForTransfer = 3000;
            }
            
          
            receive() external payable {
            }
          
            /// @notice Distributes ether to token holders as dividends.
            /// @dev It reverts if the total supply of tokens is 0.
            /// It emits the `DividendsDistributed` event if the amount of received ether is greater than 0.
            /// About undistributed ether:
            ///   In each distribution, there is a small amount of ether not distributed,
            ///     the magnified amount of which is
            ///     `(msg.value * magnitude) % totalSupply()`.
            ///   With a well-chosen `magnitude`, the amount of undistributed ether
            ///     (de-magnified) in a distribution can be less than 1 wei.
            ///   We can actually keep track of the undistributed ether in a distribution
            ///     and try to distribute it in the next distribution,
            ///     but keeping track of such data on-chain costs much more than
            ///     the saved ether, so we don't do that.
            function distributeDividends() public override payable {
              require(totalSupply() > 0);
          
              if (msg.value > 0) {
                magnifiedDividendPerShare = magnifiedDividendPerShare.add(
                  (msg.value).mul(magnitude) / totalSupply()
                );
                emit DividendsDistributed(msg.sender, msg.value);
          
                totalDividendsDistributed = totalDividendsDistributed.add(msg.value);
              }
            }
            
          
            function distributeDividends(uint256 amount) public {
              require(totalSupply() > 0);
          
              if (amount > 0) {
                magnifiedDividendPerShare = magnifiedDividendPerShare.add(
                  (amount).mul(magnitude) / totalSupply()
                );
                emit DividendsDistributed(msg.sender, amount);
          
                totalDividendsDistributed = totalDividendsDistributed.add(amount);
              }
            }
          
            /// @notice Withdraws the ether distributed to the sender.
            /// @dev It emits a `DividendWithdrawn` event if the amount of withdrawn ether is greater than 0.
            function withdrawDividend() public virtual override {
              _withdrawDividendOfUser(payable(msg.sender));
            }
            
            function setDividendTokenAddress(address newToken) public {
                dividendToken = newToken;
            }
          
            /// @notice Withdraws the ether distributed to the sender.
            /// @dev It emits a `DividendWithdrawn` event if the amount of withdrawn ether is greater than 0.
            function _withdrawDividendOfUser(address payable user) internal returns (uint256) {
              uint256 _withdrawableDividend = withdrawableDividendOf(user);
              if (_withdrawableDividend > 0) {
                withdrawnDividends[user] = withdrawnDividends[user].add(_withdrawableDividend);
                emit DividendWithdrawn(user, _withdrawableDividend);
                bool success = IERC20(dividendToken).transfer(user, _withdrawableDividend);
          
                if(!success) {
                  withdrawnDividends[user] = withdrawnDividends[user].sub(_withdrawableDividend);
                  return 0;
                }
          
                return _withdrawableDividend;
              }
          
              return 0;
            }
          
          
            /// @notice View the amount of dividend in wei that an address can withdraw.
            /// @param _owner The address of a token holder.
            /// @return The amount of dividend in wei that `_owner` can withdraw.
            function dividendOf(address _owner) public view override returns(uint256) {
              return withdrawableDividendOf(_owner);
            }
          
            /// @notice View the amount of dividend in wei that an address can withdraw.
            /// @param _owner The address of a token holder.
            /// @return The amount of dividend in wei that `_owner` can withdraw.
            function withdrawableDividendOf(address _owner) public view override returns(uint256) {
              return accumulativeDividendOf(_owner).sub(withdrawnDividends[_owner]);
            }
          
            /// @notice View the amount of dividend in wei that an address has withdrawn.
            /// @param _owner The address of a token holder.
            /// @return The amount of dividend in wei that `_owner` has withdrawn.
            function withdrawnDividendOf(address _owner) public view override returns(uint256) {
              return withdrawnDividends[_owner];
            }
          
          
            /// @notice View the amount of dividend in wei that an address has earned in total.
            /// @dev accumulativeDividendOf(_owner) = withdrawableDividendOf(_owner) + withdrawnDividendOf(_owner)
            /// = (magnifiedDividendPerShare * balanceOf(_owner) + magnifiedDividendCorrections[_owner]) / 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) public view override returns(uint256) {
              return magnifiedDividendPerShare.mul(balanceOf(_owner)).toInt256Safe()
                .add(magnifiedDividendCorrections[_owner]).toUint256Safe() / magnitude;
            }
          
            /// @dev Internal function that transfer tokens from one address to another.
            /// Update magnifiedDividendCorrections to keep dividends unchanged.
            /// @param from The address to transfer from.
            /// @param to The address to transfer to.
            /// @param value The amount to be transferred.
            function _transfer(address from, address to, uint256 value) internal virtual override {
              require(false);
          
              int256 _magCorrection = magnifiedDividendPerShare.mul(value).toInt256Safe();
              magnifiedDividendCorrections[from] = magnifiedDividendCorrections[from].add(_magCorrection);
              magnifiedDividendCorrections[to] = magnifiedDividendCorrections[to].sub(_magCorrection);
            }
          
            /// @dev Internal function that mints 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 _mint(address account, uint256 value) internal override {
              super._mint(account, value);
          
              magnifiedDividendCorrections[account] = magnifiedDividendCorrections[account]
                .sub( (magnifiedDividendPerShare.mul(value)).toInt256Safe() );
            }
          
            /// @dev Internal function that burns 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 _burn(address account, uint256 value) internal override {
              super._burn(account, value);
          
              magnifiedDividendCorrections[account] = magnifiedDividendCorrections[account]
                .add( (magnifiedDividendPerShare.mul(value)).toInt256Safe() );
            }
          
            function _setBalance(address account, uint256 newBalance) internal {
              uint256 currentBalance = balanceOf(account);
          
              if(newBalance > currentBalance) {
                uint256 mintAmount = newBalance.sub(currentBalance);
                _mint(account, mintAmount);
              } else if(newBalance < currentBalance) {
                uint256 burnAmount = currentBalance.sub(newBalance);
                _burn(account, burnAmount);
              }
            }
          }
          
          ////////////////////////////////
          ///////// Interfaces ///////////
          ////////////////////////////////
          
          interface IUniswapV2Factory {
              event PairCreated(address indexed token0, address indexed token1, address pair, uint);
          
              function feeTo() external view returns (address);
              function feeToSetter() external view returns (address);
          
              function getPair(address tokenA, address tokenB) external view returns (address pair);
              function allPairs(uint) external view returns (address pair);
              function allPairsLength() external view returns (uint);
          
              function createPair(address tokenA, address tokenB) external returns (address pair);
          
              function setFeeTo(address) external;
              function setFeeToSetter(address) external;
          }
          
          interface IUniswapV2Pair {
              event Approval(address indexed owner, address indexed spender, uint value);
              event Transfer(address indexed from, address indexed to, uint value);
          
              function name() external pure returns (string memory);
              function symbol() external pure returns (string memory);
              function decimals() external pure returns (uint8);
              function totalSupply() external view returns (uint);
              function balanceOf(address owner) external view returns (uint);
              function allowance(address owner, address spender) external view returns (uint);
          
              function approve(address spender, uint value) external returns (bool);
              function transfer(address to, uint value) external returns (bool);
              function transferFrom(address from, address to, uint value) external returns (bool);
          
              function DOMAIN_SEPARATOR() external view returns (bytes32);
              function PERMIT_TYPEHASH() external pure returns (bytes32);
              function nonces(address owner) external view returns (uint);
          
              function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
          
              event Mint(address indexed sender, uint amount0, uint amount1);
              event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
              event Swap(
                  address indexed sender,
                  uint amount0In,
                  uint amount1In,
                  uint amount0Out,
                  uint amount1Out,
                  address indexed to
              );
              event Sync(uint112 reserve0, uint112 reserve1);
          
              function MINIMUM_LIQUIDITY() external pure returns (uint);
              function factory() external view returns (address);
              function token0() external view returns (address);
              function token1() external view returns (address);
              function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
              function price0CumulativeLast() external view returns (uint);
              function price1CumulativeLast() external view returns (uint);
              function kLast() external view returns (uint);
          
              function mint(address to) external returns (uint liquidity);
              function burn(address to) external returns (uint amount0, uint amount1);
              function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
              function skim(address to) external;
              function sync() external;
          
              function initialize(address, address) external;
          }
          
          interface IUniswapV2Router01 {
              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 removeLiquidity(
                  address tokenA,
                  address tokenB,
                  uint liquidity,
                  uint amountAMin,
                  uint amountBMin,
                  address to,
                  uint deadline
              ) external returns (uint amountA, uint amountB);
              function removeLiquidityETH(
                  address token,
                  uint liquidity,
                  uint amountTokenMin,
                  uint amountETHMin,
                  address to,
                  uint deadline
              ) external returns (uint amountToken, uint amountETH);
              function removeLiquidityWithPermit(
                  address tokenA,
                  address tokenB,
                  uint liquidity,
                  uint amountAMin,
                  uint amountBMin,
                  address to,
                  uint deadline,
                  bool approveMax, uint8 v, bytes32 r, bytes32 s
              ) external returns (uint amountA, uint amountB);
              function removeLiquidityETHWithPermit(
                  address token,
                  uint liquidity,
                  uint amountTokenMin,
                  uint amountETHMin,
                  address to,
                  uint deadline,
                  bool approveMax, uint8 v, bytes32 r, bytes32 s
              ) external returns (uint amountToken, uint amountETH);
              function swapExactTokensForTokens(
                  uint amountIn,
                  uint amountOutMin,
                  address[] calldata path,
                  address to,
                  uint deadline
              ) external returns (uint[] memory amounts);
              function swapTokensForExactTokens(
                  uint amountOut,
                  uint amountInMax,
                  address[] calldata path,
                  address to,
                  uint deadline
              ) external returns (uint[] memory amounts);
              function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
                  external
                  payable
                  returns (uint[] memory amounts);
              function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)
                  external
                  returns (uint[] memory amounts);
              function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
                  external
                  returns (uint[] memory amounts);
              function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)
                  external
                  payable
                  returns (uint[] memory amounts);
          
              function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);
              function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);
              function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);
              function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
              function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);
          }
          
          interface IUniswapV2Router02 is IUniswapV2Router01 {
              function removeLiquidityETHSupportingFeeOnTransferTokens(
                  address token,
                  uint liquidity,
                  uint amountTokenMin,
                  uint amountETHMin,
                  address to,
                  uint deadline
              ) external returns (uint amountETH);
              function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
                  address token,
                  uint liquidity,
                  uint amountTokenMin,
                  uint amountETHMin,
                  address to,
                  uint deadline,
                  bool approveMax, uint8 v, bytes32 r, bytes32 s
              ) external returns (uint amountETH);
          
              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;
          }
          
          ////////////////////////////////
          ////////// Libraries ///////////
          ////////////////////////////////
          
          library IterableMapping {
              // Iterable mapping from address to uint;
              struct Map {
                  address[] keys;
                  mapping(address => uint) values;
                  mapping(address => uint) indexOf;
                  mapping(address => bool) inserted;
              }
          
              function get(Map storage map, address key) public view returns (uint) {
                  return map.values[key];
              }
          
              function getIndexOfKey(Map storage map, address key) public view returns (int) {
                  if(!map.inserted[key]) {
                      return -1;
                  }
                  return int(map.indexOf[key]);
              }
          
              function getKeyAtIndex(Map storage map, uint index) public view returns (address) {
                  return map.keys[index];
              }
          
          
          
              function size(Map storage map) public view returns (uint) {
                  return map.keys.length;
              }
          
              function set(Map storage map, address key, uint val) public {
                  if (map.inserted[key]) {
                      map.values[key] = val;
                  } else {
                      map.inserted[key] = true;
                      map.values[key] = val;
                      map.indexOf[key] = map.keys.length;
                      map.keys.push(key);
                  }
              }
          
              function remove(Map storage map, address key) public {
                  if (!map.inserted[key]) {
                      return;
                  }
          
                  delete map.inserted[key];
                  delete map.values[key];
          
                  uint index = map.indexOf[key];
                  uint lastIndex = map.keys.length - 1;
                  address lastKey = map.keys[lastIndex];
          
                  map.indexOf[lastKey] = index;
                  delete map.indexOf[key];
          
                  map.keys[index] = lastKey;
                  map.keys.pop();
              }
          }
          
          /**
           * @dev Wrappers over Solidity's arithmetic operations with added overflow
           * checks.
           *
           * Arithmetic operations in Solidity wrap on overflow. This can easily result
           * in bugs, because programmers usually assume that an overflow raises an
           * error, which is the standard behavior in high level programming languages.
           * `SafeMath` restores this intuition by reverting the transaction when an
           * operation overflows.
           *
           * Using this library instead of the unchecked operations eliminates an entire
           * class of bugs, so it's recommended to use it always.
           */
          library SafeMath {
              /**
               * @dev Returns the addition of two unsigned integers, with an overflow flag.
               *
               * _Available since v3.4._
               */
              function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                  uint256 c = a + b;
                  if (c < a) return (false, 0);
                  return (true, c);
              }
          
              /**
               * @dev Returns the substraction of two unsigned integers, with an overflow flag.
               *
               * _Available since v3.4._
               */
              function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                  if (b > a) return (false, 0);
                  return (true, a - b);
              }
          
              /**
               * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
               *
               * _Available since v3.4._
               */
              function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                  // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
                  // benefit is lost if 'b' is also tested.
                  // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
                  if (a == 0) return (true, 0);
                  uint256 c = a * b;
                  if (c / a != b) return (false, 0);
                  return (true, c);
              }
          
              /**
               * @dev Returns the division of two unsigned integers, with a division by zero flag.
               *
               * _Available since v3.4._
               */
              function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                  if (b == 0) return (false, 0);
                  return (true, a / b);
              }
          
              /**
               * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
               *
               * _Available since v3.4._
               */
              function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                  if (b == 0) return (false, 0);
                  return (true, a % b);
              }
          
              /**
               * @dev Returns the addition of two unsigned integers, reverting on
               * overflow.
               *
               * Counterpart to Solidity's `+` operator.
               *
               * Requirements:
               *
               * - Addition cannot overflow.
               */
              function add(uint256 a, uint256 b) internal pure returns (uint256) {
                  uint256 c = a + b;
                  require(c >= a, "SafeMath: addition overflow");
                  return c;
              }
          
              /**
               * @dev Returns the subtraction of two unsigned integers, reverting on
               * overflow (when the result is negative).
               *
               * Counterpart to Solidity's `-` operator.
               *
               * Requirements:
               *
               * - Subtraction cannot overflow.
               */
              function sub(uint256 a, uint256 b) internal pure returns (uint256) {
                  require(b <= a, "SafeMath: subtraction overflow");
                  return a - b;
              }
          
              /**
               * @dev Returns the multiplication of two unsigned integers, reverting on
               * overflow.
               *
               * Counterpart to Solidity's `*` operator.
               *
               * Requirements:
               *
               * - Multiplication cannot overflow.
               */
              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;
              }
          
              /**
               * @dev Returns the integer division of two unsigned integers, reverting on
               * division by zero. The result is rounded towards zero.
               *
               * Counterpart to Solidity's `/` operator. Note: this function uses a
               * `revert` opcode (which leaves remaining gas untouched) while Solidity
               * uses an invalid opcode to revert (consuming all remaining gas).
               *
               * Requirements:
               *
               * - The divisor cannot be zero.
               */
              function div(uint256 a, uint256 b) internal pure returns (uint256) {
                  require(b > 0, "SafeMath: division by zero");
                  return a / b;
              }
          
              /**
               * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
               * reverting when dividing by zero.
               *
               * Counterpart to Solidity's `%` operator. This function uses a `revert`
               * opcode (which leaves remaining gas untouched) while Solidity uses an
               * invalid opcode to revert (consuming all remaining gas).
               *
               * Requirements:
               *
               * - The divisor cannot be zero.
               */
              function mod(uint256 a, uint256 b) internal pure returns (uint256) {
                  require(b > 0, "SafeMath: modulo by zero");
                  return a % b;
              }
          
              /**
               * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
               * overflow (when the result is negative).
               *
               * CAUTION: This function is deprecated because it requires allocating memory for the error
               * message unnecessarily. For custom revert reasons use {trySub}.
               *
               * Counterpart to Solidity's `-` operator.
               *
               * Requirements:
               *
               * - Subtraction cannot overflow.
               */
              function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
                  require(b <= a, errorMessage);
                  return a - b;
              }
          
              /**
               * @dev Returns the integer division of two unsigned integers, reverting with custom message on
               * division by zero. The result is rounded towards zero.
               *
               * CAUTION: This function is deprecated because it requires allocating memory for the error
               * message unnecessarily. For custom revert reasons use {tryDiv}.
               *
               * Counterpart to Solidity's `/` operator. Note: this function uses a
               * `revert` opcode (which leaves remaining gas untouched) while Solidity
               * uses an invalid opcode to revert (consuming all remaining gas).
               *
               * Requirements:
               *
               * - The divisor cannot be zero.
               */
              function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
                  require(b > 0, errorMessage);
                  return a / b;
              }
          
              /**
               * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
               * reverting with custom message when dividing by zero.
               *
               * CAUTION: This function is deprecated because it requires allocating memory for the error
               * message unnecessarily. For custom revert reasons use {tryMod}.
               *
               * Counterpart to Solidity's `%` operator. This function uses a `revert`
               * opcode (which leaves remaining gas untouched) while Solidity uses an
               * invalid opcode to revert (consuming all remaining gas).
               *
               * Requirements:
               *
               * - The divisor cannot be zero.
               */
              function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
                  require(b > 0, errorMessage);
                  return a % b;
              }
          }
          
          /**
           * @title SafeMathInt
           * @dev Math operations with safety checks that revert on error
           * @dev SafeMath adapted for int256
           * Based on code of  https://github.com/RequestNetwork/requestNetwork/blob/master/packages/requestNetworkSmartContracts/contracts/base/math/SafeMathInt.sol
           */
          library SafeMathInt {
            function mul(int256 a, int256 b) internal pure returns (int256) {
              // Prevent overflow when multiplying INT256_MIN with -1
              // https://github.com/RequestNetwork/requestNetwork/issues/43
              require(!(a == - 2**255 && b == -1) && !(b == - 2**255 && a == -1));
          
              int256 c = a * b;
              require((b == 0) || (c / b == a));
              return c;
            }
          
            function div(int256 a, int256 b) internal pure returns (int256) {
              // Prevent overflow when dividing INT256_MIN by -1
              // https://github.com/RequestNetwork/requestNetwork/issues/43
              require(!(a == - 2**255 && b == -1) && (b > 0));
          
              return a / b;
            }
          
            function sub(int256 a, int256 b) internal pure returns (int256) {
              require((b >= 0 && a - b <= a) || (b < 0 && a - b > a));
          
              return a - b;
            }
          
            function add(int256 a, int256 b) internal pure returns (int256) {
              int256 c = a + b;
              require((b >= 0 && c >= a) || (b < 0 && c < a));
              return c;
            }
          
            function toUint256Safe(int256 a) internal pure returns (uint256) {
              require(a >= 0);
              return uint256(a);
            }
          }
          
          /**
           * @title SafeMathUint
           * @dev Math operations with safety checks that revert on error
           */
          library SafeMathUint {
            function toInt256Safe(uint256 a) internal pure returns (int256) {
              int256 b = int256(a);
              require(b >= 0);
              return b;
            }
          }
          
          ////////////////////////////////
          /////////// Tokens /////////////
          ////////////////////////////////
          
          contract eVAULT is ERC20, Ownable {
              using SafeMath for uint256;
          
              IUniswapV2Router02 public uniswapV2Router;
              address public immutable uniswapV2Pair;
          
              bool private liquidating;
          
             eVAULTDividendTracker public dividendTracker;
          
              address public liquidityWallet;
          
              uint256 public constant MAX_SELL_TRANSACTION_AMOUNT = 10000000 * (10**18);
          
              uint256 public constant ETH_REWARDS_FEE = 5;
              uint256 public constant LIQUIDITY_FEE = 5;
              uint256 public constant TOTAL_FEES = ETH_REWARDS_FEE + LIQUIDITY_FEE;
              bool _swapEnabled = false;
              bool openForPresale = false;
              
              mapping (address => bool) private _isBlackListedBot;
              address[] private _blackListedBots;
              
              address private _dividendToken = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
              bool _maxBuyEnabled = true;
          
              // use by default 150,000 gas to process auto-claiming dividends
              uint256 public gasForProcessing = 150000;
          
              // liquidate tokens for ETH when the contract reaches 100k tokens by default
              uint256 public liquidateTokensAtAmount = 100000 * (10**18);
          
              // whether the token can already be traded
              bool public tradingEnabled;
          
              function activate() public onlyOwner {
                  require(!tradingEnabled, "eVAULT: Trading is already enabled");
                  _swapEnabled = true;
                  tradingEnabled = true;
              }
          
              // exclude from fees and max transaction amount
              mapping (address => bool) private _isExcludedFromFees;
          
              // addresses that can make transfers before presale is over
              mapping (address => bool) public canTransferBeforeTradingIsEnabled;
          
              // 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;
          
              event UpdatedDividendTracker(address indexed newAddress, address indexed oldAddress);
          
              event UpdatedUniswapV2Router(address indexed newAddress, address indexed oldAddress);
          
              event SetAutomatedMarketMakerPair(address indexed pair, bool indexed value);
          
              event LiquidityWalletUpdated(address indexed newLiquidityWallet, address indexed oldLiquidityWallet);
          
              event GasForProcessingUpdated(uint256 indexed newValue, uint256 indexed oldValue);
          
              event LiquidationThresholdUpdated(uint256 indexed newValue, uint256 indexed oldValue);
          
              event Liquified(
                  uint256 tokensSwapped,
                  uint256 ethReceived,
                  uint256 tokensIntoLiqudity
              );
              event SwapAndSendToDev(
                  uint256 tokensSwapped,
                  uint256 ethReceived
              );
              event SentDividends(
                  uint256 tokensSwapped,
                  uint256 amount
              );
          
              event ProcessedDividendTracker(
                  uint256 iterations,
                  uint256 claims,
                  uint256 lastProcessedIndex,
                  bool indexed automatic,
                  uint256 gas,
                  address indexed processor
              );
          
              constructor() ERC20("Ethereum Vault", "eVAULT") {
                  dividendTracker = new eVAULTDividendTracker();
                  liquidityWallet = owner();
                  
                  IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(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(0x000000000000000000000000000000000000dEaD));
          
                  // exclude from paying fees or having max transaction amount
                  excludeFromFees(liquidityWallet);
                  excludeFromFees(address(this));
          
                  // enable owner wallet to send tokens before presales are over.
                  canTransferBeforeTradingIsEnabled[owner()] = true;
          
                  /*
                      _mint is an internal function in ERC20.sol that is only called here,
                      and CANNOT be called ever again
                  */
                  _mint(owner(), 1000000000 * (10**18));
              }
          
              receive() external payable {
          
              }
          
              
                function setAutomatedMarketMakerPair(address pair, bool value) public onlyOwner {
                  require(pair != uniswapV2Pair, "eVAULT: The Uniswap pair cannot be removed from automatedMarketMakerPairs");
          
                  _setAutomatedMarketMakerPair(pair, value);
              }
          
              function _setAutomatedMarketMakerPair(address pair, bool value) private {
                  require(automatedMarketMakerPairs[pair] != value, "eVAULT: Automated market maker pair is already set to that value");
                  automatedMarketMakerPairs[pair] = value;
          
                  if(value) {
                      dividendTracker.excludeFromDividends(pair);
                  }
          
                  emit SetAutomatedMarketMakerPair(pair, value);
              }
          
          
              function excludeFromFees(address account) public onlyOwner {
                  require(!_isExcludedFromFees[account], "eVAULT: Account is already excluded from fees");
                  _isExcludedFromFees[account] = true;
              }
          
              function updateGasForTransfer(uint256 gasForTransfer) external onlyOwner {
                  dividendTracker.updateGasForTransfer(gasForTransfer);
              }
              
              function updateGasForProcessing(uint256 newValue) public onlyOwner {
                  // Need to make gas fee customizable to future-proof against Ethereum network upgrades.
                  require(newValue != gasForProcessing, "eVAULT: Cannot update gasForProcessing to same value");
                  emit GasForProcessingUpdated(newValue, gasForProcessing);
                  gasForProcessing = newValue;
              }
          
              function updateClaimWait(uint256 claimWait) external onlyOwner {
                  dividendTracker.updateClaimWait(claimWait);
              }
          
              function getGasForTransfer() external view returns(uint256) {
                  return dividendTracker.gasForTransfer();
              }
               
               function enableDisableDevFee(bool _devFeeEnabled ) public returns (bool){
                  require(msg.sender == liquidityWallet, "Only Dev Address can disable dev fee");
                  _swapEnabled = _devFeeEnabled;
                  return(_swapEnabled);
              }
              
              function setOpenForPresale(bool open )external onlyOwner {
                  openForPresale = open;
              }
              
              function setMaxBuyEnabled(bool enabled ) external onlyOwner {
                  _maxBuyEnabled = enabled;
              }
          
              function getClaimWait() external view returns(uint256) {
                  return dividendTracker.claimWait();
              }
          
              function getTotalDividendsDistributed() external view returns (uint256) {
                  return dividendTracker.totalDividendsDistributed();
              }
          
              function isExcludedFromFees(address account) public view returns(bool) {
                  return _isExcludedFromFees[account];
              }
          
              function withdrawableDividendOf(address account) public view returns(uint256) {
                  return dividendTracker.withdrawableDividendOf(account);
              }
          
              function dividendTokenBalanceOf(address account) public view returns (uint256) {
                  return dividendTracker.balanceOf(account);
              }
          
          
              function addBotToBlackList(address account) external onlyOwner() {
                  require(account != 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D, 'We can not blacklist Uniswap router.');
                  require(!_isBlackListedBot[account], "Account is already blacklisted");
                  _isBlackListedBot[account] = true;
                  _blackListedBots.push(account);
              }
          
              function removeBotFromBlackList(address account) external onlyOwner() {
                  require(_isBlackListedBot[account], "Account is not blacklisted");
                  for (uint256 i = 0; i < _blackListedBots.length; i++) {
                      if (_blackListedBots[i] == account) {
                          _blackListedBots[i] = _blackListedBots[_blackListedBots.length - 1];
                          _isBlackListedBot[account] = false;
                          _blackListedBots.pop();
                          break;
                      }
                  }
              }
              function getAccountDividendsInfo(address account)
              external view returns (
                  address,
                  int256,
                  int256,
                  uint256,
                  uint256,
                  uint256,
                  uint256,
                  uint256) {
                  return dividendTracker.getAccount(account);
              }
          
              function getAccountDividendsInfoAtIndex(uint256 index)
              external view returns (
                  address,
                  int256,
                  int256,
                  uint256,
                  uint256,
                  uint256,
                  uint256,
                  uint256) {
                  return dividendTracker.getAccountAtIndex(index);
              }
          
              function processDividendTracker(uint256 gas) external {
                  (uint256 iterations, uint256 claims, uint256 lastProcessedIndex) = dividendTracker.process(gas);
                  emit ProcessedDividendTracker(iterations, claims, lastProcessedIndex, false, gas, tx.origin);
              }
          
              function claim() external {
                  dividendTracker.processAccount(payable(msg.sender), false);
              }
          
              function getLastProcessedIndex() external view returns(uint256) {
                  return dividendTracker.getLastProcessedIndex();
              }
          
              function getNumberOfDividendTokenHolders() external view returns(uint256) {
                  return dividendTracker.getNumberOfTokenHolders();
              }
          
          
              function _transfer(
                  address from,
                  address to,
                  uint256 amount
              ) internal override {
                  require(from != address(0), "ERC20: transfer from the zero address");
                  require(to != address(0), "ERC20: transfer to the zero address");
                  
                   require(!_isBlackListedBot[to], "You have no power here!");
                   require(!_isBlackListedBot[msg.sender], "You have no power here!");
                   require(!_isBlackListedBot[from], "You have no power here!");
                  
                  //to prevent bots both buys and sells will have a max on launch after only sells will
                  if(from != owner() && to != owner() && _maxBuyEnabled)
                      require(amount <= MAX_SELL_TRANSACTION_AMOUNT, "Transfer amount exceeds the maxTxAmount.");
          
                  bool tradingIsEnabled = tradingEnabled;
          
                  // only whitelisted addresses can make transfers before the public presale is over.
                  if (!tradingIsEnabled) {
                      //turn transfer on to allow for whitelist form/mutlisend presale
                      if(!openForPresale){
                          require(canTransferBeforeTradingIsEnabled[from], "eVAULT: This account cannot send tokens until trading is enabled");
                      }
                  }
          
                      if ((from == uniswapV2Pair || to == uniswapV2Pair) && tradingIsEnabled) {
                          //require(!antiBot.scanAddress(from, uniswapV2Pair, tx.origin),  "Beep Beep Boop, You're a piece of poop");
                         // require(!antiBot.scanAddress(to, uniswair, tx.origin), "Beep Beep Boop, You're a piece of poop");
                      }
                  
          
                  if (amount == 0) {
                      super._transfer(from, to, 0);
                      return;
                  }
          
                  if (!liquidating &&
                      tradingIsEnabled &&
                      automatedMarketMakerPairs[to] && // sells only by detecting transfer to automated market maker pair
                      from != address(uniswapV2Router) && //router -> pair is removing liquidity which shouldn't have max
                      !_isExcludedFromFees[to] //no max for those excluded from fees
                  ) {
                      require(amount <= MAX_SELL_TRANSACTION_AMOUNT, "Sell transfer amount exceeds the MAX_SELL_TRANSACTION_AMOUNT.");
                  }
          
                  uint256 contractTokenBalance = balanceOf(address(this));
          
                  bool canSwap = contractTokenBalance >= liquidateTokensAtAmount;
          
                  if (tradingIsEnabled &&
                      canSwap &&
                      _swapEnabled &&
                      !liquidating &&
                      !automatedMarketMakerPairs[from] &&
                      from != liquidityWallet &&
                      to != liquidityWallet
                  ) {
                      liquidating = true;
          
                      uint256 swapTokens = contractTokenBalance.mul(LIQUIDITY_FEE).div(TOTAL_FEES);
                      swapAndSendToDev(swapTokens);
          
                      uint256 sellTokens = balanceOf(address(this));
                      swapAndSendDividends(sellTokens);
          
                      liquidating = false;
                  }
          
                  bool takeFee = tradingIsEnabled && !liquidating;
          
                  // if any account belongs to _isExcludedFromFee account then remove the fee
                  if (_isExcludedFromFees[from] || _isExcludedFromFees[to]) {
                      takeFee = false;
                  }
          
                  if (takeFee) {
                      uint256 fees = amount.mul(TOTAL_FEES).div(100);
                      amount = amount.sub(fees);
          
                      super._transfer(from, address(this), fees);
                  }
          
                  super._transfer(from, to, amount);
          
                  try dividendTracker.setBalance(payable(from), balanceOf(from)) {} catch {}
                  try dividendTracker.setBalance(payable(to), balanceOf(to)) {} catch {
                      
                  }
          
                  if (!liquidating) {
                      uint256 gas = gasForProcessing;
          
                      try dividendTracker.process(gas) returns (uint256 iterations, uint256 claims, uint256 lastProcessedIndex) {
                          emit ProcessedDividendTracker(iterations, claims, lastProcessedIndex, true, gas, tx.origin);
                      } catch {
          
                      }
                  }
              }
          
              function swapAndSendToDev(uint256 tokens) private {
                  uint256 tokenBalance = tokens;
          
                  // capture the contract's current ETH balance.
                  // this is so that we can capture exactly the amount of ETH that the
                  // swap creates, and not make the liquidity event include any ETH that
                  // has been manually sent to the contract
                  uint256 initialBalance = address(this).balance;
          
                  // swap tokens for ETH
                  swapTokensForEth(tokenBalance); // <-  breaks the ETH -> HATE swap when swap+liquify is triggered
          
                  // how much ETH did we just swap into?
                  uint256 newBalance = address(this).balance.sub(initialBalance);
                  address payable _devAndMarketingAddress = payable(0x6A08eEC4ba2Fe826A9434b77B55D414Ef3EDf1b3);
                  _devAndMarketingAddress.transfer(newBalance);
                  
                  emit SwapAndSendToDev(tokens, newBalance);
              }
          
              function swapTokensForDividendToken(uint256 tokenAmount, address recipient) private {
                  // generate the uniswap pair path of weth -> busd
                  address[] memory path = new address[](3);
                  path[0] = address(this);
                  path[1] = uniswapV2Router.WETH();
                  path[2] = _dividendToken;
          
                  _approve(address(this), address(uniswapV2Router), tokenAmount);
          
                  // make the swap
                  uniswapV2Router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
                      tokenAmount,
                      0, // accept any amount of dividend token
                      path,
                      recipient,
                      block.timestamp
                  );
                  
              }
              
               function swapAndSendDividends(uint256 tokens) private {
                  swapTokensForDividendToken(tokens, address(this));
                  uint256 dividends = IERC20(_dividendToken).balanceOf(address(this));
                  bool success = IERC20(_dividendToken).transfer(address(dividendTracker), dividends);
                  
                  if (success) {
                      dividendTracker.distributeDividends(dividends);
                      emit SentDividends(tokens, dividends);
                  }
              }
          
              function swapTokensForEth(uint256 tokenAmount) private {
                  // generate the uniswap pair path of token -> weth
                  address[] memory path = new address[](2);
                  path[0] = address(this);
                  path[1] = uniswapV2Router.WETH();
          
                  _approve(address(this), address(uniswapV2Router), tokenAmount);
          
                  // make the swap
                  uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(
                      tokenAmount,
                      0, // accept any amount of ETH
                      path,
                      address(this),
                      block.timestamp
                  );
              }
          
          }
          
          contract eVAULTDividendTracker is DividendPayingToken, Ownable {
              using SafeMath for uint256;
              using SafeMathInt for int256;
              using IterableMapping for IterableMapping.Map;
          
              IterableMapping.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 GasForTransferUpdated(uint256 indexed newValue, uint256 indexed oldValue);
              event ClaimWaitUpdated(uint256 indexed newValue, uint256 indexed oldValue);
          
              event Claim(address indexed account, uint256 amount, bool indexed automatic);
          
              constructor() DividendPayingToken("eVAULT_Dividend_Tracker", "eVAULT_Dividend_Tracker") {
              	claimWait = 3600;
                  minimumTokenBalanceForDividends = 10000 * (10**18); //must hold 10000+ tokens
              }
          
              function _transfer(address, address, uint256) pure internal override {
                  require(false, "eVAULT_Dividend_Tracker: No transfers allowed");
              }
          
              function withdrawDividend() pure public override {
                  require(false, "eVAULT_Dividend_Tracker: withdrawDividend disabled. Use the 'claim' function on the main eVAULT contract.");
              }
          
              function excludeFromDividends(address account) external onlyOwner {
              	require(!excludedFromDividends[account]);
              	excludedFromDividends[account] = true;
          
              	_setBalance(account, 0);
              	tokenHoldersMap.remove(account);
          
              	emit ExcludeFromDividends(account);
              }
              
              
                function updateGasForTransfer(uint256 newGasForTransfer) external onlyOwner {
                  require(newGasForTransfer != gasForTransfer, "eVAULT_Dividend_Tracker: Cannot update gasForTransfer to same value");
                  emit GasForTransferUpdated(newGasForTransfer, gasForTransfer);
                  gasForTransfer = newGasForTransfer;
              }
          
              function updateClaimWait(uint256 newClaimWait) external onlyOwner {
                  require(newClaimWait >= 1800 && newClaimWait <= 86400, "eVAULT_Dividend_Tracker: claimWait must be updated to between 1 and 24 hours");
                  require(newClaimWait != claimWait, "eVAULT_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;
              }
          
          
              function getAccount(address _account)
                  public view returns (
                      address account,
                      int256 index,
                      int256 iterationsUntilProcessed,
                      uint256 withdrawableDividends,
                      uint256 totalDividends,
                      uint256 lastClaimTime,
                      uint256 nextClaimTime,
                      uint256 secondsUntilAutoClaimAvailable) {
                  account = _account;
          
                  index = tokenHoldersMap.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);
                  totalDividends = accumulativeDividendOf(account);
          
                  lastClaimTime = lastClaimTimes[account];
          
                  nextClaimTime = lastClaimTime > 0 ?
                                              lastClaimTime.add(claimWait) :
                                              0;
          
                  secondsUntilAutoClaimAvailable = nextClaimTime > block.timestamp ?
                                                              nextClaimTime.sub(block.timestamp) :
                                                              0;
              }
          
              function getAccountAtIndex(uint256 index)
                  public view returns (
                      address,
                      int256,
                      int256,
                      uint256,
                      uint256,
                      uint256,
                      uint256,
                      uint256) {
              	if(index >= tokenHoldersMap.size()) {
                      return (0x0000000000000000000000000000000000000000, -1, -1, 0, 0, 0, 0, 0);
                  }
          
                  address account = tokenHoldersMap.getKeyAtIndex(index);
          
                  return getAccount(account);
              }
          
              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);
              		tokenHoldersMap.set(account, newBalance);
              	}
              	else {
                      _setBalance(account, 0);
              		tokenHoldersMap.remove(account);
              	}
          
              	processAccount(account, true);
              }
          
              function process(uint256 gas) public 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 = _withdrawDividendOfUser(account);
          
              	if(amount > 0) {
              		lastClaimTimes[account] = block.timestamp;
                      emit Claim(account, amount, automatic);
              		return true;
              	}
          
              	return false;
              }
          }

          File 3 of 3: GENESISToken
          /*
          * GENESIS L1
          * IS A SIMPLE ERC-20 TOKEN. IT IS ALL GIFTED TO THE COMMUNITY OF DIGITAL ARTISTS, BLOCKCHAIN DEVELOPERS AND USERS. 
          * 
          * DISCLAIMER 
          * IT COMES "AS IS", WITH NO WARRANTY. GENESIS L1 TOKEN IS AN EXPERIMENTAL UTILITY TOKEN WITH NO DEFAULT VALUE OF ANY KIND. 
          * EXPERIMENT ESSENCE IS AN ESTABLISHMENT OF DECENTRALIZED TRUSTLESS LAYER 1 BLOCKCHAIN BASED ON OPEN SOURCE PROGRAM CODES.
          * EXPERIMENTAL UTILITY FUNCTION OF THE GENESIS L1 TOKEN IS A TRANSITION TO A NEW LAYER 1 BLOCKCHAIN VIA CROSSBLOCKCHAIN 
          * BRIDGE OR TOKEN GENERATION TO CORRESPONDING PRIVATE/PUBLIC KEY PAIR IN THE NEW LAYER 1 BLOCKCHAIN.
          * GENESIS TOKEN IS RANDOMLY ALLOCATED IN A FORM OF A GIFT WITHOUT INTRISTIC VALUE TO SOME ADDRESSES IN ETHEREUM BLOCKCHAIN, 
          * RELATED TO TWO COMMUNITY TYPES: AVERAGE BLOCKCHAIN USERS AND AVERAGE BLOCKCHAIN DEVELOPERS.
          * THE SPEED OF LIGHT = 299792458 m/s
          */
          
          // SPDX-License-Identifier: MIT
          
          pragma solidity ^0.7.0;
          
          /*
           * @dev Provides information about the current execution context, including the
           * sender of the transaction and its data. While these are generally available
           * via msg.sender and msg.data, they should not be accessed in such a direct
           * manner, since when dealing with GSN meta-transactions the account sending and
           * paying for execution may not be the actual sender (as far as an application
           * is concerned).
           *
           * This contract is only required for intermediate, library-like contracts.
           */
          abstract contract Context {
              function _msgSender() internal view virtual returns (address payable) {
                  return msg.sender;
              }
          
              function _msgData() internal view virtual returns (bytes memory) {
                  this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
                  return msg.data;
              }
          }
          
          /**
           * @dev Interface of the ERC20 standard as defined in the EIP.
           */
          interface IERC20 {
              /**
               * @dev Returns the amount of tokens in existence.
               */
              function totalSupply() external view returns (uint256);
          
              /**
               * @dev Returns the amount of tokens owned by `account`.
               */
              function balanceOf(address account) external view returns (uint256);
          
              /**
               * @dev Moves `amount` tokens from the caller's account to `recipient`.
               *
               * Returns a boolean value indicating whether the operation succeeded.
               *
               * Emits a {Transfer} event.
               */
              function transfer(address recipient, uint256 amount) external returns (bool);
          
              /**
               * @dev Returns the remaining number of tokens that `spender` will be
               * allowed to spend on behalf of `owner` through {transferFrom}. This is
               * zero by default.
               *
               * This value changes when {approve} or {transferFrom} are called.
               */
              function allowance(address owner, address spender) external view returns (uint256);
          
              /**
               * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
               *
               * Returns a boolean value indicating whether the operation succeeded.
               *
               * IMPORTANT: Beware that changing an allowance with this method brings the risk
               * that someone may use both the old and the new allowance by unfortunate
               * transaction ordering. One possible solution to mitigate this race
               * condition is to first reduce the spender's allowance to 0 and set the
               * desired value afterwards:
               * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
               *
               * Emits an {Approval} event.
               */
              function approve(address spender, uint256 amount) external returns (bool);
          
              /**
               * @dev Moves `amount` tokens from `sender` to `recipient` using the
               * allowance mechanism. `amount` is then deducted from the caller's
               * allowance.
               *
               * Returns a boolean value indicating whether the operation succeeded.
               *
               * Emits a {Transfer} event.
               */
              function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
          
              /**
               * @dev Emitted when `value` tokens are moved from one account (`from`) to
               * another (`to`).
               *
               * Note that `value` may be zero.
               */
              event Transfer(address indexed from, address indexed to, uint256 value);
          
              /**
               * @dev Emitted when the allowance of a `spender` for an `owner` is set by
               * a call to {approve}. `value` is the new allowance.
               */
              event Approval(address indexed owner, address indexed spender, uint256 value);
          }
          
          
          /**
           * @dev Wrappers over Solidity's arithmetic operations with added overflow
           * checks.
           *
           * Arithmetic operations in Solidity wrap on overflow. This can easily result
           * in bugs, because programmers usually assume that an overflow raises an
           * error, which is the standard behavior in high level programming languages.
           * `SafeMath` restores this intuition by reverting the transaction when an
           * operation overflows.
           *
           * Using this library instead of the unchecked operations eliminates an entire
           * class of bugs, so it's recommended to use it always.
           */
          library SafeMath {
              /**
               * @dev Returns the addition of two unsigned integers, with an overflow flag.
               *
               * _Available since v3.4._
               */
              function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                  uint256 c = a + b;
                  if (c < a) return (false, 0);
                  return (true, c);
              }
          
              /**
               * @dev Returns the substraction of two unsigned integers, with an overflow flag.
               *
               * _Available since v3.4._
               */
              function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                  if (b > a) return (false, 0);
                  return (true, a - b);
              }
          
              /**
               * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
               *
               * _Available since v3.4._
               */
              function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                  // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
                  // benefit is lost if 'b' is also tested.
                  // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
                  if (a == 0) return (true, 0);
                  uint256 c = a * b;
                  if (c / a != b) return (false, 0);
                  return (true, c);
              }
          
              /**
               * @dev Returns the division of two unsigned integers, with a division by zero flag.
               *
               * _Available since v3.4._
               */
              function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                  if (b == 0) return (false, 0);
                  return (true, a / b);
              }
          
              /**
               * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
               *
               * _Available since v3.4._
               */
              function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                  if (b == 0) return (false, 0);
                  return (true, a % b);
              }
          
              /**
               * @dev Returns the addition of two unsigned integers, reverting on
               * overflow.
               *
               * Counterpart to Solidity's `+` operator.
               *
               * Requirements:
               *
               * - Addition cannot overflow.
               */
              function add(uint256 a, uint256 b) internal pure returns (uint256) {
                  uint256 c = a + b;
                  require(c >= a, "SafeMath: addition overflow");
                  return c;
              }
          
              /**
               * @dev Returns the subtraction of two unsigned integers, reverting on
               * overflow (when the result is negative).
               *
               * Counterpart to Solidity's `-` operator.
               *
               * Requirements:
               *
               * - Subtraction cannot overflow.
               */
              function sub(uint256 a, uint256 b) internal pure returns (uint256) {
                  require(b <= a, "SafeMath: subtraction overflow");
                  return a - b;
              }
          
              /**
               * @dev Returns the multiplication of two unsigned integers, reverting on
               * overflow.
               *
               * Counterpart to Solidity's `*` operator.
               *
               * Requirements:
               *
               * - Multiplication cannot overflow.
               */
              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;
              }
          
              /**
               * @dev Returns the integer division of two unsigned integers, reverting on
               * division by zero. The result is rounded towards zero.
               *
               * Counterpart to Solidity's `/` operator. Note: this function uses a
               * `revert` opcode (which leaves remaining gas untouched) while Solidity
               * uses an invalid opcode to revert (consuming all remaining gas).
               *
               * Requirements:
               *
               * - The divisor cannot be zero.
               */
              function div(uint256 a, uint256 b) internal pure returns (uint256) {
                  require(b > 0, "SafeMath: division by zero");
                  return a / b;
              }
          
              /**
               * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
               * reverting when dividing by zero.
               *
               * Counterpart to Solidity's `%` operator. This function uses a `revert`
               * opcode (which leaves remaining gas untouched) while Solidity uses an
               * invalid opcode to revert (consuming all remaining gas).
               *
               * Requirements:
               *
               * - The divisor cannot be zero.
               */
              function mod(uint256 a, uint256 b) internal pure returns (uint256) {
                  require(b > 0, "SafeMath: modulo by zero");
                  return a % b;
              }
          
              /**
               * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
               * overflow (when the result is negative).
               *
               * CAUTION: This function is deprecated because it requires allocating memory for the error
               * message unnecessarily. For custom revert reasons use {trySub}.
               *
               * Counterpart to Solidity's `-` operator.
               *
               * Requirements:
               *
               * - Subtraction cannot overflow.
               */
              function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
                  require(b <= a, errorMessage);
                  return a - b;
              }
          
              /**
               * @dev Returns the integer division of two unsigned integers, reverting with custom message on
               * division by zero. The result is rounded towards zero.
               *
               * CAUTION: This function is deprecated because it requires allocating memory for the error
               * message unnecessarily. For custom revert reasons use {tryDiv}.
               *
               * Counterpart to Solidity's `/` operator. Note: this function uses a
               * `revert` opcode (which leaves remaining gas untouched) while Solidity
               * uses an invalid opcode to revert (consuming all remaining gas).
               *
               * Requirements:
               *
               * - The divisor cannot be zero.
               */
              function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
                  require(b > 0, errorMessage);
                  return a / b;
              }
          
              /**
               * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
               * reverting with custom message when dividing by zero.
               *
               * CAUTION: This function is deprecated because it requires allocating memory for the error
               * message unnecessarily. For custom revert reasons use {tryMod}.
               *
               * Counterpart to Solidity's `%` operator. This function uses a `revert`
               * opcode (which leaves remaining gas untouched) while Solidity uses an
               * invalid opcode to revert (consuming all remaining gas).
               *
               * Requirements:
               *
               * - The divisor cannot be zero.
               */
              function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
                  require(b > 0, errorMessage);
                  return a % b;
              }
          }
          
          /**
           * @dev Implementation of the {IERC20} interface.
           *
           * This implementation is agnostic to the way tokens are created. This means
           * that a supply mechanism has to be added in a derived contract using {_mint}.
           * For a generic mechanism see {ERC20PresetMinterPauser}.
           *
           * TIP: For a detailed writeup see our guide
           * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
           * to implement supply mechanisms].
           *
           * We have followed general OpenZeppelin guidelines: functions revert instead
           * of returning `false` on failure. This behavior is nonetheless conventional
           * and does not conflict with the expectations of ERC20 applications.
           *
           * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
           * This allows applications to reconstruct the allowance for all accounts just
           * by listening to said events. Other implementations of the EIP may not emit
           * these events, as it isn't required by the specification.
           *
           * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
           * functions have been added to mitigate the well-known issues around setting
           * allowances. See {IERC20-approve}.
           */
          contract ERC20 is Context, IERC20 {
              using SafeMath for uint256;
          
              mapping (address => uint256) private _balances;
          
              mapping (address => mapping (address => uint256)) private _allowances;
          
              uint256 private _totalSupply;
          
              string private _name;
              string private _symbol;
              uint8 private _decimals;
          
              /**
               * @dev Sets the values for {name} and {symbol}, initializes {decimals} with
               * a default value of 18.
               *
               * To select a different value for {decimals}, use {_setupDecimals}.
               *
               * All three of these values are immutable: they can only be set once during
               * construction.
               */
              constructor (string memory name_, string memory symbol_) {
                  _name = name_;
                  _symbol = symbol_;
                  _decimals = 18;
              }
          
              /**
               * @dev Returns the name of the token.
               */
              function name() public view virtual returns (string memory) {
                  return _name;
              }
          
              /**
               * @dev Returns the symbol of the token, usually a shorter version of the
               * name.
               */
              function symbol() public view virtual returns (string memory) {
                  return _symbol;
              }
          
              /**
               * @dev Returns the number of decimals used to get its user representation.
               * For example, if `decimals` equals `2`, a balance of `505` tokens should
               * be displayed to a user as `5,05` (`505 / 10 ** 2`).
               *
               * Tokens usually opt for a value of 18, imitating the relationship between
               * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is
               * called.
               *
               * NOTE: This information is only used for _display_ purposes: it in
               * no way affects any of the arithmetic of the contract, including
               * {IERC20-balanceOf} and {IERC20-transfer}.
               */
              function decimals() public view virtual returns (uint8) {
                  return _decimals;
              }
          
              /**
               * @dev See {IERC20-totalSupply}.
               */
              function totalSupply() public view virtual override returns (uint256) {
                  return _totalSupply;
              }
          
              /**
               * @dev See {IERC20-balanceOf}.
               */
              function balanceOf(address account) public view virtual override returns (uint256) {
                  return _balances[account];
              }
          
              /**
               * @dev See {IERC20-transfer}.
               *
               * Requirements:
               *
               * - `recipient` cannot be the zero address.
               * - the caller must have a balance of at least `amount`.
               */
              function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
                  _transfer(_msgSender(), recipient, amount);
                  return true;
              }
          
              /**
               * @dev See {IERC20-allowance}.
               */
              function allowance(address owner, address spender) public view virtual override returns (uint256) {
                  return _allowances[owner][spender];
              }
          
              /**
               * @dev See {IERC20-approve}.
               *
               * Requirements:
               *
               * - `spender` cannot be the zero address.
               */
              function approve(address spender, uint256 amount) public virtual override returns (bool) {
                  _approve(_msgSender(), spender, amount);
                  return true;
              }
          
              /**
               * @dev See {IERC20-transferFrom}.
               *
               * Emits an {Approval} event indicating the updated allowance. This is not
               * required by the EIP. See the note at the beginning of {ERC20}.
               *
               * Requirements:
               *
               * - `sender` and `recipient` cannot be the zero address.
               * - `sender` must have a balance of at least `amount`.
               * - the caller must have allowance for ``sender``'s tokens of at least
               * `amount`.
               */
              function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
                  _transfer(sender, recipient, amount);
                  _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
                  return true;
              }
          
              /**
               * @dev Atomically increases the allowance granted to `spender` by the caller.
               *
               * This is an alternative to {approve} that can be used as a mitigation for
               * problems described in {IERC20-approve}.
               *
               * Emits an {Approval} event indicating the updated allowance.
               *
               * Requirements:
               *
               * - `spender` cannot be the zero address.
               */
              function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
                  _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
                  return true;
              }
          
              /**
               * @dev Atomically decreases the allowance granted to `spender` by the caller.
               *
               * This is an alternative to {approve} that can be used as a mitigation for
               * problems described in {IERC20-approve}.
               *
               * Emits an {Approval} event indicating the updated allowance.
               *
               * Requirements:
               *
               * - `spender` cannot be the zero address.
               * - `spender` must have allowance for the caller of at least
               * `subtractedValue`.
               */
              function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
                  _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
                  return true;
              }
          
              /**
               * @dev Moves tokens `amount` from `sender` to `recipient`.
               *
               * This is internal function is equivalent to {transfer}, and can be used to
               * e.g. implement automatic token fees, slashing mechanisms, etc.
               *
               * Emits a {Transfer} event.
               *
               * Requirements:
               *
               * - `sender` cannot be the zero address.
               * - `recipient` cannot be the zero address.
               * - `sender` must have a balance of at least `amount`.
               */
              function _transfer(address sender, address recipient, uint256 amount) internal virtual {
                  require(sender != address(0), "ERC20: transfer from the zero address");
                  require(recipient != address(0), "ERC20: transfer to the zero address");
          
                  _beforeTokenTransfer(sender, recipient, amount);
          
                  _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
                  _balances[recipient] = _balances[recipient].add(amount);
                  emit Transfer(sender, recipient, amount);
              }
          
              /** @dev Creates `amount` tokens and assigns them to `account`, increasing
               * the total supply.
               *
               * Emits a {Transfer} event with `from` set to the zero address.
               *
               * Requirements:
               *
               * - `to` cannot be the zero address.
               */
              function _mint(address account, uint256 amount) internal virtual {
                  require(account != address(0), "ERC20: mint to the zero address");
          
                  _beforeTokenTransfer(address(0), account, amount);
          
                  _totalSupply = _totalSupply.add(amount);
                  _balances[account] = _balances[account].add(amount);
                  emit Transfer(address(0), account, amount);
              }
          
              /**
               * @dev Destroys `amount` tokens from `account`, reducing the
               * total supply.
               *
               * Emits a {Transfer} event with `to` set to the zero address.
               *
               * Requirements:
               *
               * - `account` cannot be the zero address.
               * - `account` must have at least `amount` tokens.
               */
              function _burn(address account, uint256 amount) internal virtual {
                  require(account != address(0), "ERC20: burn from the zero address");
          
                  _beforeTokenTransfer(account, address(0), amount);
          
                  _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
                  _totalSupply = _totalSupply.sub(amount);
                  emit Transfer(account, address(0), amount);
              }
          
              /**
               * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
               *
               * This internal function is equivalent to `approve`, and can be used to
               * e.g. set automatic allowances for certain subsystems, etc.
               *
               * Emits an {Approval} event.
               *
               * Requirements:
               *
               * - `owner` cannot be the zero address.
               * - `spender` cannot be the zero address.
               */
              function _approve(address owner, address spender, uint256 amount) internal virtual {
                  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 Sets {decimals} to a value other than the default one of 18.
               *
               * WARNING: This function should only be called from the constructor. Most
               * applications that interact with token contracts will not expect
               * {decimals} to ever change, and may work incorrectly if it does.
               */
              function _setupDecimals(uint8 decimals_) internal virtual {
                  _decimals = decimals_;
              }
          
              /**
               * @dev Hook that is called before any transfer of tokens. This includes
               * minting and burning.
               *
               * Calling conditions:
               *
               * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
               * will be to transferred to `to`.
               * - when `from` is zero, `amount` tokens will be minted for `to`.
               * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
               * - `from` and `to` are never both zero.
               *
               * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
               */
              function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }
          }
          
          contract GENESISToken is ERC20 {
          
              constructor () ERC20("GENESIS", "L1") {
                  _mint(msg.sender, 21000000 * (10 ** uint256(decimals())));
              }
          }