-
Notifications
You must be signed in to change notification settings - Fork 1
/
flat_contract.sol
1 lines (1 loc) · 65 KB
/
flat_contract.sol
1
{"standard_json_input": {"language": "Solidity", "sources": {"LuncxToken.sol": {"content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.15;\n\nimport \"Ownable.sol\";\nimport \"ERC20.sol\";\nimport \"ERC20Burnable.sol\";\nimport \"IUniswapV2Router02.sol\";\nimport \"IUniswapV2Factory.sol\";\nimport \"LUNCDividendTracker.sol\";\n\ncontract LuncxToken is Ownable, ERC20 {\n // Fee Percentages\n uint256 public burnFee;\n uint256 public luncFee;\n uint256 public marketingFee;\n uint256 public constant minSwap = 10_000 ether;\n // Global amounts held\n uint256 public burnAmount;\n uint256 public rewardsAmount;\n uint256 public marketingAmount;\n // Global amounts sent\n uint public marketingBnb;\n uint public lunaBurned;\n uint public lunaRewarded;\n // use by default 300,000 gas to process auto-claiming dividends\n uint256 public gasForProcessing = 300_000;\n // Constants\n uint256 public constant DIVISOR = 1_000;\n // Lock for swaps happening\n bool public swapping;\n address public marketingAddress;\n address public constant deadWallet =\n 0x000000000000000000000000000000000000dEaD;\n\n address public immutable LUNC = address(0x156ab3346823B651294766e23e6Cf87254d68962);\n address public immutable dev = address(0xdB70A0771a1d070FeDFe781f8f156b09CA3feEa6);\n\n uint256 public endAntiDump;\n\n // Router\n IUniswapV2Router02 public uniswapV2Router;\n LUNCDividendTracker public dividendToken;\n\n mapping(address => bool) public feeExcluded;\n mapping(address => bool) public blacklist;\n\n event LogEvent(string data);\n event AddedPair(address indexed _pair);\n\n event ExcludeFromFees(address indexed account, bool isExcluded);\n event ExcludeMultipleAccountsFromFees(address[] accounts, bool isExcluded);\n\n event GasForProcessingUpdated(\n uint256 indexed newValue,\n uint256 indexed oldValue\n );\n\n event UpdatedFees(\n uint256 _burn,\n uint256 _reward,\n uint256 _marketing\n );\n event UpdateDividendTracker(\n address indexed newAddress,\n address indexed oldAddress\n );\n event UpdateMarketing(address _new, address _old);\n event UpdateUniswapV2Router(\n address indexed newAddress,\n address indexed oldAddress\n );\n event ProcessedDividendTracker(\n uint256 iterations,\n uint256 claims,\n uint256 lastProcessedIndex,\n bool indexed automatic,\n uint256 gas,\n address indexed processor\n );\n\n constructor(address _marketing) ERC20(\"LUNCX\", \"LUNCX\") {\n IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(\n 0x10ED43C718714eb63d5aA57B78B54704E256024E\n );\n address _swapPair = IUniswapV2Factory(_uniswapV2Router.factory())\n .createPair(address(this), _uniswapV2Router.WETH());\n uniswapV2Router = _uniswapV2Router;\n\n\n burnFee = 30;\n luncFee = 30;\n marketingFee = 30;\n\n marketingAddress = _marketing;\n\n dividendToken = new LUNCDividendTracker();\n dividendToken.excludeFromDividends(_swapPair);\n dividendToken.excludeFromDividends(address(dividendToken));\n dividendToken.excludeFromDividends(dev);\n dividendToken.excludeFromDividends(deadWallet);\n dividendToken.excludeFromDividends(address(this));\n dividendToken.excludeFromDividends(address(0));\n dividendToken.excludeFromDividends(address(uniswapV2Router));\n\n excludeFromFees(dev, true);\n excludeFromFees(marketingAddress, true);\n excludeFromFees(address(this), true);\n _mint(dev, 100_000_000_000 ether); // 100 BILLION TOKENS TO OWNER\n transferOwnership(dev);\n }\n\n receive() external payable {}\n\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal override {\n uint256 currentBalance = balanceOf(address(this));\n bool canSwap = currentBalance >= minSwap;\n if (\n canSwap &&\n !swapping &&\n from != owner() &&\n to != owner()\n ) {\n swapping = true;\n swapRewardsAndDistribute(currentBalance);\n swapping = false;\n }\n }\n\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal override {\n try dividendToken.setBalance(from, balanceOf(from)) {} catch {}\n try dividendToken.setBalance(to, balanceOf(to)) {} catch {}\n\n if (!swapping) {\n uint256 gas = gasForProcessing;\n\n try dividendToken.process(gas) returns (\n uint256 iterations,\n uint256 claims,\n uint256 lastProcessedIndex\n ) {\n emit ProcessedDividendTracker(\n iterations,\n claims,\n lastProcessedIndex,\n true,\n gas,\n tx.origin\n );\n } catch {}\n }\n }\n\n function _transfer(\n address from,\n address to,\n uint256 amount\n ) internal override {\n require(!blacklist[from] && !blacklist[to], \"Blacklisted address\");\n if (amount == 0) {\n super._transfer(from, to, 0);\n return;\n }\n // TRY TO TAX ONLY SELLS AND BUYS THIS ALSO TAXES ADDING LIQUIDITY UNFORTUNATELY.\n // THERE'S NO WAY AROUND THIS UNLESS LIQUIDITY IS ADDED MANUALLY (NOT RECOMMENDED)\n if (!feeExcluded[from] && !swapping) {\n uint toBurn;\n uint toReward;\n uint toMarketing;\n (amount, toBurn, toReward, toMarketing) = taxAmount(amount);\n super._transfer(\n from,\n address(this),\n toBurn + toReward + toMarketing\n );\n burnAmount += toBurn;\n rewardsAmount += toReward;\n marketingAmount += toMarketing;\n }\n super._transfer(from, to, amount);\n }\n\n function taxes() external view returns(uint _tax){\n _tax = burnFee + luncFee + marketingFee;\n }\n\n function taxAmount(uint256 amount)\n private\n view\n returns (\n uint256 _newAmount,\n uint256 _burn,\n uint256 _reward,\n uint256 _marketing\n )\n {\n if(block.timestamp <= endAntiDump){\n _burn = (100 * amount) / DIVISOR;\n _reward = (200 * amount) / DIVISOR;\n _marketing = (200 * amount) / DIVISOR;\n uint256 totalFee = _burn + _reward + _marketing;\n _newAmount = amount - totalFee;\n }\n else{\n _burn = (burnFee * amount) / DIVISOR;\n _reward = (luncFee * amount) / DIVISOR;\n _marketing = (marketingFee * amount) / DIVISOR;\n uint256 totalFee = _burn + _reward + _marketing;\n _newAmount = amount - totalFee;\n }\n }\n\n //PLEASE CHANGE BACK TO PRIVATE#3\n function swapRewardsAndDistribute(uint currentBalance) internal {\n swapForEth(currentBalance);\n \n uint ethMarketing = address(this).balance * marketingAmount / (marketingAmount + burnAmount + rewardsAmount);\n \n bool txSuccess = false;\n if(ethMarketing > 0){\n (txSuccess, ) = payable(marketingAddress).call{value: ethMarketing}(\"\");\n if (txSuccess) {\n marketingAmount = 0;\n txSuccess = false;\n marketingBnb += ethMarketing;\n }\n }\n swapForLUNA();\n\n uint lunaBalance = ERC20(LUNC).balanceOf(address(this));\n uint rewardLuna = lunaBalance * rewardsAmount / (burnAmount + rewardsAmount);\n //sendToDividends( balances[0]);\n if (rewardLuna > 0) {\n txSuccess = ERC20(LUNC).transfer(address(dividendToken), rewardLuna);\n if (txSuccess) {\n dividendToken.distributeDividends(rewardLuna);\n rewardsAmount = 0;\n lunaRewarded += rewardLuna;\n txSuccess = false;\n }\n }\n \n lunaBalance -= rewardLuna;\n if(lunaBalance > 0){\n txSuccess = ERC20(LUNC).transfer(deadWallet, lunaBalance);\n if(txSuccess){\n burnAmount = 0;\n lunaBurned += lunaBalance;\n }\n }\n }\n\n //PLEASE CHANGE BACK TO PRIVATE#1\n function swapForEth(uint256 amount) private {\n address[] memory path = new address[](2);\n path[0] = address(this);\n path[1] = uniswapV2Router.WETH();\n\n _approve(address(this), address(uniswapV2Router), amount);\n\n // make the swap\n uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(\n amount,\n 0, // accept any amount of ETH\n path,\n address(this),\n block.timestamp\n );\n }\n function swapForLUNA() private {\n address[] memory path = new address[](2);\n path[0] = uniswapV2Router.WETH();\n path[1] = LUNC;\n\n // make the swap\n uniswapV2Router.swapExactETHForTokens{value: address(this).balance}(\n 0, // get all the LUNC we can\n path,\n address(this),\n block.timestamp\n );\n }\n\n //PLEASE CHANGE BACK TO PRIVATE#2\n function getPercentages(\n uint256[4] memory percentages,\n uint256 base,\n uint256 multiplier\n ) private pure returns (uint256[4] memory _finalValues) {\n for (uint8 i = 0; i < percentages.length; i++) {\n _finalValues[i] = (percentages[i] * multiplier) / base;\n }\n }\n\n function setFees(\n uint256 _burn,\n uint256 _reward,\n uint256 _marketing\n ) external onlyOwner {\n require(_burn + _reward + _marketing <= 500, \"High fees\");\n burnFee = _burn;\n luncFee = _reward;\n marketingFee = _marketing;\n emit UpdatedFees(_burn, _reward, _marketing);\n }\n\n function setMarketingWallet(address _marketingWallet)\n external\n onlyOwner\n {\n require(_marketingWallet != address(0), \"use Marketing\");\n emit UpdateMarketing(_marketingWallet, marketingAddress);\n marketingAddress = _marketingWallet;\n }\n\n function claim() external {\n dividendToken.processAccount(msg.sender, false);\n }\n\n /// @notice Updates the dividend tracker's address\n /// @param newAddress New dividend tracker address\n function updateDividendTracker(address newAddress) public onlyOwner {\n require(\n newAddress != address(dividendToken),\n \"LUNCX: The dividend tracker already has that address\"\n );\n\n LUNCDividendTracker newDividendToken = LUNCDividendTracker(\n newAddress\n );\n\n require(\n newDividendToken.owner() == address(this),\n \"LUNCX: The new dividend tracker must be owned by the deployer of the contract\"\n );\n\n newDividendToken.excludeFromDividends(address(newDividendToken));\n newDividendToken.excludeFromDividends(address(this));\n newDividendToken.excludeFromDividends(owner());\n newDividendToken.excludeFromDividends(address(uniswapV2Router));\n\n emit UpdateDividendTracker(newAddress, address(dividendToken));\n\n dividendToken = newDividendToken;\n }\n\n /// @notice Updates the uniswapV2Router's address\n /// @param newAddress New uniswapV2Router's address\n function updateUniswapV2Router(address newAddress) public onlyOwner {\n require(\n newAddress != address(uniswapV2Router),\n \"LUNCX: The router already has that address\"\n );\n emit UpdateUniswapV2Router(newAddress, address(uniswapV2Router));\n uniswapV2Router = IUniswapV2Router02(newAddress);\n address _uniswapV2Pair = IUniswapV2Factory(uniswapV2Router.factory())\n .createPair(address(this), uniswapV2Router.WETH());\n }\n\n /// @notice Excludes address from fees\n /// @param account New uniswapV2Router's address\n /// @param excluded True if excluded\n function excludeFromFees(address account, bool excluded) public onlyOwner {\n require(\n feeExcluded[account] != excluded,\n \"LUNCX: Account is already the value of 'excluded'\"\n );\n feeExcluded[account] = excluded;\n\n emit ExcludeFromFees(account, excluded);\n }\n\n /// @notice Excludes multiple accounts from fees\n /// @param accounts Array of accounts to be excluded\n /// @param excluded True if excluded\n function excludeMultipleAccountsFromFees(\n address[] calldata accounts,\n bool excluded\n ) public onlyOwner {\n for (uint256 i = 0; i < accounts.length; i++) {\n feeExcluded[accounts[i]] = excluded;\n }\n\n emit ExcludeMultipleAccountsFromFees(accounts, excluded);\n }\n\n /// @notice Includes address in the blacklist\n /// @param account Array of accounts to be excluded\n /// @param value True if excluded\n function blacklistAddress(address account, bool value) external onlyOwner {\n blacklist[account] = value;\n }\n\n /// @notice Updates gas amount for processing\n /// @param newValue New gas value\n function updateGasForProcessing(uint256 newValue) public onlyOwner {\n require(\n newValue >= 200000 && newValue <= 500000,\n \"LUNCX: gasForProcessing must be between 200,000 and 500,000\"\n );\n require(\n newValue != gasForProcessing,\n \"LUNCX: Cannot update gasForProcessing to same value\"\n );\n emit GasForProcessingUpdated(newValue, gasForProcessing);\n gasForProcessing = newValue;\n }\n\n /// @notice Allows owner to updates time to claim rewards\n /// @param claimWait New claim wait time\n function updateClaimWait(uint256 claimWait) external onlyOwner {\n dividendToken.updateClaimWait(claimWait);\n }\n\n /// @notice Checks the feeExcluded map to see if the account is excluded from fees\n /// @param account Address to check\n function isExcludedFromFees(address account) public view returns (bool) {\n return feeExcluded[account];\n }\n\n /// @notice Checks the withdrawable amount of dividends from account\n /// @param account Address to check\n function withdrawableDividendOf(address account)\n public\n view\n returns (uint256)\n {\n return dividendToken.withdrawableDividendOf(account);\n }\n\n // DIVIDEND SETTERS/GETTERS\n function dividendTokenBalanceOf(address account)\n public\n view\n returns (uint256)\n {\n return dividendToken.balanceOf(account);\n }\n\n function excludeFromDividends(address account) external onlyOwner {\n dividendToken.excludeFromDividends(account);\n }\n\n function processDividendTracker(uint256 gas) external {\n (\n uint256 iterations,\n uint256 claims,\n uint256 lastProcessedIndex\n ) = dividendToken.process(gas);\n emit ProcessedDividendTracker(\n iterations,\n claims,\n lastProcessedIndex,\n false,\n gas,\n tx.origin\n );\n }\n\n function getClaimWait() external view returns (uint256) {\n return dividendToken.claimWait();\n }\n\n function getTotalDividendsDistributed() external view returns (uint256) {\n return dividendToken.totalDividendsDistributed();\n }\n\n function getAccountDividendsInfo(address account)\n external\n view\n returns (\n address,\n int256,\n int256,\n uint256,\n uint256,\n uint256,\n uint256,\n uint256\n )\n {\n return dividendToken.getAccount(account);\n }\n\n function getAccountDividendsInfoAtIndex(uint256 index)\n external\n view\n returns (\n address,\n int256,\n int256,\n uint256,\n uint256,\n uint256,\n uint256,\n uint256\n )\n {\n return dividendToken.getAccountAtIndex(index);\n }\n\n function getLastProcessedIndex() external view returns (uint256) {\n return dividendToken.getLastProcessedIndex();\n }\n\n function getNumberOfDividendTokenHolders() external view returns (uint256) {\n return dividendToken.getNumberOfTokenHolders();\n }\n\n function startAntiDump() external onlyOwner{\n require(endAntiDump == 0, \"Already used\");\n endAntiDump = block.timestamp + 4 hours;\n emit LogEvent(\"Anti dump started\");\n }\n}"}, "Ownable.sol": {"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n"}, "Context.sol": {"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n"}, "ERC20.sol": {"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"IERC20.sol\";\nimport \"IERC20Metadata.sol\";\nimport \"Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * The default value of {decimals} is 18. To select a different value for\n * {decimals} you should overload it.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\n * overridden;\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, allowance(owner, spender) + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = allowance(owner, spender);\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `sender` to `recipient`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n }\n _balances[to] += amount;\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n _balances[account] += amount;\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n }\n _totalSupply -= amount;\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n}\n"}, "IERC20.sol": {"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n"}, "IERC20Metadata.sol": {"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n"}, "ERC20Burnable.sol": {"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Burnable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"ERC20.sol\";\nimport \"Context.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20Burnable is Context, ERC20 {\n /**\n * @dev Destroys `amount` tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) public virtual {\n _burn(_msgSender(), amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n * allowance.\n *\n * See {ERC20-_burn} and {ERC20-allowance}.\n *\n * Requirements:\n *\n * - the caller must have allowance for ``accounts``'s tokens of at least\n * `amount`.\n */\n function burnFrom(address account, uint256 amount) public virtual {\n _spendAllowance(account, _msgSender(), amount);\n _burn(account, amount);\n }\n}\n"}, "IUniswapV2Router02.sol": {"content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.15;\n\nimport \"IUniswapV2Router.sol\";\n\ninterface IUniswapV2Router02 is IUniswapV2Router01 {\n function removeLiquidityETHSupportingFeeOnTransferTokens(\n address token,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) external returns (uint256 amountETH);\n\n function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(\n address token,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountETH);\n\n function swapExactTokensForTokensSupportingFeeOnTransferTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external;\n\n function swapExactETHForTokensSupportingFeeOnTransferTokens(\n uint256 amountOutMin,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external payable;\n\n function swapExactTokensForETHSupportingFeeOnTransferTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external;\n}"}, "IUniswapV2Router.sol": {"content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.15;\n\ninterface IUniswapV2Router01 {\n function factory() external pure returns (address);\n\n function WETH() external pure returns (address);\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n );\n\n function addLiquidityETH(\n address token,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n );\n\n function removeLiquidity(\n address tokenA,\n address tokenB,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) external returns (uint256 amountA, uint256 amountB);\n\n function removeLiquidityETH(\n address token,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) external returns (uint256 amountToken, uint256 amountETH);\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB);\n\n function removeLiquidityETHWithPermit(\n address token,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH);\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external returns (uint256[] memory amounts);\n\n function swapTokensForExactTokens(\n uint256 amountOut,\n uint256 amountInMax,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external returns (uint256[] memory amounts);\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external payable returns (uint256[] memory amounts);\n\n function swapTokensForExactETH(\n uint256 amountOut,\n uint256 amountInMax,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external returns (uint256[] memory amounts);\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external returns (uint256[] memory amounts);\n\n function swapETHForExactTokens(\n uint256 amountOut,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external payable returns (uint256[] memory amounts);\n\n function quote(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) external pure returns (uint256 amountB);\n\n function getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) external pure returns (uint256 amountOut);\n\n function getAmountIn(\n uint256 amountOut,\n uint256 reserveIn,\n uint256 reserveOut\n ) external pure returns (uint256 amountIn);\n\n function getAmountsOut(uint256 amountIn, address[] calldata path)\n external\n view\n returns (uint256[] memory amounts);\n\n function getAmountsIn(uint256 amountOut, address[] calldata path)\n external\n view\n returns (uint256[] memory amounts);\n}"}, "IUniswapV2Factory.sol": {"content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.15;\n\ninterface IUniswapV2Factory {\n event PairCreated(\n address indexed token0,\n address indexed token1,\n address pair,\n uint256\n );\n\n function feeTo() external view returns (address);\n\n function feeToSetter() external view returns (address);\n\n function getPair(address tokenA, address tokenB)\n external\n view\n returns (address pair);\n\n function allPairs(uint256) external view returns (address pair);\n\n function allPairsLength() external view returns (uint256);\n\n function createPair(address tokenA, address tokenB)\n external\n returns (address pair);\n\n function setFeeTo(address) external;\n\n function setFeeToSetter(address) external;\n}"}, "LUNCDividendTracker.sol": {"content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.15;\n\nimport \"Ownable.sol\";\nimport \"DividendPayingToken.sol\";\n\nlibrary IterableMapping {\n // Iterable mapping from address to uint;\n struct Map {\n address[] keys;\n mapping(address => uint256) values;\n mapping(address => uint256) indexOf;\n mapping(address => bool) inserted;\n }\n\n function get(Map storage map, address key) public view returns (uint256) {\n return map.values[key];\n }\n\n function getIndexOfKey(Map storage map, address key)\n public\n view\n returns (int256)\n {\n if (!map.inserted[key]) {\n return -1;\n }\n return int256(map.indexOf[key]);\n }\n\n function getKeyAtIndex(Map storage map, uint256 index)\n public\n view\n returns (address)\n {\n return map.keys[index];\n }\n\n function size(Map storage map) public view returns (uint256) {\n return map.keys.length;\n }\n\n function set(\n Map storage map,\n address key,\n uint256 val\n ) public {\n if (map.inserted[key]) {\n map.values[key] = val;\n } else {\n map.inserted[key] = true;\n map.values[key] = val;\n map.indexOf[key] = map.keys.length;\n map.keys.push(key);\n }\n }\n\n function remove(Map storage map, address key) public {\n if (!map.inserted[key]) {\n return;\n }\n\n delete map.inserted[key];\n delete map.values[key];\n\n uint256 index = map.indexOf[key];\n uint256 lastIndex = map.keys.length - 1;\n address lastKey = map.keys[lastIndex];\n\n map.indexOf[lastKey] = index;\n delete map.indexOf[key];\n\n map.keys[index] = lastKey;\n map.keys.pop();\n }\n}\n\ncontract LUNCDividendTracker is Ownable, DividendPayingToken {\n using IterableMapping for IterableMapping.Map;\n\n IterableMapping.Map private tokenHoldersMap;\n uint256 public lastProcessedIndex;\n\n mapping(address => bool) public excludedFromDividends;\n\n mapping(address => uint256) public lastClaimTimes;\n\n uint256 public claimWait;\n uint256 public immutable minimumTokenBalanceForDividends;\n\n event ExcludeFromDividends(address indexed account);\n event ClaimWaitUpdated(uint256 indexed newValue, uint256 indexed oldValue);\n\n event Claim(\n address indexed account,\n uint256 amount,\n bool indexed automatic\n );\n\n constructor()\n DividendPayingToken(\"LUNAC_Dividend_Tracker\", \"LUNAC_Dividend_Tracker\")\n {\n claimWait = 3600;\n minimumTokenBalanceForDividends = 500_000 ether; //must hold tokens\n }\n\n function _transfer(\n address,\n address,\n uint256\n ) internal override {\n require(false, \"LUNAC_Dividend_Tracker: No transfers allowed\");\n }\n\n function withdrawDividend() public override {\n require(\n false,\n \"LUNAC_Dividend_Tracker: withdrawDividend disabled. Use the 'claim' function on the main DUST contract.\"\n );\n }\n\n function excludeFromDividends(address account) external onlyOwner {\n require(!excludedFromDividends[account]);\n excludedFromDividends[account] = true;\n\n _setBalance(account, 0);\n tokenHoldersMap.remove(account);\n\n emit ExcludeFromDividends(account);\n }\n\n function updateClaimWait(uint256 newClaimWait) external onlyOwner {\n require(\n newClaimWait >= 300 && newClaimWait <= 86400,\n \"LUNAC_Dividend_Tracker: claimWait must be updated to between 1 and 24 hours\"\n );\n require(\n newClaimWait != claimWait,\n \"LUNAC_Dividend_Tracker: Cannot update claimWait to same value\"\n );\n emit ClaimWaitUpdated(newClaimWait, claimWait);\n claimWait = newClaimWait;\n }\n\n function getLastProcessedIndex() external view returns (uint256) {\n return lastProcessedIndex;\n }\n\n function getNumberOfTokenHolders() external view returns (uint256) {\n return tokenHoldersMap.keys.length;\n }\n\n function getAccount(address _account)\n public\n view\n returns (\n address account,\n int256 index,\n int256 iterationsUntilProcessed,\n uint256 withdrawableDividends,\n uint256 totalDividends,\n uint256 lastClaimTime,\n uint256 nextClaimTime,\n uint256 secondsUntilAutoClaimAvailable\n )\n {\n account = _account;\n\n index = tokenHoldersMap.getIndexOfKey(account);\n\n iterationsUntilProcessed = -1;\n\n if (index >= 0) {\n if (uint256(index) > lastProcessedIndex) {\n iterationsUntilProcessed = index - int256(lastProcessedIndex);\n } else {\n uint256 processesUntilEndOfArray = tokenHoldersMap.keys.length >\n lastProcessedIndex\n ? tokenHoldersMap.keys.length - lastProcessedIndex\n : 0;\n\n iterationsUntilProcessed =\n index +\n int256(processesUntilEndOfArray);\n }\n }\n\n withdrawableDividends = withdrawableDividendOf(account);\n totalDividends = accumulativeDividendOf(account);\n\n lastClaimTime = lastClaimTimes[account];\n\n nextClaimTime = lastClaimTime > 0 ? lastClaimTime + claimWait : 0;\n\n secondsUntilAutoClaimAvailable = nextClaimTime > block.timestamp\n ? nextClaimTime - block.timestamp\n : 0;\n }\n\n function getAccountAtIndex(uint256 index)\n public\n view\n returns (\n address,\n int256,\n int256,\n uint256,\n uint256,\n uint256,\n uint256,\n uint256\n )\n {\n if (index >= tokenHoldersMap.size()) {\n return (\n 0x0000000000000000000000000000000000000000,\n -1,\n -1,\n 0,\n 0,\n 0,\n 0,\n 0\n );\n }\n\n address account = tokenHoldersMap.getKeyAtIndex(index);\n\n return getAccount(account);\n }\n\n function canAutoClaim(uint256 lastClaimTime) private view returns (bool) {\n if (lastClaimTime > block.timestamp) {\n return false;\n }\n\n return (block.timestamp - lastClaimTime) >= claimWait;\n }\n\n function setBalance(address account, uint256 newBalance)\n external\n onlyOwner\n {\n if (excludedFromDividends[account]) {\n return;\n }\n\n if (newBalance >= minimumTokenBalanceForDividends) {\n _setBalance(account, newBalance);\n tokenHoldersMap.set(account, newBalance);\n } else {\n _setBalance(account, 0);\n tokenHoldersMap.remove(account);\n }\n\n processAccount(account, true);\n }\n\n function process(uint256 gas)\n public\n returns (\n uint256,\n uint256,\n uint256\n )\n {\n uint256 numberOfTokenHolders = tokenHoldersMap.keys.length;\n\n if (numberOfTokenHolders == 0) {\n return (0, 0, lastProcessedIndex);\n }\n\n uint256 _lastProcessedIndex = lastProcessedIndex;\n\n uint256 gasUsed = 0;\n\n uint256 gasLeft = gasleft();\n\n uint256 iterations = 0;\n uint256 claims = 0;\n\n while (gasUsed < gas && iterations < numberOfTokenHolders) {\n _lastProcessedIndex++;\n\n if (_lastProcessedIndex >= tokenHoldersMap.keys.length) {\n _lastProcessedIndex = 0;\n }\n\n address account = tokenHoldersMap.keys[_lastProcessedIndex];\n\n if (canAutoClaim(lastClaimTimes[account])) {\n if (processAccount(account, true)) {\n claims++;\n }\n }\n\n iterations++;\n\n uint256 newGasLeft = gasleft();\n\n if (gasLeft > newGasLeft) {\n gasUsed = gasUsed + gasLeft - newGasLeft;\n }\n\n gasLeft = newGasLeft;\n }\n\n lastProcessedIndex = _lastProcessedIndex;\n\n return (iterations, claims, lastProcessedIndex);\n }\n\n function processAccount(address account, bool automatic)\n public\n onlyOwner\n returns (bool)\n {\n uint256 amount = _withdrawDividendOfUser(account);\n\n if (amount > 0) {\n lastClaimTimes[account] = block.timestamp;\n emit Claim(account, amount, automatic);\n return true;\n }\n\n return false;\n }\n}"}, "DividendPayingToken.sol": {"content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.15;\n\nimport \"ERC20.sol\";\nimport \"Ownable.sol\";\nimport \"IDividendPayingToken.sol\";\n\n/// @title Dividend-Paying Token\n/// @author Roger Wu (https://github.com/roger-wu)\n/// @dev A mintable ERC20 token that allows anyone to pay and distribute ether\n/// to token holders as dividends and allows token holders to withdraw their dividends.\n/// Reference: the source code of PoWH3D: https://etherscan.io/address/0xB3775fB83F7D12A36E0475aBdD1FCA35c091efBe#code\ncontract DividendPayingToken is\n ERC20,\n Ownable,\n DividendPayingTokenInterface,\n DividendPayingTokenOptionalInterface\n{\n // With `magnitude`, we can properly distribute dividends even if the amount of received ether is small.\n // For more discussion about choosing the value of `magnitude`,\n // see https://github.com/ethereum/EIPs/issues/1726#issuecomment-472352728\n uint256 internal constant magnitude = 2**128;\n\n uint256 internal magnifiedDividendPerShare;\n //LUNA CLASSIC WORMHOLE BSC MAINNET\n address public immutable LUNC = address(0x156ab3346823B651294766e23e6Cf87254d68962);\n\n // About dividendCorrection:\n // If the token balance of a `_user` is never changed, the dividend of `_user` can be computed with:\n // `dividendOf(_user) = dividendPerShare * balanceOf(_user)`.\n // When `balanceOf(_user)` is changed (via minting/burning/transferring tokens),\n // `dividendOf(_user)` should not be changed,\n // but the computed value of `dividendPerShare * balanceOf(_user)` is changed.\n // To keep the `dividendOf(_user)` unchanged, we add a correction term:\n // `dividendOf(_user) = dividendPerShare * balanceOf(_user) + dividendCorrectionOf(_user)`,\n // where `dividendCorrectionOf(_user)` is updated whenever `balanceOf(_user)` is changed:\n // `dividendCorrectionOf(_user) = dividendPerShare * (old balanceOf(_user)) - (new balanceOf(_user))`.\n // So now `dividendOf(_user)` returns the same value before and after `balanceOf(_user)` is changed.\n mapping(address => int256) internal magnifiedDividendCorrections;\n mapping(address => uint256) internal withdrawnDividends;\n\n uint256 public totalDividendsDistributed;\n\n constructor(string memory _name, string memory _symbol)\n ERC20(_name, _symbol)\n {}\n\n function distributeDividends(uint256 amount) public onlyOwner {\n require(totalSupply() > 0);\n\n if (amount > 0) {\n magnifiedDividendPerShare =\n magnifiedDividendPerShare +\n ((amount * magnitude) / totalSupply());\n emit DividendsDistributed(msg.sender, amount);\n\n totalDividendsDistributed = totalDividendsDistributed + amount;\n }\n }\n\n /// @notice Withdraws the ether distributed to the sender.\n /// @dev It emits a `DividendWithdrawn` event if the amount of withdrawn ether is greater than 0.\n function withdrawDividend() public virtual override {\n _withdrawDividendOfUser(msg.sender);\n }\n\n /// @notice Withdraws the ether distributed to the sender.\n /// @dev It emits a `DividendWithdrawn` event if the amount of withdrawn ether is greater than 0.\n function _withdrawDividendOfUser(address user)\n internal\n returns (uint256)\n {\n uint256 _withdrawableDividend = withdrawableDividendOf(user);\n if (_withdrawableDividend > 0) {\n withdrawnDividends[user] =\n withdrawnDividends[user] +\n _withdrawableDividend;\n emit DividendWithdrawn(user, _withdrawableDividend);\n bool success = IERC20(LUNC).transfer(user, _withdrawableDividend);\n\n if (!success) {\n withdrawnDividends[user] =\n withdrawnDividends[user] -\n _withdrawableDividend;\n return 0;\n }\n\n return _withdrawableDividend;\n }\n\n return 0;\n }\n\n /// @notice View the amount of dividend in wei that an address can withdraw.\n /// @param _owner The address of a token holder.\n /// @return The amount of dividend in wei that `_owner` can withdraw.\n function dividendOf(address _owner) public view override returns (uint256) {\n return withdrawableDividendOf(_owner);\n }\n\n /// @notice View the amount of dividend in wei that an address can withdraw.\n /// @param _owner The address of a token holder.\n /// @return The amount of dividend in wei that `_owner` can withdraw.\n function withdrawableDividendOf(address _owner)\n public\n view\n override\n returns (uint256)\n {\n return accumulativeDividendOf(_owner) - withdrawnDividends[_owner];\n }\n\n /// @notice View the amount of dividend in wei that an address has withdrawn.\n /// @param _owner The address of a token holder.\n /// @return The amount of dividend in wei that `_owner` has withdrawn.\n function withdrawnDividendOf(address _owner)\n public\n view\n override\n returns (uint256)\n {\n return withdrawnDividends[_owner];\n }\n\n /// @notice View the amount of dividend in wei that an address has earned in total.\n /// @dev accumulativeDividendOf(_owner) = withdrawableDividendOf(_owner) + withdrawnDividendOf(_owner)\n /// = (magnifiedDividendPerShare * balanceOf(_owner) + magnifiedDividendCorrections[_owner]) / magnitude\n /// @param _owner The address of a token holder.\n /// @return The amount of dividend in wei that `_owner` has earned in total.\n function accumulativeDividendOf(address _owner)\n public\n view\n override\n returns (uint256)\n {\n uint256 magDivUserCorr = toUint256Safe(\n toInt256Safe(magnifiedDividendPerShare * balanceOf(_owner)) +\n magnifiedDividendCorrections[_owner]\n );\n return magDivUserCorr / magnitude;\n }\n\n /// @dev Internal function that transfer tokens from one address to another.\n /// Update magnifiedDividendCorrections to keep dividends unchanged.\n /// @param from The address to transfer from.\n /// @param to The address to transfer to.\n /// @param value The amount to be transferred.\n function _transfer(\n address from,\n address to,\n uint256 value\n ) internal virtual override {\n require(false);\n\n int256 _magCorrection = toInt256Safe(magnifiedDividendPerShare * value);\n magnifiedDividendCorrections[from] =\n magnifiedDividendCorrections[from] +\n _magCorrection;\n magnifiedDividendCorrections[to] =\n magnifiedDividendCorrections[to] -\n _magCorrection;\n }\n\n /// @dev Internal function that mints tokens to an account.\n /// Update magnifiedDividendCorrections to keep dividends unchanged.\n /// @param account The account that will receive the created tokens.\n /// @param value The amount that will be created.\n function _mint(address account, uint256 value) internal override {\n super._mint(account, value);\n\n magnifiedDividendCorrections[account] =\n magnifiedDividendCorrections[account] -\n toInt256Safe(magnifiedDividendPerShare * value);\n }\n\n /// @dev Internal function that burns an amount of the token of a given account.\n /// Update magnifiedDividendCorrections to keep dividends unchanged.\n /// @param account The account whose tokens will be burnt.\n /// @param value The amount that will be burnt.\n function _burn(address account, uint256 value) internal override {\n super._burn(account, value);\n\n magnifiedDividendCorrections[account] =\n magnifiedDividendCorrections[account] +\n toInt256Safe(magnifiedDividendPerShare * value);\n }\n\n function _setBalance(address account, uint256 newBalance) internal {\n uint256 currentBalance = balanceOf(account);\n\n if (newBalance > currentBalance) {\n uint256 mintAmount = newBalance - currentBalance;\n _mint(account, mintAmount);\n } else if (newBalance < currentBalance) {\n uint256 burnAmount = currentBalance - newBalance;\n _burn(account, burnAmount);\n }\n }\n\n // INT SAFETY\n function toUint256Safe(int256 a) internal pure returns (uint256) {\n require(a >= 0);\n return uint256(a);\n }\n\n function toInt256Safe(uint256 a) internal pure returns (int256) {\n int256 b = int256(a);\n require(b >= 0);\n return b;\n }\n}"}, "IDividendPayingToken.sol": {"content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.15;\n\n/// @title Dividend-Paying Token Optional Interface\n/// @author Roger Wu (https://github.com/roger-wu)\n/// @dev OPTIONAL functions for a dividend-paying token contract.\ninterface DividendPayingTokenOptionalInterface {\n /// @notice View the amount of dividend in wei that an address can withdraw.\n /// @param _owner The address of a token holder.\n /// @return The amount of dividend in wei that `_owner` can withdraw.\n function withdrawableDividendOf(address _owner)\n external\n view\n returns (uint256);\n\n /// @notice View the amount of dividend in wei that an address has withdrawn.\n /// @param _owner The address of a token holder.\n /// @return The amount of dividend in wei that `_owner` has withdrawn.\n function withdrawnDividendOf(address _owner)\n external\n view\n returns (uint256);\n\n /// @notice View the amount of dividend in wei that an address has earned in total.\n /// @dev accumulativeDividendOf(_owner) = withdrawableDividendOf(_owner) + withdrawnDividendOf(_owner)\n /// @param _owner The address of a token holder.\n /// @return The amount of dividend in wei that `_owner` has earned in total.\n function accumulativeDividendOf(address _owner)\n external\n view\n returns (uint256);\n}\n\n/// @title Dividend-Paying Token Interface\n/// @author Roger Wu (https://github.com/roger-wu)\n/// @dev An interface for a dividend-paying token contract.\ninterface DividendPayingTokenInterface {\n /// @notice View the amount of dividend in wei that an address can withdraw.\n /// @param _owner The address of a token holder.\n /// @return The amount of dividend in wei that `_owner` can withdraw.\n function dividendOf(address _owner) external view returns (uint256);\n\n /// @notice Withdraws the ether distributed to the sender.\n /// @dev SHOULD transfer `dividendOf(msg.sender)` wei to `msg.sender`, and `dividendOf(msg.sender)` SHOULD be 0 after the transfer.\n /// MUST emit a `DividendWithdrawn` event if the amount of ether transferred is greater than 0.\n function withdrawDividend() external;\n\n /// @dev This event MUST emit when ether is distributed to token holders.\n /// @param from The address which sends ether to this contract.\n /// @param weiAmount The amount of distributed ether in wei.\n event DividendsDistributed(address indexed from, uint256 weiAmount);\n\n /// @dev This event MUST emit when an address withdraws their dividend.\n /// @param to The address which withdraws ether from this contract.\n /// @param weiAmount The amount of withdrawn ether in wei.\n event DividendWithdrawn(address indexed to, uint256 weiAmount);\n}\n\ninterface IDividendPayingToken is\n DividendPayingTokenInterface,\n DividendPayingTokenOptionalInterface\n{}"}}, "settings": {"evmVersion": "istanbul", "optimizer": {"enabled": true, "runs": 200}, "libraries": {"LuncxToken.sol": {"IterableMapping": "0x66172B6e787937b2f9078871aBA4B6484492F839"}}}}, "contract_name": "LuncxToken", "compiler_version": "0.8.15+commit.e14f2714", "optimizer_enabled": true, "optimizer_runs": 200, "license_identifier": "MIT", "bytecode_len": 55498}