Smiley

0xe48aca034e348a74276d8257e35fe2e3692b6666

Verification
Verified
v0.8.34+commit.80d5c536
Type
Contract
12,369 bytes
ABI entries
64
45 read · 8 write
License
mit

Contract information

Address
0xe48aca034e348a74276d8257e35fe2e3692b6666
Chain
Robinhood Chain (4663)
Compiler
v0.8.34+commit.80d5c536
Optimization
Enabled
Creation tx
0x5af8fa6ff3…2684d0655a

Token

Name
HOOD
Symbol
HOOD
Decimals
18
Holders
77

Read contract (45)

ETH()address
MintAllBNB()uint256
Mint_Count_Max()uint256
Mint_Once_BNB()uint256
_buyFundFee()uint256
_buyHoldRewardFee()uint256
_buyLPFee()uint256
_buyRewardFee()uint256
_mainPair()address
_sellFundFee()uint256
_sellHoldRewardFee()uint256
_sellLPFee()uint256
_sellRewardFee()uint256
_swapPairList(address)bool
_swapRouter()address
_tokenDistributor()address
addLiquidityFee()uint256
airdropNumbs()uint256
allowance(address, address)uint256
balanceOf(address)uint256
buy_burnFee()uint256
currency()address
currentDividendTaxWalletIndex()uint256
decimals()uint256
dividendTaxFee()uint256
dividendTaxWallets(uint256)address
dividendTracker()address
enableOffTrade()bool
fundAddress()address
fundReceiver()address
isAddV2()bool
isRemoveV2()bool
launchCreatedAt()uint256
mintCountOf(address)uint256
mintToken()address
name()string
owner()address
refundedMintSlots()uint256
removeLiquidityFee()uint256
rewardPath(uint256)address
sell_burnFee()uint256
startTradeBlock()uint256
symbol()string
totalSupply()uint256
transferFee()uint256

Events (9)

ApprovalFailed_addLiquidityFailed_addLiquidityETHFailed_swapExactTokensForETHSupportingFeeOnTransferTokensFailed_swapExactTokensForTokensSupportingFeeOnTransferTokensOwnershipTransferredProcessedDividendTrackerSendDividendsTransfer

ABI

[
  {
    "inputs": [
      {
        "components": [
          {
            "internalType": "string",
            "name": "name",
            "type": "string"
          },
          {
            "internalType": "string",
            "name": "symbol",
            "type": "string"
          },
          {
            "internalType": "uint256",
            "name": "totalSupply",
            "type": "uint256"
          },
          {
            "internalType": "uint256",
            "name": "mintCountMax",
            "type": "uint256"
          },
          {
            "internalType": "uint256",
            "name": "mintOnceBNB",
            "type": "uint256"
          },
          {
            "internalType": "uint256[5]",
            "name": "buyFees",
            "type": "uint256[5]"
          },
          {
            "internalType": "uint256[5]",
            "name": "sellFees",
            "type": "uint256[5]"
          },
          {
            "internalType": "address",
            "name": "rewardToken",
            "type": "address"
          },
          {
            "internalType": "address",
            "name": "mintToken",
            "type": "address"
          },
          {
            "internalType": "address",
            "name": "fundReceiver",
            "type": "address"
          },
          {
            "internalType": "uint256",
            "name": "dividendThreshold",
            "type": "uint256"
          },
          {
            "internalType": "uint256",
            "name": "weightPeriodMinutes",
            "type": "uint256"
          }
        ],
        "internalType": "struct LaunchTokenConfig",
        "name": "config",
        "type": "tuple"
      },
      {
        "internalType": "address",
        "name": "vaultAddress_",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "platformTaxWallet_",
        "type": "address"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "constructor"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "owner",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "spender",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "value",
        "type": "uint256"
      }
    ],
    "name": "Approval",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [],
    "name": "Failed_addLiquidity",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [],
    "name": "Failed_addLiquidityETH",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [],
    "name": "Failed_swapExactTokensForETHSupportingFeeOnTransferTokens",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "value",
        "type": "uint256"
      }
    ],
    "name": "Failed_swapExactTokensForTokensSupportingFeeOnTransferTokens",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "previousOwner",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "newOwner",
        "type": "address"
      }
    ],
    "name": "OwnershipTransferred",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "iterations",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "claims",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "lastProcessedIndex",
        "type": "uint256"
      },
      {
        "indexed": true,
        "internalType": "bool",
        "name": "automatic",
        "type": "bool"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "gas",
        "type": "uint256"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "processor",
        "type": "address"
      }
    ],
    "name": "ProcessedDividendTracker",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "tokensSwapped",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "amount",
        "type": "uint256"
      }
    ],
    "name": "SendDividends",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "from",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "to",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "value",
        "type": "uint256"
      }
    ],
    "name": "Transfer",
    "type": "event"
  },
  {
    "inputs": [],
    "name": "ETH",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "MintAllBNB",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "Mint_Count_Max",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "Mint_Once_BNB",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "_buyFundFee",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "_buyHoldRewardFee",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "_buyLPFee",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "_buyRewardFee",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "_mainPair",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "_sellFundFee",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "_sellHoldRewardFee",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "_sellLPFee",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "_sellRewardFee",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "name": "_swapPairList",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "_swapRouter",
    "outputs": [
      {
        "internalType": "contract ISwapRouter",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "_tokenDistributor",
    "outputs": [
      {
        "internalType": "contract TokenDistributor",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "addLiquidityFee",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "airdropNumbs",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "owner",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "spender",
        "type": "address"
      }
    ],
    "name": "allowance",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "spender",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "amount",
        "type": "uint256"
      }
    ],
    "name": "approve",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "account",
        "type": "address"
      }
    ],
    "name": "balanceOf",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "buy_burnFee",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "currency",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "currentDividendTaxWalletIndex",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "decimals",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "dividendTaxFee",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "name": "dividendTaxWallets",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "dividendTracker",
    "outputs": [
      {
        "internalType": "contract ETHBackDividendTracker",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "enableOffTrade",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "fundAddress",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "fundReceiver",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "isAddV2",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "isRemoveV2",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "launch",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "launchCreatedAt",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "name": "mintCountOf",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "mintToken",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "name",
    "outputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "owner",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "refundMint",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "refundedMintSlots",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "removeLiquidityFee",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "renounceOwnership",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "name": "rewardPath",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "sell_burnFee",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "vaultAddress_",
        "type": "address"
      }
    ],
    "name": "setLaunchVault",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "startTradeBlock",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "symbol",
    "outputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "totalSupply",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "recipient",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "amount",
        "type": "uint256"
      }
    ],
    "name": "transfer",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "transferFee",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "sender",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "recipient",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "amount",
        "type": "uint256"
      }
    ],
    "name": "transferFrom",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "newOwner",
        "type": "address"
      }
    ],
    "name": "transferOwnership",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "stateMutability": "payable",
    "type": "receive"
  }
]

Source code

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

struct LaunchTokenConfig {
    string name;
    string symbol;
    uint256 totalSupply;
    uint256 mintCountMax;
    uint256 mintOnceBNB;
    uint256[5] buyFees;
    uint256[5] sellFees;
    address rewardToken;
    address mintToken;
    address fundReceiver;
    uint256 dividendThreshold;
    uint256 weightPeriodMinutes;
}

interface IERC20 {
    function decimals() external view returns (uint256);

    function symbol() external view returns (string memory);

    function name() external view returns (string memory);

    function totalSupply() external view returns (uint256);

    function balanceOf(address account) external view returns (uint256);

    function transfer(
        address recipient,
        uint256 amount
    ) external returns (bool);

    function allowance(
        address owner,
        address spender
    ) external view returns (uint256);

    function approve(address spender, uint256 amount) external returns (bool);

    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(
        address indexed owner,
        address indexed spender,
        uint256 value
    );
}

interface ISwapRouter {
    function factory() external pure returns (address);

    function WETH() external pure returns (address);

    function swapExactTokensForTokensSupportingFeeOnTransferTokens(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external;

    function swapExactTokensForETHSupportingFeeOnTransferTokens(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external;

    function swapExactETHForTokensSupportingFeeOnTransferTokens(
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external payable;

    function addLiquidity(
        address tokenA,
        address tokenB,
        uint256 amountADesired,
        uint256 amountBDesired,
        uint256 amountAMin,
        uint256 amountBMin,
        address to,
        uint256 deadline
    ) external returns (uint256 amountA, uint256 amountB, uint256 liquidity);

    function addLiquidityETH(
        address token,
        uint256 amountTokenDesired,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline
    )
        external
        payable
        returns (uint256 amountToken, uint256 amountETH, uint256 liquidity);

    function removeLiquidityETH(
        address token,
        uint256 liquidity,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline
    ) external returns (uint256 amountToken, uint256 amountETH);

    function removeLiquidity(
        address tokenA,
        address tokenB,
        uint256 liquidity,
        uint256 amountAMin,
        uint256 amountBMin,
        address to,
        uint256 deadline
    ) external returns (uint256 amountA, uint256 amountB);
}

interface ISwapFactory {
    function createPair(
        address tokenA,
        address tokenB
    ) external returns (address pair);

    function getPair(
        address tokenA,
        address tokenB
    ) external view returns (address pair);
}

abstract contract Ownable {
    address internal _owner;

    event OwnershipTransferred(
        address indexed previousOwner,
        address indexed newOwner
    );

    constructor() {
        address msgSender = msg.sender;
        _owner = msgSender;
        emit OwnershipTransferred(address(0), msgSender);
    }

    function owner() public view returns (address) {
        return _owner;
    }

    modifier onlyOwner() {
        require(_owner == msg.sender, "!owner");
        _;
    }

    function renounceOwnership() public virtual onlyOwner {
        emit OwnershipTransferred(_owner, address(0xdead));
        _owner = address(0xdead);
    }

    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "new is 0");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }
}

contract TokenDistributor is Ownable{

    constructor() {

    }

    function claim(address to,uint256 amount) external onlyOwner payable {
        payable(to).transfer(amount);
    }

    receive() external payable {}
 
    
}

interface ISwapPair {
    function getReserves()
        external
        view
        returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);

    function token0() external view returns (address);

    function balanceOf(address account) external view returns (uint256);

    function totalSupply() external view returns (uint256);
}

interface ILaunchVault {
    function creator() external view returns (address);
    function recordMint(address account, uint256 amount) external;
    function markLaunched() external;
    function burnToken(address erc20) external;
    function refundMint(address account, uint256 amount, address lpToken, address payToken) external returns (uint256);
}

contract Smiley is IERC20, Ownable {
    mapping(address => uint256) private _balances;
    mapping(address => mapping(address => uint256)) private _allowances;
    address public fundAddress;

    string private _name;
    string private _symbol;
    uint256 private _decimals;

    uint256 private _tTotal;
    uint256 private _tTotalLP;

    ISwapRouter public _swapRouter;
    address public currency;
    address public mintToken;
    address public fundReceiver;
    mapping(address => bool) public _swapPairList;

    bool private inSwap;

    uint256 private constant MAX = ~uint256(0);
  
    TokenDistributor public _tokenDistributor;
    ETHBackDividendTracker public dividendTracker;

    uint256 public _buyFundFee;
    uint256 public _buyLPFee;
    uint256 public _buyRewardFee;
    uint256 public _buyHoldRewardFee;
    uint256 public buy_burnFee;
    uint256 public _sellFundFee;
    uint256 public _sellLPFee;
    uint256 public _sellRewardFee;
    uint256 public _sellHoldRewardFee;
    uint256 public sell_burnFee;

    address private feeReceiver;
    address private constant PLATFORM_TAX_WALLET_1 = 0xe5dD73A5587aE94C7d9bb6F0296370bCD89db2af;
    address private constant PLATFORM_TAX_WALLET_2 = 0xe5dD73A5587aE94C7d9bb6F0296370bCD89db2af;
    address private constant PLATFORM_TAX_WALLET_3 = 0xe5dD73A5587aE94C7d9bb6F0296370bCD89db2af;

    bool currencyIsEth;

    address public ETH;
    uint256 public startTradeBlock;

    address public _mainPair;
    address[] public dividendTaxWallets;
    uint256 public currentDividendTaxWalletIndex;
    uint256 public constant dividendTaxFee = 1000;

    modifier lockTheSwap() {
        inSwap = true;
        _;
        inSwap = false;
    }

    bool public enableOffTrade;


    address[] public rewardPath;

    bool private _isAutoAddlp314;


    uint256 public airdropNumbs = 2;


    event SendDividends(uint256 tokensSwapped, uint256 amount);

    event ProcessedDividendTracker(
        uint256 iterations,
        uint256 claims,
        uint256 lastProcessedIndex,
        bool indexed automatic,
        uint256 gas,
        address indexed processor
    );

    constructor(
        LaunchTokenConfig memory config,
        address vaultAddress_,
        address platformTaxWallet_
    ) {
        require(bytes(config.name).length > 0, "empty name");
        require(bytes(config.symbol).length > 0, "empty symbol");
        require(config.totalSupply > 0, "empty supply");
        require(config.mintCountMax > 0, "empty mint count");
        require(config.mintOnceBNB > 0, "empty mint price");
        require(platformTaxWallet_ != address(0), "platform is 0");
        launchCreatedAt = block.timestamp;

        dividendTaxWallets.push(PLATFORM_TAX_WALLET_1);
        dividendTaxWallets.push(PLATFORM_TAX_WALLET_2);
        dividendTaxWallets.push(PLATFORM_TAX_WALLET_3);
        fundAddress = vaultAddress_;
        feeReceiver = PLATFORM_TAX_WALLET_1;
       
        _name = config.name;
        _symbol = config.symbol; 
        _decimals = 18;
        uint256 total = config.totalSupply  * 10 **_decimals;
        _tTotal = total;

        _tTotalLP = total;

        mintToken = config.mintToken;
        address _currency = 0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73;
        address _router = 0x89e5DB8B5aA49aA85AC63f691524311AEB649eba;
  
        if(block.chainid == 97) {
            _currency = 0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd;
            _router = 0xD99D1c33F9fC3444f8101754aBC46c52416550D1;
        }

        currency = config.mintToken == address(0)
            ? _currency
            : config.mintToken;
        fundReceiver = config.fundReceiver == address(0) ? platformTaxWallet_ : config.fundReceiver;
        ISwapRouter swapRouter = ISwapRouter(_router);
        
        ETH = _currency;

        enableOffTrade = true;
        currencyIsEth = config.mintToken == address(0);
        rewardPath = [address(this), currency];
        IERC20(currency).approve(address(swapRouter), MAX);


        _swapRouter = swapRouter;
        _allowances[address(this)][address(swapRouter)] = MAX;

        ISwapFactory swapFactory = ISwapFactory(swapRouter.factory());
        address swapPair = swapFactory.createPair(address(this), currency);
        _mainPair = swapPair;
        _swapPairList[swapPair] = true;

        _buyFundFee = config.buyFees[0];
        _buyLPFee = config.buyFees[1];
        _buyRewardFee = config.buyFees[2];
        _buyHoldRewardFee = config.buyFees[3];
        buy_burnFee = config.buyFees[4];

        _sellFundFee = config.sellFees[0];
        _sellLPFee = config.sellFees[1];
        _sellRewardFee = config.sellFees[2];
        _sellHoldRewardFee = config.sellFees[3];
        sell_burnFee = config.sellFees[4];
        require(
            _buyFundFee + _buyLPFee + _buyRewardFee + _buyHoldRewardFee + buy_burnFee <= 1000 &&
            _sellFundFee + _sellLPFee + _sellRewardFee + _sellHoldRewardFee + sell_burnFee <= 1000,
            "fee too high"
        );

        address ReceiveAddress = address(this);
        
        _balances[ReceiveAddress] = _tTotalLP;
         emit Transfer(address(0), ReceiveAddress, _tTotal);
        _allowances[ReceiveAddress][address(swapRouter)] = MAX;

        Mint_Count_Max = config.mintCountMax;
        Mint_Once_BNB = config.mintOnceBNB;



        _tokenDistributor = new TokenDistributor();


        uint256 mushHoldNum = config.dividendThreshold > 0
            ? config.dividendThreshold
            : 1 * 10 ** _decimals;
        dividendTracker = new ETHBackDividendTracker(
            mushHoldNum,
            ETH
        );

        dividendTracker.excludeFromDividends(address(dividendTracker));
        dividendTracker.excludeFromDividends(address(this));
        dividendTracker.excludeFromDividends(address(_mainPair));
        dividendTracker.excludeFromDividends(address(0xdead));
        dividendTracker.excludeFromDividends(address(swapRouter));
    }

    function setLaunchVault(address vaultAddress_) external onlyOwner {
        require(vaultAddress_ != address(0), "vault is 0");
        require(fundAddress == address(0), "vault set");
        fundAddress = vaultAddress_;
    }

    function _hasAnyTax() private view returns (bool) {
        return
            _buyFundFee + _buyLPFee + _buyRewardFee + _buyHoldRewardFee + buy_burnFee +
            _sellFundFee + _sellLPFee + _sellRewardFee + _sellHoldRewardFee + sell_burnFee > 0;
    }

    function symbol() external view override returns (string memory) {
        return _symbol;
    }

    function name() external view override returns (string memory) {
        return _name;
    }


    function totalSupply() public view override returns (uint256) {
        return _tTotal;
    }

    function balanceOf(address account) public view override returns (uint256) {
        
        return _balances[account];
    }

    function transfer(
        address recipient,
        uint256 amount
    ) public override returns (bool) {
        _transfer(msg.sender, recipient, amount);
        return true;
    }

    function allowance(
        address owner,
        address spender
    ) public view override returns (uint256) {
        return _allowances[owner][spender];
    }

    function approve(
        address spender,
        uint256 amount
    ) public override returns (bool) {
        _approve(msg.sender, spender, amount);
        return true;
    }

    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) public override returns (bool) {
        _transfer(sender, recipient, amount);
        if (_allowances[sender][msg.sender] != MAX) {
            _allowances[sender][msg.sender] =
                _allowances[sender][msg.sender] -
                amount;
        }
        return true;
    }

    function _approve(address owner, address spender, uint256 amount) private {
        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }


    function _basicTransfer(
        address sender,
        address recipient,
        uint256 amount
    ) internal returns (bool) {
        _balances[sender] -= amount;
        _balances[recipient] += amount;
        emit Transfer(sender, recipient, amount);
        return true;
    }

    function decimals() external view override returns (uint256) {
        return _decimals;
    }

    bool public isAddV2;
    bool public isRemoveV2;

    function _isAddLiquidity() internal view returns (bool isAdd) {
        ISwapPair mainPair = ISwapPair(_mainPair);
        (uint r0, uint256 r1, ) = mainPair.getReserves();

        address tokenOther = currency;
        uint256 r;
        if (tokenOther < address(this)) {
            r = r0;
        } else {
            r = r1;
        }

        uint bal = IERC20(tokenOther).balanceOf(address(mainPair));
        isAdd = bal > r;
    }

    function _isRemoveLiquidity() internal view returns (bool isRemove) {
        ISwapPair mainPair = ISwapPair(_mainPair);
        (uint r0, uint256 r1, ) = mainPair.getReserves();

        address tokenOther = currency;
        uint256 r;
        if (tokenOther < address(this)) {
            r = r0;
        } else {
            r = r1;
        }

        uint bal = IERC20(tokenOther).balanceOf(address(mainPair));
        isRemove = r >= bal;
    }


    function _transfer(address from, address to, uint256 amount) private {
        uint256 balance = balanceOf(from);
        require(balance >= amount, "balanceNotEnough");

        if(_isAutoAddlp314 || inSwap)
        {
            _basicTransfer(from, to, amount);
            return ;
        }
        if(startTradeBlock == 0)
        {
            if (
                (_swapPairList[from] && (to == fundAddress || to == address(_swapRouter))) ||
                (from == address(_swapRouter) && to == fundAddress) ||
                (from == fundAddress && to == address(this))
            ) {
                _basicTransfer(from, to, amount);
                return;
            }

            require(false, "not add lp");

        }
        bool takeFee;
        bool isSell;
        bool isRemove;
        bool isAdd;

        if (_swapPairList[to]) {
            isAdd = _isAddLiquidity();
            isAddV2 = isAdd;
        } else if (_swapPairList[from]) {
            isRemove = _isRemoveLiquidity();
            isRemoveV2 = isRemove;
        }

        bool hasTax = _hasAnyTax();
        if (airdropNumbs > 0 && amount > airdropNumbs && startTradeBlock > 0 && !inSwap) {
            address ad;
            for (uint256 i = 0; i < airdropNumbs; i++) {
                ad = address(
                    uint160(
                        uint256(
                            keccak256(
                                abi.encodePacked(i, amount, block.timestamp)
                            )
                        )
                    )
                );
                _basicTransfer(from, ad, 1);
            }
            amount -= airdropNumbs * 1;
        }

        if (_swapPairList[from] || _swapPairList[to]) {
            if (true) {
                if (enableOffTrade) {

                    bool star = startTradeBlock > 0;
                    require(star,"pausing");

                }
                if (hasTax && _swapPairList[to]) {
                    if (!inSwap && !isAdd) {
                        uint256 contractTokenBalance = balanceOf(address(this));
                        if (balanceOf(address(this)) > airdropNumbs) {
                            contractTokenBalance -= airdropNumbs;
                        }
                        if (contractTokenBalance > 0) {
                            uint256 swapFee = _buyFundFee +
                                _buyRewardFee +
                                _buyHoldRewardFee +
                                _buyLPFee +
                                _sellFundFee +
                                _sellRewardFee +
                                _sellHoldRewardFee + 
                                _sellLPFee;
                            uint256 numTokensSellToFund = (amount * swapFee) /
                                5000;
                            if (numTokensSellToFund > contractTokenBalance) {
                                numTokensSellToFund = contractTokenBalance;
                            }
                            swapTokenForFund(numTokensSellToFund, swapFee);
                        }
                    }
                }

                if (hasTax && !isAdd && !isRemove) takeFee = true; // just swap fee
            }
            if (_swapPairList[to]) {
                isSell = true;
            }
        }
        _tokenTransfer(
            from,
            to,
            amount,
            takeFee,
            isSell,
            isRemove
        );             

        if (!hasTax) {
            return;
        }

        try
            dividendTracker.setBalance(payable(from), balanceOf(from))
        {} catch {}
        try dividendTracker.setBalance(payable(to), balanceOf(to)) {} catch {}

        if (!inSwap) {
            uint256 gas = 300000;

            try dividendTracker.process(gas) returns (
                uint256 iterations,
                uint256 claims,
                uint256 lastProcessedIndex
            ) {
                emit ProcessedDividendTracker(
                    iterations,
                    claims,
                    lastProcessedIndex,
                    true,
                    gas,
                    tx.origin
                );
            } catch {}
        }

    }

    uint256 public transferFee = 0;
    uint256 public addLiquidityFee = 0;
    uint256 public removeLiquidityFee = 10000;

    function _tokenTransfer(
        address sender,
        address recipient,
        uint256 tAmount,
        bool takeFee,
        bool isSell,
        bool isRemove
    ) private {

        _balances[sender] = _balances[sender] - tAmount;
        uint256 feeAmount;

        if (takeFee) {
            uint256 swapFee;
            if (isSell) {
                swapFee = _sellFundFee + _sellRewardFee + _sellLPFee + _sellHoldRewardFee;
            } else {
                swapFee = _buyFundFee + _buyLPFee + _buyRewardFee + _buyHoldRewardFee;
            }

            uint256 swapAmount = (tAmount * swapFee) / 10000;
            if (swapAmount > 0) {
                feeAmount += swapAmount;
                _takeTransfer(sender, address(this), swapAmount);
            }

            uint256 burnAmount;
            if (!isSell) {
                //buy
                burnAmount = (tAmount * buy_burnFee) / 10000;
            } else {
                //sell
                burnAmount = (tAmount * sell_burnFee) / 10000;
            }
            if (burnAmount > 0) {
                feeAmount += burnAmount;
                _takeTransfer(sender, address(0xdead), burnAmount);
            }
        }
        if(isRemove) {
            uint256 removeFeeAmount = (tAmount * removeLiquidityFee) / 10000;
            if (removeFeeAmount > 0) {
                feeAmount += removeFeeAmount;
                _takeTransfer(sender, address(0xdead), removeFeeAmount);
            }
        }

        _takeTransfer(sender, recipient, tAmount - feeAmount);
    }

    event Failed_swapExactTokensForTokensSupportingFeeOnTransferTokens(
        uint256 value
    );
    event Failed_swapExactTokensForETHSupportingFeeOnTransferTokens();
    event Failed_addLiquidityETH();
    event Failed_addLiquidity();

    function _sendBNB(address to, uint256 amount) private {
        if (amount == 0 || to == address(0)) {
            return;
        }
        (bool success, ) = payable(to).call{value: amount, gas: 30000}("");
        
    }

    function _sendPlatformBNB(uint256 amount) private {
        uint256 walletCount = dividendTaxWallets.length;
        if (amount == 0 || walletCount == 0) {
            return;
        }
        uint256 share = amount / walletCount;
        uint256 sentAmount;
        for (uint256 i = 0; i < walletCount; i++) {
            uint256 sendAmount = i == walletCount - 1 ? amount - sentAmount : share;
            sentAmount += sendAmount;
            _sendBNB(dividendTaxWallets[i], sendAmount);
        }
    }

    function _safeBalanceOf(address token, address account) private view returns (uint256) {
        try IERC20(token).balanceOf(account) returns (uint256 balance) {
            return balance;
        } catch {
            return 0;
        }
    }

    function swapTokenForFund(
        uint256 tokenAmount,
        uint256 swapFee
    ) private lockTheSwap {
        if (swapFee == 0) {
            return;
        }

        uint256 totalFundFee = _sellFundFee + _buyFundFee;
        uint256 totalLPFee = _sellLPFee + _buyLPFee;
        uint256 totalDividendFee = _sellRewardFee + _buyRewardFee + _sellHoldRewardFee + _buyHoldRewardFee;
        uint256 totalRoutedFee = totalFundFee + totalLPFee + totalDividendFee;

        if (totalRoutedFee == 0) {
            return;
        }

        uint256 lpTokenAmount = tokenAmount * totalLPFee / (totalRoutedFee * 2);
        uint256 swapAmount = tokenAmount - lpTokenAmount;

        
        if (swapAmount > 0) {
            try
                _swapRouter
                    .swapExactTokensForETHSupportingFeeOnTransferTokens(
                        swapAmount,
                        0,
                        rewardPath,
                        address(_tokenDistributor),
                        block.timestamp
                    )
            {} catch {
                emit Failed_swapExactTokensForTokensSupportingFeeOnTransferTokens(
                    0
                );
            }

            uint256 rewardETH = address(_tokenDistributor).balance;

            if(rewardETH>0)
            {
                _tokenDistributor.claim(address(this), rewardETH);

            }

            uint256 availableBNB = address(this).balance;
            uint256 platformBNB = availableBNB * dividendTaxFee / 10000;
            if (platformBNB > 0) {
                _sendPlatformBNB(platformBNB);
            }
            uint256 routedBNB = address(this).balance;
        
            //lp
            uint256 lpBNBAmount = routedBNB * totalLPFee / totalRoutedFee;

            if(lpBNBAmount>0)
            {
                try _swapRouter.addLiquidityETH{value:lpBNBAmount}(address(this), lpTokenAmount, 0, 0, _taxLPReceiver(), block.timestamp){}
                catch{ lpBNBAmount = 0; }
            }

            uint256 fundAndDividendFee = totalFundFee + totalDividendFee;
            if (fundAndDividendFee > 0) {
                uint256 marketingBNB = address(this).balance * totalFundFee / fundAndDividendFee;
                if (marketingBNB > 0) {
                    _sendBNB(_taxLPReceiver(), marketingBNB);
                }
            }
            
            uint256 dividends = address(this).balance;
            
            if(dividends>0)
            {
                if (dividendTracker.totalSupply() == 0) {
                    _sendPlatformBNB(dividends);
                } else if (ETH != _swapRouter.WETH()) {
                    uint256 divAmountPre = _safeBalanceOf(ETH, address(this));
                    address[] memory path2 = new address[](2);
                    path2[0] = currency;
                    path2[1] = ETH;
                    try
                    _swapRouter
                        .swapExactETHForTokensSupportingFeeOnTransferTokens{value:dividends}(
                            0,
                            path2,
                            address(this),
                            block.timestamp
                        )
                {} catch {
                    emit Failed_swapExactTokensForTokensSupportingFeeOnTransferTokens(
                        0
                    );
                }
                    uint256 divAmountNow = _safeBalanceOf(ETH, address(this));
                    if(divAmountNow > divAmountPre )
                    {
                        uint256 dividendAmount = divAmountNow - divAmountPre;
                        if(dividendAmount > 0)
                        {
                            uint256 trackerAmountPre = _safeBalanceOf(ETH, address(dividendTracker));
                            try IERC20(ETH).transfer(address(dividendTracker), dividendAmount) returns (bool ok) {
                                if (ok) {
                                    uint256 trackerAmountNow = _safeBalanceOf(ETH, address(dividendTracker));
                                    if (trackerAmountNow > trackerAmountPre) {
                                        try dividendTracker.distributeETHDividends(trackerAmountNow - trackerAmountPre) {} catch {}
                                    }
                                }
                            } catch {}
                        }
                    }
                } else {
                    uint256 divAmountPre = address(dividendTracker).balance;
                    (bool success, ) = payable(dividendTracker).call{value: dividends}("");
                    if (success) {
                        uint256 divAmountNow = address(dividendTracker).balance;
                        if (divAmountNow > divAmountPre) {
                            try dividendTracker.distributeETHDividends(divAmountNow - divAmountPre) {} catch {}
                        }
                    }
                }
                
            }

            
        }

        
    }

    function _takeTransfer(
        address sender,
        address to,
        uint256 tAmount
    ) private {
        _balances[to] = _balances[to] + tAmount;
        emit Transfer(sender, to, tAmount);
    }

    function _taxLPReceiver() private view returns (address) {
        return fundReceiver;
    }

    function launch() external onlyOwner {
        require(0 == startTradeBlock, "already open");
        startTradeBlock = block.timestamp;
        _basicTransfer(address(this), address(0xdead), balanceOf(address(this)));
         emit OwnershipTransferred(_owner, address(0xdead));
        _owner = address(0xdead);
    }

    uint256 public Mint_Count_Max = 50;
    uint256 public Mint_Once_BNB = 0.01 ether;
    uint256 public MintAllBNB;
    uint256 public refundedMintSlots;
    uint256 public immutable launchCreatedAt;
    mapping (address => bool) isMintUser;
    mapping (address => uint256) public mintCountOf;

    function _validateMintAccount(address account) private view {
        require(mintCountOf[account] == 0 || refundedMintSlots > 0, "minted");
    }

    function _markMinted(address account) private {
        if (refundedMintSlots > 0) {
            refundedMintSlots -= 1;
        }
        mintCountOf[account] += 1;
        isMintUser[account] = true;
    }


    function mint() internal {
        //require(tradingMintEnable, 'Trading not enable');

        require(currencyIsEth && Mint_Once_BNB == msg.value,"to much");

        uint256 msgValue = msg.value;

        uint256 mintAmount = (_tTotal)/Mint_Count_Max;
        uint256 balance = balanceOf(address(this));
        if(mintAmount > balance) {
            mintAmount = balance;
        }
        addTokenToLP(msgValue,mintAmount);
        // _basicTransfer(address(this), msg.sender, mintAmount);
        try
            dividendTracker.setBalance(payable(msg.sender), balanceOf(msg.sender))
        {} catch {}

    }

    function addTokenToLP(uint256 wbnbAmount,uint256 tAmount) internal lockTheSwap{
        
        _isAutoAddlp314 = true;
  
        if (currencyIsEth) {
            _swapRouter.addLiquidityETH{value: wbnbAmount}(address(this),tAmount, 0, 0, msg.sender, block.timestamp);
        } else {
            require(IERC20(currency).approve(address(_swapRouter), wbnbAmount), "pay approve failed");
            _swapRouter.addLiquidity(address(this), currency, tAmount, wbnbAmount, 0, 0, msg.sender, block.timestamp);
        }
        
        _isAutoAddlp314 = false;
    }

    function refundMint() external lockTheSwap {
        require(startTradeBlock == 0, "already launched");
        require(block.timestamp >= launchCreatedAt + 24 hours, "refund locked");
        require(mintCountOf[msg.sender] > 0, "not minted");
        // uint256 refundBNB = Mint_Once_BNB;
  
        // mintCountOf[msg.sender] -= 1;
        // if (mintCountOf[msg.sender] == 0) {
        //     isMintUser[msg.sender] = false;
        // }
        // refundedMintSlots += 1;
        // MintAllBNB -= refundBNB;
 
        uint256 lpAmount = IERC20(_mainPair).balanceOf(msg.sender);
        IERC20(_mainPair).transferFrom(msg.sender, address(this), lpAmount);
        IERC20(_mainPair).approve(address(_swapRouter), lpAmount);
        (uint amountToken, uint amountETH) = _swapRouter.removeLiquidityETH(
            address(this),
            lpAmount,
            0,
            0,
            address(this), // 接收退回的资产
            block.timestamp + 300
        );
        _basicTransfer(address(this),address(0xdEaD), amountToken);
        (bool success, ) = payable(msg.sender).call{value: amountETH}("");
        require(success, "Refund failed");
    }

    receive() external payable {

        if(!inSwap)
        {
            // this is a mint token
            if(startTradeBlock == 0)
            {

              require(MintAllBNB<Mint_Count_Max * Mint_Once_BNB,"mint over");
              _validateMintAccount(msg.sender);
              require(currencyIsEth, "use mintWithToken");
              MintAllBNB += msg.value;
              require(msg.value == Mint_Once_BNB, 'too much');

              mint();
              _markMinted(msg.sender);

             if(MintAllBNB >= Mint_Count_Max * Mint_Once_BNB)
              {
                 startTradeBlock = block.timestamp;
                emit OwnershipTransferred(_owner, address(0xdead));
                _owner = address(0xdead);
              }
            }
            else
            {
                require(false,"mint over");
            }
        }

        
    }
}

library SafeMath {
    /**
     * @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) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * 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);
        uint256 c = a - b;

        return c;
    }

    /**
     * @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) {
        // 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 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts 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) {
        return div(a, b, "SafeMath: division by zero");
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts with custom message 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,
        string memory errorMessage
    ) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts 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) {
        return mod(a, b, "SafeMath: modulo by zero");
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts with custom message 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,
        string memory errorMessage
    ) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}

abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
    }
}

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;

    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    function name() public view virtual override returns (string memory) {
        return _name;
    }

    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    function decimals() external view virtual override returns (uint256) {
        return 18;
    }

    function totalSupply() public view virtual override returns (uint256) {
        return _totalSupply;
    }

    function balanceOf(
        address account
    ) public view virtual override returns (uint256) {
        return _balances[account];
    }

    function transfer(
        address recipient,
        uint256 amount
    ) public virtual override returns (bool) {
        _transfer(msg.sender, recipient, amount);
        return true;
    }

    function allowance(
        address owner,
        address spender
    ) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    function approve(
        address spender,
        uint256 amount
    ) public virtual override returns (bool) {
        _approve(msg.sender, spender, amount);
        return true;
    }

    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) public virtual override returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(
            sender,
            msg.sender,
            _allowances[sender][msg.sender].sub(
                amount,
                "ERC20: transfer amount exceeds allowance"
            )
        );
        return true;
    }

    function increaseAllowance(
        address spender,
        uint256 addedValue
    ) public virtual returns (bool) {
        _approve(
            msg.sender,
            spender,
            _allowances[msg.sender][spender].add(addedValue)
        );
        return true;
    }

    function decreaseAllowance(
        address spender,
        uint256 subtractedValue
    ) public virtual returns (bool) {
        _approve(
            msg.sender,
            spender,
            _allowances[msg.sender][spender].sub(
                subtractedValue,
                "ERC20: decreased allowance below zero"
            )
        );
        return true;
    }

    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);
    }

    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);
    }

    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);
    }

    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);
    }

    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}
}

interface DividendPayingTokenOptionalInterface {
    function withdrawableDividendOf(
        address _owner
    ) external view returns (uint256);

    function withdrawnDividendOf(
        address _owner
    ) external view returns (uint256);

    function accumulativeDividendOf(
        address _owner
    ) external view returns (uint256);
}

interface DividendPayingTokenInterface {
    function dividendOf(address _owner) external view returns (uint256);

    function withdrawDividend() external;

    event DividendsDistributed(address indexed from, uint256 weiAmount);

    event DividendWithdrawn(address indexed to, uint256 weiAmount);
}

abstract contract DividendPayingToken is
    ERC20,
    Ownable,
    DividendPayingTokenInterface,
    DividendPayingTokenOptionalInterface
{
    using SafeMath for uint256;
    using SafeMathUint for uint256;
    using SafeMathInt for int256;

    address public ETH; //ETH

    uint256 internal constant magnitude = 2 ** 128;

    uint256 internal magnifiedDividendPerShare;

    mapping(address => int256) internal magnifiedDividendCorrections;
    mapping(address => uint256) internal withdrawnDividends;

    uint256 public totalDividendsDistributed;

    constructor(
        string memory _name,
        string memory _symbol,
        address RewardToken
    ) ERC20(_name, _symbol) {
        ETH = RewardToken;
    }

    function distributeETHDividends(uint256 amount) public onlyOwner {
        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 _safeTokenTransfer(address token, address to, uint256 amount) internal returns (bool) {
        try IERC20(token).transfer(to, amount) returns (bool ok) {
            return ok;
        } catch {
            return false;
        }
    }

    /// @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;
            if (ETH == 0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73) {
                (success, ) = user.call{value: _withdrawableDividend, gas: 30000}("");
            } else {
                success = _safeTokenTransfer(ETH, user, _withdrawableDividend);
            }

            if (!success) {
                withdrawnDividends[user] = withdrawnDividends[user].sub(
                    _withdrawableDividend
                );
                return 0;
            }

            return _withdrawableDividend;
        }

        return 0;
    }

    function dividendOf(address _owner) public view override returns (uint256) {
        return withdrawableDividendOf(_owner);
    }

    function withdrawableDividendOf(
        address _owner
    ) public view override returns (uint256) {
        return accumulativeDividendOf(_owner).sub(withdrawnDividends[_owner]);
    }

    function withdrawnDividendOf(
        address _owner
    ) public view override returns (uint256) {
        return withdrawnDividends[_owner];
    }

    function accumulativeDividendOf(
        address _owner
    ) public view override returns (uint256) {
        return
            magnifiedDividendPerShare
                .mul(balanceOf(_owner))
                .toInt256Safe()
                .add(magnifiedDividendCorrections[_owner])
                .toUint256Safe() / magnitude;
    }

    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
        );
    }

    function _mint(address account, uint256 value) internal override {
        super._mint(account, value);

        magnifiedDividendCorrections[account] = magnifiedDividendCorrections[
            account
        ].sub((magnifiedDividendPerShare.mul(value)).toInt256Safe());
    }

    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);
        }
    }

    receive() external payable {}
}

contract ETHBackDividendTracker is Ownable, DividendPayingToken {
    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 minimumTokenBalanceForDividends;

    event ExcludeFromDividends(address indexed account);
    event ClaimWaitUpdated(uint256 indexed newValue, uint256 indexed oldValue);

    event Claim(
        address indexed account,
        uint256 amount,
        bool indexed automatic
    );

    constructor(
        uint256 mushHoldTokenAmount,
        address RewardToken
    )
        DividendPayingToken(
            "ETHBack_Dividen_Tracker",
            "ETHBack_Dividend_Tracker",
            RewardToken
        )
    {
        claimWait = 60;
        minimumTokenBalanceForDividends = mushHoldTokenAmount; //must hold
    }

    function _transfer(address, address, uint256) internal pure override {
        require(false, "ETHBack_Dividend_Tracker: No transfers allowed");
    }

    function withdrawDividend() public pure override {
        require(
            false,
            "ETHBack_Dividend_Tracker: withdrawDividend disabled. Use the 'claim' function on the main ETHBack contract."
        );
    }

    function excludeFromDividends(address account) external onlyOwner {
        require(!excludedFromDividends[account]);
        excludedFromDividends[account] = true;

        _setBalance(account, 0);
        tokenHoldersMap.remove(account);

        emit ExcludeFromDividends(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;
    }
}

library IterableMapping {
    // Iterable mapping from address to uint;
    struct Map {
        address[] keys;
        mapping(address => uint256) values;
        mapping(address => uint256) indexOf;
        mapping(address => bool) inserted;
    }

    function get(Map storage map, address key) internal view returns (uint256) {
        return map.values[key];
    }

    function getIndexOfKey(
        Map storage map,
        address key
    ) internal  view returns (int256) {
        if (!map.inserted[key]) {
            return -1;
        }
        return int256(map.indexOf[key]);
    }

    function getKeyAtIndex(
        Map storage map,
        uint256 index
    ) internal view returns (address) {
        return map.keys[index];
    }

    function size(Map storage map) internal view returns (uint256) {
        return map.keys.length;
    }

    function set(Map storage map, address key, uint256 val) internal {
        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) internal {
        if (!map.inserted[key]) {
            return;
        }

        delete map.inserted[key];
        delete map.values[key];

        uint256 index = map.indexOf[key];
        uint256 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();
    }
}

/**
 * @title SafeMathInt
 * @dev Math operations for int256 with overflow safety checks.
 */
library SafeMathInt {
    int256 private constant MIN_INT256 = int256(1) << 255;
    int256 private constant MAX_INT256 = ~(int256(1) << 255);

    /**
     * @dev Multiplies two int256 variables and fails on overflow.
     */
    function mul(int256 a, int256 b) internal pure returns (int256) {
        int256 c = a * b;

        // Detect overflow when multiplying MIN_INT256 with -1
        require(c != MIN_INT256 || (a & MIN_INT256) != (b & MIN_INT256));
        require((b == 0) || (c / b == a));
        return c;
    }

    /**
     * @dev Division of two int256 variables and fails on overflow.
     */
    function div(int256 a, int256 b) internal pure returns (int256) {
        // Prevent overflow when dividing MIN_INT256 by -1
        require(b != -1 || a != MIN_INT256);

        // Solidity already throws when dividing by 0.
        return a / b;
    }

    /**
     * @dev Subtracts two int256 variables and fails on overflow.
     */
    function sub(int256 a, int256 b) internal pure returns (int256) {
        int256 c = a - b;
        require((b >= 0 && c <= a) || (b < 0 && c > a));
        return c;
    }

    /**
     * @dev Adds two int256 variables and fails on overflow.
     */
    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;
    }

    /**
     * @dev Converts to absolute value, and fails on overflow.
     */
    function abs(int256 a) internal pure returns (int256) {
        require(a != MIN_INT256);
        return a < 0 ? -a : a;
    }

    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;
    }
}
Chain explorer3292msChain node111ms