Ape Curtis Testnet

Token

PUPS2 (PUP2)
ERC-20

Overview

Max Total Supply

1,000,000 PUP2

Holders

1

Total Transfers

-

Market

Price

$0.00 @ 0.000000 APE

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information

Contract Source Code Verified (Exact Match)

Contract Name:
DividendApeToken

Compiler Version
v0.8.24+commit.e11b9ed9

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 18 : DividendApeToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import {ERC20Burnable, ERC20} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import {DividendTracker} from "../dividend/DividendTracker.sol";
import {IDividendApeToken} from "./IDividendApeToken.sol";
import {ICamelotRouter} from "./ICamelotRouter.sol";
import {ICamelotFactory} from "./ICamelotFactory.sol";
import {ICamelotPair} from "./ICamelotPair.sol";

/**
 * @title  Official gemlabs dividend APE token contract
 * @author The gemlabs crew | https://www.gemlabs.wtf | X: https://twitter.com/gemlabs_wtf | Telegram: https://t.me/gemlabs_wtf
 */
contract DividendApeToken is ERC20Burnable, Ownable, IDividendApeToken, ReentrancyGuard {
    uint256 private constant DENOMINATOR = 100_00;
    uint256 private constant GAS_FOR_PROCESSING = 500_000;
    address public constant PINK_LOCK_CONTRACT = 0xdD6E31A046b828CbBAfb939C2a394629aff8BBdC; // Maybe remove or adjust this ?

    ICamelotRouter public camelotV2Router;
    ICamelotPair public camelotV2Pair;
    DividendTracker public dividendTracker;
    uint256 public swapTokensAtAmount;

    address public deployerWallet;
    address public teamWallet;
    uint256 public dividendsFee;
    uint256 public teamFee;
    uint256 public burnFee;

    mapping(address => bool) public _isExcludedFromFees;
    mapping(address => bool) public automatedMarketMakerPairs;
    bool private swapping;

    constructor(
        string memory _name,
        string memory _symbol,
        uint256 _initialSupply,
        address _router,
        uint256 _minimumTokenBalanceForDividendsPct,
        address _teamWallet,
        uint256 _teamFee,
        uint256 _dividendsFee,
        uint256 _burnFee
    ) ERC20(_name, _symbol) Ownable(msg.sender) {
        deployerWallet = msg.sender;
        teamWallet = _teamWallet;

        dividendsFee = _dividendsFee;
        teamFee = _teamFee;
        burnFee = _burnFee;

        uint256 totalFee = dividendsFee + teamFee + burnFee;

        if (totalFee > 10000) {
            revert InvalidFee(totalFee);
        }

        swapTokensAtAmount = (_initialSupply) / (DENOMINATOR * 100); // 0.0001%

        dividendTracker = new DividendTracker((_initialSupply * _minimumTokenBalanceForDividendsPct) / DENOMINATOR);

        camelotV2Router = ICamelotRouter(_router);
        // camelotV2Pair = ICamelotPair(
        //     ICamelotFactory(camelotV2Router.factory()).createPair(address(this), camelotV2Router.WETH())
        // );

        //_setAutomatedMarketMakerPair(address(camelotV2Pair), true);

        // exclude from receiving dividends
        dividendTracker.excludeFromDividends(address(dividendTracker));
        dividendTracker.excludeFromDividends(address(this));
        dividendTracker.excludeFromDividends(teamWallet);
        dividendTracker.excludeFromDividends(msg.sender);
        dividendTracker.excludeFromDividends(address(0xdead));
        dividendTracker.excludeFromDividends(address(0x0000000000000000000000000000000000000002));
        dividendTracker.excludeFromDividends(address(0));
        dividendTracker.excludeFromDividends(address(camelotV2Router));
        //dividendTracker.excludeFromDividends(address(camelotV2Pair));
        dividendTracker.excludeFromDividends(PINK_LOCK_CONTRACT);

        // exclude from paying fees or having max transaction amount
        _isExcludedFromFees[msg.sender] = true;
        _isExcludedFromFees[teamWallet] = true;
        _isExcludedFromFees[address(this)] = true;
        _isExcludedFromFees[PINK_LOCK_CONTRACT] = true;

        _mint(msg.sender, _initialSupply);
    }

    receive() external payable {}

    /**
     * @notice Excludes or includes an account from fees.
     * @param account The address of the account to be excluded or included.
     * @param excluded A boolean indicating whether the account is to be excluded (true) or included (false) in fees.
     * @dev Only callable by the owner.
     */
    function excludeFromFees(address account, bool excluded) external onlyOwner {
        _isExcludedFromFees[account] = excluded;
        emit ExcludeFromFees(account, excluded);
    }

    /**
     * @notice Sets the team wallet address.
     * @param wallet The address of the new team wallet.
     * @dev Only callable by the owner.
     */
    function setTeamWallet(address payable wallet) external onlyOwner {
        teamWallet = wallet;
    }

    /**
     * @notice Sets the team fee.
     * @param value The new value for the team fee.
     * @dev Only callable by the owner.
     */
    function setTeamFee(uint256 value) external onlyOwner {
        if (value > 10000) {
            revert InvalidFee(value);
        }
        teamFee = value;
    }

    /**
     * @notice Sets the dividends fee.
     * @param value The new value for the dividends fee.
     * @dev Only callable by the owner.
     */
    function setDividendsFee(uint256 value) external onlyOwner {
        if (value > 10000) {
            revert InvalidFee(value);
        }
        dividendsFee = value;
    }

    /**
     * @notice Sets the burn fee.
     * @param value The new value for the burn fee.
     * @dev Only callable by the owner.
     */
    function setBurnFee(uint256 value) external onlyOwner {
        if (value > 10000) {
            revert InvalidFee(value);
        }
        burnFee = value;
    }

    /**
     * @notice Sets or unsets an address as an automated market maker pair.
     * @param pair The address of the pair to be set or unset.
     * @param value A boolean indicating whether to set (true) or unset (false) the pair as an automated market maker.
     */
    function setAutomatedMarketMakerPair(address pair, bool value) external {
        if (msg.sender != deployerWallet) {
            return;
        }

        if (pair == address(camelotV2Pair)) {
            revert CannotRemoveCamlotPair(pair);
        }

        _setAutomatedMarketMakerPair(pair, value);
    }

    function _setAutomatedMarketMakerPair(address pair, bool value) private {
        if (automatedMarketMakerPairs[pair] == value) {
            revert PairAlreadySetToValue(pair, value);
        }
        automatedMarketMakerPairs[pair] = value;

        if (value) {
            dividendTracker.excludeFromDividends(pair);
        }

        emit SetAutomatedMarketMakerPair(pair, value);
    }

    /**
     * @notice Updates the claim wait time for dividends.
     * @param claimWait The new claim wait time in seconds.
     * @dev Calls the updateClaimWait function on the dividendTracker to update the claim wait time.
     *      Only callable by the owner.
     */
    function updateClaimWait(uint256 claimWait) external onlyOwner {
        dividendTracker.updateClaimWait(claimWait);
    }

    /**
     * @notice Checks if an account is excluded from fees.
     * @param account The address of the account to check.
     * @return A boolean indicating whether the account is excluded from fees.
     */
    function isExcludedFromFees(address account) external view returns (bool) {
        return _isExcludedFromFees[account];
    }

    /**
     * @notice Gets the amount of withdrawable dividends for an account.
     * @param account The address of the account to check.
     * @return The amount of withdrawable dividends for the specified account.
     * @dev Calls the withdrawableDividendOf function on the dividendTracker to get the amount of withdrawable dividends.
     */
    function withdrawableDividendOf(address account) external view returns (uint256) {
        return dividendTracker.withdrawableDividendOf(account);
    }

    /**
     * @notice Excludes an account from receiving dividends.
     * @param account The address of the account to exclude.
     * @dev Calls the excludeFromDividends function on the dividendTracker to exclude the specified account from receiving dividends.
     *      Only callable by the owner.
     */
    function excludeFromDividends(address account) external onlyOwner {
        dividendTracker.excludeFromDividends(account);
    }

    /**
     * @notice Processes the dividend tracker with a specified amount of gas.
     * @param gas The amount of gas to use for processing.
     * @dev Calls the process function on the dividendTracker with the specified gas.
     */
    function processDividendTracker(uint256 gas) external {
        (uint256 iterations, uint256 claims, uint256 lastProcessedIndex) = dividendTracker.process(gas);

        emit ProcessedDividendTracker(iterations, claims, lastProcessedIndex, false, gas, tx.origin);
    }

    /**
     * @notice Claims dividends for the caller.
     * @dev Calls the processAccount function on the dividendTracker for the caller.
     */
    function claim() external {
        dividendTracker.processAccount(payable(msg.sender), false);
    }

    function _update(address from, address to, uint256 amount) internal virtual override {
        if (amount == 0) {
            super._update(from, to, 0);
            return;
        }

        uint256 contractTokenBalance = balanceOf(address(this));
        bool canSwap = contractTokenBalance >= swapTokensAtAmount;
        uint256 totalFees = dividendsFee + teamFee + burnFee;

        if (canSwap && !swapping && !automatedMarketMakerPairs[from] && from != owner() && to != owner()) {
            swapping = true;

            // Calculate the tokens needed for team and dividends combined
            uint256 tokensForTeamAndDividends = (contractTokenBalance * (teamFee + dividendsFee)) / totalFees;

            // Swap the combined amount of tokens for ETH
            if (tokensForTeamAndDividends > 0) {
                swapTokensForNative(tokensForTeamAndDividends);
                uint256 ethBalance = address(this).balance;

                // Calculate the ETH portion for the team and dividends
                uint256 teamETH = (ethBalance * teamFee) / (teamFee + dividendsFee);
                uint256 dividendsETH = ethBalance - teamETH;

                // Transfer the calculated ETH to the team wallet
                if (teamETH > 0) {
                    _safeTransferETH(teamWallet, teamETH);
                }

                // Distribute the remaining ETH to the dividend tracker
                if (dividendsETH > 0) {
                    sendAndDistributeDividends(dividendsETH);
                }
            }

            // Burn remaining tokens from the contract balance if applicable
            if (burnFee > 0) {
                uint256 tokensToBurn = (contractTokenBalance * burnFee) / totalFees;
                _burn(address(this), tokensToBurn);
            }

            swapping = false;
        }

        bool takeFee = !swapping;

        // Skip the fee for normal transfers (not buy or sell)
        if (!automatedMarketMakerPairs[from] && !automatedMarketMakerPairs[to]) {
            takeFee = false;
        }

        if (_isExcludedFromFees[from] || _isExcludedFromFees[to]) {
            takeFee = false;
        }

        if (takeFee) {
            uint256 fees = (amount * totalFees) / 10000;
            super._update(from, address(this), fees);
            updateTokenHolder(address(this));
            amount = amount - fees;
        }

        super._update(from, to, amount);

        updateTokenHolder(from);
        updateTokenHolder(to);

        if (!swapping) {
            uint256 gas = GAS_FOR_PROCESSING;

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

    function updateTokenHolder(address account) private {
        uint256 balance = balanceOf(account);
        dividendTracker.setBalance(payable(account), balance);
    }

    function swapTokensForNative(uint256 tokenAmount) private {
        address[] memory path = new address[](2);
        path[0] = address(this);
        path[1] = camelotV2Router.WETH();

        _approve(address(this), address(camelotV2Router), tokenAmount);

        camelotV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(
            tokenAmount,
            0, // accept any amount of ETH
            path,
            address(this),
            address(0),
            block.timestamp + 300
        );
    }

    function sendAndDistributeDividends(uint256 ethAmount) private {
        bool success = _safeTransferETH(payable(address(dividendTracker)), ethAmount);

        if (success) {
            dividendTracker.distributeDividends(ethAmount);
            emit SendDividends(ethAmount);
        }
    }

    function _safeTransferETH(address to, uint256 value) private returns (bool) {
        (bool success, ) = to.call{value: value, gas: 30_000}(new bytes(0));
        return success;
    }
}

File 2 of 18 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;

import {Context} from "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * The initial owner is set to the address provided by the deployer. This can
 * later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

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

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

File 3 of 18 : draft-IERC6093.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol)
pragma solidity ^0.8.20;

/**
 * @dev Standard ERC20 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens.
 */
interface IERC20Errors {
    /**
     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param balance Current balance for the interacting account.
     * @param needed Minimum amount required to perform a transfer.
     */
    error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC20InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC20InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     * @param allowance Amount of tokens a `spender` is allowed to operate with.
     * @param needed Minimum amount required to perform a transfer.
     */
    error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC20InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `spender` to be approved. Used in approvals.
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC20InvalidSpender(address spender);
}

/**
 * @dev Standard ERC721 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens.
 */
interface IERC721Errors {
    /**
     * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20.
     * Used in balance queries.
     * @param owner Address of the current owner of a token.
     */
    error ERC721InvalidOwner(address owner);

    /**
     * @dev Indicates a `tokenId` whose `owner` is the zero address.
     * @param tokenId Identifier number of a token.
     */
    error ERC721NonexistentToken(uint256 tokenId);

    /**
     * @dev Indicates an error related to the ownership over a particular token. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param tokenId Identifier number of a token.
     * @param owner Address of the current owner of a token.
     */
    error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC721InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC721InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     * @param tokenId Identifier number of a token.
     */
    error ERC721InsufficientApproval(address operator, uint256 tokenId);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC721InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC721InvalidOperator(address operator);
}

/**
 * @dev Standard ERC1155 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens.
 */
interface IERC1155Errors {
    /**
     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param balance Current balance for the interacting account.
     * @param needed Minimum amount required to perform a transfer.
     * @param tokenId Identifier number of a token.
     */
    error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC1155InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC1155InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     * @param owner Address of the current owner of a token.
     */
    error ERC1155MissingApprovalForAll(address operator, address owner);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC1155InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC1155InvalidOperator(address operator);

    /**
     * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
     * Used in batch transfers.
     * @param idsLength Length of the array of token identifiers
     * @param valuesLength Length of the array of token amounts
     */
    error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}

File 4 of 18 : ERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "./IERC20.sol";
import {IERC20Metadata} from "./extensions/IERC20Metadata.sol";
import {Context} from "../../utils/Context.sol";
import {IERC20Errors} from "../../interfaces/draft-IERC6093.sol";

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * The default value of {decimals} is 18. To change this, you should override
 * this function so it returns a different value.
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of ERC20
 * applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 */
abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
    mapping(address account => uint256) private _balances;

    mapping(address account => mapping(address spender => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5.05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the default value returned by this function, unless
     * it's overridden.
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual returns (uint8) {
        return 18;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view virtual returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - the caller must have a balance of at least `value`.
     */
    function transfer(address to, uint256 value) public virtual returns (bool) {
        address owner = _msgSender();
        _transfer(owner, to, value);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on
     * `transferFrom`. This is semantically equivalent to an infinite approval.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 value) public virtual returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, value);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * NOTE: Does not update the allowance if the current allowance
     * is the maximum `uint256`.
     *
     * Requirements:
     *
     * - `from` and `to` cannot be the zero address.
     * - `from` must have a balance of at least `value`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `value`.
     */
    function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, value);
        _transfer(from, to, value);
        return true;
    }

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to`.
     *
     * This internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead.
     */
    function _transfer(address from, address to, uint256 value) internal {
        if (from == address(0)) {
            revert ERC20InvalidSender(address(0));
        }
        if (to == address(0)) {
            revert ERC20InvalidReceiver(address(0));
        }
        _update(from, to, value);
    }

    /**
     * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`
     * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding
     * this function.
     *
     * Emits a {Transfer} event.
     */
    function _update(address from, address to, uint256 value) internal virtual {
        if (from == address(0)) {
            // Overflow check required: The rest of the code assumes that totalSupply never overflows
            _totalSupply += value;
        } else {
            uint256 fromBalance = _balances[from];
            if (fromBalance < value) {
                revert ERC20InsufficientBalance(from, fromBalance, value);
            }
            unchecked {
                // Overflow not possible: value <= fromBalance <= totalSupply.
                _balances[from] = fromBalance - value;
            }
        }

        if (to == address(0)) {
            unchecked {
                // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.
                _totalSupply -= value;
            }
        } else {
            unchecked {
                // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.
                _balances[to] += value;
            }
        }

        emit Transfer(from, to, value);
    }

    /**
     * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).
     * Relies on the `_update` mechanism
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead.
     */
    function _mint(address account, uint256 value) internal {
        if (account == address(0)) {
            revert ERC20InvalidReceiver(address(0));
        }
        _update(address(0), account, value);
    }

    /**
     * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.
     * Relies on the `_update` mechanism.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead
     */
    function _burn(address account, uint256 value) internal {
        if (account == address(0)) {
            revert ERC20InvalidSender(address(0));
        }
        _update(account, address(0), value);
    }

    /**
     * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     *
     * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
     */
    function _approve(address owner, address spender, uint256 value) internal {
        _approve(owner, spender, value, true);
    }

    /**
     * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.
     *
     * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by
     * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any
     * `Approval` event during `transferFrom` operations.
     *
     * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to
     * true using the following override:
     * ```
     * function _approve(address owner, address spender, uint256 value, bool) internal virtual override {
     *     super._approve(owner, spender, value, true);
     * }
     * ```
     *
     * Requirements are the same as {_approve}.
     */
    function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {
        if (owner == address(0)) {
            revert ERC20InvalidApprover(address(0));
        }
        if (spender == address(0)) {
            revert ERC20InvalidSpender(address(0));
        }
        _allowances[owner][spender] = value;
        if (emitEvent) {
            emit Approval(owner, spender, value);
        }
    }

    /**
     * @dev Updates `owner` s allowance for `spender` based on spent `value`.
     *
     * Does not update the allowance value in case of infinite allowance.
     * Revert if not enough allowance is available.
     *
     * Does not emit an {Approval} event.
     */
    function _spendAllowance(address owner, address spender, uint256 value) internal virtual {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance != type(uint256).max) {
            if (currentAllowance < value) {
                revert ERC20InsufficientAllowance(spender, currentAllowance, value);
            }
            unchecked {
                _approve(owner, spender, currentAllowance - value, false);
            }
        }
    }
}

File 5 of 18 : ERC20Burnable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/ERC20Burnable.sol)

pragma solidity ^0.8.20;

import {ERC20} from "../ERC20.sol";
import {Context} from "../../../utils/Context.sol";

/**
 * @dev Extension of {ERC20} that allows token holders to destroy both their own
 * tokens and those that they have an allowance for, in a way that can be
 * recognized off-chain (via event analysis).
 */
abstract contract ERC20Burnable is Context, ERC20 {
    /**
     * @dev Destroys a `value` amount of tokens from the caller.
     *
     * See {ERC20-_burn}.
     */
    function burn(uint256 value) public virtual {
        _burn(_msgSender(), value);
    }

    /**
     * @dev Destroys a `value` amount of tokens from `account`, deducting from
     * the caller's allowance.
     *
     * See {ERC20-_burn} and {ERC20-allowance}.
     *
     * Requirements:
     *
     * - the caller must have allowance for ``accounts``'s tokens of at least
     * `value`.
     */
    function burnFrom(address account, uint256 value) public virtual {
        _spendAllowance(account, _msgSender(), value);
        _burn(account, value);
    }
}

File 6 of 18 : IERC20Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

File 7 of 18 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the value of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 value) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 value) external returns (bool);
}

File 8 of 18 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

File 9 of 18 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol)

pragma solidity ^0.8.20;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant NOT_ENTERED = 1;
    uint256 private constant ENTERED = 2;

    uint256 private _status;

    /**
     * @dev Unauthorized reentrant call.
     */
    error ReentrancyGuardReentrantCall();

    constructor() {
        _status = NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be NOT_ENTERED
        if (_status == ENTERED) {
            revert ReentrancyGuardReentrantCall();
        }

        // Any calls to nonReentrant after this point will fail
        _status = ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = NOT_ENTERED;
    }

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == ENTERED;
    }
}

File 10 of 18 : IUniswapV2Router01.sol
pragma solidity >=0.6.2;

interface IUniswapV2Router01 {
    function factory() external pure returns (address);
    function WETH() external pure returns (address);

    function addLiquidity(
        address tokenA,
        address tokenB,
        uint amountADesired,
        uint amountBDesired,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline
    ) external returns (uint amountA, uint amountB, uint liquidity);
    function addLiquidityETH(
        address token,
        uint amountTokenDesired,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external payable returns (uint amountToken, uint amountETH, uint liquidity);
    function removeLiquidity(
        address tokenA,
        address tokenB,
        uint liquidity,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline
    ) external returns (uint amountA, uint amountB);
    function removeLiquidityETH(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external returns (uint amountToken, uint amountETH);
    function removeLiquidityWithPermit(
        address tokenA,
        address tokenB,
        uint liquidity,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external returns (uint amountA, uint amountB);
    function removeLiquidityETHWithPermit(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external returns (uint amountToken, uint amountETH);
    function swapExactTokensForTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external returns (uint[] memory amounts);
    function swapTokensForExactTokens(
        uint amountOut,
        uint amountInMax,
        address[] calldata path,
        address to,
        uint deadline
    ) external returns (uint[] memory amounts);
    function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
        external
        payable
        returns (uint[] memory amounts);
    function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)
        external
        returns (uint[] memory amounts);
    function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
        external
        returns (uint[] memory amounts);
    function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)
        external
        payable
        returns (uint[] memory amounts);

    function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);
    function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);
    function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);
    function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
    function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);
}

File 11 of 18 : IUniswapV2Router02.sol
pragma solidity >=0.6.2;

import './IUniswapV2Router01.sol';

interface IUniswapV2Router02 is IUniswapV2Router01 {
    function removeLiquidityETHSupportingFeeOnTransferTokens(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external returns (uint amountETH);
    function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external returns (uint amountETH);

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

File 12 of 18 : ICamelotFactory.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

interface ICamelotFactory {
    event PairCreated(address indexed token0, address indexed token1, address pair, uint256);

    function owner() external view returns (address);
    function feePercentOwner() external view returns (address);
    function setStableOwner() external view returns (address);
    function feeTo() external view returns (address);

    function ownerFeeShare() external view returns (uint256);
    function referrersFeeShare(address) external view returns (uint256);

    function getPair(address tokenA, address tokenB) external view returns (address pair);
    function allPairs(uint256) external view returns (address pair);
    function allPairsLength() external view returns (uint256);

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

    function setFeeTo(address) external;
    function feeInfo() external view returns (uint _ownerFeeShare, address _feeTo);
}

File 13 of 18 : ICamelotPair.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

interface ICamelotPair {
    event Approval(address indexed owner, address indexed spender, uint value);
    event Transfer(address indexed from, address indexed to, uint value);

    function name() external pure returns (string memory);
    function symbol() external pure returns (string memory);
    function decimals() external pure returns (uint8);
    function totalSupply() external view returns (uint);
    function balanceOf(address owner) external view returns (uint);
    function allowance(address owner, address spender) external view returns (uint);

    function approve(address spender, uint value) external returns (bool);
    function transfer(address to, uint value) external returns (bool);
    function transferFrom(address from, address to, uint value) external returns (bool);

    function DOMAIN_SEPARATOR() external view returns (bytes32);
    function PERMIT_TYPEHASH() external pure returns (bytes32);
    function nonces(address owner) external view returns (uint);

    function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;

    event Mint(address indexed sender, uint amount0, uint amount1);
    event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
    event Swap(
        address indexed sender,
        uint amount0In,
        uint amount1In,
        uint amount0Out,
        uint amount1Out,
        address indexed to
    );
    event Sync(uint112 reserve0, uint112 reserve1);

    function MINIMUM_LIQUIDITY() external pure returns (uint);
    function factory() external view returns (address);
    function token0() external view returns (address);
    function token1() external view returns (address);
    function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint16 token0feePercent, uint16 token1FeePercent);
    function getAmountOut(uint amountIn, address tokenIn) external view returns (uint);
    function kLast() external view returns (uint);

    function setFeePercent(uint16 token0FeePercent, uint16 token1FeePercent) external;
    function mint(address to) external returns (uint liquidity);
    function burn(address to) external returns (uint amount0, uint amount1);
    function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
    function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data, address referrer) external;
    function skim(address to) external;
    function sync() external;

    function initialize(address, address) external;
}

File 14 of 18 : ICamelotRouter.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import {IUniswapV2Router02} from "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol";

interface ICamelotRouter is IUniswapV2Router02 {
  function removeLiquidityETHSupportingFeeOnTransferTokens(
    address token,
    uint liquidity,
    uint amountTokenMin,
    uint amountETHMin,
    address to,
    uint deadline
  ) external returns (uint amountETH);

  function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
    address token,
    uint liquidity,
    uint amountTokenMin,
    uint amountETHMin,
    address to,
    uint deadline,
    bool approveMax, uint8 v, bytes32 r, bytes32 s
  ) external returns (uint amountETH);

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

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

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


}

File 15 of 18 : IDividendApeToken.sol
// SPDX-License-Identifier: MIT
// Factory: gemlabs
pragma solidity ^0.8.24;

interface IDividendApeToken {
    event ExcludeFromFees(address indexed account, bool isExcluded);

    event SetAutomatedMarketMakerPair(address indexed pair, bool indexed value);
    event SendDividends(uint256 amount);
    event ProcessedDividendTracker(
        uint256 iterations,
        uint256 claims,
        uint256 lastProcessedIndex,
        bool indexed automatic,
        uint256 gas,
        address indexed processor
    );

    error InvalidFee(uint256 totalFee);
    error CannotRemoveCamlotPair(address pair);
    error PairAlreadySetToValue(address pair, bool value);

    function excludeFromFees(address account, bool excluded) external;
    function setTeamWallet(address payable wallet) external;
    function setDividendsFee(uint256 value) external;
    function setTeamFee(uint256 value) external;
    function setBurnFee(uint256 value) external;
    function setAutomatedMarketMakerPair(address pair, bool value) external;
    function updateClaimWait(uint256 claimWait) external;
    function isExcludedFromFees(address account) external view returns (bool);
    function withdrawableDividendOf(address account) external view returns (uint256);
    function excludeFromDividends(address account) external;
    function processDividendTracker(uint256 gas) external;
    function claim() external;
}

File 16 of 18 : DividendTracker.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {IDividendTracker} from "./IDividendTracker.sol";
import {IterableMapping} from "./IterableMapping.sol";

/**
 * @title  Official gemlabs dividend tracker contract
 * @author The gemlabs crew | https://www.gemlabs.wtf | X: https://twitter.com/gemlabs_wtf | Telegram: https://t.me/gemlabs_wtf
 */
contract DividendTracker is Ownable, IDividendTracker {
    uint256 private constant MAGNITUDE = 2 ** 128;
    using IterableMapping for IterableMapping.Map;

    IterableMapping.Map private tokenHoldersMap;
    uint256 public lastProcessedIndex;
    uint256 public totalSupply;
    uint256 public magnifiedDividendPerShare;
    uint256 public totalDividendsDistributed;
    uint256 public claimWait;
    uint256 public minimumTokenBalanceForDividends;

    mapping(address => bool) public excludedFromDividends;
    mapping(address => uint256) public lastClaimTimes;
    mapping(address => uint256) public tokenHolderBalances;
    mapping(address => int256) private magnifiedDividendCorrections;
    mapping(address => uint256) private withdrawnDividends;

    constructor(uint256 minimumTokenBalanceForDividends_) Ownable(msg.sender) {
        claimWait = 3600;
        minimumTokenBalanceForDividends = minimumTokenBalanceForDividends_;
    }

    /**
     * @notice Excludes an account from receiving dividends.
     * @param account The address of the account to be excluded.
     * @dev Only callable by the owner (Dividend Token).
     */
    function excludeFromDividends(address account) external onlyOwner {
        excludedFromDividends[account] = true;

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

        emit ExcludeFromDividends(account);
    }

    /**
     * @notice Updates the waiting time between claims.
     * @param newClaimWait The new claim wait time in seconds.
     * @dev Only callable by the owner (Dividend Token).
     */
    function updateClaimWait(uint256 newClaimWait) external onlyOwner {
        if (newClaimWait < 3600 || newClaimWait > 86400) {
            revert InvalidClaimWait(newClaimWait, 3600, 86400);
        }
        if (newClaimWait == claimWait) {
            revert ClaimWaitAlreadySet(newClaimWait);
        }

        claimWait = newClaimWait;

        emit ClaimWaitUpdated(newClaimWait, claimWait);
    }

    /**
     * @notice Retrieves the number of token holders.
     * @return uint256 The number of token holders.
     */
    function getNumberOfTokenHolders() external view returns (uint256) {
        return tokenHoldersMap.keys.length;
    }

    /**
     * @notice Retrieves the token balance of a specific account.
     * @param account The address of the account.
     * @return uint256 The balance of the account.
     */
    function getTokenHolderBalance(address account) external view returns (uint256) {
        return tokenHolderBalances[account];
    }

    /**
     * @notice Retrieves account information for a specific account.
     * @param _account The address of the account.
     * @return account The address of the account.
     * @return index The index of the account in the token holders map.
     * @return iterationsUntilProcessed The number of iterations until the account is processed.
     * @return withdrawableDividends The amount of dividends that can be withdrawn by the account.
     * @return totalDividends The total amount of dividends earned by the account.
     * @return lastClaimTime The last time the account claimed dividends.
     * @return nextClaimTime The next time the account can claim dividends.
     * @return secondsUntilAutoClaimAvailable The number of seconds until the account can automatically claim dividends.
     */
    function getAccount(
        address _account
    )
        public
        view
        returns (
            address account,
            int256 index,
            int256 iterationsUntilProcessed,
            uint256 withdrawableDividends,
            uint256 totalDividends,
            uint256 lastClaimTime,
            uint256 nextClaimTime,
            uint256 secondsUntilAutoClaimAvailable
        )
    {
        account = _account;
        index = tokenHoldersMap.getIndexOfKey(account);
        iterationsUntilProcessed = -1;

        if (index >= 0) {
            if (uint256(index) > lastProcessedIndex) {
                iterationsUntilProcessed = index - int256(lastProcessedIndex);
            } else {
                uint256 processesUntilEndOfArray = tokenHoldersMap.keys.length > lastProcessedIndex
                    ? tokenHoldersMap.keys.length - lastProcessedIndex
                    : 0;

                iterationsUntilProcessed = index + int256(processesUntilEndOfArray);
            }
        }

        withdrawableDividends = withdrawableDividendOf(account);
        totalDividends = accumulativeDividendOf(account);

        lastClaimTime = lastClaimTimes[account];
        nextClaimTime = lastClaimTime > 0 ? lastClaimTime + claimWait : 0;
        secondsUntilAutoClaimAvailable = nextClaimTime > block.timestamp ? nextClaimTime - block.timestamp : 0;
    }

    /**
     * @notice Retrieves account information at a specific index.
     * @param index The index in the token holders map.
     * @return (see getAccount)
     */
    function getAccountAtIndex(
        uint256 index
    ) external view returns (address, int256, int256, uint256, uint256, uint256, uint256, uint256) {
        if (index >= tokenHoldersMap.size()) {
            return (address(0), -1, -1, 0, 0, 0, 0, 0);
        }

        address account = tokenHoldersMap.getKeyAtIndex(index);

        return getAccount(account);
    }

    function canAutoClaim(uint256 lastClaimTime) private view returns (bool) {
        if (lastClaimTime > block.timestamp) {
            return false;
        }

        return block.timestamp - lastClaimTime >= claimWait;
    }

    /**
     * @notice Processes dividend claims for token holders within the specified gas limit.
     * @param gas The maximum amount of gas to be used for processing.
     * @return (uint256, uint256, uint256) Returns the number of iterations, the number of claims, and the last processed index.
     */
    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 + gasLeft - newGasLeft;
            }

            gasLeft = newGasLeft;
        }

        lastProcessedIndex = _lastProcessedIndex;

        return (iterations, claims, lastProcessedIndex);
    }

    /**
     * @notice Processes the account for dividend withdrawal.
     * @param account The address of the account to process.
     * @param automatic A boolean indicating if the process was triggered automatically.
     * @return bool Returns true if dividends were withdrawn successfully, otherwise false.
     * @dev Only callable by the owner (Dividend Token).
     */
    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;
    }

    /**
     * @notice Distributes the specified amount of dividends to token holders.
     * @param amount The amount of dividends to distribute.
     * @dev Only callable by the owner (Dividend Token).
     */
    function distributeDividends(uint256 amount) public onlyOwner {
        if (totalSupply == 0) {
            revert NoTotalSupply();
        }

        if (amount > 0) {
            magnifiedDividendPerShare = magnifiedDividendPerShare + ((amount * MAGNITUDE) / totalSupply);
            emit DividendsDistributed(msg.sender, amount);

            totalDividendsDistributed = totalDividendsDistributed + amount;
        }
    }

    /**
     * @notice Withdraws the dividend for the caller.
     * @dev Calls the internal function to handle the dividend withdrawal process.
     */
    function withdrawDividend() external {
        _withdrawDividendOfUser(payable(msg.sender));
    }

    function _withdrawDividendOfUser(address payable user) internal returns (uint256) {
        uint256 _withdrawableDividend = withdrawableDividendOf(user);
        if (_withdrawableDividend > 0) {
            withdrawnDividends[user] = withdrawnDividends[user] + _withdrawableDividend;

            bool success = _safeTransferETH(user, _withdrawableDividend);

            emit DividendWithdrawn(user, _withdrawableDividend);

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

            return _withdrawableDividend;
        }

        return 0;
    }

    /**
     * @notice View the amount of dividend in wei that an address can withdraw.
     * @param _owner The address of a token holder.
     * @return The amount of dividend in wei that `_owner` can withdraw.
     */
    function withdrawableDividendOf(address _owner) public view returns (uint256) {
        return accumulativeDividendOf(_owner) - (withdrawnDividends[_owner]);
    }

    /**
     * @notice View the amount of dividend in wei that an address has withdrawn.
     * @param _owner The address of a token holder.
     * @return The amount of dividend in wei that `_owner` has withdrawn.
     */
    function withdrawnDividendOf(address _owner) public view returns (uint256) {
        return withdrawnDividends[_owner];
    }

    /**
     * @notice View the amount of dividend in wei that an address has earned in total.
     * @dev accumulativeDividendOf(_owner) = withdrawableDividendOf(_owner) + withdrawnDividendOf(_owner)
     * @param _owner The address of a token holder.
     * @return The amount of dividend in wei that `_owner` has earned in total.
     */
    function accumulativeDividendOf(address _owner) public view returns (uint256) {
        uint256 balance = tokenHolderBalances[_owner];
        int256 correction = magnifiedDividendCorrections[_owner];
        int256 accumulatedDividend = int256(magnifiedDividendPerShare) * int256(balance) + correction;

        if (accumulatedDividend < 0) {
            return 0;
        } else {
            return uint256(accumulatedDividend) / MAGNITUDE;
        }
    }

    /**
     * @notice Gets the largest holder and their balance.
     * @return largestHolder The address of the largest holder.
     * @return largestBalance The balance of the largest holder.
     */
    function getLargestHolder() external view returns (address largestHolder, uint256 largestBalance) {
        uint256 numberOfTokenHolders = tokenHoldersMap.keys.length;

        largestBalance = 0;

        for (uint256 i = 0; i < numberOfTokenHolders; i++) {
            address account = tokenHoldersMap.keys[i];
            uint256 balance = tokenHolderBalances[account];

            if (balance > largestBalance) {
                largestBalance = balance;
                largestHolder = account;
            }
        }

        return (largestHolder, largestBalance);
    }

    /**
     * @notice Set the balance of an account and update dividend eligibility.
     * @param account The address of the account.
     * @param newBalance The new balance for the account.
     * @dev Only callable by the owner (Dividend Token).
     */
    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 _setBalance(address account, uint256 newBalance) private {
        uint256 currentBalance = tokenHolderBalances[account];

        if (newBalance > currentBalance) {
            uint256 increaseAmount = newBalance - currentBalance;
            totalSupply += increaseAmount;
            tokenHolderBalances[account] += increaseAmount;
            magnifiedDividendCorrections[account] -= int256(increaseAmount * magnifiedDividendPerShare);
        } else if (newBalance < currentBalance) {
            uint256 decreaseAmount = currentBalance - newBalance;
            totalSupply -= decreaseAmount;
            tokenHolderBalances[account] -= decreaseAmount;
            magnifiedDividendCorrections[account] += int256(decreaseAmount * magnifiedDividendPerShare);
        }
    }
    function _safeTransferETH(address to, uint256 value) private returns (bool) {
        (bool success, ) = to.call{value: value, gas: 30_000}(new bytes(0));
        return success;
    }

    receive() external payable {}

    fallback() external payable {}
}

File 17 of 18 : IDividendTracker.sol
// SPDX-License-Identifier: MIT
// Factory: gemlabs
pragma solidity ^0.8.24;

interface IDividendTracker {
    event ExcludeFromDividends(address indexed account);
    event ClaimWaitUpdated(uint256 indexed newValue, uint256 indexed oldValue);
    event Claim(address indexed account, uint256 amount, bool indexed automatic);
    event DividendsDistributed(address indexed from, uint256 weiAmount);
    event DividendWithdrawn(address indexed to, uint256 weiAmount);

    error InvalidClaimWait(uint256 provided, uint256 min, uint256 max);
    error ClaimWaitAlreadySet(uint256 provided);
    error NoTotalSupply();

    function excludeFromDividends(address account) external;
    function updateClaimWait(uint256 newClaimWait) external;
    function getNumberOfTokenHolders() external view returns (uint256);
    function getTokenHolderBalance(address account) external view returns (uint256);
    function getAccount(
        address _account
    )
        external
        view
        returns (
            address account,
            int256 index,
            int256 iterationsUntilProcessed,
            uint256 withdrawableDividends,
            uint256 totalDividends,
            uint256 lastClaimTime,
            uint256 nextClaimTime,
            uint256 secondsUntilAutoClaimAvailable
        );
    function getAccountAtIndex(
        uint256 index
    ) external view returns (address, int256, int256, uint256, uint256, uint256, uint256, uint256);
    function process(uint256 gas) external returns (uint256, uint256, uint256);
    function processAccount(address payable account, bool automatic) external returns (bool);
    function distributeDividends(uint256 amount) external;
    function withdrawDividend() external;
    function withdrawableDividendOf(address _owner) external view returns (uint256);
    function withdrawnDividendOf(address _owner) external view returns (uint256);
    function accumulativeDividendOf(address _owner) external view returns (uint256);
    function getLargestHolder() external view returns (address largestHolder, uint256 largestBalance);
    function setBalance(address payable account, uint256 newBalance) external;
}

File 18 of 18 : IterableMapping.sol
// SPDX-License-Identifier: MIT
// Factory: gemlabs
pragma solidity ^0.8.24;

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

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

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

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

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

    function set(Map storage map, address key, uint 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];

        uint index = map.indexOf[key];
        uint lastIndex = map.keys.length - 1;
        address lastKey = map.keys[lastIndex];

        map.indexOf[lastKey] = index;
        delete map.indexOf[key];

        map.keys[index] = lastKey;
        map.keys.pop();
    }
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "viaIR": true,
  "evmVersion": "paris",
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract ABI

[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"uint256","name":"_initialSupply","type":"uint256"},{"internalType":"address","name":"_router","type":"address"},{"internalType":"uint256","name":"_minimumTokenBalanceForDividendsPct","type":"uint256"},{"internalType":"address","name":"_teamWallet","type":"address"},{"internalType":"uint256","name":"_teamFee","type":"uint256"},{"internalType":"uint256","name":"_dividendsFee","type":"uint256"},{"internalType":"uint256","name":"_burnFee","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"pair","type":"address"}],"name":"CannotRemoveCamlotPair","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"inputs":[{"internalType":"uint256","name":"totalFee","type":"uint256"}],"name":"InvalidFee","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"pair","type":"address"},{"internalType":"bool","name":"value","type":"bool"}],"name":"PairAlreadySetToValue","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"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":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"bool","name":"isExcluded","type":"bool"}],"name":"ExcludeFromFees","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":"amount","type":"uint256"}],"name":"SendDividends","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pair","type":"address"},{"indexed":true,"internalType":"bool","name":"value","type":"bool"}],"name":"SetAutomatedMarketMakerPair","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":"PINK_LOCK_CONTRACT","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"_isExcludedFromFees","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"automatedMarketMakerPairs","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"burnFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"burnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"camelotV2Pair","outputs":[{"internalType":"contract ICamelotPair","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"camelotV2Router","outputs":[{"internalType":"contract ICamelotRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"deployerWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dividendTracker","outputs":[{"internalType":"contract DividendTracker","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dividendsFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"excludeFromDividends","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"excluded","type":"bool"}],"name":"excludeFromFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isExcludedFromFees","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":[{"internalType":"uint256","name":"gas","type":"uint256"}],"name":"processDividendTracker","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pair","type":"address"},{"internalType":"bool","name":"value","type":"bool"}],"name":"setAutomatedMarketMakerPair","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"setBurnFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"setDividendsFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"setTeamFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"wallet","type":"address"}],"name":"setTeamWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swapTokensAtAmount","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":"teamFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"teamWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","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"},{"inputs":[{"internalType":"uint256","name":"claimWait","type":"uint256"}],"name":"updateClaimWait","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"withdrawableDividendOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

60808060405234620008ad576000620041458038038091620000228286620008dc565b843982019061012083830312620008aa5782516001600160401b038111620005055782620000529185016200091c565b60208401519092906001600160401b038111620005ee5790620000779185016200091c565b6040840151926200008b6060860162000987565b90608086015190620000a060a0880162000987565b9360c08801519061010060e08a01519901519280519060018060401b0382116200089657600354600181811c911680156200088b575b602082101462000877579081601f84931162000807575b50602090601f83116001146200077a578a926200076e575b50508160011b916000199060031b1c1916176003555b8051906001600160401b0382116200075a57600454600181811c911680156200074f575b60208210146200073b579081601f849311620006cb575b50602090601f83116001146200064357899262000637575b50508160011b916000199060031b1c1916176004555b33156200061e57600580546001600160a01b031980821633908117909355996001600160a01b03976200021495946200020e9490938a92919083167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08d80a36001600655338d600b541617600b55168b600c541617600c5580600d5581600e5583600f556200099c565b6200099c565b90612710918281116200060657506200023790620f42408704600a5586620009c0565b604051916113198084019291909104906001600160401b03831184841017620005f25791839160209362002e0c8439815203019084f08015620005095782169482600992878385541617845516906007541617600755843b15620005ee578290604051828163031e79db60e41b988982528060048301528160249687925af180156200053557620005d8575b5082815416803b156200055c5784809184604051809481938c83523060048401525af180156200053557908591620005c0575b50508281541683600c5416813b156200054057859184839260405194859384928d845260048401525af180156200053557908591620005a8575b505082815416803b156200055c5784809184604051809481938c83523360048401525af18015620005355790859162000590575b505082815416803b156200055c5784809184604051809481938c835261dead60048401525af18015620005355790859162000578575b505082815416803b156200055c5784809184604051809481938c8352600260048401525af18015620005355790859162000560575b505082815416803b156200055c5784809184604051809481938c83528160048401525af18015620005355790859162000544575b5050828154168360075416813b156200054057859184839260405194859384928d845260048401525af180156200053557849291869162000518575b5050541694853b15620005145783906040519283918252818373dd6e31a046b828cbbafb939c2a394629aff8bbdc998a60048401525af180156200050957620004ed575b50620004dd933383526010602052604083209160ff1992600184825416179055600c541683526040832060018382541617905530835260408320600183825416179055825260016040832091825416179055339062000a1f565b604051611a5f9081620013ad8239f35b620004f98391620008b2565b62000505573862000483565b5080fd5b6040513d85823e3d90fd5b8380fd5b6200052691929350620008b2565b6200051457829084386200043f565b6040513d87823e3d90fd5b8580fd5b6200054f90620008b2565b6200051457833862000403565b8480fd5b6200056b90620008b2565b62000514578338620003cf565b6200058390620008b2565b620005145783386200039a565b6200059b90620008b2565b6200051457833862000364565b620005b390620008b2565b6200051457833862000330565b620005cb90620008b2565b62000514578338620002f6565b620005e690949194620008b2565b9238620002c3565b8280fd5b634e487b7160e01b87526041600452602487fd5b6024906040519063179c637760e11b82526004820152fd5b604051631e4fbdf760e01b815260048101879052602490fd5b0151905038806200016e565b60048a527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b9250601f1984168a5b818110620006b2575090846001959493921062000698575b505050811b0160045562000184565b015160001960f88460031b161c1916905538808062000689565b9293602060018192878601518155019501930162000671565b60048a529091507f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b601f840160051c81016020851062000733575b90849392915b601f830160051c820181106200072457505062000156565b8b81558594506001016200070c565b508062000706565b634e487b7160e01b89526022600452602489fd5b90607f16906200013f565b634e487b7160e01b88526041600452602488fd5b01519050388062000105565b60038b528a93507fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b91905b601f1984168510620007eb576001945083601f19811610620007d1575b505050811b016003556200011b565b015160001960f88460031b161c19169055388080620007c2565b81810151835560209485019460019093019290910190620007a5565b60038b529091507fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b601f840160051c8101602085106200086f575b90849392915b601f830160051c8201811062000860575050620000ed565b8c815585945060010162000848565b508062000842565b634e487b7160e01b8a52602260045260248afd5b90607f1690620000d6565b634e487b7160e01b89526041600452602489fd5b80fd5b600080fd5b6001600160401b038111620008c657604052565b634e487b7160e01b600052604160045260246000fd5b601f909101601f19168101906001600160401b03821190821017620008c657604052565b6001600160401b038111620008c657601f01601f191660200190565b9080601f83011215620008ad57815190620009378262000900565b92620009476040519485620008dc565b82845260209160208483010111620008ad5760005b838110620009735750505060206000918301015290565b81810183015185820184015282016200095c565b51906001600160a01b0382168203620008ad57565b91908201809211620009aa57565b634e487b7160e01b600052601160045260246000fd5b81810292918115918404141715620009aa57565b8115620009df570490565b634e487b7160e01b600052601260045260246000fd5b91908203918211620009aa57565b90816060910312620008ad578051916040602083015192015190565b821562000e585730600090815260208190526040902054600a548110159062000a5c62000a52600d54600e54906200099c565b600f54906200099c565b918062000e40575b8062000e11575b8062000df8575b8062000ddf575b62000cbb575b509062000b1b62000b219462000b1b9362000aa462000aa060125460ff1690565b1590565b6001600160a01b038516600090815260116020526040902062000ace9062000aa0905b5460ff1690565b8062000c8c575b62000c83575b6001600160a01b038516600090815260106020526040902062000afe9062000ac7565b801562000c59575b62000c50575b62000c0d575b50848362000ee1565b62001340565b62000b3262000aa060125460ff1690565b62000b3957565b6009546001600160a01b03166040516001624d3b8760e01b031981526207a120600482015290606090829060249082906000905af16000918160009160009362000bd1575b5062000b8957505050565b6040805193845260208401919091528201526207a120606082015232906001907fc864333d6121033635ab41b29ae52f10a22cf4438c3e4f1c4c68518feb2f8a9890608090a3565b9150925062000bfc915060603d60601162000c05575b62000bf38183620008dc565b81019062000a03565b91923862000b7e565b503d62000be7565b9062000c2a62000c2262000c499383620009c0565b612710900490565b9062000c3882308762000ee1565b62000c433062001340565b620009f5565b3862000b12565b50600062000b0c565b506001600160a01b038716600090815260106020526040902062000c7d9062000ac7565b62000b06565b50600062000adb565b506001600160a01b038716600090815260116020526040902062000cb59062000aa09062000ac7565b62000ad5565b62000cce600160ff196012541617601255565b62000cf58262000cef62000ce8600e54600d54906200099c565b84620009c0565b620009d4565b8062000d5c575b50600f54908162000d34575b50509062000b1b62000b219462000b1b9362000d2960ff1960125416601255565b929350945062000a7f565b8262000cef62000d539362000d4c93969596620009c0565b3062001309565b90388062000d08565b62000d679062000fae565b4762000d9d62000d95600e5462000d8e62000d838286620009c0565b91600d54906200099c565b90620009d4565b8092620009f5565b908062000dbf575b50801562000cfc5762000db8906200125e565b3862000cfc565b600c5462000dd791906001600160a01b0316620011fe565b503862000da5565b506005546001600160a01b038581169116141562000a79565b506005546001600160a01b038481169116141562000a72565b506001600160a01b038316600090815260116020526040902062000e3a9062000aa09062000ac7565b62000a6b565b5062000e5262000aa060125460ff1690565b62000a64565b62000e64925062000e66565b565b6000916001600160a01b0391821691908262000ec057600080516020620041258339815191529160209162000e9e866002546200099c565b6002555b16938462000eb4575b604051908152a3565b84815280825262000eab565b82845260208481526000805160206200412583398151915292909162000ea2565b6001600160a01b03908116918262000f4b57600080516020620041258339815191529160209162000f15866002546200099c565b6002555b16938462000f32578060025403600255604051908152a3565b8460005260008252604060002081815401905562000eab565b600083815280602052604081205485811062000f8a57918160408760209588600080516020620041258339815191529896528387520391205562000f19565b84866064926040519263391434e360e21b8452600484015260248301526044820152fd5b60408051606081016001600160401b03811182821017620008c6578252600281526020908181019083368337805115620011e85730825260075484516315ab88c960e31b81526001600160a01b0394909160049190861681848481845afa938415620011dd576000946200119e575b508451936001946001101562001189578716888601523015620011725780156200115b5730600052600182528760002081600052825288886000205587518981527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925833092a385600754169561012c4201948542116200114657873b15620008ad5798959493918893919351998a97632955261160e11b895260c48901938901526000602489015260c060448901525180925260e4870195936000905b8382106200112b57505050505050600083819593819330606484015283608484015260a483015203925af1908115620011215750620011165750565b62000e6490620008b2565b513d6000823e3d90fd5b8551811688528b9850968201969482019490840190620010da565b601184634e487b7160e01b6000525260246000fd5b8751634a1406b160e11b8152600081850152602490fd5b875163e602df0560e01b8152600081850152602490fd5b603284634e487b7160e01b6000525260246000fd5b9093508181813d8311620011d5575b620011b98183620008dc565b81010312620008ad57620011cd9062000987565b92386200101d565b503d620011ad565b88513d6000823e3d90fd5b634e487b7160e01b600052603260045260246000fd5b604051602081016001600160401b03811182821017620008c6576040526000808094819482809552617530f1903d156200125a573d906200123f8262000900565b916200124f6040519384620008dc565b825260203d92013e90565b5090565b6009546001600160a01b0390620012799083908316620011fe565b62001282575050565b6009541690813b15620008ad5760008092602460405180958193633243c79160e01b83528660048401525af1908115620012fd577fb0cc2628d6d644cf6be9d8110e142297ac910d6d8026d795a99f272fd9ad60b192602092620012eb575b50604051908152a1565b620012f690620008b2565b38620012e1565b6040513d6000823e3d90fd5b906001600160a01b038216156200132757600062000e649262000a1f565b604051634b637e8f60e11b815260006004820152602490fd5b6001600160a01b03908116600081815260208190526040812054600954909316929091833b15620005ee5790604483928360405196879485936338c110ef60e21b8552600485015260248401525af1908115620013a05750620011165750565b604051903d90823e3d90fdfe6080604081815260049182361015610022575b505050361561002057600080fd5b005b600092833560e01c91826306fdde0314610bf557508163095ea7b314610bcb5781630acafbec14610b9c5781631525ff7d14610b5357816318160ddd14610b3457816323b872dd14610af75781632891721814610ace5781632c1f521614610aa5578163313ce56714610a8957816331e79db014610a1457816342966c68146109f65781634bf2c7c9146109c7578382634e71d92d14610940575081634fbee1931461037457816359927044146109175781635d60c7be146108ee578163700bb1911461081857816370a08231146107e1578163715018a61461078357816379cc67901461075357816387c34ae2146107245781638da5cb5b146106fb57816395d89b41146105f65781639a7a23d6146105db5781639c436254146105b2578163a8b9d24014610516578163a9059cbb146104e5578163aeca8f9f146104c6578163b62496f514610488578163c02466681461041f578163d7c94efd14610400578163dd62ed3e146103b2578163e0bf7fd114610374578163e2f4560514610355578163e6ec64ec1461031157838263e98030c71461028e57508163f2fde38b146101f9575063fce589d8146101d85780610012565b346101f557816003193601126101f557602090600f549051908152f35b5080fd5b90503461028a57602036600319011261028a57610214610d2f565b9061021d610f3c565b6001600160a01b03918216928315610274575050600554826bffffffffffffffffffffffff60a01b821617600555167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a380f35b51631e4fbdf760e01b8152908101849052602490fd5b8280fd5b8091843461030d57602036600319011261030d576102aa610f3c565b6009546001600160a01b031691823b15610308578392602484928451958693849263e98030c760e01b84528035908401525af19081156102ff57506102ec5750f35b6102f590610d8f565b6102fc5780f35b80fd5b513d84823e3d90fd5b505050fd5b5050fd5b90503461028a57602036600319011261028a5780359161032f610f3c565b6127108311610340575050600e5580f35b91602492519163179c637760e11b8352820152fd5b5050346101f557816003193601126101f557602090600a549051908152f35b5050346101f55760203660031901126101f55760209160ff9082906001600160a01b0361039f610d2f565b1681526010855220541690519015158152f35b5050346101f557806003193601126101f5576020916103cf610d2f565b826103d8610d4a565b6001600160a01b03928316845260018652922091166000908152908352819020549051908152f35b5050346101f557816003193601126101f557602090600e549051908152f35b5050346101f5577f9d8f7706ea1113d1a167b526eca956215946dd36cc7df39eb16180222d8b5df7602061045236610d60565b9061045b610f3c565b6001600160a01b031680865260108352848620805460ff191660ff8415151617905593519015158152a280f35b5050346101f55760203660031901126101f55760209160ff9082906001600160a01b036104b3610d2f565b1681526011855220541690519015158152f35b5050346101f557816003193601126101f557602090600d549051908152f35b5050346101f557806003193601126101f55760209061050f610505610d2f565b602435903361103b565b5160018152f35b8383346101f5576020928360031936011261028a5783610534610d2f565b60095484516302a2e74960e61b81526001600160a01b039283169481019490945283916024918391165afa9283156105a7578093610575575b505051908152f35b909192508382813d83116105a0575b61058e8183610db9565b810103126102fc57505190838061056d565b503d610584565b8251903d90823e3d90fd5b5050346101f557816003193601126101f55760085490516001600160a01b039091168152602090f35b83346102fc576105f36105ed36610d60565b90610df6565b80f35b8383346101f557816003193601126101f55780519180938054916001908360011c92600185169485156106f1575b60209586861081146106de578589529081156106ba5750600114610662575b61065e8787610654828c0383610db9565b5191829182610ce6565b0390f35b81529295507f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b5b8284106106a7575050508261065e9461065492820101948680610643565b8054868501880152928601928101610689565b60ff19168887015250505050151560051b83010192506106548261065e8680610643565b634e487b7160e01b845260228352602484fd5b93607f1693610624565b5050346101f557816003193601126101f55760055490516001600160a01b039091168152602090f35b90503461028a57602036600319011261028a57803591610742610f3c565b6127108311610340575050600d5580f35b5050346101f5573660031901126102fc576105f361076f610d2f565b6024359061077e823383610f68565b611091565b83346102fc57806003193601126102fc5761079c610f3c565b600580546001600160a01b031981169091556000906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b5050346101f55760203660031901126101f55760209181906001600160a01b03610809610d2f565b16815280845220549051908152f35b9190503461028a57602036600319011261028a5760095481516001624d3b8760e01b0319815283359381018490529291906060908490602490829088906001600160a01b03165af19081156108e5578493859086936108af575b50815194855260208501528301526060820152817fc864333d6121033635ab41b29ae52f10a22cf4438c3e4f1c4c68518feb2f8a9860803293a380f35b919450506108d5915060603d6060116108de575b6108cd8183610db9565b810190610ddb565b91939038610872565b503d6108c3565b513d85823e3d90fd5b5050346101f557816003193601126101f557600b5490516001600160a01b039091168152602090f35b5050346101f557816003193601126101f557600c5490516001600160a01b039091168152602090f35b9291503461030d578260031936011261030d57602090604460018060a01b0360095416918451958693849263bc4c4b3760e01b845233908401528160248401525af19081156102ff5750610992575080f35b6020813d6020116109bf575b816109ab60209383610db9565b810103126101f55751801515036102fc5780f35b3d915061099e565b90503461028a57602036600319011261028a578035916109e5610f3c565b6127108311610340575050600f5580f35b8390346101f55760203660031901126101f5576105f3903533611091565b9190503461028a57602036600319011261028a5782610a31610d2f565b610a39610f3c565b6009546001600160a01b039190821690813b15610a8557836024928651978895869463031e79db60e41b865216908401525af19081156102ff5750610a7c575080f35b6105f390610d8f565b8380fd5b5050346101f557816003193601126101f5576020905160128152f35b5050346101f557816003193601126101f55760095490516001600160a01b039091168152602090f35b5050346101f557816003193601126101f55760075490516001600160a01b039091168152602090f35b5050346101f55760603660031901126101f55760209061050f610b18610d2f565b610b20610d4a565b60443591610b2f833383610f68565b61103b565b5050346101f557816003193601126101f5576020906002549051908152f35b8390346101f55760203660031901126101f557356001600160a01b038116908190036101f557610b81610f3c565b6bffffffffffffffffffffffff60a01b600c541617600c5580f35b5050346101f557816003193601126101f5576020905173dd6e31a046b828cbbafb939c2a394629aff8bbdc8152f35b5050346101f557806003193601126101f55760209061050f610beb610d2f565b60243590336110ac565b92915034610a855783600319360112610a8557600354600181811c9186908281168015610cdc575b6020958686108214610cc95750848852908115610ca75750600114610c4e575b61065e8686610654828b0383610db9565b929550600383527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b5b828410610c94575050508261065e94610654928201019438610c3d565b8054868501880152928601928101610c77565b60ff191687860152505050151560051b83010192506106548261065e38610c3d565b634e487b7160e01b845260229052602483fd5b93607f1693610c1d565b6020808252825181830181905290939260005b828110610d1b57505060409293506000838284010152601f8019910116010190565b818101860151848201604001528501610cf9565b600435906001600160a01b0382168203610d4557565b600080fd5b602435906001600160a01b0382168203610d4557565b6040906003190112610d45576004356001600160a01b0381168103610d4557906024358015158103610d455790565b67ffffffffffffffff8111610da357604052565b634e487b7160e01b600052604160045260246000fd5b90601f8019910116810190811067ffffffffffffffff821117610da357604052565b90816060910312610d45578051916040602083015192015190565b600b546000906001600160a01b039081163303610f36578080600854169316928314610f1d57828252601160205260ff604083205416938015158095151514610eff578383526011602052610e5a81604085209060ff801983541691151516179055565b610e86575b50807fffa9187bf1f18bf477bd0ea1bcbb64e93b6a98132473929edfce215cd9b16fab91a3565b60095416803b156101f55781809160246040518094819363031e79db60e41b83528860048401525af18015610ef457907fffa9187bf1f18bf477bd0ea1bcbb64e93b6a98132473929edfce215cd9b16fab9291610ee5575b5090610e5f565b610eee90610d8f565b38610ede565b6040513d84823e3d90fd5b6044848660405191632b100e0760e21b835260048301526024820152fd5b604051636b6fda0f60e11b815260048101849052602490fd5b50505050565b6005546001600160a01b03163303610f5057565b60405163118cdaa760e01b8152336004820152602490fd5b9160018060a01b038093169160009383855260016020526040938486209183169182875260205284862054926000198403610fa7575b50505050505050565b84841061100b57508015610ff3578115610fdb57855260016020528385209085526020520391205538808080808080610f9e565b8451634a1406b160e11b815260048101879052602490fd5b845163e602df0560e01b815260048101879052602490fd5b8551637dc7a0d960e11b81526001600160a01b039190911660048201526024810184905260448101859052606490fd5b91906001600160a01b03808416156110785781161561105f5761105d926111a2565b565b60405163ec442f0560e01b815260006004820152602490fd5b604051634b637e8f60e11b815260006004820152602490fd5b906001600160a01b0382161561107857600061105d926111a2565b6001600160a01b03908116918215611126571691821561110d5760207f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925918360005260018252604060002085600052825280604060002055604051908152a3565b604051634a1406b160e11b815260006004820152602490fd5b60405163e602df0560e01b815260006004820152602490fd5b9190820180921161114c57565b634e487b7160e01b600052601160045260246000fd5b8181029291811591840414171561114c57565b811561117f570490565b634e487b7160e01b600052601260045260246000fd5b9190820391821161114c57565b82156115925730600090815260208190526040902054600a54811015906111da6111d1600d54600e549061113f565b600f549061113f565b918061157d575b80611552575b8061152b575b80611504575b611406575b509061128561128a946112859361121861121460125460ff1690565b1590565b6001600160a01b038516600090815260116020526040902061124090611214905b5460ff1690565b806113db575b6113d3575b6001600160a01b038516600090815260106020526040902061126c90611239565b80156113ac575b6113a4575b61136b575b50848361160a565b6119a0565b61129961121460125460ff1690565b61129f57565b6009546112bc906001600160a01b03165b6001600160a01b031690565b6040516001624d3b8760e01b031981526207a120600482015290606090829060249082906000905af160009181600091600093611346575b506112fe57505050565b6040805193845260208401919091528201526207a120606082015232906001907fc864333d6121033635ab41b29ae52f10a22cf4438c3e4f1c4c68518feb2f8a9890608090a3565b91509250611363915060603d6060116108de576108cd8183610db9565b9192386112f4565b9061138461137c61139e9383611162565b612710900490565b9061139082308761160a565b611399306119a0565b611195565b3861127d565b506000611278565b506001600160a01b03871660009081526010602052604090206113ce90611239565b611273565b50600061124b565b506001600160a01b03871660009081526011602052604090206114019061121490611239565b611246565b611418600160ff196012541617601255565b6114398261143461142e600e54600d549061113f565b84611162565b611175565b80611493575b50600f549081611471575b50509061128561128a946112859361146760ff1960125416601255565b92935094506111f8565b8261143461148b9361148593969596611162565b30611091565b90388061144a565b61149c906116e2565b476114ca6114c3600e546114bd6114b38286611162565b91600d549061113f565b90611175565b8092611195565b90806114e7575b50801561143f576114e1906118fe565b3861143f565b600c546114fd91906001600160a01b0316611884565b50386114d1565b5060055461151a906001600160a01b03166112b0565b6001600160a01b03851614156111f3565b50600554611541906001600160a01b03166112b0565b6001600160a01b03841614156111ed565b506001600160a01b03831660009081526011602052604090206115789061121490611239565b6111e7565b5061158d61121460125460ff1690565b6111e1565b61105d92506000916001600160a01b039182169190826115eb57600080516020611a0a833981519152916020916115cb8660025461113f565b6002555b1693846115e0575b604051908152a3565b8481528082526115d7565b8284526020848152600080516020611a0a8339815191529290916115cf565b6001600160a01b03808216929091836116715750600080516020611a0a8339815191529160209161163d8660025461113f565b6002555b169384611659578060025403600255604051908152a3565b846000526000825260406000208181540190556115d7565b600090848252816020526040822054908682106116b05750918160408760209588600080516020611a0a83398151915298965283875203912055611641565b60405163391434e360e21b81526001600160a01b03919091166004820152602481019190915260448101869052606490fd5b60408051916060830183811067ffffffffffffffff821117610da35782526002835260209081840190833683378451156118295730825260075484516315ab88c960e31b81526001600160a01b0392909183168583600481845afa9283156118795760009361183f575b50875192600193600110156118295761176d9185849216898b0152306110ac565b82600754169461012c42019384421161114c57863b15610d4557918798959493919851988996632955261160e11b885260c488019260048901526000602489015260c060448901525180925260e4870195936000905b83821061180f57505050505050600083819593819330606484015283608484015260a483015203925af190811561180557506117fc5750565b61105d90610d8f565b513d6000823e3d90fd5b8551811688528b98509682019694820194908401906117c3565b634e487b7160e01b600052603260045260246000fd5b8681819593953d8311611872575b6118578183610db9565b810103126101f557519084821682036102fc5750913861174c565b503d61184d565b87513d6000823e3d90fd5b60405167ffffffffffffffff91906020810183811182821017610da3576040526000808095819482809552617530f1913d156118f9573d9182116118e557604051916118da601f8201601f191660200184610db9565b825260203d92013e90565b634e487b7160e01b81526041600452602490fd5b505090565b6009546001600160a01b03906119179083908316611884565b61191f575050565b6009541690813b15610d455760008092602460405180958193633243c79160e01b83528660048401525af1908115611994577fb0cc2628d6d644cf6be9d8110e142297ac910d6d8026d795a99f272fd9ad60b192602092611985575b50604051908152a1565b61198e90610d8f565b3861197b565b6040513d6000823e3d90fd5b6001600160a01b03908116600081815260208190526040812054600954909316929091833b1561028a5790604483928360405196879485936338c110ef60e21b8552600485015260248401525af19081156119fd57506117fc5750565b604051903d90823e3d90fdfeddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220425b67829947d144c6e012cb2d28f285c11e7c12adba85f9bc8dd8052b16c81364736f6c634300081800336080346100bc57601f61131938819003918201601f19168301916001600160401b038311848410176100c1578084926020946040528339810103126100bc575133156100a35760008054336001600160a01b0319821681178355604051939290916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a3610e10600955600a5561124190816100d88239f35b604051631e4fbdf760e01b815260006004820152602490fd5b600080fd5b634e487b7160e01b600052604160045260246000fdfe608060408181526004918236101561001f575b505050361561001d57005b005b600090813560e01c90816309bbedde1461084e5750806318160ddd1461082f578063226cfa3d146107f557806327ce0147146107c45780633009a609146107a557806331e79db0146107245780633243c791146106605780633a7960e0146106415780634e7b827f146106025780635183d6fd146105e25780636a474002146105c45780636f2789ec146105a5578063715018a61461054b57806385a6b3ae1461052c5780638da5cb5b14610504578063a2ec70d2146103f4578063a8b9d240146104cc578063aafd847a14610492578063bc4c4b371461044d578063be10b6141461042e578063d3573e42146103f4578063e30443bc146103c0578063e98030c714610314578063f223273a14610296578063f2fde38b14610207578063fbcbc0f1146101845763ffb2c479036100125734610181576020366003190112610181575061016f60609235610e01565b91929081519384526020840152820152f35b80fd5b5091346102035760203660031901126102035735916001600160a01b038316830361018157506101b66101ff92610d30565b97516001600160a01b039097168752602087019590955260408601939093526060850191909152608084015260a083015260c082015260e0810191909152908190610100820190565b0390f35b8280fd5b50919034610203576020366003190112610203576001600160a01b038235818116939192908490036102925761023b610f1b565b831561027c57505082546001600160a01b0319811683178455167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b51631e4fbdf760e01b8152908101849052602490fd5b8480fd5b5034610181578060031936011261018157806001805482805b8281106102d057505084516001600160a01b03909416845250506020820152f35b6102d981610cca565b905460039190911b1c6001600160a01b0316808352600d60205287832054868111610308575b505083016102af565b909650945083886102ff565b50913461020357602036600319011261020357803591610332610f1b565b610e1080841080156103b4575b6103905750600954831461037b57505080600955807f474ea64804364a1e29a4487ddb63c3342a2dd826ccd8acf48825e680a0e6f20f8380a380f35b916024925191632c42b16760e01b8352820152fd5b90926064935192630100828360e11b84528301526024820152620151806044820152fd5b5062015180841161033f565b5090346103f057366003190112610181576103ed6103dc61086a565b6103e4610f1b565b60243590610ab6565b80f35b5080fd5b50913461020357602036600319011261020357356001600160a01b038116908190036102035782829160209452600d845220549051908152f35b5090346103f057816003193601126103f057602090600a549051908152f35b5090346103f057806003193601126103f05761046761086a565b602435928315158403610181575060209261048991610484610f1b565b6109f5565b90519015158152f35b50913461020357602036600319011261020357356001600160a01b038116908190036102035782829160209452600f845220549051908152f35b5091346102035760203660031901126102035735916001600160a01b038316830361018157506104fd6020926109c5565b9051908152f35b5090346103f057816003193601126103f057905490516001600160a01b039091168152602090f35b5090346103f057816003193601126103f0576020906008549051908152f35b5034610181578060031936011261018157610564610f1b565b80546001600160a01b03198116825581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b5090346103f057816003193601126103f0576020906009549051908152f35b50346101815780600319360112610181576105de3361108c565b5080f35b503461018157602036600319011261018157506101b66101ff9235610965565b50913461020357602036600319011261020357356001600160a01b0381169081900361020357818360ff9260209552600b855220541690519015158152f35b5090346103f057816003193601126103f0576020906007549051908152f35b5090346103f05760203660031901126103f05782359061067e610f1b565b6006548015610714578215908115610694578480f35b60075491608085901b90600160801b868304141715610701576106f5959650906106c092910490610958565b600755518181527fa493a9229478c3fcd73f66d2cdeb7f94fd0f341da924d1054236d7845411651160203392a2600854610958565b60085580388080808480f35b634e487b7160e01b865260118752602486fd5b8151636328a90f60e11b81528590fd5b50913461020357602036600319011261020357356001600160a01b03811691908281036107a15761077a91610757610f1b565b838552600b6020528420805460ff1916600117905561077581610f47565b610fad565b7fa878b31040b2e6d0a9a3d3361209db3908ba62014b0dca52adbaee451d128b258280a280f35b8380fd5b5090346103f057816003193601126103f0576020906005549051908152f35b5091346102035760203660031901126102035735916001600160a01b038316830361018157506104fd6020926108b7565b50913461020357602036600319011261020357356001600160a01b038116908190036102035782829160209452600c845220549051908152f35b5090346103f057816003193601126103f0576020906006549051908152f35b9050346103f057816003193601126103f0576020906001548152f35b600435906001600160a01b038216820361088057565b600080fd5b919091600083820193841291129080158216911516176108a157565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b03166000908152600d6020908152604080832054600e90925282205460075490918181029190848212600160ff1b82141661093157818305149015171561091d579061090991610885565b81811215610915575090565b905060801c90565b634e487b7160e01b83526011600452602483fd5b634e487b7160e01b85526011600452602485fd5b818102929181159184041417156108a157565b919082018092116108a157565b6001548110156109a25761097b61099291610cca565b905460039190911b1c6001600160a01b0316610d30565b9697959694959394929391929091565b5060009060001990819083908190819081908190565b919082039182116108a157565b6109f2906109d2816108b7565b6001600160a01b039091166000908152600f6020526040902054906109b8565b90565b906109ff8261108c565b9182610a0d57505050600090565b60207fa2c38e2d2fb7e3e1912d937fd1ca11ed6d51864dee4cfa7a7bf02becd7acf0929160018060a01b03169283600052600c825242604060002055604051948552151593a3600190565b610a618161108c565b80610a6d575050600090565b7fa2c38e2d2fb7e3e1912d937fd1ca11ed6d51864dee4cfa7a7bf02becd7acf0926020600193848060a01b03169283600052600c825242604060002055604051908152a3600190565b6001600160a01b0381166000818152600b602090815260408083205494959460ff16610cc257600a548510610cac57838352600d8252808320548581811115610c4d57610b3591610b06916109b8565b610b1281600654610958565b600655858552600d8452828520610b2a828254610958565b905560075490610945565b848452600e8352610b4a828520918254610d17565b90555b6001600160a01b03841660009081526004602052604090205460ff1615610b9e575050506001600160a01b0316600090815260026020526040902055610b9b905b610b96610f1b565b610a58565b50565b6001600160a01b03841660009081526004602052604090209394600394805460ff191660011790556001600160a01b0386166000908152600260205260409020556001549384928685525282205568010000000000000000821015610c395750610b9b9291610c16826001610c349401600155610cca565b90919060018060a01b038084549260031b9316831b921b1916179055565b610b8e565b634e487b7160e01b81526041600452602490fd5b90808210610c5d575b5050610b4d565b610c8e91610c6a916109b8565b610c76816006546109b8565b600655858552600d8452828520610b2a8282546109b8565b848452600e8352610ca3828520918254610885565b90558438610c56565b505050610b9b92915080610775610c3492610f47565b505050505050565b600154811015610d015760016000527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60190600090565b634e487b7160e01b600052603260045260246000fd5b818103929160001380158285131691841216176108a157565b9081610d3b816111b8565b916000199160009182851215610daa575b610d55826109c5565b92610d5f836108b7565b6001600160a01b039093168152600c6020526040812054918215610da457610d8960095484610958565b915b8242811115610da0576109f2915042906109b8565b5090565b81610d8b565b9250600554808511600014610dc957610dc39085610d17565b92610d4c565b60015481811115610de757610dc391610de1916109b8565b85610885565b5050610dc382610de1565b60001981146108a15760010190565b600191600154918215610f0d57916005549260005a90866000946000985b610e32575b505050505082600555929190565b90919293949685841080610f04575b15610efd57610e4f90610df2565b968254881015610ef4575b610e6388610cca565b60018060a01b0391549060031b1c1680600052600c602052610e896040600020546111ec565b610ec8575b50610e9890610df2565b945a94858111610eae575b509392919081610e1f565b85610ebd610ec2928697610958565b6109b8565b93610ea3565b610ed490610b96610f1b565b610edf575b38610e8e565b97610eec610e9891610df2565b989050610ed9565b60009750610e5a565b9694610e24565b50818810610e41565b506005546000935083925090565b6000546001600160a01b03163303610f2f57565b60405163118cdaa760e01b8152336004820152602490fd5b6001600160a01b03166000818152600d602052604081205480610f6957505050565b610fa991610f9882610f7f6040946006546109b8565b600655858352600d602052838320610b2a8282546109b8565b938152600e60205220918254610885565b9055565b6001600160a01b039081166000818152600460205260408120805460ff8116156110855760ff1916905560026020528060408120556003602052604081205491600154926000199384810190811161107157611035929186611011610c1693610cca565b90549060031b1c169283865260036020528160408720558552846040812055610cca565b60015490811561105d5750019061104b82610cca565b909182549160031b1b19169055600155565b634e487b7160e01b81526031600452602490fd5b634e487b7160e01b84526011600452602484fd5b5050505050565b6001600160a01b031661109e816109c5565b90816110ab575050600090565b6000908082526020600f81526040906110c78583862054610958565b838552600f825282852055815167ffffffffffffffff908083018281118282101761119e578452859052848080808988617530f1903d156111b2573d81811161119e57845191601f8201601f19908116603f011683019081118382101761118a578552815285833d92013e5b837fee503bee2bb6a87e57bc57db795f98137327401a0e7b7ce42e37926cc1a9ca4d838551898152a215611168575050505090565b611180849584600f94959652838352848720546109b8565b9385525282205590565b634e487b7160e01b88526041600452602488fd5b634e487b7160e01b87526041600452602487fd5b50611133565b6001600160a01b031660009081526004602052604090205460ff16156111e657600360205260406000205490565b60001990565b428111611205576111fd90426109b8565b600954111590565b5060009056fea2646970667358221220793a0e8d3b5d6f63c59be1e24000ae2abef254699377f165bc11e5b9777e253764736f6c63430008180033ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef0000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000d3c21bcecceda100000000000000000000000000000018e621b64d7808c3c47bccbbd7485d23f257d26f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000033f5dcece4505afeb69c6d0f2bf856d13b2afab8000000000000000000000000000000000000000000000000000000000000009600000000000000000000000000000000000000000000000000000000000000fa00000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000005505550533200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045055503200000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x6080604081815260049182361015610022575b505050361561002057600080fd5b005b600092833560e01c91826306fdde0314610bf557508163095ea7b314610bcb5781630acafbec14610b9c5781631525ff7d14610b5357816318160ddd14610b3457816323b872dd14610af75781632891721814610ace5781632c1f521614610aa5578163313ce56714610a8957816331e79db014610a1457816342966c68146109f65781634bf2c7c9146109c7578382634e71d92d14610940575081634fbee1931461037457816359927044146109175781635d60c7be146108ee578163700bb1911461081857816370a08231146107e1578163715018a61461078357816379cc67901461075357816387c34ae2146107245781638da5cb5b146106fb57816395d89b41146105f65781639a7a23d6146105db5781639c436254146105b2578163a8b9d24014610516578163a9059cbb146104e5578163aeca8f9f146104c6578163b62496f514610488578163c02466681461041f578163d7c94efd14610400578163dd62ed3e146103b2578163e0bf7fd114610374578163e2f4560514610355578163e6ec64ec1461031157838263e98030c71461028e57508163f2fde38b146101f9575063fce589d8146101d85780610012565b346101f557816003193601126101f557602090600f549051908152f35b5080fd5b90503461028a57602036600319011261028a57610214610d2f565b9061021d610f3c565b6001600160a01b03918216928315610274575050600554826bffffffffffffffffffffffff60a01b821617600555167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a380f35b51631e4fbdf760e01b8152908101849052602490fd5b8280fd5b8091843461030d57602036600319011261030d576102aa610f3c565b6009546001600160a01b031691823b15610308578392602484928451958693849263e98030c760e01b84528035908401525af19081156102ff57506102ec5750f35b6102f590610d8f565b6102fc5780f35b80fd5b513d84823e3d90fd5b505050fd5b5050fd5b90503461028a57602036600319011261028a5780359161032f610f3c565b6127108311610340575050600e5580f35b91602492519163179c637760e11b8352820152fd5b5050346101f557816003193601126101f557602090600a549051908152f35b5050346101f55760203660031901126101f55760209160ff9082906001600160a01b0361039f610d2f565b1681526010855220541690519015158152f35b5050346101f557806003193601126101f5576020916103cf610d2f565b826103d8610d4a565b6001600160a01b03928316845260018652922091166000908152908352819020549051908152f35b5050346101f557816003193601126101f557602090600e549051908152f35b5050346101f5577f9d8f7706ea1113d1a167b526eca956215946dd36cc7df39eb16180222d8b5df7602061045236610d60565b9061045b610f3c565b6001600160a01b031680865260108352848620805460ff191660ff8415151617905593519015158152a280f35b5050346101f55760203660031901126101f55760209160ff9082906001600160a01b036104b3610d2f565b1681526011855220541690519015158152f35b5050346101f557816003193601126101f557602090600d549051908152f35b5050346101f557806003193601126101f55760209061050f610505610d2f565b602435903361103b565b5160018152f35b8383346101f5576020928360031936011261028a5783610534610d2f565b60095484516302a2e74960e61b81526001600160a01b039283169481019490945283916024918391165afa9283156105a7578093610575575b505051908152f35b909192508382813d83116105a0575b61058e8183610db9565b810103126102fc57505190838061056d565b503d610584565b8251903d90823e3d90fd5b5050346101f557816003193601126101f55760085490516001600160a01b039091168152602090f35b83346102fc576105f36105ed36610d60565b90610df6565b80f35b8383346101f557816003193601126101f55780519180938054916001908360011c92600185169485156106f1575b60209586861081146106de578589529081156106ba5750600114610662575b61065e8787610654828c0383610db9565b5191829182610ce6565b0390f35b81529295507f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b5b8284106106a7575050508261065e9461065492820101948680610643565b8054868501880152928601928101610689565b60ff19168887015250505050151560051b83010192506106548261065e8680610643565b634e487b7160e01b845260228352602484fd5b93607f1693610624565b5050346101f557816003193601126101f55760055490516001600160a01b039091168152602090f35b90503461028a57602036600319011261028a57803591610742610f3c565b6127108311610340575050600d5580f35b5050346101f5573660031901126102fc576105f361076f610d2f565b6024359061077e823383610f68565b611091565b83346102fc57806003193601126102fc5761079c610f3c565b600580546001600160a01b031981169091556000906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b5050346101f55760203660031901126101f55760209181906001600160a01b03610809610d2f565b16815280845220549051908152f35b9190503461028a57602036600319011261028a5760095481516001624d3b8760e01b0319815283359381018490529291906060908490602490829088906001600160a01b03165af19081156108e5578493859086936108af575b50815194855260208501528301526060820152817fc864333d6121033635ab41b29ae52f10a22cf4438c3e4f1c4c68518feb2f8a9860803293a380f35b919450506108d5915060603d6060116108de575b6108cd8183610db9565b810190610ddb565b91939038610872565b503d6108c3565b513d85823e3d90fd5b5050346101f557816003193601126101f557600b5490516001600160a01b039091168152602090f35b5050346101f557816003193601126101f557600c5490516001600160a01b039091168152602090f35b9291503461030d578260031936011261030d57602090604460018060a01b0360095416918451958693849263bc4c4b3760e01b845233908401528160248401525af19081156102ff5750610992575080f35b6020813d6020116109bf575b816109ab60209383610db9565b810103126101f55751801515036102fc5780f35b3d915061099e565b90503461028a57602036600319011261028a578035916109e5610f3c565b6127108311610340575050600f5580f35b8390346101f55760203660031901126101f5576105f3903533611091565b9190503461028a57602036600319011261028a5782610a31610d2f565b610a39610f3c565b6009546001600160a01b039190821690813b15610a8557836024928651978895869463031e79db60e41b865216908401525af19081156102ff5750610a7c575080f35b6105f390610d8f565b8380fd5b5050346101f557816003193601126101f5576020905160128152f35b5050346101f557816003193601126101f55760095490516001600160a01b039091168152602090f35b5050346101f557816003193601126101f55760075490516001600160a01b039091168152602090f35b5050346101f55760603660031901126101f55760209061050f610b18610d2f565b610b20610d4a565b60443591610b2f833383610f68565b61103b565b5050346101f557816003193601126101f5576020906002549051908152f35b8390346101f55760203660031901126101f557356001600160a01b038116908190036101f557610b81610f3c565b6bffffffffffffffffffffffff60a01b600c541617600c5580f35b5050346101f557816003193601126101f5576020905173dd6e31a046b828cbbafb939c2a394629aff8bbdc8152f35b5050346101f557806003193601126101f55760209061050f610beb610d2f565b60243590336110ac565b92915034610a855783600319360112610a8557600354600181811c9186908281168015610cdc575b6020958686108214610cc95750848852908115610ca75750600114610c4e575b61065e8686610654828b0383610db9565b929550600383527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b5b828410610c94575050508261065e94610654928201019438610c3d565b8054868501880152928601928101610c77565b60ff191687860152505050151560051b83010192506106548261065e38610c3d565b634e487b7160e01b845260229052602483fd5b93607f1693610c1d565b6020808252825181830181905290939260005b828110610d1b57505060409293506000838284010152601f8019910116010190565b818101860151848201604001528501610cf9565b600435906001600160a01b0382168203610d4557565b600080fd5b602435906001600160a01b0382168203610d4557565b6040906003190112610d45576004356001600160a01b0381168103610d4557906024358015158103610d455790565b67ffffffffffffffff8111610da357604052565b634e487b7160e01b600052604160045260246000fd5b90601f8019910116810190811067ffffffffffffffff821117610da357604052565b90816060910312610d45578051916040602083015192015190565b600b546000906001600160a01b039081163303610f36578080600854169316928314610f1d57828252601160205260ff604083205416938015158095151514610eff578383526011602052610e5a81604085209060ff801983541691151516179055565b610e86575b50807fffa9187bf1f18bf477bd0ea1bcbb64e93b6a98132473929edfce215cd9b16fab91a3565b60095416803b156101f55781809160246040518094819363031e79db60e41b83528860048401525af18015610ef457907fffa9187bf1f18bf477bd0ea1bcbb64e93b6a98132473929edfce215cd9b16fab9291610ee5575b5090610e5f565b610eee90610d8f565b38610ede565b6040513d84823e3d90fd5b6044848660405191632b100e0760e21b835260048301526024820152fd5b604051636b6fda0f60e11b815260048101849052602490fd5b50505050565b6005546001600160a01b03163303610f5057565b60405163118cdaa760e01b8152336004820152602490fd5b9160018060a01b038093169160009383855260016020526040938486209183169182875260205284862054926000198403610fa7575b50505050505050565b84841061100b57508015610ff3578115610fdb57855260016020528385209085526020520391205538808080808080610f9e565b8451634a1406b160e11b815260048101879052602490fd5b845163e602df0560e01b815260048101879052602490fd5b8551637dc7a0d960e11b81526001600160a01b039190911660048201526024810184905260448101859052606490fd5b91906001600160a01b03808416156110785781161561105f5761105d926111a2565b565b60405163ec442f0560e01b815260006004820152602490fd5b604051634b637e8f60e11b815260006004820152602490fd5b906001600160a01b0382161561107857600061105d926111a2565b6001600160a01b03908116918215611126571691821561110d5760207f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925918360005260018252604060002085600052825280604060002055604051908152a3565b604051634a1406b160e11b815260006004820152602490fd5b60405163e602df0560e01b815260006004820152602490fd5b9190820180921161114c57565b634e487b7160e01b600052601160045260246000fd5b8181029291811591840414171561114c57565b811561117f570490565b634e487b7160e01b600052601260045260246000fd5b9190820391821161114c57565b82156115925730600090815260208190526040902054600a54811015906111da6111d1600d54600e549061113f565b600f549061113f565b918061157d575b80611552575b8061152b575b80611504575b611406575b509061128561128a946112859361121861121460125460ff1690565b1590565b6001600160a01b038516600090815260116020526040902061124090611214905b5460ff1690565b806113db575b6113d3575b6001600160a01b038516600090815260106020526040902061126c90611239565b80156113ac575b6113a4575b61136b575b50848361160a565b6119a0565b61129961121460125460ff1690565b61129f57565b6009546112bc906001600160a01b03165b6001600160a01b031690565b6040516001624d3b8760e01b031981526207a120600482015290606090829060249082906000905af160009181600091600093611346575b506112fe57505050565b6040805193845260208401919091528201526207a120606082015232906001907fc864333d6121033635ab41b29ae52f10a22cf4438c3e4f1c4c68518feb2f8a9890608090a3565b91509250611363915060603d6060116108de576108cd8183610db9565b9192386112f4565b9061138461137c61139e9383611162565b612710900490565b9061139082308761160a565b611399306119a0565b611195565b3861127d565b506000611278565b506001600160a01b03871660009081526010602052604090206113ce90611239565b611273565b50600061124b565b506001600160a01b03871660009081526011602052604090206114019061121490611239565b611246565b611418600160ff196012541617601255565b6114398261143461142e600e54600d549061113f565b84611162565b611175565b80611493575b50600f549081611471575b50509061128561128a946112859361146760ff1960125416601255565b92935094506111f8565b8261143461148b9361148593969596611162565b30611091565b90388061144a565b61149c906116e2565b476114ca6114c3600e546114bd6114b38286611162565b91600d549061113f565b90611175565b8092611195565b90806114e7575b50801561143f576114e1906118fe565b3861143f565b600c546114fd91906001600160a01b0316611884565b50386114d1565b5060055461151a906001600160a01b03166112b0565b6001600160a01b03851614156111f3565b50600554611541906001600160a01b03166112b0565b6001600160a01b03841614156111ed565b506001600160a01b03831660009081526011602052604090206115789061121490611239565b6111e7565b5061158d61121460125460ff1690565b6111e1565b61105d92506000916001600160a01b039182169190826115eb57600080516020611a0a833981519152916020916115cb8660025461113f565b6002555b1693846115e0575b604051908152a3565b8481528082526115d7565b8284526020848152600080516020611a0a8339815191529290916115cf565b6001600160a01b03808216929091836116715750600080516020611a0a8339815191529160209161163d8660025461113f565b6002555b169384611659578060025403600255604051908152a3565b846000526000825260406000208181540190556115d7565b600090848252816020526040822054908682106116b05750918160408760209588600080516020611a0a83398151915298965283875203912055611641565b60405163391434e360e21b81526001600160a01b03919091166004820152602481019190915260448101869052606490fd5b60408051916060830183811067ffffffffffffffff821117610da35782526002835260209081840190833683378451156118295730825260075484516315ab88c960e31b81526001600160a01b0392909183168583600481845afa9283156118795760009361183f575b50875192600193600110156118295761176d9185849216898b0152306110ac565b82600754169461012c42019384421161114c57863b15610d4557918798959493919851988996632955261160e11b885260c488019260048901526000602489015260c060448901525180925260e4870195936000905b83821061180f57505050505050600083819593819330606484015283608484015260a483015203925af190811561180557506117fc5750565b61105d90610d8f565b513d6000823e3d90fd5b8551811688528b98509682019694820194908401906117c3565b634e487b7160e01b600052603260045260246000fd5b8681819593953d8311611872575b6118578183610db9565b810103126101f557519084821682036102fc5750913861174c565b503d61184d565b87513d6000823e3d90fd5b60405167ffffffffffffffff91906020810183811182821017610da3576040526000808095819482809552617530f1913d156118f9573d9182116118e557604051916118da601f8201601f191660200184610db9565b825260203d92013e90565b634e487b7160e01b81526041600452602490fd5b505090565b6009546001600160a01b03906119179083908316611884565b61191f575050565b6009541690813b15610d455760008092602460405180958193633243c79160e01b83528660048401525af1908115611994577fb0cc2628d6d644cf6be9d8110e142297ac910d6d8026d795a99f272fd9ad60b192602092611985575b50604051908152a1565b61198e90610d8f565b3861197b565b6040513d6000823e3d90fd5b6001600160a01b03908116600081815260208190526040812054600954909316929091833b1561028a5790604483928360405196879485936338c110ef60e21b8552600485015260248401525af19081156119fd57506117fc5750565b604051903d90823e3d90fdfeddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220425b67829947d144c6e012cb2d28f285c11e7c12adba85f9bc8dd8052b16c81364736f6c63430008180033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

0000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000d3c21bcecceda100000000000000000000000000000018e621b64d7808c3c47bccbbd7485d23f257d26f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000033f5dcece4505afeb69c6d0f2bf856d13b2afab8000000000000000000000000000000000000000000000000000000000000009600000000000000000000000000000000000000000000000000000000000000fa00000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000005505550533200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045055503200000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _name (string): PUPS2
Arg [1] : _symbol (string): PUP2
Arg [2] : _initialSupply (uint256): 1000000000000000000000000
Arg [3] : _router (address): 0x18E621B64d7808c3C47bccbbD7485d23F257D26f
Arg [4] : _minimumTokenBalanceForDividendsPct (uint256): 0
Arg [5] : _teamWallet (address): 0x33F5DCECe4505aFEb69c6d0f2bf856D13B2AFAb8
Arg [6] : _teamFee (uint256): 150
Arg [7] : _dividendsFee (uint256): 250
Arg [8] : _burnFee (uint256): 100

-----Encoded View---------------
13 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000120
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000160
Arg [2] : 00000000000000000000000000000000000000000000d3c21bcecceda1000000
Arg [3] : 00000000000000000000000018e621b64d7808c3c47bccbbd7485d23f257d26f
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [5] : 00000000000000000000000033f5dcece4505afeb69c6d0f2bf856d13b2afab8
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000096
Arg [7] : 00000000000000000000000000000000000000000000000000000000000000fa
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000064
Arg [9] : 0000000000000000000000000000000000000000000000000000000000000005
Arg [10] : 5055505332000000000000000000000000000000000000000000000000000000
Arg [11] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [12] : 5055503200000000000000000000000000000000000000000000000000000000


[ Download: CSV Export  ]
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.