ETH Price: $3,415.83 (-0.16%)

Token

Etheism (E)
 

Overview

Max Total Supply

977.495655892 E

Holders

1,744

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 9 Decimals)

Filtered by Token Holder
onlyshauns.eth
Balance
0.034168323 E

Value
$0.00
0x15FCa867b0521995Dba0525cb3Ec8E281B9A5807
Loading...
Loading
Loading...
Loading
Loading...
Loading

OVERVIEW

Etheism embodies an experimental approach to blending art and blockchain technology, leveraging unique methods to offer both aesthetic and collectible value.

# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
Etheism

Compiler Version
v0.8.25+commit.b61c2a91

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion
File 1 of 19 : Etheism.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "./Token.sol";
import "./Breed.sol";

contract HoldersList {
    mapping(uint index => address holder) _holders;
    mapping(address holder => uint index) _holder_index;
    uint public holders_count;

    function get_holders_list(
        uint index,
        uint count
    ) external view returns (uint page_count, address[] memory accounts) {
        if (index >= holders_count) return (0, new address[](0));

        uint end = index + count;
        if (end > holders_count) {
            end = holders_count;
        }
        page_count = end - index;

        accounts = new address[](page_count);
        uint i;
        for (i = index; i < page_count; ++i) {
            accounts[i] = _holders[index + i];
        }
    }

    function add_holder(address value) internal {
        uint index = holders_count++;
        _holders[index] = value;
        _holder_index[value] = index;
    }

    function remove_holder(address value) internal {
        if (holders_count == 0) return;

        uint removingIndex = _holder_index[value];
        if (removingIndex != holders_count - 1) {
            address lastHolder = _holders[holders_count - 1];
            _holders[removingIndex] = lastHolder;
            _holder_index[lastHolder] = removingIndex;
        }

        --holders_count;
        delete _holder_index[value];
        delete _holders[holders_count];
    }
}

contract Etheism is Token, ReentrancyGuard, HoldersList {
    uint constant MAX_GENS_START = 1000;
    uint public constant GEN_MIN = 1;
    uint public constant gen_max = MAX_GENS_START;
    uint public gen = MAX_GENS_START;
    uint public constant max_breed = 1000;
    mapping(address owner => mapping(uint index => Breed)) public breeds;
    mapping(address owner => uint) public counts;
    uint public breed_total_count;
    uint breed_id;

    constructor() Token("Etheism", "E") {}

    function _add_breed_to_owner(address account, Breed memory breed) private {
        if (account == _pair) return;
        if (++counts[account] == 1) add_holder(account);
        ++breed_total_count;
        uint index = counts[account] - 1;
        breeds[account][index] = breed;
    }

    function _remove_breed_from_owner_by_index(
        address account,
        uint index
    ) private {
        if (account == _pair) return;
        if (--counts[account] == 0) remove_holder(account);
        --breed_total_count;
        uint last_index = counts[account];
        if (index != last_index) {
            Breed memory last_breed = breeds[account][last_index];
            breeds[account][index] = last_breed;
        }
        delete breeds[account][last_index];
    }

    function _transfer_breed_from_to_by_index(
        address account,
        uint index,
        address to
    ) private {
        Breed memory breed = breeds[account][index];
        super.transfer_internal(account, to, 10 ** DECIMALS);
        _remove_breed_from_owner_by_index(account, index);
        _add_breed_to_owner(to, breed);
    }

    function transfer_breed_from_to_by_index(uint index, address to) external {
        require(index < counts[msg.sender], "incorrect index");
        _transfer_breed_from_to_by_index(msg.sender, index, to);
    }

    function gen_mode(uint value) private returns (uint) {
        value = (value * gen) / gen_max;
        if (value == 0) value = 1;
        if (gen > GEN_MIN) --gen;
        return value;
    }

    function buy(
        address to,
        uint256 amount
    ) internal virtual override nonReentrant {
        uint last_balance = balanceOf(to);
        uint balance = last_balance + amount;
        uint count = balance /
            (10 ** decimals()) -
            last_balance /
            (10 ** decimals());
        uint i;
        for (i = 0; i < count; ++i) {
            Breed memory breed = Breed(++breed_id, gen_mode(max_breed));
            _add_breed_to_owner(to, breed);
        }
        super.buy(to, amount);
    }

    function sell(
        address from,
        uint256 amount
    ) internal virtual override lockFee nonReentrant {
        uint last_balance = balanceOf(from);
        uint balance = last_balance - amount;
        uint count = last_balance /
            (10 ** decimals()) -
            balance /
            (10 ** decimals());
        uint i;
        uint owner_count = counts[from];
        for (i = 0; i < count; ++i) {
            if (gen < gen_max) ++gen;
            if (owner_count > 0)
                _remove_breed_from_owner_by_index(from, --owner_count);
        }
        super._transfer(from, _pair, amount);
    }

    function transfer_internal(
        address from,
        address to,
        uint256 amount
    ) internal virtual override nonReentrant {
        uint last_balance_from = balanceOf(from);
        uint balance_from = last_balance_from - amount;
        uint last_balance_to = balanceOf(to);
        uint balance_to = last_balance_to + amount;
        if (to == address(0) || to == DEAD_ADDRESS) {
            last_balance_to = 0;
            balance_to = 0;
        }

        uint count_from = last_balance_from /
            (10 ** decimals()) -
            balance_from /
            (10 ** decimals());
        uint count_to = balance_to /
            (10 ** decimals()) -
            last_balance_to /
            (10 ** decimals());
        // calculate transfer count
        uint transfer_count = count_from;

        if (transfer_count > count_to) transfer_count = count_to;
        // transfer
        uint i;
        uint owner_count = counts[from];
        for (i = 0; i < transfer_count; ++i) {
            if (owner_count == 0) break;
            uint from_index = --owner_count;
            Breed memory breed = breeds[from][from_index];
            _remove_breed_from_owner_by_index(from, from_index);
            _add_breed_to_owner(to, breed);
        }
        uint transfered = i;

        // remove from
        for (i = transfer_count; i < count_from; ++i) {
            uint from_index = --owner_count;
            _remove_breed_from_owner_by_index(from, from_index);
        }

        // generate to
        for (i = transfered; i < count_to; ++i) {
            Breed memory breed = Breed(++breed_id, gen_mode(max_breed));
            _add_breed_to_owner(to, breed);
        }

        super.transfer_internal(from, to, amount);
    }

    function get_item_acc_index(
        address account,
        uint index
    ) external view returns (ItemData memory) {
        return this.get_item(breeds[account][index]);
    }

    function get_svg_acc_index(
        address account,
        uint index
    ) external view returns (string memory) {
        return toSvg(this.get_item_acc_index(account, index));
    }

    function get_account_breeds(
        address account,
        uint index,
        uint count
    ) external view returns (uint page_count, Breed[] memory accounts) {
        uint account_count = counts[account];
        if (index >= account_count) return (0, new Breed[](0));

        uint end = index + count;
        if (end > account_count) {
            end = account_count;
        }
        page_count = end - index;

        accounts = new Breed[](page_count);
        uint i;
        for (i = 0; i < page_count; ++i) {
            accounts[i] = breeds[account][index + i];
        }
    }

    function get_account_items(
        address account,
        uint index,
        uint count
    ) external view returns (uint page_count, ItemData[] memory accounts) {
        uint account_count = counts[account];
        if (index >= account_count) return (0, new ItemData[](0));

        uint end = index + count;
        if (end > account_count) {
            end = account_count;
        }
        page_count = end - index;

        accounts = new ItemData[](page_count);
        uint i;
        for (i = 0; i < page_count; ++i) {
            accounts[i] = this.get_item(breeds[account][index + i]);
        }
    }

    function get_account_svgs(
        address account,
        uint index,
        uint count
    ) external view returns (uint page_count, string[] memory accounts) {
        uint account_count = counts[account];
        if (index >= account_count) return (0, new string[](0));

        uint end = index + count;
        if (end > account_count) {
            end = account_count;
            page_count = index - end;
        }

        accounts = new string[](page_count);
        uint i;
        uint n = 0;
        for (i = index; i < end; ++i) {
            accounts[n++] = toSvg(this.get_item(breeds[account][i]));
        }
    }
}

File 2 of 19 : 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 3 of 19 : 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 4 of 19 : 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 5 of 19 : 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 6 of 19 : 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 7 of 19 : 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 8 of 19 : Colors.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;

library ColorConvert {
    function toSvgColor(uint24 value) internal pure returns (string memory) {
        return string(abi.encodePacked("#", toHex(value)));
    }

    function toHex(uint24 value) internal pure returns (bytes memory) {
        bytes memory buffer = new bytes(6);
        for (uint i = 0; i < 3; ++i) {
            buffer[5 - i * 2] = hexChar(uint8(value) & 0x0f);
            buffer[4 - i * 2] = hexChar((uint8(value) >> 4) & 0x0f);
            value >>= 8;
        }
        return buffer;
    }

    function hexChar(uint8 value) internal pure returns (bytes1) {
        if (value < 10) return bytes1(uint8(48 + (uint(value) % 10)));
        return bytes1(uint8(65 + uint256((value - 10) % 6)));
    }
}

File 9 of 19 : Files.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;

import './Path.sol';

struct FileData {
    uint file;
    Path[] paths;
}

library FilesLib {
    function set_file(
        mapping(uint => Path[]) storage paths,
        FileData calldata input,
        uint8 count
    ) internal returns (uint8) {
        Path[] storage storageFile = paths[input.file];
        if (storageFile.length > 0) delete paths[input.file - 1];
        else ++count;
        for (uint i = 0; i < input.paths.length; ++i) {
            storageFile.push(input.paths[i]);
        }
        return count;
    }

    function set_files(
        mapping(uint => Path[]) storage paths,
        FileData[] calldata input,
        uint8 count
    ) internal returns (uint8) {
        if (input.length == 0) return count;
        uint i;
        for (i = 0; i < input.length; ++i)
            count = set_file(paths, input[i], count);
        return count;
    }
}

File 10 of 19 : Generator.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;

import "./Path.sol";
import "./String.sol";
import "./Files.sol";
import "./Colors.sol";
import "./IGenerator.sol";
import "../token/Breed.sol";
import "./Random.sol";
import "../lib/Ownable.sol";

uint8 constant PIXELS_COUNT = 10;

contract Generator is Ownable {
    using FilesLib for mapping(uint => Path[]);
    using PathLib for Path;
    using PathLib for Path[];
    using RandLib for Rand;
    using RandLib for string[];

    string[] public background_colors = [
        "#20a826",
        "#f4910a",
        "#003cff",
        "#f8e424",
        "#a0301d",
        "#4bcadd",
        "#ff2a2a",
        "#7400a4",
        "#78c59b",
        "#f8Bac7"
    ];
    string[] public body_colors = [
        "#eec39a",
        "#ffc387",
        "#f9c37d",
        "#fea89e",
        "#ffffff",
        "#323232",
        "#c8d54a",
        "#cb2e3b",
        "#dfb85b",
        "#d5eaec"
    ];
    string[] public mouth_colors = [
        "#bf856a",
        "#f09964",
        "#ed9b4a",
        "#d67958",
        "#dcdcdc",
        "#1e1e1e",
        "#b0bc41",
        "#ad2732",
        "#815b43",
        "#9bdced"
    ];
    string[] public nose_colors = [
        "#88553d",
        "#9b4e24",
        "#8d4026",
        "#b0493d",
        "#b7b7b7",
        "#111111",
        "#818a30",
        "#92262f",
        "#71463e",
        "#809ce3"
    ];
    string[] public shirt_1_colors = [
        "#ffffff",
        "#724547",
        "#788dd7",
        "#ffcd08",
        "#ebddd8",
        "#6c7292",
        "#fef100",
        "#c55b41",
        "#fbf8b7",
        "#c4b9bc"
    ];
    string[] public shirt_2_colors = [
        "#936060",
        "#63423f",
        "#fff9bd",
        "#6c5975",
        "#e16a22",
        "#c52c46",
        "#4b40b3",
        "#6c5975",
        "#afdea1",
        "#ebbe21"
    ];
    string[] public shirt_3_colors = [
        "#724547",
        "#51332d",
        "#bb644a",
        "#483d56",
        "#793131",
        "#6d2d2e",
        "#4a3951",
        "#412c43",
        "#5ebb6f",
        "#bb682f"
    ];
    string[] public facial_hair_colors = [
        "#503434",
        "#4e4154",
        "#5f4e4f",
        "#444f46",
        "#d5810e",
        "#712d2f",
        "#823635",
        "#8d5327",
        "#cb5211",
        "#555555"
    ];
    string[] public hair_colors = [
        "#bb682f",
        "#50657b",
        "#816158",
        "#616c53",
        "#ffdd66",
        "#e13236",
        "#c04f41",
        "#d98d00",
        "#ff7e00",
        "#bf8f00"
    ];
    string[] public eyes_colors = [
        "#ffffff",
        "#c3e3e5",
        "#9be6f8",
        "#fffff9",
        "#effbfa",
        "#fbeede",
        "#d7dad6",
        "#a8e41e",
        "#98c9df",
        "#c54989"
    ];
    string[] public eyes_base_colors = [
        "#0a0a0a",
        "#c9418f",
        "#f80812",
        "#00bef9",
        "#3fd58e",
        "#d58111",
        "#e03149",
        "#1fb34f",
        "#c54989",
        "#fc202a"
    ];
    string[] public hat_colors = [
        "#a55b48",
        "#e5aa7a",
        "#ffc208",
        "#8d8790",
        "#bf1a43",
        "#57586c",
        "#a1758d",
        "#a1758d",
        "#99ddee",
        "#22a435"
    ];
    string[] public accessories_colors = [
        "#91a8b0",
        "#50667c",
        "#b3f31c",
        "#d0b6c0",
        "#c32d25",
        "#1ea4d0",
        "#ca4c2c",
        "#e03248",
        "#f779a2",
        "#3362c2d"
    ];
    string[] public mask_colors = [
        "#ffffff",
        "#fea746",
        "#712d2f",
        "#b44a3f",
        "#df485b",
        "#fe8237",
        "#bc3e69",
        "#365c978",
        "#fef33c",
        "#8a5f4f"
    ];

    mapping(uint => Path[]) body;
    mapping(uint => Path[]) facial_hair;
    mapping(uint => Path[]) shirt_1;
    mapping(uint => Path[]) shirt_2;
    mapping(uint => Path[]) shirt_3;
    mapping(uint => Path[]) nose;
    mapping(uint => Path[]) mouth;
    mapping(uint => Path[]) eyes_base;
    mapping(uint => Path[]) eyes;
    mapping(uint => Path[]) hair;
    mapping(uint => Path[]) hat;
    mapping(uint => Path[]) accessories;
    mapping(uint => Path[]) mask;

    uint8 body_count;
    uint8 facial_hair_count;
    uint8 shirt_1_count;
    uint8 shirt_2_count;
    uint8 shirt_3_count;
    uint8 nose_count;
    uint8 mouth_count;
    uint8 eyes_base_count;
    uint8 eyes_count;
    uint8 hair_count;
    uint8 hat_count;
    uint8 accessories_count;
    uint8 mask_count;
    uint color_step_base = 1000;
    uint MAX = 1000;

    function set_max_base(uint max) external onlyOwner {
        MAX = max;
    }

    function set_color_step_base(uint step_base) external onlyOwner {
        color_step_base = step_base;
    }

    function pick_0(uint count, uint random) internal pure returns (uint) {
        return random % count;
    }

    function pick_1(uint count, uint random) internal pure returns (uint) {
        return (random % count) + 1;
    }

    function get_step(uint breed2) internal view returns (uint) {
        if (breed2 < color_step_base) return color_step_base - breed2;
        return 1;
    }

    function pick_progressive(
        uint count,
        uint random
    ) internal pure returns (uint) {
        uint s = ((1 + count) * count) / 2;
        random %= s;
        uint sum;
        uint i;
        for (i = 0; i < count; ++i) {
            sum += i + 1;
            if (sum >= random) return count - i - 1;
        }
        return 0;
    }

    function pick_color_internal(
        uint count,
        uint random_value,
        uint step
    ) public pure returns (uint) {
        uint sum = 0;
        uint i;
        for (i = 0; i < count; ++i) sum += i * step + step;
        random_value = random_value % sum;
        sum = 0;
        for (i = 0; i < count; ++i) {
            sum += i * step + step;
            if (sum >= random_value) return i;
        }
        return 0;
    }

    function pick_color(
        string[] storage colors,
        uint random_value,
        uint step
    ) private view returns (uint) {
        return pick_color_internal(colors.length, random_value, step);
    }

    function set_body(FileData[] calldata data) external onlyOwner {
        body_count = body.set_files(data, body_count);
    }

    function set_facial_hair(FileData[] calldata data) external onlyOwner {
        facial_hair_count = facial_hair.set_files(data, facial_hair_count);
    }

    function set_shirt_1(FileData[] calldata data) external onlyOwner {
        shirt_1_count = shirt_1.set_files(data, shirt_1_count);
    }

    function set_shirt_2(FileData[] calldata data) external onlyOwner {
        shirt_2_count = shirt_2.set_files(data, shirt_2_count);
    }

    function set_shirt_3(FileData[] calldata data) external onlyOwner {
        shirt_3_count = shirt_3.set_files(data, shirt_3_count);
    }

    function set_nose(FileData[] calldata data) external onlyOwner {
        nose_count = nose.set_files(data, nose_count);
    }

    function set_mouth(FileData[] calldata data) external onlyOwner {
        mouth_count = mouth.set_files(data, mouth_count);
    }

    function set_eyes(FileData[] calldata data) external onlyOwner {
        eyes_count = eyes.set_files(data, eyes_count);
    }

    function set_eyes_base(FileData[] calldata data) external onlyOwner {
        eyes_base_count = eyes_base.set_files(data, eyes_base_count);
    }

    function set_hair(FileData[] calldata data) external onlyOwner {
        hair_count = hair.set_files(data, hair_count);
    }

    function set_hat(FileData[] calldata data) external onlyOwner {
        hat_count = hat.set_files(data, hat_count);
    }

    function set_accessories(FileData[] calldata data) external onlyOwner {
        accessories_count = accessories.set_files(data, accessories_count);
    }

    function set_mask(FileData[] calldata data) external onlyOwner {
        mask_count = mask.set_files(data, mask_count);
    }

    function get_item(
        Breed calldata breed
    ) external view returns (ItemData memory) {
        Rand memory rnd = Rand(breed, 0);

        ItemData memory data;
        data.background_color = rnd.next() % background_colors.length;
        data.body = pick_1(body_count, rnd.next());
        data.body_color = pick_color(
            body_colors,
            rnd.next(),
            get_step(rnd.breed.breed2)
        );
        if (rnd.next_breed2_clamped() > (MAX / 3)) {
            data.facial_hair = pick_1(facial_hair_count, rnd.next());
            data.facial_hair_color = pick_color(
                facial_hair_colors,
                rnd.next(),
                get_step(rnd.breed.breed2)
            );
        }
        data.shirt_1 = pick_1(shirt_1_count, rnd.next());
        data.shirt_1_color = rnd.next() % shirt_1_colors.length;
        if (rnd.next_breed2_clamped() > (MAX / 3)) {
            data.shirt_2 = pick_1(shirt_2_count, rnd.next());
            data.shirt_2_color = pick_color(
                shirt_2_colors,
                rnd.next(),
                get_step(rnd.breed.breed2)
            );
        }
        if (rnd.next_breed2_clamped() > (MAX / 3)) {
            data.shirt_3 = pick_1(shirt_3_count, rnd.next());
            data.shirt_3_color = pick_color(
                shirt_3_colors,
                rnd.next(),
                get_step(rnd.breed.breed2)
            );
        }
        if (rnd.next_breed2_clamped() > (MAX / 3)) {
            data.nose = pick_1(nose_count, rnd.next());
            data.nose_color = pick_color(
                nose_colors,
                rnd.next(),
                get_step(rnd.breed.breed2)
            );
        }
        if (rnd.next_breed2_clamped() > (MAX / 3)) {
            data.mouth = pick_1(mouth_count, rnd.next());
            data.mouth_color = pick_color(
                mouth_colors,
                rnd.next(),
                get_step(rnd.breed.breed2)
            );
        }
        data.eyes_base_color = pick_color(
            eyes_base_colors,
            rnd.next(),
            get_step(rnd.breed.breed2)
        );
        data.eyes = pick_1(eyes_count, rnd.next());
        data.eyes_color = pick_color(
            eyes_colors,
            rnd.next(),
            get_step(rnd.breed.breed2)
        );
        if (rnd.next_breed2_clamped() > (MAX / 3)) {
            data.hair = pick_1(hair_count, rnd.next());
            data.hair_color = pick_color(
                hair_colors,
                rnd.next(),
                get_step(rnd.breed.breed2)
            );
        }
        if (rnd.next_breed2_clamped() > (MAX / 3)) {
            data.hat = pick_1(hat_count, rnd.next());
            data.hat_color = pick_color(
                hat_colors,
                rnd.next(),
                get_step(rnd.breed.breed2)
            );
        }
        if (rnd.next_breed2_clamped() > (MAX / 3)) {
            data.accessories = pick_1(accessories_count, rnd.next());
            data.accessories_color = pick_color(
                accessories_colors,
                rnd.next(),
                get_step(rnd.breed.breed2)
            );
        }
        if (rnd.next_breed2_clamped() > (MAX / 3)) {
            data.mask = pick_1(mask_count, rnd.next());
            data.mask_color = pick_color(
                mask_colors,
                rnd.next(),
                get_step(rnd.breed.breed2)
            );
        }

        return data;
    }

    function getSvg(
        Breed calldata breed
    ) external view returns (string memory) {
        return toSvg(this.get_item(breed));
    }

    function toSvg(ItemData memory data) internal view returns (string memory) {
        bytes memory svgStart = abi.encodePacked(
            "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0",
            " ",
            StringConverter.toString(PIXELS_COUNT),
            " ",
            StringConverter.toString(PIXELS_COUNT),
            "'>"
        );

        bytes memory b1 = abi.encodePacked(
            svgStart,
            abi.encodePacked(
                "<rect x='0' y='0'",
                " width='",
                StringConverter.toString(PIXELS_COUNT),
                "' height='",
                StringConverter.toString(PIXELS_COUNT),
                "' fill='",
                background_colors[data.background_color],
                "'/>"
            ),
            toSvg(body, body_colors, data.body, data.body_color),
            toSvg(shirt_1, shirt_1_colors, data.shirt_1, data.shirt_1_color),
            toSvg(
                facial_hair,
                facial_hair_colors,
                data.facial_hair,
                data.facial_hair_color
            ),
            toSvg(shirt_2, shirt_2_colors, data.shirt_2, data.shirt_2_color),
            toSvg(shirt_3, shirt_3_colors, data.shirt_3, data.shirt_3_color),
            toSvg(nose, nose_colors, data.nose, data.nose_color),
            toSvg(mouth, mouth_colors, data.mouth, data.mouth_color)
        );
        bytes memory b2 = abi.encodePacked(
            toSvg(eyes_base, eyes_base_colors, 1, data.eyes_base_color),
            toSvg(eyes, eyes_colors, data.eyes, data.eyes_color),
            toSvg(hair, hair_colors, data.hair, data.hair_color),
            toSvg(hat, hat_colors, data.hat, data.hat_color),
            toSvg(mask, mask_colors, data.mask, data.mask_color),
            toSvg_accessory(
                accessories,
                accessories_colors,
                data.accessories,
                data.accessories_color
            )
        );

        return string(abi.encodePacked(b1, b2, "</svg>"));
    }

    function toSvg(
        mapping(uint => Path[]) storage paths,
        string[] storage colors,
        uint item_id,
        uint color_index
    ) private view returns (string memory) {
        if (item_id == 0) return "";
        return paths[item_id - 1].toSvg(colors[color_index]);
    }

    function toSvg_accessory(
        mapping(uint => Path[]) storage paths,
        string[] storage colors,
        uint item_id,
        uint color_index
    ) private view returns (string memory) {
        if (item_id == 0) return "";
        if (item_id == 1) return paths[item_id - 1].toSvg();
        return paths[item_id - 1].toSvg(colors[color_index]);
    }
}

File 11 of 19 : IGenerator.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "../token/Breed.sol";
import "./ItemData.sol";

interface IGenerator {
    function get_item(
        Breed calldata seed_data
    ) external view returns (ItemData memory);

    function getSvg(
        Breed calldata seed_data
    ) external view returns (string memory);
}

File 12 of 19 : ItemData.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;

struct ItemData {
    uint background_color;
    uint body;
    uint body_color;
    uint facial_hair;
    uint facial_hair_color;
    uint shirt_1;
    uint shirt_1_color;
    uint shirt_2;
    uint shirt_2_color;
    uint shirt_3;
    uint shirt_3_color;
    uint nose;
    uint nose_color;
    uint mouth;
    uint mouth_color;
    uint eyes_base_color;
    uint eyes;
    uint eyes_color;
    uint hair;
    uint hair_color;
    uint hat;
    uint hat_color;
    uint accessories;
    uint accessories_color;
    uint mask;
    uint mask_color;
}

File 13 of 19 : Path.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;

import "./Path.sol";
import "./String.sol";
import "./Colors.sol";
import "./Random.sol";

struct Path {
    string fill;
    string data;
}

library PathLib {
    using PathLib for Path;
    using RandLib for Rand;
    using RandLib for string[];
    using StringConverter for uint8;
    using ColorConvert for uint24;
    using StringLib for string;

    function toSvg(Path memory p) internal pure returns (string memory) {
        return
            string(
                abi.encodePacked("<path fill='", p.fill, "' d='", p.data, "'/>")
            );
    }

    function toSvg(
        Path memory p,
        string memory color
    ) internal pure returns (string memory) {
        return
            string(
                abi.encodePacked(
                    "<path fill='",
                    color,
                    "' d='",
                    p.data,
                    color,
                    "'/>"
                )
            );
    }

    function toSvg(
        Path[] storage paths,
        string memory color
    ) internal view returns (string memory) {
        string memory res;
        for (uint i = 0; i < paths.length; ++i) {
            res = string(abi.encodePacked(res, paths[i].toSvg(color)));
        }
        return res;
    }

    function toSvg(Path[] storage paths) internal view returns (string memory) {
        string memory res;
        for (uint i = 0; i < paths.length; ++i) {
            res = string(abi.encodePacked(res, paths[i].toSvg()));
        }
        return res;
    }
}

File 14 of 19 : Random.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;

import "../token/Breed.sol";

struct Rand {
    Breed breed;
    uint nonce;
}

library RandLib {
    function next(Rand memory rnd) internal pure returns (uint) {
        return
            uint(
                keccak256(
                    abi.encodePacked(
                        rnd.breed.serial_number,
                        rnd.breed.breed2,
                        rnd.nonce++
                    )
                )
            );
    }

    function next_breed2_clamped(Rand memory rnd) internal pure returns (uint) {
        return next(rnd) % rnd.breed.breed2;
    }
}

File 15 of 19 : String.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;

library StringLib {
    function equals(
        string memory s1,
        string memory s2
    ) internal pure returns (bool) {
        return (keccak256(abi.encodePacked((s1))) ==
            keccak256(abi.encodePacked((s2))));
    }
}

library StringConverter {
    function toString(uint value) internal pure returns (string memory) {
        if (value == 0) {
            return "0";
        }
        uint temp = value;
        uint digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }
}

File 16 of 19 : Ownable.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract Ownable {
    address _owner;

    event RenounceOwnership();

    constructor() {
        _owner = msg.sender;
    }

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

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

    function ownerRenounce() public onlyOwner {
        _owner = address(0);
        emit RenounceOwnership();
    }

    function transferOwnership(address newOwner) external onlyOwner {
        _owner = newOwner;
    }
}

File 17 of 19 : Breed.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;

struct Breed {
    uint serial_number; // serial number
    uint breed2; // value breed
}

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

pragma solidity ^0.8.20;

import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import {Context} from "@openzeppelin/contracts/utils/Context.sol";
import {IERC20Errors} from "@openzeppelin/contracts/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 ERC20Token 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 virtual {
        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 19 of 19 : Token.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;

import "./ERC20Token.sol";
import "../generator/Generator.sol";

address constant DEAD_ADDRESS = 0x000000000000000000000000000000000000dEaD;

contract Token is ERC20Token, Generator {
    uint8 constant DECIMALS = 9;

    uint256 constant _startTotalSupply = 1000 * (10 ** DECIMALS);
    uint256 constant _startMaxBuyCount = (_startTotalSupply * 5) / 10000;
    uint256 constant _addMaxBuyPercentPerSec = 1; // 100%=_addMaxBuyPrecesion add 0.005%/second
    uint256 constant _addMaxBuyPrecesion = 10000;
    uint256 constant _taxPrecesion = 1000;
    uint256 constant _transferZeroTaxSeconds = 1000; // zero tax transfer time
    address internal _pair;
    address immutable _deployer;
    bool internal _feeLocked;
    uint256 internal _startTime;

    constructor(
        string memory name_,
        string memory symbol_
    ) ERC20Token(name_, symbol_) {
        _deployer = msg.sender;
        _mint(msg.sender, _startTotalSupply);
    }

    modifier maxBuyLimit(uint256 amount) {
        require(amount <= maxBuy(), "max buy");
        _;
    }
    modifier lockFee() {
        _feeLocked = true;
        _;
        _feeLocked = false;
    }

    function decimals() public pure override returns (uint8) {
        return DECIMALS;
    }

    function start(address pair) external onlyOwner {
        _pair = pair;
        _startTime = block.timestamp;
    }

    function isStarted() public view returns (bool) {
        return _pair != address(0);
    }

    receive() external payable {
        bool sent;
        (sent, ) = payable(_deployer).call{value: msg.value}("");
        require(sent, "can not get ether");
    }

    function maxBuy() public view returns (uint256) {
        if (!isStarted()) return _startTotalSupply;
        uint256 count = _startMaxBuyCount +
            (_startTotalSupply *
                (block.timestamp - _startTime) *
                _addMaxBuyPercentPerSec) /
            _addMaxBuyPrecesion;
        if (count > _startTotalSupply) count = _startTotalSupply;
        return count;
    }

    function _transfer(
        address from,
        address to,
        uint256 amount
    ) internal override {
        // allow burning
        if (to == address(0) || to == DEAD_ADDRESS) {
            transfer_internal(from, to, amount);
            return;
        }

        // system transfers
        if (
            !isStarted() &&
            (from == address(0) ||
                from == address(this) ||
                from == _deployer ||
                to == _deployer)
        ) {
            super._transfer(from, to, amount);
            return;
        }

        // transfers with fee
        if (_feeLocked) {
            super._transfer(from, to, amount);
            return;
        } else {
            if (from == _pair) {
                buy(to, amount);
                return;
            } else if (to == _pair) {
                sell(from, amount);
                return;
            } else transfer_internal(from, to, amount);
        }
    }

    function buy(
        address to,
        uint256 amount
    ) internal virtual maxBuyLimit(amount) lockFee {
        super._transfer(_pair, to, amount);
    }

    function sell(address from, uint256 amount) internal virtual lockFee {
        super._transfer(from, _pair, amount);
    }

    function transfer_internal(
        address from,
        address to,
        uint256 amount
    ) internal virtual lockFee {
        if (to == address(0) || to == DEAD_ADDRESS) {
            _burn(from, amount);
            return;
        }
        super._transfer(from, to, amount);
    }
}

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

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"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":[],"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":[],"name":"RenounceOwnership","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":"GEN_MIN","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"accessories_colors","outputs":[{"internalType":"string","name":"","type":"string"}],"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":"uint256","name":"","type":"uint256"}],"name":"background_colors","outputs":[{"internalType":"string","name":"","type":"string"}],"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":"","type":"uint256"}],"name":"body_colors","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"breed_total_count","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"breeds","outputs":[{"internalType":"uint256","name":"serial_number","type":"uint256"},{"internalType":"uint256","name":"breed2","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"counts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"eyes_base_colors","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"eyes_colors","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"facial_hair_colors","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gen","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gen_max","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"serial_number","type":"uint256"},{"internalType":"uint256","name":"breed2","type":"uint256"}],"internalType":"struct Breed","name":"breed","type":"tuple"}],"name":"getSvg","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"count","type":"uint256"}],"name":"get_account_breeds","outputs":[{"internalType":"uint256","name":"page_count","type":"uint256"},{"components":[{"internalType":"uint256","name":"serial_number","type":"uint256"},{"internalType":"uint256","name":"breed2","type":"uint256"}],"internalType":"struct Breed[]","name":"accounts","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"count","type":"uint256"}],"name":"get_account_items","outputs":[{"internalType":"uint256","name":"page_count","type":"uint256"},{"components":[{"internalType":"uint256","name":"background_color","type":"uint256"},{"internalType":"uint256","name":"body","type":"uint256"},{"internalType":"uint256","name":"body_color","type":"uint256"},{"internalType":"uint256","name":"facial_hair","type":"uint256"},{"internalType":"uint256","name":"facial_hair_color","type":"uint256"},{"internalType":"uint256","name":"shirt_1","type":"uint256"},{"internalType":"uint256","name":"shirt_1_color","type":"uint256"},{"internalType":"uint256","name":"shirt_2","type":"uint256"},{"internalType":"uint256","name":"shirt_2_color","type":"uint256"},{"internalType":"uint256","name":"shirt_3","type":"uint256"},{"internalType":"uint256","name":"shirt_3_color","type":"uint256"},{"internalType":"uint256","name":"nose","type":"uint256"},{"internalType":"uint256","name":"nose_color","type":"uint256"},{"internalType":"uint256","name":"mouth","type":"uint256"},{"internalType":"uint256","name":"mouth_color","type":"uint256"},{"internalType":"uint256","name":"eyes_base_color","type":"uint256"},{"internalType":"uint256","name":"eyes","type":"uint256"},{"internalType":"uint256","name":"eyes_color","type":"uint256"},{"internalType":"uint256","name":"hair","type":"uint256"},{"internalType":"uint256","name":"hair_color","type":"uint256"},{"internalType":"uint256","name":"hat","type":"uint256"},{"internalType":"uint256","name":"hat_color","type":"uint256"},{"internalType":"uint256","name":"accessories","type":"uint256"},{"internalType":"uint256","name":"accessories_color","type":"uint256"},{"internalType":"uint256","name":"mask","type":"uint256"},{"internalType":"uint256","name":"mask_color","type":"uint256"}],"internalType":"struct ItemData[]","name":"accounts","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"count","type":"uint256"}],"name":"get_account_svgs","outputs":[{"internalType":"uint256","name":"page_count","type":"uint256"},{"internalType":"string[]","name":"accounts","type":"string[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"count","type":"uint256"}],"name":"get_holders_list","outputs":[{"internalType":"uint256","name":"page_count","type":"uint256"},{"internalType":"address[]","name":"accounts","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"serial_number","type":"uint256"},{"internalType":"uint256","name":"breed2","type":"uint256"}],"internalType":"struct Breed","name":"breed","type":"tuple"}],"name":"get_item","outputs":[{"components":[{"internalType":"uint256","name":"background_color","type":"uint256"},{"internalType":"uint256","name":"body","type":"uint256"},{"internalType":"uint256","name":"body_color","type":"uint256"},{"internalType":"uint256","name":"facial_hair","type":"uint256"},{"internalType":"uint256","name":"facial_hair_color","type":"uint256"},{"internalType":"uint256","name":"shirt_1","type":"uint256"},{"internalType":"uint256","name":"shirt_1_color","type":"uint256"},{"internalType":"uint256","name":"shirt_2","type":"uint256"},{"internalType":"uint256","name":"shirt_2_color","type":"uint256"},{"internalType":"uint256","name":"shirt_3","type":"uint256"},{"internalType":"uint256","name":"shirt_3_color","type":"uint256"},{"internalType":"uint256","name":"nose","type":"uint256"},{"internalType":"uint256","name":"nose_color","type":"uint256"},{"internalType":"uint256","name":"mouth","type":"uint256"},{"internalType":"uint256","name":"mouth_color","type":"uint256"},{"internalType":"uint256","name":"eyes_base_color","type":"uint256"},{"internalType":"uint256","name":"eyes","type":"uint256"},{"internalType":"uint256","name":"eyes_color","type":"uint256"},{"internalType":"uint256","name":"hair","type":"uint256"},{"internalType":"uint256","name":"hair_color","type":"uint256"},{"internalType":"uint256","name":"hat","type":"uint256"},{"internalType":"uint256","name":"hat_color","type":"uint256"},{"internalType":"uint256","name":"accessories","type":"uint256"},{"internalType":"uint256","name":"accessories_color","type":"uint256"},{"internalType":"uint256","name":"mask","type":"uint256"},{"internalType":"uint256","name":"mask_color","type":"uint256"}],"internalType":"struct ItemData","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"get_item_acc_index","outputs":[{"components":[{"internalType":"uint256","name":"background_color","type":"uint256"},{"internalType":"uint256","name":"body","type":"uint256"},{"internalType":"uint256","name":"body_color","type":"uint256"},{"internalType":"uint256","name":"facial_hair","type":"uint256"},{"internalType":"uint256","name":"facial_hair_color","type":"uint256"},{"internalType":"uint256","name":"shirt_1","type":"uint256"},{"internalType":"uint256","name":"shirt_1_color","type":"uint256"},{"internalType":"uint256","name":"shirt_2","type":"uint256"},{"internalType":"uint256","name":"shirt_2_color","type":"uint256"},{"internalType":"uint256","name":"shirt_3","type":"uint256"},{"internalType":"uint256","name":"shirt_3_color","type":"uint256"},{"internalType":"uint256","name":"nose","type":"uint256"},{"internalType":"uint256","name":"nose_color","type":"uint256"},{"internalType":"uint256","name":"mouth","type":"uint256"},{"internalType":"uint256","name":"mouth_color","type":"uint256"},{"internalType":"uint256","name":"eyes_base_color","type":"uint256"},{"internalType":"uint256","name":"eyes","type":"uint256"},{"internalType":"uint256","name":"eyes_color","type":"uint256"},{"internalType":"uint256","name":"hair","type":"uint256"},{"internalType":"uint256","name":"hair_color","type":"uint256"},{"internalType":"uint256","name":"hat","type":"uint256"},{"internalType":"uint256","name":"hat_color","type":"uint256"},{"internalType":"uint256","name":"accessories","type":"uint256"},{"internalType":"uint256","name":"accessories_color","type":"uint256"},{"internalType":"uint256","name":"mask","type":"uint256"},{"internalType":"uint256","name":"mask_color","type":"uint256"}],"internalType":"struct ItemData","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"get_svg_acc_index","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"hair_colors","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"hat_colors","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"holders_count","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isStarted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"mask_colors","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxBuy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"max_breed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"mouth_colors","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"nose_colors","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ownerRenounce","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"count","type":"uint256"},{"internalType":"uint256","name":"random_value","type":"uint256"},{"internalType":"uint256","name":"step","type":"uint256"}],"name":"pick_color_internal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"file","type":"uint256"},{"components":[{"internalType":"string","name":"fill","type":"string"},{"internalType":"string","name":"data","type":"string"}],"internalType":"struct Path[]","name":"paths","type":"tuple[]"}],"internalType":"struct FileData[]","name":"data","type":"tuple[]"}],"name":"set_accessories","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"file","type":"uint256"},{"components":[{"internalType":"string","name":"fill","type":"string"},{"internalType":"string","name":"data","type":"string"}],"internalType":"struct Path[]","name":"paths","type":"tuple[]"}],"internalType":"struct FileData[]","name":"data","type":"tuple[]"}],"name":"set_body","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"step_base","type":"uint256"}],"name":"set_color_step_base","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"file","type":"uint256"},{"components":[{"internalType":"string","name":"fill","type":"string"},{"internalType":"string","name":"data","type":"string"}],"internalType":"struct Path[]","name":"paths","type":"tuple[]"}],"internalType":"struct FileData[]","name":"data","type":"tuple[]"}],"name":"set_eyes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"file","type":"uint256"},{"components":[{"internalType":"string","name":"fill","type":"string"},{"internalType":"string","name":"data","type":"string"}],"internalType":"struct Path[]","name":"paths","type":"tuple[]"}],"internalType":"struct FileData[]","name":"data","type":"tuple[]"}],"name":"set_eyes_base","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"file","type":"uint256"},{"components":[{"internalType":"string","name":"fill","type":"string"},{"internalType":"string","name":"data","type":"string"}],"internalType":"struct Path[]","name":"paths","type":"tuple[]"}],"internalType":"struct FileData[]","name":"data","type":"tuple[]"}],"name":"set_facial_hair","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"file","type":"uint256"},{"components":[{"internalType":"string","name":"fill","type":"string"},{"internalType":"string","name":"data","type":"string"}],"internalType":"struct Path[]","name":"paths","type":"tuple[]"}],"internalType":"struct FileData[]","name":"data","type":"tuple[]"}],"name":"set_hair","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"file","type":"uint256"},{"components":[{"internalType":"string","name":"fill","type":"string"},{"internalType":"string","name":"data","type":"string"}],"internalType":"struct Path[]","name":"paths","type":"tuple[]"}],"internalType":"struct FileData[]","name":"data","type":"tuple[]"}],"name":"set_hat","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"file","type":"uint256"},{"components":[{"internalType":"string","name":"fill","type":"string"},{"internalType":"string","name":"data","type":"string"}],"internalType":"struct Path[]","name":"paths","type":"tuple[]"}],"internalType":"struct FileData[]","name":"data","type":"tuple[]"}],"name":"set_mask","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"max","type":"uint256"}],"name":"set_max_base","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"file","type":"uint256"},{"components":[{"internalType":"string","name":"fill","type":"string"},{"internalType":"string","name":"data","type":"string"}],"internalType":"struct Path[]","name":"paths","type":"tuple[]"}],"internalType":"struct FileData[]","name":"data","type":"tuple[]"}],"name":"set_mouth","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"file","type":"uint256"},{"components":[{"internalType":"string","name":"fill","type":"string"},{"internalType":"string","name":"data","type":"string"}],"internalType":"struct Path[]","name":"paths","type":"tuple[]"}],"internalType":"struct FileData[]","name":"data","type":"tuple[]"}],"name":"set_nose","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"file","type":"uint256"},{"components":[{"internalType":"string","name":"fill","type":"string"},{"internalType":"string","name":"data","type":"string"}],"internalType":"struct Path[]","name":"paths","type":"tuple[]"}],"internalType":"struct FileData[]","name":"data","type":"tuple[]"}],"name":"set_shirt_1","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"file","type":"uint256"},{"components":[{"internalType":"string","name":"fill","type":"string"},{"internalType":"string","name":"data","type":"string"}],"internalType":"struct Path[]","name":"paths","type":"tuple[]"}],"internalType":"struct FileData[]","name":"data","type":"tuple[]"}],"name":"set_shirt_2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"file","type":"uint256"},{"components":[{"internalType":"string","name":"fill","type":"string"},{"internalType":"string","name":"data","type":"string"}],"internalType":"struct Path[]","name":"paths","type":"tuple[]"}],"internalType":"struct FileData[]","name":"data","type":"tuple[]"}],"name":"set_shirt_3","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"shirt_1_colors","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"shirt_2_colors","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"shirt_3_colors","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pair","type":"address"}],"name":"start","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"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":"index","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"transfer_breed_from_to_by_index","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

60076101e081815266119918309c191b60c91b6102005260a0908152610220828152662366343931306160c81b6102405260c0526102608281526611981819b1b33360c91b6102805260e0526102a08281526608d98e194d0c8d60ca1b6102c052610100526102e08281526608d84c0ccc0c5960ca1b61030052610120526103208281526608cd1898d8591960ca1b6103405261014052610360828152662366663261326160c81b61038052610160526103a08281526608cdcd0c0c184d60ca1b6103c052610180526103e082815266119b9c319a9cb160c91b610400526101a052610460604052610420918252662366384261633760c81b610440526101c09190915261011190600690600a611457565b50604080516101808101825260076101408201818152662365656333396160c81b610160840152825282518084018452818152662366666333383760c81b60208281019190915280840191909152835180850185528281526608d98e58cccdd960ca1b818301528385015283518085018552828152662366656138396560c81b818301526060840152835180850185528281526611b3333333333360c91b81830152608084015283518085018552828152661199991999199960c91b8183015260a084015283518085018552828152662363386435346160c81b8183015260c0840152835180850185528281526611b1b1193299b160c91b8183015260e0840152835180850185528281526611b233311c1ab160c91b818301526101008401528351808501909452818452662364356561656360c81b908401526101208201929092526102609190600a611457565b50604080516101808101825260076101408201818152662362663835366160c81b6101608401528252825180840184528181526608d98c0e4e4d8d60ca1b6020828101919091528084019190915283518085018552828152662365643962346160c81b81830152838501528351808501855282815266046c86c6e726a760cb1b81830152606084015283518085018552828152662364636463646360c81b81830152608084015283518085018552828152662331653165316560c81b8183015260a084015283518085018552828152662362306263343160c81b8183015260c0840152835180850185528281526611b0b2191b999960c91b8183015260e084015283518085018552828152662338313562343360c81b8183015261010084015283518085019094529083526608ce589918d95960ca1b908301526101208101919091526103b190600890600a611457565b506040805161018081018252600761014082018181526608ce0e0d4d4cd960ca1b6101608401528252825180840184528181526608ce588d194c8d60ca1b602082810191909152808401919091528351808501855282815266119c321a18191b60c91b8183015283850152835180850185528281526608d88c0d0e4cd960ca1b81830152606084015283518085018552828152662362376237623760c81b81830152608084015283518085018552828152662331313131313160c81b8183015260a084015283518085018552828152660233831386133360cc1b8183015260c08401528351808501855282815266119c99191b193360c91b8183015260e084015283518085018552828152662337313436336560c81b818301526101008401528351808501909452908352662338303963653360c81b9083015261012081019190915261050290600990600a611457565b506040805161018081018252600761014082018181526611b3333333333360c91b610160840152825282518084018452818152662337323435343760c81b6020828101919091528084019190915283518085018552828152662337383864643760c81b81830152838501528351808501855282815266046ccccc6c860760cb1b8183015260608401528351808501855282815266046cac4c8c8c8760cb1b8183015260808401528351808501855282815266119b319b991c9960c91b8183015260a084015283518085018552828152660236665663130360cc1b8183015260c084015283518085018552828152662363353562343160c81b8183015260e084015283518085018552828152662366626638623760c81b818301526101008401528351808501909452908352662363346239626360c81b9083015261012081019190915261065290600a9081611457565b50604080516101808101825260076101408201818152660233933363036360cc1b61016084015282528251808401845281815266119b199a1919b360c91b60208281019190915280840191909152835180850185528281526608d999998e589960ca1b818301528385015283518085018552828152662336633539373560c81b8183018190526060850191909152845180860186528381526611b2989b30991960c91b818401526080850152845180860186528381526611b19a99319a1b60c91b8184015260a085015284518086018652838152662334623430623360c81b8184015260c0850152845180860186528381528083019190915260e084015283518085018552828152662361666465613160c81b818301526101008401528351808501909452908352662365626265323160c81b908301526101208101919091526107a090600b90600a611457565b50604080516101808101825260076101408201818152662337323435343760c81b6101608401528252825180840184528181526608cd4c4ccccc9960ca1b6020828101919091528084019190915283518085018552828152662362623634346160c81b81830152838501528351808501855282815266119a1c19b21a9b60c91b81830152606084015283518085018552828152662337393331333160c81b81830152608084015283518085018552828152662336643264326560c81b8183015260a084015283518085018552828152662334613339353160c81b8183015260c084015283518085018552828152662334313263343360c81b8183015260e08401528351808501855282815266119ab2b1311b3360c91b8183015261010084015283518085019094529083526611b1311b1c193360c91b908301526101208101919091526108f190600c90600a611457565b506040805161018081018252600761014082018181526608cd4c0ccd0ccd60ca1b6101608401528252825180840184528181526608cd194d0c4d4d60ca1b602082810191909152808401919091528351808501855282815266119ab31a329a3360c91b81830152838501528351808501855282815266119a1a1a331a1b60c91b81830152606084015283518085018552828152662364353831306560c81b8183015260808401528351808501855282815266119b989932193360c91b8183015260a084015283518085018552828152662338323336333560c81b8183015260c084015283518085018552828152662338643533323760c81b8183015260e084015283518085018552828152662363623532313160c81b818301526101008401528351808501909452908352662335353535353560c81b90830152610120810191909152610a4290600d90600a611457565b506040805161018081018252600761014082018181526611b1311b1c193360c91b61016084015282528251808401845281815266119a981b1a9bb160c91b60208281019190915280840191909152835180850185528281526604670626c626a760cb1b818301528385015283518085018552828152662336313663353360c81b818301526060840152835180850185528281526611b33332321b1b60c91b818301526080840152835180850185528281526611b2989999199b60c91b8183015260a084015283518085018552828152662363303466343160c81b8183015260c084015283518085018552828152660236439386430360cc1b8183015260e084015283518085018552828152660236666376530360cc1b818301526101008401528351808501909452908352660236266386630360cc1b90830152610120810191909152610b9390600e90600a611457565b506040805161018081018252600761014082018181526611b3333333333360c91b610160840152825282518084018452818152662363336533653560c81b60208281019190915280840191909152835180850185528281526604672c4ca6ccc760cb1b818301528385015283518085018552828152662366666666663960c81b81830152606084015283518085018552828152662365666662666160c81b81830152608084015283518085018552828152662366626565646560c81b8183015260a0840152835180850185528281526611b21bb230b21b60c91b8183015260c084015283518085018552828152662361386534316560c81b8183015260e08401528351808501855282815266119c9c319cb23360c91b818301526101008401528351808501909452908352662363353439383960c81b90830152610120810191909152610ce490600f90600a611457565b50604080516101808101825260076101408201818152662330613061306160c81b6101608401528252825180840184528181526611b19c9a189c3360c91b60208281019190915280840191909152835180850185528281526611b31c181c189960c91b818301528385015283518085018552828152662330306265663960c81b81830152606084015283518085018552828152662333666435386560c81b81830152608084015283518085018552828152662364353831313160c81b8183015260a084015283518085018552828152662365303331343960c81b8183015260c084015283518085018552828152661198b331199a3360c91b8183015260e084015283518085018552828152662363353439383960c81b818301526101008401528351808501909452908352662366633230326160c81b90830152610120810191909152610e3590601090600a611457565b5060408051610180810182526007610140820181815266046c26a6ac468760cb1b610160840152825282518084018452818152662365356161376160c81b602082810191909152808401919091528351808501855282815266046ccccc66460760cb1b818301528385015283518085018552828152660233864383739360cc1b81830152606084015283518085018552828152662362663161343360c81b81830152608084015283518085018552828152662335373538366360c81b8183015260a0840152835180850185528281526608d84c4dcd4e1960ca1b81830181905260c0850191909152845180860186528381528083019190915260e084015283518085018552828152662339396464656560c81b818301526101008401528351808501909452908352662332326134333560c81b90830152610120810191909152610f8390601190600a611457565b50604080516101808101825260076101408201818152660233931613862360cc1b610160840152825282518084018452818152662335303636376360c81b6020828101919091528084019190915283518085018552828152662362336633316360c81b818301528385015283518085018552828152660236430623663360cc1b81830152606084015283518085018552828152662363333264323560c81b81830152608084015283518085018552828152660233165613464360cc1b8183015260a084015283518085018552828152662363613463326360c81b8183015260c08401528351808501855282815266046ca60666468760cb1b8183015260e0840152835180850185529182526611b31b9b9cb09960c91b828201526101008301919091528251808401909352600883526708cccccd8c98cc9960c21b908301526101208101919091526110d990601290600a611457565b506040805161018081018252600761014082018181526611b3333333333360c91b6101608401528252825180840184528181526611b332b09b9a1b60c91b602082810191909152808401919091528351808501855282815266119b989932193360c91b8183015283850152835180850185528281526611b11a1a3099b360c91b818301526060840152835180850185528281526611b2331a1c1ab160c91b81830152608084015283518085018552828152662366653832333760c81b8183015260a084015283518085018552828152662362633365363960c81b8183015260c0840152835180850185526008815267046666c6ac6726e760c31b8183015260e084015283518085018552828152662366656633336360c81b81830152610100840152835180850190945290835266119c309ab31a3360c91b9083015261012081019190915261122c90601390600a611457565b506103e86022556103e86023556103e8602a5534801561124b57600080fd5b50604051806040016040528060078152602001664574686569736d60c81b815250604051806040016040528060018152602001604560f81b8152508181816003908161129791906115bd565b5060046112a482826115bd565b5050600580546001600160a01b0319163390811790915560808190526112e291506112d16009600a611778565b6112dd906103e861178e565b6112ee565b505060016026556117b8565b6001600160a01b03821661131d5760405163ec442f0560e01b8152600060048201526024015b60405180910390fd5b6113296000838361132d565b5050565b6001600160a01b03831661135857806002600082825461134d91906117a5565b909155506113ca9050565b6001600160a01b038316600090815260208190526040902054818110156113ab5760405163391434e360e21b81526001600160a01b03851660048201526024810182905260448101839052606401611314565b6001600160a01b03841660009081526020819052604090209082900390555b6001600160a01b0382166113e657600280548290039055611405565b6001600160a01b03821660009081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161144a91815260200190565b60405180910390a3505050565b82805482825590600052602060002090810192821561149d579160200282015b8281111561149d578251829061148d90826115bd565b5091602001919060010190611477565b506114a99291506114ad565b5090565b808211156114a95760006114c182826114ca565b506001016114ad565b5080546114d690611532565b6000825580601f106114e6575050565b601f0160209004906000526020600020908101906115049190611507565b50565b5b808211156114a95760008155600101611508565b634e487b7160e01b600052604160045260246000fd5b600181811c9082168061154657607f821691505b60208210810361156657634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156115b8576000816000526020600020601f850160051c810160208610156115955750805b601f850160051c820191505b818110156115b4578281556001016115a1565b5050505b505050565b81516001600160401b038111156115d6576115d661151c565b6115ea816115e48454611532565b8461156c565b602080601f83116001811461161f57600084156116075750858301515b600019600386901b1c1916600185901b1785556115b4565b600085815260208120601f198616915b8281101561164e5788860151825594840194600190910190840161162f565b508582101561166c5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052601160045260246000fd5b600181815b808511156116cd5781600019048211156116b3576116b361167c565b808516156116c057918102915b93841c9390800290611697565b509250929050565b6000826116e457506001611772565b816116f157506000611772565b816001811461170757600281146117115761172d565b6001915050611772565b60ff8411156117225761172261167c565b50506001821b611772565b5060208310610133831016604e8410600b8410161715611750575081810a611772565b61175a8383611692565b806000190482111561176e5761176e61167c565b0290505b92915050565b600061178760ff8416836116d5565b9392505050565b80820281158282048414176117725761177261167c565b808201808211156117725761177261167c565b608051614b706117e1600039600081816103ba0152818161236f01526123ab0152614b706000f3fe6080604052600436106103b15760003560e01c80637673bfa4116101e7578063afd1e4d81161010d578063dd0b281e116100a0578063eb0ffeb81161006f578063eb0ffeb814610c27578063f2fde38b14610c47578063f578990e14610c67578063fe6fb9a014610c8757600080fd5b8063dd0b281e14610ba1578063dd62ed3e14610bc1578063dde415fa1461094e578063e7a966b614610c0757600080fd5b8063b4f243a4116100dc578063b4f243a414610b13578063bdc1827c14610b33578063c01e21af14610b53578063d5a4260614610b7357600080fd5b8063afd1e4d814610a9d578063b42781ee14610abd578063b42dfa0d14610add578063b4377a3e14610af357600080fd5b8063984bb7a611610185578063a46f3d4b11610154578063a46f3d4b14610a27578063a4ea3c3314610a47578063a9059cbb14610a67578063af504def14610a8757600080fd5b8063984bb7a61461099957806398bafaa3146109b95780639b439dc5146109e75780639c7d73e614610a0757600080fd5b80638da5cb5b116101c15780638da5cb5b146109265780638fdada4a1461094e578063943a6ff61461096457806395d89b411461098457600080fd5b80637673bfa4146108c65780637c3b3b87146108e657806387cd15551461090657600080fd5b80633fc0fdcb116102d75780635e927ceb1161026a578063719f150711610239578063719f150714610838578063719fa9b11461085857806374ae513614610878578063750e8d101461089857600080fd5b80635e927ceb146107795780636a29f5e51461079957806370a08231146107ed57806370db69d61461082357600080fd5b806353c55061116102a657806353c55061146106f9578063544736e6146107195780635534b159146107395780635e5b6dfd1461075957600080fd5b80633fc0fdcb1461066c578063422b9e23146106995780634dc46def146106b957806353388fd5146106d957600080fd5b806318160ddd1161034f578063313ce5671161031e578063313ce567146105ed578063333a00721461060957806336d208cf1461061e5780633860a3931461063e57600080fd5b806318160ddd1461058357806323b872dd146105985780632547b84d146105b85780632d12d34b146105d857600080fd5b806306fdde031161038b57806306fdde03146104fe578063095ea7b3146105135780630dfa2c481461054357806312ac5d0f1461056357600080fd5b8063018a37411461047b5780630568e65e146104a457806306a86dd7146104d157600080fd5b366104765760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163460405160006040518083038185875af1925050503d8060008114610423576040519150601f19603f3d011682016040523d82523d6000602084013e610428565b606091505b505080915050806104745760405162461bcd60e51b815260206004820152601160248201527031b0b7103737ba1033b2ba1032ba3432b960791b60448201526064015b60405180910390fd5b005b600080fd5b34801561048757600080fd5b5061049160295481565b6040519081526020015b60405180910390f35b3480156104b057600080fd5b506104916104bf366004613b61565b602c6020526000908152604090205481565b3480156104dd57600080fd5b506104f16104ec366004613b7c565b610ca7565b60405161049b9190613be5565b34801561050a57600080fd5b506104f1610d53565b34801561051f57600080fd5b5061053361052e366004613bf8565b610de5565b604051901515815260200161049b565b34801561054f57600080fd5b506104f161055e366004613b7c565b610dff565b34801561056f57600080fd5b506104f161057e366004613b7c565b610e0f565b34801561058f57600080fd5b50600254610491565b3480156105a457600080fd5b506105336105b3366004613c22565b610e1f565b3480156105c457600080fd5b506104f16105d3366004613b7c565b610e45565b3480156105e457600080fd5b50610491600181565b3480156105f957600080fd5b506040516009815260200161049b565b34801561061557600080fd5b50610474610e55565b34801561062a57600080fd5b50610474610639366004613c5e565b610eba565b34801561064a57600080fd5b5061065e610659366004613cd3565b610f1f565b60405161049b929190613cf5565b34801561067857600080fd5b5061068c610687366004613bf8565b611027565b60405161049b9190613e5f565b3480156106a557600080fd5b506104f16106b4366004613e6e565b6110bf565b3480156106c557600080fd5b506104746106d4366004613c5e565b611137565b3480156106e557600080fd5b506104f16106f4366004613b7c565b61119c565b34801561070557600080fd5b506104f1610714366004613b7c565b6111ac565b34801561072557600080fd5b506024546001600160a01b03161515610533565b34801561074557600080fd5b506104f1610754366004613b7c565b6111bc565b34801561076557600080fd5b50610474610774366004613c5e565b6111cc565b34801561078557600080fd5b50610474610794366004613b7c565b611234565b3480156107a557600080fd5b506107d86107b4366004613bf8565b602b6020908152600092835260408084209091529082529020805460019091015482565b6040805192835260208301919091520161049b565b3480156107f957600080fd5b50610491610808366004613b61565b6001600160a01b031660009081526020819052604090205490565b34801561082f57600080fd5b50610491611263565b34801561084457600080fd5b50610474610853366004613c5e565b611360565b34801561086457600080fd5b50610474610873366004613c5e565b6113c7565b34801561088457600080fd5b506104f1610893366004613b7c565b611430565b3480156108a457600080fd5b506108b86108b3366004613e86565b611440565b60405161049b929190613eb9565b3480156108d257600080fd5b506104f16108e1366004613b7c565b6115fc565b3480156108f257600080fd5b5061068c610901366004613e6e565b61160c565b34801561091257600080fd5b506104f1610921366004613b7c565b611a15565b34801561093257600080fd5b506005546040516001600160a01b03909116815260200161049b565b34801561095a57600080fd5b506104916103e881565b34801561097057600080fd5b506104f161097f366004613b7c565b611a25565b34801561099057600080fd5b506104f1611a35565b3480156109a557600080fd5b506104746109b4366004613c5e565b611a44565b3480156109c557600080fd5b506109d96109d4366004613e86565b611aa8565b60405161049b929190613f07565b3480156109f357600080fd5b50610474610a02366004613c5e565b611c18565b348015610a1357600080fd5b50610474610a22366004613c5e565b611c7b565b348015610a3357600080fd5b50610474610a42366004613c5e565b611ce0565b348015610a5357600080fd5b50610474610a62366004613c5e565b611d45565b348015610a7357600080fd5b50610533610a82366004613bf8565b611dab565b348015610a9357600080fd5b50610491602d5481565b348015610aa957600080fd5b506104f1610ab8366004613b7c565b611db9565b348015610ac957600080fd5b50610474610ad8366004613b7c565b611dc9565b348015610ae957600080fd5b50610491602a5481565b348015610aff57600080fd5b50610474610b0e366004613f62565b611df8565b348015610b1f57600080fd5b506104f1610b2e366004613bf8565b611e57565b348015610b3f57600080fd5b50610474610b4e366004613c5e565b611e91565b348015610b5f57600080fd5b50610491610b6e366004613f8e565b611ef6565b348015610b7f57600080fd5b50610b93610b8e366004613e86565b611f8e565b60405161049b929190613fba565b348015610bad57600080fd5b50610474610bbc366004613b61565b6120fc565b348015610bcd57600080fd5b50610491610bdc366004614026565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b348015610c1357600080fd5b506104f1610c22366004613b7c565b61214c565b348015610c3357600080fd5b50610474610c42366004613c5e565b61215c565b348015610c5357600080fd5b50610474610c62366004613b61565b6121b4565b348015610c7357600080fd5b506104f1610c82366004613b7c565b612200565b348015610c9357600080fd5b50610474610ca2366004613c5e565b612210565b60078181548110610cb757600080fd5b906000526020600020016000915090508054610cd290614050565b80601f0160208091040260200160405190810160405280929190818152602001828054610cfe90614050565b8015610d4b5780601f10610d2057610100808354040283529160200191610d4b565b820191906000526020600020905b815481529060010190602001808311610d2e57829003601f168201915b505050505081565b606060038054610d6290614050565b80601f0160208091040260200160405190810160405280929190818152602001828054610d8e90614050565b8015610ddb5780601f10610db057610100808354040283529160200191610ddb565b820191906000526020600020905b815481529060010190602001808311610dbe57829003601f168201915b5050505050905090565b600033610df3818585612275565b60019150505b92915050565b600a8181548110610cb757600080fd5b600c8181548110610cb757600080fd5b600033610e2d858285612287565b610e38858585612305565b60019150505b9392505050565b600d8181548110610cb757600080fd5b6005546001600160a01b03163314610e7f5760405162461bcd60e51b815260040161046b90614084565b600580546001600160a01b03191690556040517f6e4ee811a17215345b89e3506064ff2d62f4feedff3566e9d09219cda7e8cadb90600090a1565b6005546001600160a01b03163314610ee45760405162461bcd60e51b815260040161046b90614084565b602154610f0190601790849084906301000000900460ff16612457565b602160036101000a81548160ff021916908360ff1602179055505050565b600060606029548410610f4357505060408051600080825260208201909252611020565b6000610f4f84866140d4565b9050602954811115610f6057506029545b610f6a85826140e7565b92508267ffffffffffffffff811115610f8557610f856140a8565b604051908082528060200260200182016040528015610fae578160200160208202803683370190505b509150845b8381101561101d5760276000610fc983896140d4565b815260200190815260200160002060009054906101000a90046001600160a01b0316838281518110610ffd57610ffd6140fa565b6001600160a01b0390921660209283029190910190910152600101610fb3565b50505b9250929050565b61102f6139ee565b6001600160a01b0383166000908152602b60209081526040808320858452909152908190209051637c3b3b8760e01b81528154600482015260019091015460248201523090637c3b3b879060440161034060405180830381865afa15801561109b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e3e919061413a565b604051637c3b3b8760e01b81528135600482015260208201356024820152606090610df9903090637c3b3b87906044015b61034060405180830381865afa15801561110e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611132919061413a565b6124b7565b6005546001600160a01b031633146111615760405162461bcd60e51b815260040161046b90614084565b60215461117e90601e9084908490600160501b900460ff16612457565b6021600a6101000a81548160ff021916908360ff1602179055505050565b60088181548110610cb757600080fd5b60098181548110610cb757600080fd5b60118181548110610cb757600080fd5b6005546001600160a01b031633146111f65760405162461bcd60e51b815260040161046b90614084565b60215461121690601a90849084906601000000000000900460ff16612457565b602160066101000a81548160ff021916908360ff1602179055505050565b6005546001600160a01b0316331461125e5760405162461bcd60e51b815260040161046b90614084565b602355565b60006112796024546001600160a01b0316151590565b61129a576112896009600a614352565b611295906103e8614361565b905090565b60006127106001602554426112af91906140e7565b6112bb6009600a614352565b6112c7906103e8614361565b6112d19190614361565b6112db9190614361565b6112e5919061438e565b6127106112f46009600a614352565b611300906103e8614361565b61130b906005614361565b611315919061438e565b61131f91906140d4565b905061132d6009600a614352565b611339906103e8614361565b81111561135b5761134c6009600a614352565b611358906103e8614361565b90505b919050565b6005546001600160a01b0316331461138a5760405162461bcd60e51b815260040161046b90614084565b6021546113a9906019908490849065010000000000900460ff16612457565b602160056101000a81548160ff021916908360ff1602179055505050565b6005546001600160a01b031633146113f15760405162461bcd60e51b815260040161046b90614084565b60215461141290601b9084908490670100000000000000900460ff16612457565b602160076101000a81548160ff021916908360ff1602179055505050565b600f8181548110610cb757600080fd5b6001600160a01b0383166000908152602c602052604081205460609080851061149f576040805160008082526020820190925281611494565b6114816139ee565b8152602001906001900390816114795790505b5092509250506115f4565b60006114ab85876140d4565b9050818111156114b85750805b6114c286826140e7565b93508367ffffffffffffffff8111156114dd576114dd6140a8565b60405190808252806020026020018201604052801561151657816020015b6115036139ee565b8152602001906001900390816114fb5790505b50925060005b848110156115f0576001600160a01b0388166000908152602b602052604081203091637c3b3b87919061154f858c6140d4565b81526020019081526020016000206040518263ffffffff1660e01b8152600401611589919081548152600190910154602082015260400190565b61034060405180830381865afa1580156115a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115cb919061413a565b8482815181106115dd576115dd6140fa565b602090810291909101015260010161151c565b5050505b935093915050565b60068181548110610cb757600080fd5b6116146139ee565b600060405180604001604052808480360381019061163291906143a2565b8152602001600081525090506116466139ee565b600654611652836126f5565b61165c91906143f1565b81526021546116769060ff16611671846126f5565b61274b565b602082015261169d6007611689846126f5565b84516020015161169890612762565b612784565b60408201526023546116b19060039061438e565b6116ba83612794565b11156116f1576021546116d890610100900460ff16611671846126f5565b60608201526116eb600d611689846126f5565b60808201525b60215461170a9062010000900460ff16611671846126f5565b60a0820152600a5461171b836126f5565b61172591906143f1565b60c08201526023546117399060039061438e565b61174283612794565b111561177c57602154611762906301000000900460ff16611671846126f5565b60e0820152611775600b611689846126f5565b6101008201525b600360235461178b919061438e565b61179483612794565b11156117d0576021546117b590640100000000900460ff16611671846126f5565b6101208201526117c9600c611689846126f5565b6101408201525b60036023546117df919061438e565b6117e883612794565b11156118255760215461180a9065010000000000900460ff16611671846126f5565b61016082015261181e6009611689846126f5565b6101808201525b6003602354611834919061438e565b61183d83612794565b111561187b57602154611860906601000000000000900460ff16611671846126f5565b6101a08201526118746008611689846126f5565b6101c08201525b6118896010611689846126f5565b6101e08201526021546118a990600160401b900460ff16611671846126f5565b6102008201526118bd600f611689846126f5565b6102208201526023546118d29060039061438e565b6118db83612794565b1115611916576021546118fb90600160481b900460ff16611671846126f5565b61024082015261190f600e611689846126f5565b6102608201525b6003602354611925919061438e565b61192e83612794565b11156119695760215461194e90600160501b900460ff16611671846126f5565b6102808201526119626011611689846126f5565b6102a08201525b6003602354611978919061438e565b61198183612794565b11156119bc576021546119a190600160581b900460ff16611671846126f5565b6102c08201526119b56012611689846126f5565b6102e08201525b60036023546119cb919061438e565b6119d483612794565b1115610e3e576021546119f490600160601b900460ff16611671846126f5565b610300820152611a086013611689846126f5565b6103208201529392505050565b60108181548110610cb757600080fd5b600e8181548110610cb757600080fd5b606060048054610d6290614050565b6005546001600160a01b03163314611a6e5760405162461bcd60e51b815260040161046b90614084565b602154611a8a906016908490849062010000900460ff16612457565b602160026101000a81548160ff021916908360ff1602179055505050565b6001600160a01b0383166000908152602c6020526040812054606090808510611b12576040805160008082526020820190925281611494565b6040805180820190915260008082526020820152815260200190600190039081611ae15790505092509250506115f4565b6000611b1e85876140d4565b905081811115611b2b5750805b611b3586826140e7565b93508367ffffffffffffffff811115611b5057611b506140a8565b604051908082528060200260200182016040528015611b9557816020015b6040805180820190915260008082526020820152815260200190600190039081611b6e5790505b50925060005b848110156115f0576001600160a01b0388166000908152602b6020526040812090611bc6838a6140d4565b815260200190815260200160002060405180604001604052908160008201548152602001600182015481525050848281518110611c0557611c056140fa565b6020908102919091010152600101611b9b565b6005546001600160a01b03163314611c425760405162461bcd60e51b815260040161046b90614084565b602154611c5d9060159084908490610100900460ff16612457565b602160016101000a81548160ff021916908360ff1602179055505050565b6005546001600160a01b03163314611ca55760405162461bcd60e51b815260040161046b90614084565b602154611cc29060209084908490600160601b900460ff16612457565b6021600c6101000a81548160ff021916908360ff1602179055505050565b6005546001600160a01b03163314611d0a5760405162461bcd60e51b815260040161046b90614084565b602154611d2790601c9084908490600160401b900460ff16612457565b602160086101000a81548160ff021916908360ff1602179055505050565b6005546001600160a01b03163314611d6f5760405162461bcd60e51b815260040161046b90614084565b602154611d8d9060189084908490640100000000900460ff16612457565b602160046101000a81548160ff021916908360ff1602179055505050565b600033610df3818585612305565b60138181548110610cb757600080fd5b6005546001600160a01b03163314611df35760405162461bcd60e51b815260040161046b90614084565b602255565b336000908152602c60205260409020548210611e485760405162461bcd60e51b815260206004820152600f60248201526e0d2dcc6dee4e4cac6e840d2dcc8caf608b1b604482015260640161046b565b611e533383836127b0565b5050565b604051633fc0fdcb60e01b81526001600160a01b038316600482015260248101829052606090610e3e903090633fc0fdcb906044016110f0565b6005546001600160a01b03163314611ebb5760405162461bcd60e51b815260040161046b90614084565b602154611ed890601d9084908490600160481b900460ff16612457565b602160096101000a81548160ff021916908360ff1602179055505050565b600080805b85811015611f2c5783611f0e8183614361565b611f1891906140d4565b611f2290836140d4565b9150600101611efb565b611f3682866143f1565b945060009150600090505b85811015611f825783611f548183614361565b611f5e91906140d4565b611f6890836140d4565b9150848210611f7a579150610e3e9050565b600101611f41565b50600095945050505050565b6001600160a01b0383166000908152602c6020526040812054606090808510611fe6576040805160008082526020820190925281611494565b6060815260200190600190039081611fc75790505092509250506115f4565b6000611ff285876140d4565b90508181111561200b57508061200881876140e7565b93505b8367ffffffffffffffff811115612024576120246140a8565b60405190808252806020026020018201604052801561205757816020015b60608152602001906001900390816120425790505b5092508560005b828210156120f0576001600160a01b0389166000908152602b60209081526040808320858452909152908190209051637c3b3b8760e01b81528154600482015260019091015460248201526120bd903090637c3b3b87906044016110f0565b85826120c881614405565b9350815181106120da576120da6140fa565b602002602001018190525081600101915061205e565b50505050935093915050565b6005546001600160a01b031633146121265760405162461bcd60e51b815260040161046b90614084565b602480546001600160a01b0319166001600160a01b039290921691909117905542602555565b60128181548110610cb757600080fd5b6005546001600160a01b031633146121865760405162461bcd60e51b815260040161046b90614084565b60215461219c906014908490849060ff16612457565b6021805460ff191660ff929092169190911790555050565b6005546001600160a01b031633146121de5760405162461bcd60e51b815260040161046b90614084565b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600b8181548110610cb757600080fd5b6005546001600160a01b0316331461223a5760405162461bcd60e51b815260040161046b90614084565b60215461225790601f9084908490600160581b900460ff16612457565b6021600b6101000a81548160ff021916908360ff1602179055505050565b6122828383836001612812565b505050565b6001600160a01b0383811660009081526001602090815260408083209386168352929052205460001981146122ff57818110156122f057604051637dc7a0d960e11b81526001600160a01b0384166004820152602481018290526044810183905260640161046b565b6122ff84848484036000612812565b50505050565b6001600160a01b038216158061232557506001600160a01b03821661dead145b15612335576122828383836128e7565b6024546001600160a01b03161580156123df57506001600160a01b038316158061236757506001600160a01b03831630145b806123a357507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316145b806123df57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316145b156123ef57612282838383612b2b565b602454600160a01b900460ff161561240c57612282838383612b2b565b6024546001600160a01b039081169084160361242c576122828282612b8a565b6024546001600160a01b039081169083160361244c576122828382612c5d565b6122828383836128e7565b60008281036124675750806124af565b60005b838110156124aa576124a086868684818110612488576124886140fa565b905060200281019061249a919061441e565b85612d7a565b925060010161246a565b829150505b949350505050565b606060006124c5600a612e4a565b6124cf600a612e4a565b6040516020016124e092919061443e565b60408051601f1981840301815291905290506000816124ff600a612e4a565b612509600a612e4a565b6006876000015181548110612520576125206140fa565b9060005260206000200160405160200161253c939291906144d9565b6040516020818303038152906040526125616014600788602001518960400151612f4b565b6125776016600a8960a001518a60c00151612f4b565b61258d6015600d8a606001518b60800151612f4b565b6125a46017600b8b60e001518c6101000151612f4b565b6125bc6018600c8c61012001518d6101400151612f4b565b6125d4601960098d61016001518e6101800151612f4b565b6125ec601a60088e6101a001518f6101c00151612f4b565b604051602001612604999897969594939291906145e9565b6040516020818303038152906040529050600061262b601b60106001886101e00151612f4b565b612643601c600f886102000151896102200151612f4b565b61265b601d600e8961024001518a6102600151612f4b565b612673601e60118a61028001518b6102a00151612f4b565b61268b602060138b61030001518c6103200151612f4b565b6126a3601f60128c6102c001518d6102e00151613047565b6040516020016126b8969594939291906146aa565b604051602081830303815290604052905081816040516020016126dc929190614729565b6040516020818303038152906040529350505050919050565b8051805160209182015191830180516000939161271182614405565b9052604080516020810194909452830191909152606082015260800160408051601f19818403018152919052805160209091012092915050565b600061275783836143f1565b610e3e9060016140d4565b600060225482101561277c5781602254610df991906140e7565b506001919050565b82546000906124af908484611ef6565b8051602001516000906127a6836126f5565b610df991906143f1565b6001600160a01b0383166000908152602b6020908152604080832085845282529182902082518084019093528054835260010154908201526127fe84836127f96009600a614352565b613099565b61280884846130fd565b6122ff8282613207565b6001600160a01b03841661283c5760405163e602df0560e01b81526000600482015260240161046b565b6001600160a01b03831661286657604051634a1406b160e11b81526000600482015260240161046b565b6001600160a01b03808516600090815260016020908152604080832093871683529290522082905580156122ff57826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516128d991815260200190565b60405180910390a350505050565b6128ef6132cc565b6001600160a01b0383166000908152602081905260408120549061291383836140e7565b90506000612936856001600160a01b031660009081526020819052604090205490565b9050600061294485836140d4565b90506001600160a01b038616158061296657506001600160a01b03861661dead145b15612972575060009050805b60006129806009600a614352565b61298a908561438e565b6129966009600a614352565b6129a0908761438e565b6129aa91906140e7565b905060006129ba6009600a614352565b6129c4908561438e565b6129d06009600a614352565b6129da908561438e565b6129e491906140e7565b905081818111156129f25750805b6001600160a01b038a166000908152602c60205260408120545b82821015612a84578015612a84576000612a2582614769565b6001600160a01b038e166000908152602b602090815260408083208484528252918290208251808401909352805483526001015490820152909250829150612a6d8e836130fd565b612a778d82613207565b5050816001019150612a0c565b82915b85831015612ab5576000612a9a83614769565b9250829050612aa98e826130fd565b50826001019250612a87565b8092505b84831015612b0c5760006040518060400160405280602e60008154612add90614405565b91829055508152602001612af26103e86132f6565b90529050612b008d82613207565b50826001019250612ab9565b612b178d8d8d613099565b505050505050505050506122826001602655565b6001600160a01b038316612b5557604051634b637e8f60e11b81526000600482015260240161046b565b6001600160a01b038216612b7f5760405163ec442f0560e01b81526000600482015260240161046b565b612282838383613345565b612b926132cc565b6001600160a01b03821660009081526020819052604081205490612bb683836140d4565b90506000612bc66009600a614352565b612bd0908461438e565b612bdc6009600a614352565b612be6908461438e565b612bf091906140e7565b905060005b81811015612c455760006040518060400160405280602e60008154612c1990614405565b91829055508152602001612c2e6103e86132f6565b90529050612c3c8782613207565b50600101612bf5565b612c4f868661346f565b50505050611e536001602655565b6024805460ff60a01b1916600160a01b179055612c786132cc565b6001600160a01b03821660009081526020819052604081205490612c9c83836140e7565b90506000612cac6009600a614352565b612cb6908361438e565b612cc26009600a614352565b612ccc908561438e565b612cd691906140e7565b6001600160a01b0386166000908152602c6020526040812054919250905b82821015612d42576103e8602a541015612d1c57602a60008154612d1790614405565b909155505b8015612d3757612d3787612d2f83614769565b9250826130fd565b816001019150612cf4565b602454612d5a9088906001600160a01b031688612305565b5050505050612d696001602655565b50506024805460ff60a01b19169055565b81356000908152602084905260408120805415612dbf57846000612da0600187356140e7565b81526020019081526020016000206000612dba9190613ab1565b612dcb565b612dc883614780565b92505b60005b612ddb602086018661479f565b9050811015612e405781612df2602087018761479f565b83818110612e0257612e026140fa565b9050602002810190612e14919061441e565b815460018101835560009283526020909220909160020201612e368282614941565b5050600101612dce565b5091949350505050565b606081600003612e715750506040805180820190915260018152600360fc1b602082015290565b8160005b8115612e9b5780612e8581614405565b9150612e949050600a8361438e565b9150612e75565b60008167ffffffffffffffff811115612eb657612eb66140a8565b6040519080825280601f01601f191660200182016040528015612ee0576020820181803683370190505b5090505b84156124af57612ef56001836140e7565b9150612f02600a866143f1565b612f0d9060306140d4565b60f81b818381518110612f2257612f226140fa565b60200101906001600160f81b031916908160001a905350612f44600a8661438e565b9450612ee4565b606082600003612f6a57506040805160208101909152600081526124af565b61303e848381548110612f7f57612f7f6140fa565b906000526020600020018054612f9490614050565b80601f0160208091040260200160405190810160405280929190818152602001828054612fc090614050565b801561300d5780601f10612fe25761010080835404028352916020019161300d565b820191906000526020600020905b815481529060010190602001808311612ff057829003601f168201915b505050505086600060018761302291906140e7565b81526020019081526020016000206134da90919063ffffffff16565b95945050505050565b60608260000361306657506040805160208101909152600081526124af565b82600103612f6a5761309285600061307f6001876140e7565b815260200190815260200160002061367e565b90506124af565b6024805460ff60a01b1916600160a01b1790556001600160a01b03821615806130cc57506001600160a01b03821661dead145b156130e0576130db8382613817565b6130eb565b6130eb838383612b2b565b50506024805460ff60a01b1916905550565b6024546001600160a01b0390811690831603613117575050565b6001600160a01b0382166000908152602c60205260408120805490919061313d90614769565b9182905550600003613152576131528261384d565b602d6000815461316190614769565b909155506001600160a01b0382166000908152602c60205260409020548181146131d5576001600160a01b0383166000908152602b60209081526040808320848452808352818420825180840184528154815260019182015481860190815288875292909452919093209151825591519101555b6001600160a01b039092166000908152602b602090815260408083209483529390529182208281556001019190915550565b6024546001600160a01b0390811690831603613221575050565b6001600160a01b0382166000908152602c60205260408120805490919061324790614405565b918290555060010361325c5761325c82613934565b602d6000815461326b90614405565b909155506001600160a01b0382166000908152602c6020526040812054613294906001906140e7565b6001600160a01b03939093166000908152602b6020908152604080832095835294815293902082518155919092015160019091015550565b6002602654036132ef57604051633ee5aeb560e01b815260040160405180910390fd5b6002602655565b60006103e8602a54836133099190614361565b613313919061438e565b91508160000361332257600191505b6001602a54111561334157602a6000815461333c90614769565b909155505b5090565b6001600160a01b03831661337057806002600082825461336591906140d4565b909155506133e29050565b6001600160a01b038316600090815260208190526040902054818110156133c35760405163391434e360e21b81526001600160a01b0385166004820152602481018290526044810183905260640161046b565b6001600160a01b03841660009081526020819052604090209082900390555b6001600160a01b0382166133fe5760028054829003905561341d565b6001600160a01b03821660009081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161346291815260200190565b60405180910390a3505050565b80613478611263565b8111156134b15760405162461bcd60e51b81526020600482015260076024820152666d61782062757960c81b604482015260640161046b565b6024805460ff60a01b198116600160a01b179091556130eb906001600160a01b03168484612b2b565b60608060005b8454811015613676578161364b85878481548110613500576135006140fa565b906000526020600020906002020160405180604001604052908160008201805461352990614050565b80601f016020809104026020016040519081016040528092919081815260200182805461355590614050565b80156135a25780601f10613577576101008083540402835291602001916135a2565b820191906000526020600020905b81548152906001019060200180831161358557829003601f168201915b505050505081526020016001820180546135bb90614050565b80601f01602080910402602001604051908101604052809291908181526020018280546135e790614050565b80156136345780601f1061360957610100808354040283529160200191613634565b820191906000526020600020905b81548152906001019060200180831161361757829003601f168201915b50505050508152505061398990919063ffffffff16565b60405160200161365c929190614a24565b60408051601f1981840301815291905291506001016134e0565b509392505050565b60608060005b835481101561381057816137e58583815481106136a3576136a36140fa565b90600052602060002090600202016040518060400160405290816000820180546136cc90614050565b80601f01602080910402602001604051908101604052809291908181526020018280546136f890614050565b80156137455780601f1061371a57610100808354040283529160200191613745565b820191906000526020600020905b81548152906001019060200180831161372857829003601f168201915b5050505050815260200160018201805461375e90614050565b80601f016020809104026020016040519081016040528092919081815260200182805461378a90614050565b80156137d75780601f106137ac576101008083540402835291602001916137d7565b820191906000526020600020905b8154815290600101906020018083116137ba57829003601f168201915b5050505050815250506139bb565b6040516020016137f6929190614a24565b60408051601f198184030181529190529150600101613684565b5092915050565b6001600160a01b03821661384157604051634b637e8f60e11b81526000600482015260240161046b565b611e5382600083613345565b60295460000361385a5750565b6001600160a01b038116600090815260286020526040902054602954613882906001906140e7565b81146138e757600060276000600160295461389d91906140e7565b815260208082019290925260409081016000908120548582526027845282822080546001600160a01b0319166001600160a01b039092169182179055815260289092529020829055505b6029600081546138f690614769565b90915550506001600160a01b0316600090815260286020908152604080832083905560295483526027909152902080546001600160a01b0319169055565b602980546000918261394583614405565b90915550600081815260276020908152604080832080546001600160a01b039097166001600160a01b03199097168717905594825260289052929092209190915550565b6060818360200151836040516020016139a493929190614a53565b604051602081830303815290604052905092915050565b6060816000015182602001516040516020016139d8929190614ad2565b6040516020818303038152906040529050919050565b60405180610340016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b5080546000825560020290600052602060002090810190613ad29190613ad5565b50565b80821115613341576000613ae98282613b00565b613af7600183016000613b00565b50600201613ad5565b508054613b0c90614050565b6000825580601f10613b1c575050565b601f016020900490600052602060002090810190613ad291905b808211156133415760008155600101613b36565b80356001600160a01b038116811461135b57600080fd5b600060208284031215613b7357600080fd5b610e3e82613b4a565b600060208284031215613b8e57600080fd5b5035919050565b60005b83811015613bb0578181015183820152602001613b98565b50506000910152565b60008151808452613bd1816020860160208601613b95565b601f01601f19169290920160200192915050565b602081526000610e3e6020830184613bb9565b60008060408385031215613c0b57600080fd5b613c1483613b4a565b946020939093013593505050565b600080600060608486031215613c3757600080fd5b613c4084613b4a565b9250613c4e60208501613b4a565b9150604084013590509250925092565b60008060208385031215613c7157600080fd5b823567ffffffffffffffff80821115613c8957600080fd5b818501915085601f830112613c9d57600080fd5b813581811115613cac57600080fd5b8660208260051b8501011115613cc157600080fd5b60209290920196919550909350505050565b60008060408385031215613ce657600080fd5b50508035926020909101359150565b60006040820184835260206040602085015281855180845260608601915060208701935060005b81811015613d415784516001600160a01b031683529383019391830191600101613d1c565b5090979650505050505050565b805182526020808201519083015260408082015190830152606080820151908301526080808201519083015260a0808201519083015260c0808201519083015260e08082015190830152610100808201519083015261012080820151908301526101408082015190830152610160808201519083015261018080820151908301526101a080820151908301526101c080820151908301526101e08082015190830152610200808201519083015261022080820151908301526102408082015190830152610260808201519083015261028080820151908301526102a080820151908301526102c080820151908301526102e08082015190830152610300808201519083015261032090810151910152565b6103408101610df98284613d4e565b600060408284031215613e8057600080fd5b50919050565b600080600060608486031215613e9b57600080fd5b613ea484613b4a565b95602085013595506040909401359392505050565b60006040820184835260206040602085015281855180845260608601915060208701935060005b81811015613d4157613ef3838651613d4e565b938301936103409290920191600101613ee0565b6000604080830185845260206040602086015281865180845260608701915060208801935060005b81811015613f5457845180518452840151848401529383019391850191600101613f2f565b509098975050505050505050565b60008060408385031215613f7557600080fd5b82359150613f8560208401613b4a565b90509250929050565b600080600060608486031215613fa357600080fd5b505081359360208301359350604090920135919050565b60006040820184835260206040602085015281855180845260608601915060608160051b87010193506020870160005b8281101561401857605f19888703018452614006868351613bb9565b95509284019290840190600101613fea565b509398975050505050505050565b6000806040838503121561403957600080fd5b61404283613b4a565b9150613f8560208401613b4a565b600181811c9082168061406457607f821691505b602082108103613e8057634e487b7160e01b600052602260045260246000fd5b6020808252600a908201526937b7363c9037bbb732b960b11b604082015260600190565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b80820180821115610df957610df96140be565b81810381811115610df957610df96140be565b634e487b7160e01b600052603260045260246000fd5b604051610340810167ffffffffffffffff81118282101715614134576141346140a8565b60405290565b6000610340828403121561414d57600080fd5b614155614110565b825181526020808401519082015260408084015190820152606080840151908201526080808401519082015260a0808401519082015260c0808401519082015260e08084015190820152610100808401519082015261012080840151908201526101408084015190820152610160808401519082015261018080840151908201526101a080840151908201526101c080840151908201526101e08084015190820152610200808401519082015261022080840151908201526102408084015190820152610260808401519082015261028080840151908201526102a080840151908201526102c080840151908201526102e080840151908201526103008084015190820152610320928301519281019290925250919050565b600181815b808511156142a957816000190482111561428f5761428f6140be565b8085161561429c57918102915b93841c9390800290614273565b509250929050565b6000826142c057506001610df9565b816142cd57506000610df9565b81600181146142e357600281146142ed57614309565b6001915050610df9565b60ff8411156142fe576142fe6140be565b50506001821b610df9565b5060208310610133831016604e8410600b841016171561432c575081810a610df9565b614336838361426e565b806000190482111561434a5761434a6140be565b029392505050565b6000610e3e60ff8416836142b1565b8082028115828204841417610df957610df96140be565b634e487b7160e01b600052601260045260246000fd5b60008261439d5761439d614378565b500490565b6000604082840312156143b457600080fd5b6040516040810181811067ffffffffffffffff821117156143d7576143d76140a8565b604052823581526020928301359281019290925250919050565b60008261440057614400614378565b500690565b600060018201614417576144176140be565b5060010190565b60008235603e1983360301811261443457600080fd5b9190910192915050565b7f3c73766720786d6c6e733d27687474703a2f2f7777772e77332e6f72672f3230815273030302f737667272076696577426f783d273020360641b60208201526000600160fd1b806034840152845161449e816035860160208901613b95565b8084019050816035820152845191506144be826036830160208801613b95565b61139f60f11b91016036810191909152603801949350505050565b703c7265637420783d27302720793d27302760781b8152672077696474683d2760c01b6011820152600084516020614518826019860160208a01613b95565b6927206865696768743d2760b01b6019928501928301528551614542816023850160208a01613b95565b80830192505067272066696c6c3d2760c01b6023830152602b6000865461456881614050565b60018281168015614580576001811461459b576145cd565b60ff198416602b890152602b831515840289010194506145cd565b8a600052602060002060005b848110156145c25781548a82018901529083019088016145a7565b5050602b8389010194505b50506213979f60e91b8352505060030198975050505050505050565b60008a516145fb818460208f01613b95565b8a5161460d8183860160208f01613b95565b8a519184010190614622818360208e01613b95565b89516146348183850160208e01613b95565b895192909101019061464a818360208c01613b95565b875161465c8183850160208c01613b95565b8751929091010190614672818360208a01613b95565b85516146848183850160208a01613b95565b855192909101019061469a818360208801613b95565b019b9a5050505050505050505050565b6000875160206146bd8285838d01613b95565b8851918401916146d08184848d01613b95565b88519201916146e28184848c01613b95565b87519201916146f48184848b01613b95565b86519201916147068184848a01613b95565b85519201916147188184848901613b95565b919091019998505050505050505050565b6000835161473b818460208801613b95565b83519083019061474f818360208801613b95565b651e17b9bb339f60d11b9101908152600601949350505050565b600081614778576147786140be565b506000190190565b600060ff821660ff8103614796576147966140be565b60010192915050565b6000808335601e198436030181126147b657600080fd5b83018035915067ffffffffffffffff8211156147d157600080fd5b6020019150600581901b360382131561102057600080fd5b6000808335601e1984360301811261480057600080fd5b83018035915067ffffffffffffffff82111561481b57600080fd5b60200191503681900382131561102057600080fd5b601f821115612282576000816000526020600020601f850160051c810160208610156148595750805b601f850160051c820191505b8181101561487857828155600101614865565b505050505050565b67ffffffffffffffff831115614898576148986140a8565b6148ac836148a68354614050565b83614830565b6000601f8411600181146148e057600085156148c85750838201355b600019600387901b1c1916600186901b17835561493a565b600083815260209020601f19861690835b8281101561491157868501358255602094850194600190920191016148f1565b508682101561492e5760001960f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b61494b82836147e9565b67ffffffffffffffff811115614963576149636140a8565b614977816149718554614050565b85614830565b6000601f8211600181146149ab57600083156149935750838201355b600019600385901b1c1916600184901b178555614a05565b600085815260209020601f19841690835b828110156149dc57868501358255602094850194600190920191016149bc565b50848210156149f95760001960f88660031b161c19848701351681555b505060018360011b0185555b50505050614a1660208301836147e9565b6122ff818360018601614880565b60008351614a36818460208801613b95565b835190830190614a4a818360208801613b95565b01949350505050565b6b3c706174682066696c6c3d2760a01b815260008451614a7a81600c850160208901613b95565b642720643d2760d81b600c918401918201528451614a9f816011840160208901613b95565b8451910190614ab5816011840160208801613b95565b6213979f60e91b6011929091019182015260140195945050505050565b6b3c706174682066696c6c3d2760a01b815260008351614af981600c850160208801613b95565b642720643d2760d81b600c918401918201528351614b1e816011840160208801613b95565b6213979f60e91b6011929091019182015260140194935050505056fea26469706673582212206cb8964b13f99ca4a0bed9ed23fd1195e1528ddce336b412da3426f4517ca45064736f6c63430008190033

Deployed Bytecode

0x6080604052600436106103b15760003560e01c80637673bfa4116101e7578063afd1e4d81161010d578063dd0b281e116100a0578063eb0ffeb81161006f578063eb0ffeb814610c27578063f2fde38b14610c47578063f578990e14610c67578063fe6fb9a014610c8757600080fd5b8063dd0b281e14610ba1578063dd62ed3e14610bc1578063dde415fa1461094e578063e7a966b614610c0757600080fd5b8063b4f243a4116100dc578063b4f243a414610b13578063bdc1827c14610b33578063c01e21af14610b53578063d5a4260614610b7357600080fd5b8063afd1e4d814610a9d578063b42781ee14610abd578063b42dfa0d14610add578063b4377a3e14610af357600080fd5b8063984bb7a611610185578063a46f3d4b11610154578063a46f3d4b14610a27578063a4ea3c3314610a47578063a9059cbb14610a67578063af504def14610a8757600080fd5b8063984bb7a61461099957806398bafaa3146109b95780639b439dc5146109e75780639c7d73e614610a0757600080fd5b80638da5cb5b116101c15780638da5cb5b146109265780638fdada4a1461094e578063943a6ff61461096457806395d89b411461098457600080fd5b80637673bfa4146108c65780637c3b3b87146108e657806387cd15551461090657600080fd5b80633fc0fdcb116102d75780635e927ceb1161026a578063719f150711610239578063719f150714610838578063719fa9b11461085857806374ae513614610878578063750e8d101461089857600080fd5b80635e927ceb146107795780636a29f5e51461079957806370a08231146107ed57806370db69d61461082357600080fd5b806353c55061116102a657806353c55061146106f9578063544736e6146107195780635534b159146107395780635e5b6dfd1461075957600080fd5b80633fc0fdcb1461066c578063422b9e23146106995780634dc46def146106b957806353388fd5146106d957600080fd5b806318160ddd1161034f578063313ce5671161031e578063313ce567146105ed578063333a00721461060957806336d208cf1461061e5780633860a3931461063e57600080fd5b806318160ddd1461058357806323b872dd146105985780632547b84d146105b85780632d12d34b146105d857600080fd5b806306fdde031161038b57806306fdde03146104fe578063095ea7b3146105135780630dfa2c481461054357806312ac5d0f1461056357600080fd5b8063018a37411461047b5780630568e65e146104a457806306a86dd7146104d157600080fd5b366104765760007f000000000000000000000000ebfaefee647f359564062b2bf01a156aca296a0d6001600160a01b03163460405160006040518083038185875af1925050503d8060008114610423576040519150601f19603f3d011682016040523d82523d6000602084013e610428565b606091505b505080915050806104745760405162461bcd60e51b815260206004820152601160248201527031b0b7103737ba1033b2ba1032ba3432b960791b60448201526064015b60405180910390fd5b005b600080fd5b34801561048757600080fd5b5061049160295481565b6040519081526020015b60405180910390f35b3480156104b057600080fd5b506104916104bf366004613b61565b602c6020526000908152604090205481565b3480156104dd57600080fd5b506104f16104ec366004613b7c565b610ca7565b60405161049b9190613be5565b34801561050a57600080fd5b506104f1610d53565b34801561051f57600080fd5b5061053361052e366004613bf8565b610de5565b604051901515815260200161049b565b34801561054f57600080fd5b506104f161055e366004613b7c565b610dff565b34801561056f57600080fd5b506104f161057e366004613b7c565b610e0f565b34801561058f57600080fd5b50600254610491565b3480156105a457600080fd5b506105336105b3366004613c22565b610e1f565b3480156105c457600080fd5b506104f16105d3366004613b7c565b610e45565b3480156105e457600080fd5b50610491600181565b3480156105f957600080fd5b506040516009815260200161049b565b34801561061557600080fd5b50610474610e55565b34801561062a57600080fd5b50610474610639366004613c5e565b610eba565b34801561064a57600080fd5b5061065e610659366004613cd3565b610f1f565b60405161049b929190613cf5565b34801561067857600080fd5b5061068c610687366004613bf8565b611027565b60405161049b9190613e5f565b3480156106a557600080fd5b506104f16106b4366004613e6e565b6110bf565b3480156106c557600080fd5b506104746106d4366004613c5e565b611137565b3480156106e557600080fd5b506104f16106f4366004613b7c565b61119c565b34801561070557600080fd5b506104f1610714366004613b7c565b6111ac565b34801561072557600080fd5b506024546001600160a01b03161515610533565b34801561074557600080fd5b506104f1610754366004613b7c565b6111bc565b34801561076557600080fd5b50610474610774366004613c5e565b6111cc565b34801561078557600080fd5b50610474610794366004613b7c565b611234565b3480156107a557600080fd5b506107d86107b4366004613bf8565b602b6020908152600092835260408084209091529082529020805460019091015482565b6040805192835260208301919091520161049b565b3480156107f957600080fd5b50610491610808366004613b61565b6001600160a01b031660009081526020819052604090205490565b34801561082f57600080fd5b50610491611263565b34801561084457600080fd5b50610474610853366004613c5e565b611360565b34801561086457600080fd5b50610474610873366004613c5e565b6113c7565b34801561088457600080fd5b506104f1610893366004613b7c565b611430565b3480156108a457600080fd5b506108b86108b3366004613e86565b611440565b60405161049b929190613eb9565b3480156108d257600080fd5b506104f16108e1366004613b7c565b6115fc565b3480156108f257600080fd5b5061068c610901366004613e6e565b61160c565b34801561091257600080fd5b506104f1610921366004613b7c565b611a15565b34801561093257600080fd5b506005546040516001600160a01b03909116815260200161049b565b34801561095a57600080fd5b506104916103e881565b34801561097057600080fd5b506104f161097f366004613b7c565b611a25565b34801561099057600080fd5b506104f1611a35565b3480156109a557600080fd5b506104746109b4366004613c5e565b611a44565b3480156109c557600080fd5b506109d96109d4366004613e86565b611aa8565b60405161049b929190613f07565b3480156109f357600080fd5b50610474610a02366004613c5e565b611c18565b348015610a1357600080fd5b50610474610a22366004613c5e565b611c7b565b348015610a3357600080fd5b50610474610a42366004613c5e565b611ce0565b348015610a5357600080fd5b50610474610a62366004613c5e565b611d45565b348015610a7357600080fd5b50610533610a82366004613bf8565b611dab565b348015610a9357600080fd5b50610491602d5481565b348015610aa957600080fd5b506104f1610ab8366004613b7c565b611db9565b348015610ac957600080fd5b50610474610ad8366004613b7c565b611dc9565b348015610ae957600080fd5b50610491602a5481565b348015610aff57600080fd5b50610474610b0e366004613f62565b611df8565b348015610b1f57600080fd5b506104f1610b2e366004613bf8565b611e57565b348015610b3f57600080fd5b50610474610b4e366004613c5e565b611e91565b348015610b5f57600080fd5b50610491610b6e366004613f8e565b611ef6565b348015610b7f57600080fd5b50610b93610b8e366004613e86565b611f8e565b60405161049b929190613fba565b348015610bad57600080fd5b50610474610bbc366004613b61565b6120fc565b348015610bcd57600080fd5b50610491610bdc366004614026565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b348015610c1357600080fd5b506104f1610c22366004613b7c565b61214c565b348015610c3357600080fd5b50610474610c42366004613c5e565b61215c565b348015610c5357600080fd5b50610474610c62366004613b61565b6121b4565b348015610c7357600080fd5b506104f1610c82366004613b7c565b612200565b348015610c9357600080fd5b50610474610ca2366004613c5e565b612210565b60078181548110610cb757600080fd5b906000526020600020016000915090508054610cd290614050565b80601f0160208091040260200160405190810160405280929190818152602001828054610cfe90614050565b8015610d4b5780601f10610d2057610100808354040283529160200191610d4b565b820191906000526020600020905b815481529060010190602001808311610d2e57829003601f168201915b505050505081565b606060038054610d6290614050565b80601f0160208091040260200160405190810160405280929190818152602001828054610d8e90614050565b8015610ddb5780601f10610db057610100808354040283529160200191610ddb565b820191906000526020600020905b815481529060010190602001808311610dbe57829003601f168201915b5050505050905090565b600033610df3818585612275565b60019150505b92915050565b600a8181548110610cb757600080fd5b600c8181548110610cb757600080fd5b600033610e2d858285612287565b610e38858585612305565b60019150505b9392505050565b600d8181548110610cb757600080fd5b6005546001600160a01b03163314610e7f5760405162461bcd60e51b815260040161046b90614084565b600580546001600160a01b03191690556040517f6e4ee811a17215345b89e3506064ff2d62f4feedff3566e9d09219cda7e8cadb90600090a1565b6005546001600160a01b03163314610ee45760405162461bcd60e51b815260040161046b90614084565b602154610f0190601790849084906301000000900460ff16612457565b602160036101000a81548160ff021916908360ff1602179055505050565b600060606029548410610f4357505060408051600080825260208201909252611020565b6000610f4f84866140d4565b9050602954811115610f6057506029545b610f6a85826140e7565b92508267ffffffffffffffff811115610f8557610f856140a8565b604051908082528060200260200182016040528015610fae578160200160208202803683370190505b509150845b8381101561101d5760276000610fc983896140d4565b815260200190815260200160002060009054906101000a90046001600160a01b0316838281518110610ffd57610ffd6140fa565b6001600160a01b0390921660209283029190910190910152600101610fb3565b50505b9250929050565b61102f6139ee565b6001600160a01b0383166000908152602b60209081526040808320858452909152908190209051637c3b3b8760e01b81528154600482015260019091015460248201523090637c3b3b879060440161034060405180830381865afa15801561109b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e3e919061413a565b604051637c3b3b8760e01b81528135600482015260208201356024820152606090610df9903090637c3b3b87906044015b61034060405180830381865afa15801561110e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611132919061413a565b6124b7565b6005546001600160a01b031633146111615760405162461bcd60e51b815260040161046b90614084565b60215461117e90601e9084908490600160501b900460ff16612457565b6021600a6101000a81548160ff021916908360ff1602179055505050565b60088181548110610cb757600080fd5b60098181548110610cb757600080fd5b60118181548110610cb757600080fd5b6005546001600160a01b031633146111f65760405162461bcd60e51b815260040161046b90614084565b60215461121690601a90849084906601000000000000900460ff16612457565b602160066101000a81548160ff021916908360ff1602179055505050565b6005546001600160a01b0316331461125e5760405162461bcd60e51b815260040161046b90614084565b602355565b60006112796024546001600160a01b0316151590565b61129a576112896009600a614352565b611295906103e8614361565b905090565b60006127106001602554426112af91906140e7565b6112bb6009600a614352565b6112c7906103e8614361565b6112d19190614361565b6112db9190614361565b6112e5919061438e565b6127106112f46009600a614352565b611300906103e8614361565b61130b906005614361565b611315919061438e565b61131f91906140d4565b905061132d6009600a614352565b611339906103e8614361565b81111561135b5761134c6009600a614352565b611358906103e8614361565b90505b919050565b6005546001600160a01b0316331461138a5760405162461bcd60e51b815260040161046b90614084565b6021546113a9906019908490849065010000000000900460ff16612457565b602160056101000a81548160ff021916908360ff1602179055505050565b6005546001600160a01b031633146113f15760405162461bcd60e51b815260040161046b90614084565b60215461141290601b9084908490670100000000000000900460ff16612457565b602160076101000a81548160ff021916908360ff1602179055505050565b600f8181548110610cb757600080fd5b6001600160a01b0383166000908152602c602052604081205460609080851061149f576040805160008082526020820190925281611494565b6114816139ee565b8152602001906001900390816114795790505b5092509250506115f4565b60006114ab85876140d4565b9050818111156114b85750805b6114c286826140e7565b93508367ffffffffffffffff8111156114dd576114dd6140a8565b60405190808252806020026020018201604052801561151657816020015b6115036139ee565b8152602001906001900390816114fb5790505b50925060005b848110156115f0576001600160a01b0388166000908152602b602052604081203091637c3b3b87919061154f858c6140d4565b81526020019081526020016000206040518263ffffffff1660e01b8152600401611589919081548152600190910154602082015260400190565b61034060405180830381865afa1580156115a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115cb919061413a565b8482815181106115dd576115dd6140fa565b602090810291909101015260010161151c565b5050505b935093915050565b60068181548110610cb757600080fd5b6116146139ee565b600060405180604001604052808480360381019061163291906143a2565b8152602001600081525090506116466139ee565b600654611652836126f5565b61165c91906143f1565b81526021546116769060ff16611671846126f5565b61274b565b602082015261169d6007611689846126f5565b84516020015161169890612762565b612784565b60408201526023546116b19060039061438e565b6116ba83612794565b11156116f1576021546116d890610100900460ff16611671846126f5565b60608201526116eb600d611689846126f5565b60808201525b60215461170a9062010000900460ff16611671846126f5565b60a0820152600a5461171b836126f5565b61172591906143f1565b60c08201526023546117399060039061438e565b61174283612794565b111561177c57602154611762906301000000900460ff16611671846126f5565b60e0820152611775600b611689846126f5565b6101008201525b600360235461178b919061438e565b61179483612794565b11156117d0576021546117b590640100000000900460ff16611671846126f5565b6101208201526117c9600c611689846126f5565b6101408201525b60036023546117df919061438e565b6117e883612794565b11156118255760215461180a9065010000000000900460ff16611671846126f5565b61016082015261181e6009611689846126f5565b6101808201525b6003602354611834919061438e565b61183d83612794565b111561187b57602154611860906601000000000000900460ff16611671846126f5565b6101a08201526118746008611689846126f5565b6101c08201525b6118896010611689846126f5565b6101e08201526021546118a990600160401b900460ff16611671846126f5565b6102008201526118bd600f611689846126f5565b6102208201526023546118d29060039061438e565b6118db83612794565b1115611916576021546118fb90600160481b900460ff16611671846126f5565b61024082015261190f600e611689846126f5565b6102608201525b6003602354611925919061438e565b61192e83612794565b11156119695760215461194e90600160501b900460ff16611671846126f5565b6102808201526119626011611689846126f5565b6102a08201525b6003602354611978919061438e565b61198183612794565b11156119bc576021546119a190600160581b900460ff16611671846126f5565b6102c08201526119b56012611689846126f5565b6102e08201525b60036023546119cb919061438e565b6119d483612794565b1115610e3e576021546119f490600160601b900460ff16611671846126f5565b610300820152611a086013611689846126f5565b6103208201529392505050565b60108181548110610cb757600080fd5b600e8181548110610cb757600080fd5b606060048054610d6290614050565b6005546001600160a01b03163314611a6e5760405162461bcd60e51b815260040161046b90614084565b602154611a8a906016908490849062010000900460ff16612457565b602160026101000a81548160ff021916908360ff1602179055505050565b6001600160a01b0383166000908152602c6020526040812054606090808510611b12576040805160008082526020820190925281611494565b6040805180820190915260008082526020820152815260200190600190039081611ae15790505092509250506115f4565b6000611b1e85876140d4565b905081811115611b2b5750805b611b3586826140e7565b93508367ffffffffffffffff811115611b5057611b506140a8565b604051908082528060200260200182016040528015611b9557816020015b6040805180820190915260008082526020820152815260200190600190039081611b6e5790505b50925060005b848110156115f0576001600160a01b0388166000908152602b6020526040812090611bc6838a6140d4565b815260200190815260200160002060405180604001604052908160008201548152602001600182015481525050848281518110611c0557611c056140fa565b6020908102919091010152600101611b9b565b6005546001600160a01b03163314611c425760405162461bcd60e51b815260040161046b90614084565b602154611c5d9060159084908490610100900460ff16612457565b602160016101000a81548160ff021916908360ff1602179055505050565b6005546001600160a01b03163314611ca55760405162461bcd60e51b815260040161046b90614084565b602154611cc29060209084908490600160601b900460ff16612457565b6021600c6101000a81548160ff021916908360ff1602179055505050565b6005546001600160a01b03163314611d0a5760405162461bcd60e51b815260040161046b90614084565b602154611d2790601c9084908490600160401b900460ff16612457565b602160086101000a81548160ff021916908360ff1602179055505050565b6005546001600160a01b03163314611d6f5760405162461bcd60e51b815260040161046b90614084565b602154611d8d9060189084908490640100000000900460ff16612457565b602160046101000a81548160ff021916908360ff1602179055505050565b600033610df3818585612305565b60138181548110610cb757600080fd5b6005546001600160a01b03163314611df35760405162461bcd60e51b815260040161046b90614084565b602255565b336000908152602c60205260409020548210611e485760405162461bcd60e51b815260206004820152600f60248201526e0d2dcc6dee4e4cac6e840d2dcc8caf608b1b604482015260640161046b565b611e533383836127b0565b5050565b604051633fc0fdcb60e01b81526001600160a01b038316600482015260248101829052606090610e3e903090633fc0fdcb906044016110f0565b6005546001600160a01b03163314611ebb5760405162461bcd60e51b815260040161046b90614084565b602154611ed890601d9084908490600160481b900460ff16612457565b602160096101000a81548160ff021916908360ff1602179055505050565b600080805b85811015611f2c5783611f0e8183614361565b611f1891906140d4565b611f2290836140d4565b9150600101611efb565b611f3682866143f1565b945060009150600090505b85811015611f825783611f548183614361565b611f5e91906140d4565b611f6890836140d4565b9150848210611f7a579150610e3e9050565b600101611f41565b50600095945050505050565b6001600160a01b0383166000908152602c6020526040812054606090808510611fe6576040805160008082526020820190925281611494565b6060815260200190600190039081611fc75790505092509250506115f4565b6000611ff285876140d4565b90508181111561200b57508061200881876140e7565b93505b8367ffffffffffffffff811115612024576120246140a8565b60405190808252806020026020018201604052801561205757816020015b60608152602001906001900390816120425790505b5092508560005b828210156120f0576001600160a01b0389166000908152602b60209081526040808320858452909152908190209051637c3b3b8760e01b81528154600482015260019091015460248201526120bd903090637c3b3b87906044016110f0565b85826120c881614405565b9350815181106120da576120da6140fa565b602002602001018190525081600101915061205e565b50505050935093915050565b6005546001600160a01b031633146121265760405162461bcd60e51b815260040161046b90614084565b602480546001600160a01b0319166001600160a01b039290921691909117905542602555565b60128181548110610cb757600080fd5b6005546001600160a01b031633146121865760405162461bcd60e51b815260040161046b90614084565b60215461219c906014908490849060ff16612457565b6021805460ff191660ff929092169190911790555050565b6005546001600160a01b031633146121de5760405162461bcd60e51b815260040161046b90614084565b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600b8181548110610cb757600080fd5b6005546001600160a01b0316331461223a5760405162461bcd60e51b815260040161046b90614084565b60215461225790601f9084908490600160581b900460ff16612457565b6021600b6101000a81548160ff021916908360ff1602179055505050565b6122828383836001612812565b505050565b6001600160a01b0383811660009081526001602090815260408083209386168352929052205460001981146122ff57818110156122f057604051637dc7a0d960e11b81526001600160a01b0384166004820152602481018290526044810183905260640161046b565b6122ff84848484036000612812565b50505050565b6001600160a01b038216158061232557506001600160a01b03821661dead145b15612335576122828383836128e7565b6024546001600160a01b03161580156123df57506001600160a01b038316158061236757506001600160a01b03831630145b806123a357507f000000000000000000000000ebfaefee647f359564062b2bf01a156aca296a0d6001600160a01b0316836001600160a01b0316145b806123df57507f000000000000000000000000ebfaefee647f359564062b2bf01a156aca296a0d6001600160a01b0316826001600160a01b0316145b156123ef57612282838383612b2b565b602454600160a01b900460ff161561240c57612282838383612b2b565b6024546001600160a01b039081169084160361242c576122828282612b8a565b6024546001600160a01b039081169083160361244c576122828382612c5d565b6122828383836128e7565b60008281036124675750806124af565b60005b838110156124aa576124a086868684818110612488576124886140fa565b905060200281019061249a919061441e565b85612d7a565b925060010161246a565b829150505b949350505050565b606060006124c5600a612e4a565b6124cf600a612e4a565b6040516020016124e092919061443e565b60408051601f1981840301815291905290506000816124ff600a612e4a565b612509600a612e4a565b6006876000015181548110612520576125206140fa565b9060005260206000200160405160200161253c939291906144d9565b6040516020818303038152906040526125616014600788602001518960400151612f4b565b6125776016600a8960a001518a60c00151612f4b565b61258d6015600d8a606001518b60800151612f4b565b6125a46017600b8b60e001518c6101000151612f4b565b6125bc6018600c8c61012001518d6101400151612f4b565b6125d4601960098d61016001518e6101800151612f4b565b6125ec601a60088e6101a001518f6101c00151612f4b565b604051602001612604999897969594939291906145e9565b6040516020818303038152906040529050600061262b601b60106001886101e00151612f4b565b612643601c600f886102000151896102200151612f4b565b61265b601d600e8961024001518a6102600151612f4b565b612673601e60118a61028001518b6102a00151612f4b565b61268b602060138b61030001518c6103200151612f4b565b6126a3601f60128c6102c001518d6102e00151613047565b6040516020016126b8969594939291906146aa565b604051602081830303815290604052905081816040516020016126dc929190614729565b6040516020818303038152906040529350505050919050565b8051805160209182015191830180516000939161271182614405565b9052604080516020810194909452830191909152606082015260800160408051601f19818403018152919052805160209091012092915050565b600061275783836143f1565b610e3e9060016140d4565b600060225482101561277c5781602254610df991906140e7565b506001919050565b82546000906124af908484611ef6565b8051602001516000906127a6836126f5565b610df991906143f1565b6001600160a01b0383166000908152602b6020908152604080832085845282529182902082518084019093528054835260010154908201526127fe84836127f96009600a614352565b613099565b61280884846130fd565b6122ff8282613207565b6001600160a01b03841661283c5760405163e602df0560e01b81526000600482015260240161046b565b6001600160a01b03831661286657604051634a1406b160e11b81526000600482015260240161046b565b6001600160a01b03808516600090815260016020908152604080832093871683529290522082905580156122ff57826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516128d991815260200190565b60405180910390a350505050565b6128ef6132cc565b6001600160a01b0383166000908152602081905260408120549061291383836140e7565b90506000612936856001600160a01b031660009081526020819052604090205490565b9050600061294485836140d4565b90506001600160a01b038616158061296657506001600160a01b03861661dead145b15612972575060009050805b60006129806009600a614352565b61298a908561438e565b6129966009600a614352565b6129a0908761438e565b6129aa91906140e7565b905060006129ba6009600a614352565b6129c4908561438e565b6129d06009600a614352565b6129da908561438e565b6129e491906140e7565b905081818111156129f25750805b6001600160a01b038a166000908152602c60205260408120545b82821015612a84578015612a84576000612a2582614769565b6001600160a01b038e166000908152602b602090815260408083208484528252918290208251808401909352805483526001015490820152909250829150612a6d8e836130fd565b612a778d82613207565b5050816001019150612a0c565b82915b85831015612ab5576000612a9a83614769565b9250829050612aa98e826130fd565b50826001019250612a87565b8092505b84831015612b0c5760006040518060400160405280602e60008154612add90614405565b91829055508152602001612af26103e86132f6565b90529050612b008d82613207565b50826001019250612ab9565b612b178d8d8d613099565b505050505050505050506122826001602655565b6001600160a01b038316612b5557604051634b637e8f60e11b81526000600482015260240161046b565b6001600160a01b038216612b7f5760405163ec442f0560e01b81526000600482015260240161046b565b612282838383613345565b612b926132cc565b6001600160a01b03821660009081526020819052604081205490612bb683836140d4565b90506000612bc66009600a614352565b612bd0908461438e565b612bdc6009600a614352565b612be6908461438e565b612bf091906140e7565b905060005b81811015612c455760006040518060400160405280602e60008154612c1990614405565b91829055508152602001612c2e6103e86132f6565b90529050612c3c8782613207565b50600101612bf5565b612c4f868661346f565b50505050611e536001602655565b6024805460ff60a01b1916600160a01b179055612c786132cc565b6001600160a01b03821660009081526020819052604081205490612c9c83836140e7565b90506000612cac6009600a614352565b612cb6908361438e565b612cc26009600a614352565b612ccc908561438e565b612cd691906140e7565b6001600160a01b0386166000908152602c6020526040812054919250905b82821015612d42576103e8602a541015612d1c57602a60008154612d1790614405565b909155505b8015612d3757612d3787612d2f83614769565b9250826130fd565b816001019150612cf4565b602454612d5a9088906001600160a01b031688612305565b5050505050612d696001602655565b50506024805460ff60a01b19169055565b81356000908152602084905260408120805415612dbf57846000612da0600187356140e7565b81526020019081526020016000206000612dba9190613ab1565b612dcb565b612dc883614780565b92505b60005b612ddb602086018661479f565b9050811015612e405781612df2602087018761479f565b83818110612e0257612e026140fa565b9050602002810190612e14919061441e565b815460018101835560009283526020909220909160020201612e368282614941565b5050600101612dce565b5091949350505050565b606081600003612e715750506040805180820190915260018152600360fc1b602082015290565b8160005b8115612e9b5780612e8581614405565b9150612e949050600a8361438e565b9150612e75565b60008167ffffffffffffffff811115612eb657612eb66140a8565b6040519080825280601f01601f191660200182016040528015612ee0576020820181803683370190505b5090505b84156124af57612ef56001836140e7565b9150612f02600a866143f1565b612f0d9060306140d4565b60f81b818381518110612f2257612f226140fa565b60200101906001600160f81b031916908160001a905350612f44600a8661438e565b9450612ee4565b606082600003612f6a57506040805160208101909152600081526124af565b61303e848381548110612f7f57612f7f6140fa565b906000526020600020018054612f9490614050565b80601f0160208091040260200160405190810160405280929190818152602001828054612fc090614050565b801561300d5780601f10612fe25761010080835404028352916020019161300d565b820191906000526020600020905b815481529060010190602001808311612ff057829003601f168201915b505050505086600060018761302291906140e7565b81526020019081526020016000206134da90919063ffffffff16565b95945050505050565b60608260000361306657506040805160208101909152600081526124af565b82600103612f6a5761309285600061307f6001876140e7565b815260200190815260200160002061367e565b90506124af565b6024805460ff60a01b1916600160a01b1790556001600160a01b03821615806130cc57506001600160a01b03821661dead145b156130e0576130db8382613817565b6130eb565b6130eb838383612b2b565b50506024805460ff60a01b1916905550565b6024546001600160a01b0390811690831603613117575050565b6001600160a01b0382166000908152602c60205260408120805490919061313d90614769565b9182905550600003613152576131528261384d565b602d6000815461316190614769565b909155506001600160a01b0382166000908152602c60205260409020548181146131d5576001600160a01b0383166000908152602b60209081526040808320848452808352818420825180840184528154815260019182015481860190815288875292909452919093209151825591519101555b6001600160a01b039092166000908152602b602090815260408083209483529390529182208281556001019190915550565b6024546001600160a01b0390811690831603613221575050565b6001600160a01b0382166000908152602c60205260408120805490919061324790614405565b918290555060010361325c5761325c82613934565b602d6000815461326b90614405565b909155506001600160a01b0382166000908152602c6020526040812054613294906001906140e7565b6001600160a01b03939093166000908152602b6020908152604080832095835294815293902082518155919092015160019091015550565b6002602654036132ef57604051633ee5aeb560e01b815260040160405180910390fd5b6002602655565b60006103e8602a54836133099190614361565b613313919061438e565b91508160000361332257600191505b6001602a54111561334157602a6000815461333c90614769565b909155505b5090565b6001600160a01b03831661337057806002600082825461336591906140d4565b909155506133e29050565b6001600160a01b038316600090815260208190526040902054818110156133c35760405163391434e360e21b81526001600160a01b0385166004820152602481018290526044810183905260640161046b565b6001600160a01b03841660009081526020819052604090209082900390555b6001600160a01b0382166133fe5760028054829003905561341d565b6001600160a01b03821660009081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161346291815260200190565b60405180910390a3505050565b80613478611263565b8111156134b15760405162461bcd60e51b81526020600482015260076024820152666d61782062757960c81b604482015260640161046b565b6024805460ff60a01b198116600160a01b179091556130eb906001600160a01b03168484612b2b565b60608060005b8454811015613676578161364b85878481548110613500576135006140fa565b906000526020600020906002020160405180604001604052908160008201805461352990614050565b80601f016020809104026020016040519081016040528092919081815260200182805461355590614050565b80156135a25780601f10613577576101008083540402835291602001916135a2565b820191906000526020600020905b81548152906001019060200180831161358557829003601f168201915b505050505081526020016001820180546135bb90614050565b80601f01602080910402602001604051908101604052809291908181526020018280546135e790614050565b80156136345780601f1061360957610100808354040283529160200191613634565b820191906000526020600020905b81548152906001019060200180831161361757829003601f168201915b50505050508152505061398990919063ffffffff16565b60405160200161365c929190614a24565b60408051601f1981840301815291905291506001016134e0565b509392505050565b60608060005b835481101561381057816137e58583815481106136a3576136a36140fa565b90600052602060002090600202016040518060400160405290816000820180546136cc90614050565b80601f01602080910402602001604051908101604052809291908181526020018280546136f890614050565b80156137455780601f1061371a57610100808354040283529160200191613745565b820191906000526020600020905b81548152906001019060200180831161372857829003601f168201915b5050505050815260200160018201805461375e90614050565b80601f016020809104026020016040519081016040528092919081815260200182805461378a90614050565b80156137d75780601f106137ac576101008083540402835291602001916137d7565b820191906000526020600020905b8154815290600101906020018083116137ba57829003601f168201915b5050505050815250506139bb565b6040516020016137f6929190614a24565b60408051601f198184030181529190529150600101613684565b5092915050565b6001600160a01b03821661384157604051634b637e8f60e11b81526000600482015260240161046b565b611e5382600083613345565b60295460000361385a5750565b6001600160a01b038116600090815260286020526040902054602954613882906001906140e7565b81146138e757600060276000600160295461389d91906140e7565b815260208082019290925260409081016000908120548582526027845282822080546001600160a01b0319166001600160a01b039092169182179055815260289092529020829055505b6029600081546138f690614769565b90915550506001600160a01b0316600090815260286020908152604080832083905560295483526027909152902080546001600160a01b0319169055565b602980546000918261394583614405565b90915550600081815260276020908152604080832080546001600160a01b039097166001600160a01b03199097168717905594825260289052929092209190915550565b6060818360200151836040516020016139a493929190614a53565b604051602081830303815290604052905092915050565b6060816000015182602001516040516020016139d8929190614ad2565b6040516020818303038152906040529050919050565b60405180610340016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b5080546000825560020290600052602060002090810190613ad29190613ad5565b50565b80821115613341576000613ae98282613b00565b613af7600183016000613b00565b50600201613ad5565b508054613b0c90614050565b6000825580601f10613b1c575050565b601f016020900490600052602060002090810190613ad291905b808211156133415760008155600101613b36565b80356001600160a01b038116811461135b57600080fd5b600060208284031215613b7357600080fd5b610e3e82613b4a565b600060208284031215613b8e57600080fd5b5035919050565b60005b83811015613bb0578181015183820152602001613b98565b50506000910152565b60008151808452613bd1816020860160208601613b95565b601f01601f19169290920160200192915050565b602081526000610e3e6020830184613bb9565b60008060408385031215613c0b57600080fd5b613c1483613b4a565b946020939093013593505050565b600080600060608486031215613c3757600080fd5b613c4084613b4a565b9250613c4e60208501613b4a565b9150604084013590509250925092565b60008060208385031215613c7157600080fd5b823567ffffffffffffffff80821115613c8957600080fd5b818501915085601f830112613c9d57600080fd5b813581811115613cac57600080fd5b8660208260051b8501011115613cc157600080fd5b60209290920196919550909350505050565b60008060408385031215613ce657600080fd5b50508035926020909101359150565b60006040820184835260206040602085015281855180845260608601915060208701935060005b81811015613d415784516001600160a01b031683529383019391830191600101613d1c565b5090979650505050505050565b805182526020808201519083015260408082015190830152606080820151908301526080808201519083015260a0808201519083015260c0808201519083015260e08082015190830152610100808201519083015261012080820151908301526101408082015190830152610160808201519083015261018080820151908301526101a080820151908301526101c080820151908301526101e08082015190830152610200808201519083015261022080820151908301526102408082015190830152610260808201519083015261028080820151908301526102a080820151908301526102c080820151908301526102e08082015190830152610300808201519083015261032090810151910152565b6103408101610df98284613d4e565b600060408284031215613e8057600080fd5b50919050565b600080600060608486031215613e9b57600080fd5b613ea484613b4a565b95602085013595506040909401359392505050565b60006040820184835260206040602085015281855180845260608601915060208701935060005b81811015613d4157613ef3838651613d4e565b938301936103409290920191600101613ee0565b6000604080830185845260206040602086015281865180845260608701915060208801935060005b81811015613f5457845180518452840151848401529383019391850191600101613f2f565b509098975050505050505050565b60008060408385031215613f7557600080fd5b82359150613f8560208401613b4a565b90509250929050565b600080600060608486031215613fa357600080fd5b505081359360208301359350604090920135919050565b60006040820184835260206040602085015281855180845260608601915060608160051b87010193506020870160005b8281101561401857605f19888703018452614006868351613bb9565b95509284019290840190600101613fea565b509398975050505050505050565b6000806040838503121561403957600080fd5b61404283613b4a565b9150613f8560208401613b4a565b600181811c9082168061406457607f821691505b602082108103613e8057634e487b7160e01b600052602260045260246000fd5b6020808252600a908201526937b7363c9037bbb732b960b11b604082015260600190565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b80820180821115610df957610df96140be565b81810381811115610df957610df96140be565b634e487b7160e01b600052603260045260246000fd5b604051610340810167ffffffffffffffff81118282101715614134576141346140a8565b60405290565b6000610340828403121561414d57600080fd5b614155614110565b825181526020808401519082015260408084015190820152606080840151908201526080808401519082015260a0808401519082015260c0808401519082015260e08084015190820152610100808401519082015261012080840151908201526101408084015190820152610160808401519082015261018080840151908201526101a080840151908201526101c080840151908201526101e08084015190820152610200808401519082015261022080840151908201526102408084015190820152610260808401519082015261028080840151908201526102a080840151908201526102c080840151908201526102e080840151908201526103008084015190820152610320928301519281019290925250919050565b600181815b808511156142a957816000190482111561428f5761428f6140be565b8085161561429c57918102915b93841c9390800290614273565b509250929050565b6000826142c057506001610df9565b816142cd57506000610df9565b81600181146142e357600281146142ed57614309565b6001915050610df9565b60ff8411156142fe576142fe6140be565b50506001821b610df9565b5060208310610133831016604e8410600b841016171561432c575081810a610df9565b614336838361426e565b806000190482111561434a5761434a6140be565b029392505050565b6000610e3e60ff8416836142b1565b8082028115828204841417610df957610df96140be565b634e487b7160e01b600052601260045260246000fd5b60008261439d5761439d614378565b500490565b6000604082840312156143b457600080fd5b6040516040810181811067ffffffffffffffff821117156143d7576143d76140a8565b604052823581526020928301359281019290925250919050565b60008261440057614400614378565b500690565b600060018201614417576144176140be565b5060010190565b60008235603e1983360301811261443457600080fd5b9190910192915050565b7f3c73766720786d6c6e733d27687474703a2f2f7777772e77332e6f72672f3230815273030302f737667272076696577426f783d273020360641b60208201526000600160fd1b806034840152845161449e816035860160208901613b95565b8084019050816035820152845191506144be826036830160208801613b95565b61139f60f11b91016036810191909152603801949350505050565b703c7265637420783d27302720793d27302760781b8152672077696474683d2760c01b6011820152600084516020614518826019860160208a01613b95565b6927206865696768743d2760b01b6019928501928301528551614542816023850160208a01613b95565b80830192505067272066696c6c3d2760c01b6023830152602b6000865461456881614050565b60018281168015614580576001811461459b576145cd565b60ff198416602b890152602b831515840289010194506145cd565b8a600052602060002060005b848110156145c25781548a82018901529083019088016145a7565b5050602b8389010194505b50506213979f60e91b8352505060030198975050505050505050565b60008a516145fb818460208f01613b95565b8a5161460d8183860160208f01613b95565b8a519184010190614622818360208e01613b95565b89516146348183850160208e01613b95565b895192909101019061464a818360208c01613b95565b875161465c8183850160208c01613b95565b8751929091010190614672818360208a01613b95565b85516146848183850160208a01613b95565b855192909101019061469a818360208801613b95565b019b9a5050505050505050505050565b6000875160206146bd8285838d01613b95565b8851918401916146d08184848d01613b95565b88519201916146e28184848c01613b95565b87519201916146f48184848b01613b95565b86519201916147068184848a01613b95565b85519201916147188184848901613b95565b919091019998505050505050505050565b6000835161473b818460208801613b95565b83519083019061474f818360208801613b95565b651e17b9bb339f60d11b9101908152600601949350505050565b600081614778576147786140be565b506000190190565b600060ff821660ff8103614796576147966140be565b60010192915050565b6000808335601e198436030181126147b657600080fd5b83018035915067ffffffffffffffff8211156147d157600080fd5b6020019150600581901b360382131561102057600080fd5b6000808335601e1984360301811261480057600080fd5b83018035915067ffffffffffffffff82111561481b57600080fd5b60200191503681900382131561102057600080fd5b601f821115612282576000816000526020600020601f850160051c810160208610156148595750805b601f850160051c820191505b8181101561487857828155600101614865565b505050505050565b67ffffffffffffffff831115614898576148986140a8565b6148ac836148a68354614050565b83614830565b6000601f8411600181146148e057600085156148c85750838201355b600019600387901b1c1916600186901b17835561493a565b600083815260209020601f19861690835b8281101561491157868501358255602094850194600190920191016148f1565b508682101561492e5760001960f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b61494b82836147e9565b67ffffffffffffffff811115614963576149636140a8565b614977816149718554614050565b85614830565b6000601f8211600181146149ab57600083156149935750838201355b600019600385901b1c1916600184901b178555614a05565b600085815260209020601f19841690835b828110156149dc57868501358255602094850194600190920191016149bc565b50848210156149f95760001960f88660031b161c19848701351681555b505060018360011b0185555b50505050614a1660208301836147e9565b6122ff818360018601614880565b60008351614a36818460208801613b95565b835190830190614a4a818360208801613b95565b01949350505050565b6b3c706174682066696c6c3d2760a01b815260008451614a7a81600c850160208901613b95565b642720643d2760d81b600c918401918201528451614a9f816011840160208901613b95565b8451910190614ab5816011840160208801613b95565b6213979f60e91b6011929091019182015260140195945050505050565b6b3c706174682066696c6c3d2760a01b815260008351614af981600c850160208801613b95565b642720643d2760d81b600c918401918201528351614b1e816011840160208801613b95565b6213979f60e91b6011929091019182015260140194935050505056fea26469706673582212206cb8964b13f99ca4a0bed9ed23fd1195e1528ddce336b412da3426f4517ca45064736f6c63430008190033

Loading...
Loading
Loading...
Loading
[ 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.