ETH Price: $3,912.30 (+5.80%)

Token

Dogs Unchained (DOGU)
 

Overview

Max Total Supply

5,852 DOGU

Holders

2,120

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Filtered by Token Holder
tsella.eth
Balance
0 DOGU
0x7d5a90dc04f1b7525cc5145c7b8bc8d918f3433c
Loading...
Loading
Loading...
Loading
Loading...
Loading

OVERVIEW

9,999 Deflationary Dogs we’ve unleashed on the blockchain.

# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
DogsUnchained

Compiler Version
v0.6.4+commit.1dca32f3

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2021-10-02
*/

// SPDX-License-Identifier: MIT

// File: @openzeppelin/contracts/utils/Context.sol

pragma solidity >=0.6.0 <0.8.0;

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

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

// File: @openzeppelin/contracts/access/Ownable.sol

pragma solidity >=0.6.0 <0.8.0;

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

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

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor () internal {
        address msgSender = _msgSender();
        _owner = msgSender;
        emit OwnershipTransferred(address(0), msgSender);
    }

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

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

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

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }
}

// File: @openzeppelin/contracts/utils/ReentrancyGuard.sol

pragma solidity >=0.6.0 <0.8.0;

/**
 * @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;

    constructor () internal {
        _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 make it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

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

        _;

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

// File: @openzeppelin/contracts/introspection/IERC165.sol

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

// File: @openzeppelin/contracts/token/ERC721/IERC721.sol

pragma solidity >=0.6.2 <0.8.0;


/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 tokenId) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool _approved) external;

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);

    /**
      * @dev Safely transfers `tokenId` token from `from` to `to`.
      *
      * Requirements:
      *
      * - `from` cannot be the zero address.
      * - `to` cannot be the zero address.
      * - `tokenId` token must exist and be owned by `from`.
      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
      *
      * Emits a {Transfer} event.
      */
    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
}

// File: @openzeppelin/contracts/token/ERC721/IERC721Metadata.sol

pragma solidity >=0.6.2 <0.8.0;


/**
 * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Metadata is IERC721 {

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

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

    /**
     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
     */
    function tokenURI(uint256 tokenId) external view returns (string memory);
}

// File: @openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol

pragma solidity >=0.6.2 <0.8.0;


/**
 * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Enumerable is IERC721 {

    /**
     * @dev Returns the total amount of tokens stored by the contract.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.
     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);

    /**
     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
     * Use along with {totalSupply} to enumerate all tokens.
     */
    function tokenByIndex(uint256 index) external view returns (uint256);
}

// File: @openzeppelin/contracts/token/ERC721/IERC721Receiver.sol

pragma solidity >=0.6.0 <0.8.0;

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
interface IERC721Receiver {
    /**
     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
     * by `operator` from `from`, this function is called.
     *
     * It must return its Solidity selector to confirm the token transfer.
     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
     *
     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.
     */
    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);
}

// File: @openzeppelin/contracts/introspection/ERC165.sol

pragma solidity >=0.6.0 <0.8.0;


/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts may inherit from this and call {_registerInterface} to declare
 * their support of an interface.
 */
abstract contract ERC165 is IERC165 {
    /*
     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7
     */
    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;

    /**
     * @dev Mapping of interface ids to whether or not it's supported.
     */
    mapping(bytes4 => bool) private _supportedInterfaces;

    constructor () internal {
        // Derived contracts need only register support for their own interfaces,
        // we register support for ERC165 itself here
        _registerInterface(_INTERFACE_ID_ERC165);
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     *
     * Time complexity O(1), guaranteed to always use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return _supportedInterfaces[interfaceId];
    }

    /**
     * @dev Registers the contract as an implementer of the interface defined by
     * `interfaceId`. Support of the actual ERC165 interface is automatic and
     * registering its interface id is not required.
     *
     * See {IERC165-supportsInterface}.
     *
     * Requirements:
     *
     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).
     */
    function _registerInterface(bytes4 interfaceId) internal virtual {
        require(interfaceId != 0xffffffff, "ERC165: invalid interface id");
        _supportedInterfaces[interfaceId] = true;
    }
}

// File: @openzeppelin/contracts/math/SafeMath.sol

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        uint256 c = a + b;
        if (c < a) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b > a) return (false, 0);
        return (true, a - b);
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) return (true, 0);
        uint256 c = a * b;
        if (c / a != b) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a / b);
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a % b);
    }

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");
        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a, "SafeMath: subtraction overflow");
        return a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) return 0;
        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");
        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b > 0, "SafeMath: division by zero");
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b > 0, "SafeMath: modulo by zero");
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        return a - b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryDiv}.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        return a % b;
    }
}

// File: @openzeppelin/contracts/utils/Address.sol

pragma solidity >=0.6.2 <0.8.0;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly { size := extcodesize(account) }
        return size > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (bool success, ) = recipient.call{ value: amount }("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain`call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
      return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{ value: value }(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.staticcall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

// File: @openzeppelin/contracts/utils/EnumerableSet.sol

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
 * and `uint256` (`UintSet`) are supported.
 */
library EnumerableSet {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

    struct Set {
        // Storage of set values
        bytes32[] _values;

        // Position of the value in the `values` array, plus 1 because index 0
        // means a value is not in the set.
        mapping (bytes32 => uint256) _indexes;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function _add(Set storage set, bytes32 value) private returns (bool) {
        if (!_contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._indexes[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function _remove(Set storage set, bytes32 value) private returns (bool) {
        // We read and store the value's index to prevent multiple reads from the same storage slot
        uint256 valueIndex = set._indexes[value];

        if (valueIndex != 0) { // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 toDeleteIndex = valueIndex - 1;
            uint256 lastIndex = set._values.length - 1;

            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs
            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.

            bytes32 lastvalue = set._values[lastIndex];

            // Move the last value to the index where the value to delete is
            set._values[toDeleteIndex] = lastvalue;
            // Update the index for the moved value
            set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the index for the deleted slot
            delete set._indexes[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function _contains(Set storage set, bytes32 value) private view returns (bool) {
        return set._indexes[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function _length(Set storage set) private view returns (uint256) {
        return set._values.length;
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function _at(Set storage set, uint256 index) private view returns (bytes32) {
        require(set._values.length > index, "EnumerableSet: index out of bounds");
        return set._values[index];
    }

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _add(set._inner, value);
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _remove(set._inner, value);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
        return _contains(set._inner, value);
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(Bytes32Set storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
        return _at(set._inner, index);
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(AddressSet storage set, address value) internal returns (bool) {
        return _add(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(AddressSet storage set, address value) internal returns (bool) {
        return _remove(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(AddressSet storage set, address value) internal view returns (bool) {
        return _contains(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(AddressSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function at(AddressSet storage set, uint256 index) internal view returns (address) {
        return address(uint160(uint256(_at(set._inner, index))));
    }


    // UintSet

    struct UintSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(UintSet storage set, uint256 value) internal returns (bool) {
        return _add(set._inner, bytes32(value));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(UintSet storage set, uint256 value) internal returns (bool) {
        return _remove(set._inner, bytes32(value));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(UintSet storage set, uint256 value) internal view returns (bool) {
        return _contains(set._inner, bytes32(value));
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function length(UintSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function at(UintSet storage set, uint256 index) internal view returns (uint256) {
        return uint256(_at(set._inner, index));
    }
}

// File: @openzeppelin/contracts/utils/EnumerableMap.sol

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Library for managing an enumerable variant of Solidity's
 * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]
 * type.
 *
 * Maps have the following properties:
 *
 * - Entries are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Entries are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```
 * contract Example {
 *     // Add the library methods
 *     using EnumerableMap for EnumerableMap.UintToAddressMap;
 *
 *     // Declare a set state variable
 *     EnumerableMap.UintToAddressMap private myMap;
 * }
 * ```
 *
 * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are
 * supported.
 */
library EnumerableMap {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Map type with
    // bytes32 keys and values.
    // The Map implementation uses private functions, and user-facing
    // implementations (such as Uint256ToAddressMap) are just wrappers around
    // the underlying Map.
    // This means that we can only create new EnumerableMaps for types that fit
    // in bytes32.

    struct MapEntry {
        bytes32 _key;
        bytes32 _value;
    }

    struct Map {
        // Storage of map keys and values
        MapEntry[] _entries;

        // Position of the entry defined by a key in the `entries` array, plus 1
        // because index 0 means a key is not in the map.
        mapping (bytes32 => uint256) _indexes;
    }

    /**
     * @dev Adds a key-value pair to a map, or updates the value for an existing
     * key. O(1).
     *
     * Returns true if the key was added to the map, that is if it was not
     * already present.
     */
    function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {
        // We read and store the key's index to prevent multiple reads from the same storage slot
        uint256 keyIndex = map._indexes[key];

        if (keyIndex == 0) { // Equivalent to !contains(map, key)
            map._entries.push(MapEntry({ _key: key, _value: value }));
            // The entry is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            map._indexes[key] = map._entries.length;
            return true;
        } else {
            map._entries[keyIndex - 1]._value = value;
            return false;
        }
    }

    /**
     * @dev Removes a key-value pair from a map. O(1).
     *
     * Returns true if the key was removed from the map, that is if it was present.
     */
    function _remove(Map storage map, bytes32 key) private returns (bool) {
        // We read and store the key's index to prevent multiple reads from the same storage slot
        uint256 keyIndex = map._indexes[key];

        if (keyIndex != 0) { // Equivalent to contains(map, key)
            // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one
            // in the array, and then remove the last entry (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 toDeleteIndex = keyIndex - 1;
            uint256 lastIndex = map._entries.length - 1;

            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs
            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.

            MapEntry storage lastEntry = map._entries[lastIndex];

            // Move the last entry to the index where the entry to delete is
            map._entries[toDeleteIndex] = lastEntry;
            // Update the index for the moved entry
            map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based

            // Delete the slot where the moved entry was stored
            map._entries.pop();

            // Delete the index for the deleted slot
            delete map._indexes[key];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the key is in the map. O(1).
     */
    function _contains(Map storage map, bytes32 key) private view returns (bool) {
        return map._indexes[key] != 0;
    }

    /**
     * @dev Returns the number of key-value pairs in the map. O(1).
     */
    function _length(Map storage map) private view returns (uint256) {
        return map._entries.length;
    }

   /**
    * @dev Returns the key-value pair stored at position `index` in the map. O(1).
    *
    * Note that there are no guarantees on the ordering of entries inside the
    * array, and it may change when more entries are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {
        require(map._entries.length > index, "EnumerableMap: index out of bounds");

        MapEntry storage entry = map._entries[index];
        return (entry._key, entry._value);
    }

    /**
     * @dev Tries to returns the value associated with `key`.  O(1).
     * Does not revert if `key` is not in the map.
     */
    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {
        uint256 keyIndex = map._indexes[key];
        if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)
        return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based
    }

    /**
     * @dev Returns the value associated with `key`.  O(1).
     *
     * Requirements:
     *
     * - `key` must be in the map.
     */
    function _get(Map storage map, bytes32 key) private view returns (bytes32) {
        uint256 keyIndex = map._indexes[key];
        require(keyIndex != 0, "EnumerableMap: nonexistent key"); // Equivalent to contains(map, key)
        return map._entries[keyIndex - 1]._value; // All indexes are 1-based
    }

    /**
     * @dev Same as {_get}, with a custom error message when `key` is not in the map.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {_tryGet}.
     */
    function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {
        uint256 keyIndex = map._indexes[key];
        require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)
        return map._entries[keyIndex - 1]._value; // All indexes are 1-based
    }

    // UintToAddressMap

    struct UintToAddressMap {
        Map _inner;
    }

    /**
     * @dev Adds a key-value pair to a map, or updates the value for an existing
     * key. O(1).
     *
     * Returns true if the key was added to the map, that is if it was not
     * already present.
     */
    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {
        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the key was removed from the map, that is if it was present.
     */
    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {
        return _remove(map._inner, bytes32(key));
    }

    /**
     * @dev Returns true if the key is in the map. O(1).
     */
    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {
        return _contains(map._inner, bytes32(key));
    }

    /**
     * @dev Returns the number of elements in the map. O(1).
     */
    function length(UintToAddressMap storage map) internal view returns (uint256) {
        return _length(map._inner);
    }

   /**
    * @dev Returns the element stored at position `index` in the set. O(1).
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function at(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {
        (bytes32 key, bytes32 value) = _at(map._inner, index);
        return (uint256(key), address(uint160(uint256(value))));
    }

    /**
     * @dev Tries to returns the value associated with `key`.  O(1).
     * Does not revert if `key` is not in the map.
     *
     * _Available since v3.4._
     */
    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {
        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));
        return (success, address(uint160(uint256(value))));
    }

    /**
     * @dev Returns the value associated with `key`.  O(1).
     *
     * Requirements:
     *
     * - `key` must be in the map.
     */
    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {
        return address(uint160(uint256(_get(map._inner, bytes32(key)))));
    }

    /**
     * @dev Same as {get}, with a custom error message when `key` is not in the map.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryGet}.
     */
    function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {
        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));
    }
}

// File: @openzeppelin/contracts/utils/Strings.sol

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev String operations.
 */
library Strings {
    /**
     * @dev Converts a `uint256` to its ASCII `string` representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        uint256 index = digits - 1;
        temp = value;
        while (temp != 0) {
            buffer[index--] = bytes1(uint8(48 + temp % 10));
            temp /= 10;
        }
        return string(buffer);
    }
}

// File: @openzeppelin/contracts/token/ERC721/ERC721.sol

pragma solidity >=0.6.0 <0.8.0;

/**
 * @title ERC721 Non-Fungible Token Standard basic implementation
 * @dev see https://eips.ethereum.org/EIPS/eip-721
 */
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {
    using SafeMath for uint256;
    using Address for address;
    using EnumerableSet for EnumerableSet.UintSet;
    using EnumerableMap for EnumerableMap.UintToAddressMap;
    using Strings for uint256;

    // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`
    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;

    // Mapping from holder address to their (enumerable) set of owned tokens
    mapping (address => EnumerableSet.UintSet) private _holderTokens;

    // Enumerable mapping from token ids to their owners
    EnumerableMap.UintToAddressMap private _tokenOwners;

    // Mapping from token ID to approved address
    mapping (uint256 => address) private _tokenApprovals;

    // Mapping from owner to operator approvals
    mapping (address => mapping (address => bool)) private _operatorApprovals;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // Optional mapping for token URIs
    mapping (uint256 => string) private _tokenURIs;

    // Base URI
    string private _baseURI;

    /*
     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231
     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e
     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3
     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc
     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465
     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5
     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd
     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e
     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde
     *
     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^
     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd
     */
    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;

    /*
     *     bytes4(keccak256('name()')) == 0x06fdde03
     *     bytes4(keccak256('symbol()')) == 0x95d89b41
     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd
     *
     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f
     */
    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;

    /*
     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd
     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59
     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7
     *
     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63
     */
    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;

    /**
     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
     */
    constructor (string memory name_, string memory symbol_) public {
        _name = name_;
        _symbol = symbol_;

        // register the supported interfaces to conform to ERC721 via ERC165
        _registerInterface(_INTERFACE_ID_ERC721);
        _registerInterface(_INTERFACE_ID_ERC721_METADATA);
        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);
    }

    /**
     * @dev See {IERC721-balanceOf}.
     */
    function balanceOf(address owner) public view virtual override returns (uint256) {
        require(owner != address(0), "ERC721: balance query for the zero address");
        return _holderTokens[owner].length();
    }

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId) public view virtual override returns (address) {
        return _tokenOwners.get(tokenId, "ERC721: owner query for nonexistent token");
    }

    /**
     * @dev See {IERC721Metadata-name}.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev See {IERC721Metadata-symbol}.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");

        string memory _tokenURI = _tokenURIs[tokenId];
        string memory base = baseURI();

        // If there is no base URI, return the token URI.
        if (bytes(base).length == 0) {
            return _tokenURI;
        }
        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).
        if (bytes(_tokenURI).length > 0) {
            return string(abi.encodePacked(base, _tokenURI));
        }
        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.
        return string(abi.encodePacked(base, tokenId.toString()));
    }

    /**
    * @dev Returns the base URI set via {_setBaseURI}. This will be
    * automatically added as a prefix in {tokenURI} to each token's URI, or
    * to the token ID if no specific URI is set for that token ID.
    */
    function baseURI() public view virtual returns (string memory) {
        return _baseURI;
    }

    /**
     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {
        return _holderTokens[owner].at(index);
    }

    /**
     * @dev See {IERC721Enumerable-totalSupply}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds
        return _tokenOwners.length();
    }

    /**
     * @dev See {IERC721Enumerable-tokenByIndex}.
     */
    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {
        (uint256 tokenId, ) = _tokenOwners.at(index);
        return tokenId;
    }

    /**
     * @dev See {IERC721-approve}.
     */
    function approve(address to, uint256 tokenId) public virtual override {
        address owner = ERC721.ownerOf(tokenId);
        require(to != owner, "ERC721: approval to current owner");

        require(_msgSender() == owner || ERC721.isApprovedForAll(owner, _msgSender()),
            "ERC721: approve caller is not owner nor approved for all"
        );

        _approve(to, tokenId);
    }

    /**
     * @dev See {IERC721-getApproved}.
     */
    function getApproved(uint256 tokenId) public view virtual override returns (address) {
        require(_exists(tokenId), "ERC721: approved query for nonexistent token");

        return _tokenApprovals[tokenId];
    }

    /**
     * @dev See {IERC721-setApprovalForAll}.
     */
    function setApprovalForAll(address operator, bool approved) public virtual override {
        require(operator != _msgSender(), "ERC721: approve to caller");

        _operatorApprovals[_msgSender()][operator] = approved;
        emit ApprovalForAll(_msgSender(), operator, approved);
    }

    /**
     * @dev See {IERC721-isApprovedForAll}.
     */
    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
        return _operatorApprovals[owner][operator];
    }

    /**
     * @dev See {IERC721-transferFrom}.
     */
    function transferFrom(address from, address to, uint256 tokenId) public virtual override {
        //solhint-disable-next-line max-line-length
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");

        _transfer(from, to, tokenId);
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {
        safeTransferFrom(from, to, tokenId, "");
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
        _safeTransfer(from, to, tokenId, _data);
    }

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * `_data` is additional data, it has no specified format and it is sent in call to `to`.
     *
     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
     * implement alternative mechanisms to perform token transfer, such as signature-based.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {
        _transfer(from, to, tokenId);
        require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
    }

    /**
     * @dev Returns whether `tokenId` exists.
     *
     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
     *
     * Tokens start existing when they are minted (`_mint`),
     * and stop existing when they are burned (`_burn`).
     */
    function _exists(uint256 tokenId) internal view virtual returns (bool) {
        return _tokenOwners.contains(tokenId);
    }

    /**
     * @dev Returns whether `spender` is allowed to manage `tokenId`.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
        require(_exists(tokenId), "ERC721: operator query for nonexistent token");
        address owner = ERC721.ownerOf(tokenId);
        return (spender == owner || getApproved(tokenId) == spender || ERC721.isApprovedForAll(owner, spender));
    }

    /**
     * @dev Safely mints `tokenId` and transfers it to `to`.
     *
     * Requirements:
     d*
     * - `tokenId` must not exist.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeMint(address to, uint256 tokenId) internal virtual {
        _safeMint(to, tokenId, "");
    }

    /**
     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
     */
    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {
        _mint(to, tokenId);
        require(_checkOnERC721Received(address(0), to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
    }

    /**
     * @dev Mints `tokenId` and transfers it to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - `to` cannot be the zero address.
     *
     * Emits a {Transfer} event.
     */
    function _mint(address to, uint256 tokenId) internal virtual {
        require(to != address(0), "ERC721: mint to the zero address");
        require(!_exists(tokenId), "ERC721: token already minted");

        _beforeTokenTransfer(address(0), to, tokenId);

        _holderTokens[to].add(tokenId);

        _tokenOwners.set(tokenId, to);

        emit Transfer(address(0), to, tokenId);
    }

    /**
     * @dev Destroys `tokenId`.
     * The approval is cleared when the token is burned.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     *
     * Emits a {Transfer} event.
     */
    function _burn(uint256 tokenId) internal virtual {
        address owner = ERC721.ownerOf(tokenId); // internal owner

        _beforeTokenTransfer(owner, address(0), tokenId);

        // Clear approvals
        _approve(address(0), tokenId);

        // Clear metadata (if any)
        if (bytes(_tokenURIs[tokenId]).length != 0) {
            delete _tokenURIs[tokenId];
        }

        _holderTokens[owner].remove(tokenId);

        _tokenOwners.remove(tokenId);

        emit Transfer(owner, address(0), tokenId);
    }

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     *
     * Emits a {Transfer} event.
     */
    function _transfer(address from, address to, uint256 tokenId) internal virtual {
        require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer of token that is not own"); // internal owner
        require(to != address(0), "ERC721: transfer to the zero address");

        _beforeTokenTransfer(from, to, tokenId);

        // Clear approvals from the previous owner
        _approve(address(0), tokenId);

        _holderTokens[from].remove(tokenId);
        _holderTokens[to].add(tokenId);

        _tokenOwners.set(tokenId, to);

        emit Transfer(from, to, tokenId);
    }

    /**
     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {
        require(_exists(tokenId), "ERC721Metadata: URI set of nonexistent token");
        _tokenURIs[tokenId] = _tokenURI;
    }

    /**
     * @dev Internal function to set the base URI for all token IDs. It is
     * automatically added as a prefix to the value returned in {tokenURI},
     * or to the token ID if {tokenURI} is empty.
     */
    function _setBaseURI(string memory baseURI_) internal virtual {
        _baseURI = baseURI_;
    }

    /**
     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
     * The call is not executed if the target address is not a contract.
     *
     * @param from address representing the previous owner of the given token ID
     * @param to target address that will receive the tokens
     * @param tokenId uint256 ID of the token to be transferred
     * @param _data bytes optional data to send along with the call
     * @return bool whether the call correctly returned the expected magic value
     */
    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)
        private returns (bool)
    {
        if (!to.isContract()) {
            return true;
        }
        bytes memory returndata = to.functionCall(abi.encodeWithSelector(
            IERC721Receiver(to).onERC721Received.selector,
            _msgSender(),
            from,
            tokenId,
            _data
        ), "ERC721: transfer to non ERC721Receiver implementer");
        bytes4 retval = abi.decode(returndata, (bytes4));
        return (retval == _ERC721_RECEIVED);
    }

    /**
     * @dev Approve `to` to operate on `tokenId`
     *
     * Emits an {Approval} event.
     */
    function _approve(address to, uint256 tokenId) internal virtual {
        _tokenApprovals[tokenId] = to;
        emit Approval(ERC721.ownerOf(tokenId), to, tokenId); // internal owner
    }

    /**
     * @dev Hook that is called before any token transfer. This includes minting
     * and burning.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
     * transferred to `to`.
     * - When `from` is zero, `tokenId` will be minted for `to`.
     * - When `to` is zero, ``from``'s `tokenId` will be burned.
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }
}

// File: contracts/interface/IProofOfSteak.sol

pragma solidity >=0.6.2 <0.8.0;

interface IProofOfSteak {
    function redeem(address sender, uint256 tokenId, uint256 quantity) external;
}

// File: contracts/Random.sol

pragma solidity >=0.6.0 <0.8.0;

contract Random is Ownable {
    using SafeMath for uint256;

    address public controller;

    constructor() public {
        controller = _msgSender();
    }

    function generate(address sender, uint256 nonce1, uint256 nonce2) external view returns (bytes32) {
      // HIDDEN
    }
    
    function setController(address _controller) external onlyOwner {
      controller = _controller;
    }
}

// File: contracts/DogsUnchained.sol

pragma solidity >= 0.6.0 <0.8.0;






contract DogsUnchained is 
    Ownable, 
    ReentrancyGuard, 
    ERC721
{
    using SafeMath for uint256;

    bool public generalLock = true;
    bool public steakholderLock = true;

    struct Dog {
        uint16 id;
        uint8 breed;
        uint8 background;
        uint8 skin;
        uint8 shirt;
        uint8 neck;
        uint8 mouth;
        uint8 eyes;
        uint8 head;
        uint8 level;
    }
    
    uint256 private teamMint;
    uint256 public constant MAX_TEAM_DOGS = 100; 

    uint256 public charitableMints;
    uint256 public charitableWithdrawals;

    uint256 public STEAKS_RESERVED;
    uint256 public steaksRedeemed;
    uint16[] private steakIndices;
    
    uint256 public MAX_RESERVATIONS;
    uint256 public totalReservations;
    mapping(address => uint256) public reservations;
    uint256 public reservationsRedeemed;
    uint16[] private reservationIndices;

    uint256 public MAX_DOGS;
    
    mapping(uint256 => Dog) private dogs;
    mapping(uint256 => uint256) public traitMaps;

    IProofOfSteak public proofOfSteak;

    // addresses to withdraw funds
    address payable public teamAddress;
    address payable public charityAddress;

    string public prefix;
    string public suffix;

    Random private generator;

    event TokenUpdated(
        uint256 tokenId,
        uint256 traitMap,
        uint256 parent1,
        uint256 parent2
    );

    event TraitsBurned(
        uint256 tokenId,
        uint256 traitMap
    );
    
    constructor(
        uint256 _MAX_DOGS,
        string memory _prefix,
        string memory _suffix,
        address _proofOfSteakAddress,
        address _generatorAddress
    ) ERC721("Dogs Unchained", "DOGU") public {
        MAX_DOGS = _MAX_DOGS;
        prefix = _prefix;
        suffix = _suffix;
        proofOfSteak = IProofOfSteak(_proofOfSteakAddress);
        teamAddress = _msgSender();
        charityAddress = _msgSender();
        generator = Random(_generatorAddress);
    }

    /*************************/
    /******* MODIFIERS *******/
    /*************************/

    modifier onlySteakholderUnlocked() {
        require(!steakholderLock, "Function is locked");
        _;
    }

    modifier onlyGeneralUnlocked() {
        require(!generalLock, "Function is locked");
        _;
    }

    /****************************/
    /******* INTERACTIONS *******/
    /****************************/

    /**
     * @notice redeems Proof of Steak balances for Dogs
     * @param steakId the ID of the Proof of Steak to redeem against
     * @param quantity the number of Dogs to mint
     * @param charitable whether or not the sender is including a charitable donation
     */
    function redeemSteak(uint256 steakId, uint256 quantity, bool charitable) external payable nonReentrant onlySteakholderUnlocked {
        require(quantity > 0, "Cannot mint 0 Dogs");
        require(quantity <= 10, "Cannot redeem more than 10 Dogs at once");
        require(msg.value == charitableCost(quantity, charitable), "Incorrect charitable amount");
        proofOfSteak.redeem(_msgSender(), steakId, quantity);

        uint256 randomId;
        for (uint i = 0; i < quantity; i++) {
            randomId = randomSteakID();
            createDog(randomId, charitable);
            steaksRedeemed = steaksRedeemed.add(1);
        }

        if (charitable) {
            charitableMints = charitableMints.add(quantity);
        }
    }

    /**
     * @notice redeems reservations for Dogs
     * @param quantity the number of Dogs to mint
     * @param charitable whether or not the sender is including a charitable donation
     */
    function redeemReservation(uint256 quantity, bool charitable) external payable nonReentrant onlyGeneralUnlocked {
        require(quantity > 0, "Cannot mint 0 Dogs");
        require(quantity <= reservations[_msgSender()], "Cannot redeem more than reservation");
        require(quantity <= 10, "Cannot mint more than 10 dogs at once");
        require(
            reservationsRedeemed
            .add(STEAKS_RESERVED)
            .add(MAX_TEAM_DOGS)
            .add(quantity)
            <= MAX_DOGS,
            "Creating more dogs than limit"
        );
        require(msg.value == mintCost(quantity).add(charitableCost(quantity, charitable)), "Incorrect payment amount");
        reservations[_msgSender()] = reservations[_msgSender()].sub(quantity);
        
        uint256 randomId;
        for (uint i = 0; i < quantity; i++) {
            randomId = randomReservationID();
            createDog(randomId, charitable);
            reservationsRedeemed = reservationsRedeemed.add(1);
        }

        if (charitable) {
            charitableMints = charitableMints.add(quantity);
        }
    }

    /**
     * @notice combines two Dogs with specified traits
     * @param dogId1 ID of first Dog to combine
     * @param dogId2 ID of second Dog to combine
     * @param traitMap mapping of traits to use
     */
    function combineDogs(uint256 dogId1, uint256 dogId2, uint256 traitMap) external nonReentrant onlySteakholderUnlocked {
        require(ownerOf(dogId1) == _msgSender(), "Must own these Dogs");
        require(ownerOf(dogId2) == _msgSender(), "Must own these Dogs");

        Dog storage dog1 = dogs[dogId1];
        uint256 dog1map = structToBitmap(dog1);
        Dog storage dog2 = dogs[dogId2];
        uint256 dog2map = structToBitmap(dog2);

        uint16 id = uint16(traitMap & 0xFFFF); // ID
        require(dog1.id == id || dog2.id == id, "Invalid ID");

        Dog memory newDog = dogs[id];
        Dog memory unusedTraits;

        newDog.breed = unpackUint8(traitMap, 16);// breed
        require(dog1.breed == newDog.breed || dog2.breed == newDog.breed, "Invalid breed");
        unusedTraits.breed = dog1.breed == newDog.breed ? dog2.breed : dog1.breed;

        newDog.background = unpackUint8(traitMap, 24);// background
        require(dog1.background == newDog.background || dog2.background == newDog.background, "Invalid background");
        unusedTraits.background = dog1.background == newDog.background ? dog2.background : dog1.background;

        newDog.skin = unpackUint8(traitMap, 32); // skin
        require(dog1.skin == newDog.skin || dog2.skin == newDog.skin, "Invalid skin");
        unusedTraits.skin = dog1.skin == newDog.skin ? dog2.skin : dog1.skin;

        newDog.shirt = unpackUint8(traitMap, 40); // shirt
        require(dog1.shirt == newDog.shirt || dog2.shirt == newDog.shirt, "Invalid shirt");
        unusedTraits.shirt = dog1.shirt == newDog.shirt ? dog2.shirt : dog1.shirt;

        newDog.neck = unpackUint8(traitMap, 48); // neck
        require(dog1.neck == newDog.neck || dog2.neck == newDog.neck, "Invalid neck");
        unusedTraits.neck = dog1.neck == newDog.neck ? dog2.neck : dog1.neck;

        newDog.mouth = unpackUint8(traitMap, 56); // mouth
        require(dog1.mouth == newDog.mouth || dog2.mouth == newDog.mouth, "Invalid mouth");
        unusedTraits.mouth = dog1.mouth == newDog.mouth ? dog2.mouth : dog1.mouth;

        newDog.eyes = unpackUint8(traitMap, 64); // eyes
        require(dog1.eyes == newDog.eyes || dog2.eyes == newDog.eyes, "Invalid eyes");
        unusedTraits.eyes = dog1.eyes == newDog.eyes ? dog2.eyes : dog1.eyes;

        newDog.head = unpackUint8(traitMap, 72); // head
        require(dog1.head == newDog.head || dog2.head == newDog.head, "Invalid head");
        unusedTraits.head = dog1.head == newDog.head ? dog2.head : dog1.head;

        uint256 bitmap = structToBitmap(newDog);
        require(traitMaps[bitmap] == 0, "This trait combination already exists");
        traitMaps[bitmap] = newDog.id;

        newDog.level = dog1.level > dog2.level ? dog1.level + 1 : dog2.level + 1;

        emit TokenUpdated(
            newDog.id, 
            bitmap, 
            dog1map + dog1.id + (uint256(dog1.level) << 80), 
            dog2map + dog2.id + (uint256(dog2.level) << 80)
        );
        emit TraitsBurned(newDog.id == dog1.id ? dog2.id : dog1.id, structToBitmap(unusedTraits));

        dogs[id] = newDog;

        if (newDog.id == dog1.id) {
            _burn(dog2.id);
        } else {
            _burn(dog1.id);
        }
        delete traitMaps[dog1map];
        delete traitMaps[dog2map];
    }

    /***********************/
    /******* Getters *******/
    /***********************/

    /**
     * @notice cost to mint Dogs
     * @param quantity number of Dogs to mint
     * @return cost to mint
     */
    function mintCost(uint256 quantity) public pure returns (uint256) {
        return quantity.mul(0.08 ether);               // CHANGE FOR DEPLOYMENT
    }

    function charitableCost(uint256 quantity, bool charitable) public pure returns (uint256) {
        return charitable ? quantity.mul(0.01 ether) : 0;                    // CHANGE FOR DEPLOYMENT
    }

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");

        // https://cloudflare-ipfs.com/ipns/ {TOKEN ID} .dogsunchainednft.com
        return string(abi.encodePacked(prefix, tokenId.toString(), suffix));
    }

    /*********************/
    /******* ADMIN *******/
    /*********************/

    /**
     * @notice function to set the number of Dogs reserved in Proof of Steak
     * @param quantity number of Dogs reserved
     */
    function setSteaksReserved(uint256 quantity) public onlyOwner {
        STEAKS_RESERVED = quantity;
        steakIndices = new uint16[](STEAKS_RESERVED);
        MAX_RESERVATIONS = MAX_DOGS - STEAKS_RESERVED - MAX_TEAM_DOGS;
        reservationIndices = new uint16[](MAX_RESERVATIONS);
    }

    /**
     * @notice gives the team up to MAX_TEAM_DOGS tokens
     */
    function devMint() public onlyOwner {
        require(teamMint.add(10) <= MAX_TEAM_DOGS, "Cannot dev mint more");
        for (uint i = 0; i < 10; i++) {
            teamMint = teamMint.add(1);
            createDog(teamMint, true);
        }
    }

    /**
     * @notice withdraws funds that are owed to the project
     */
    function withdraw() public onlyOwner {
        uint256 dueToCharity = (charitableMints.sub(charitableWithdrawals)).mul(0.02 ether);
        payable(teamAddress).transfer(
            address(this).balance.sub(dueToCharity)
        );
    }

    /**
     * @notice withdraws funds that are owed to charity
     */
    function withdrawCharitable() public onlyOwner {
        payable(charityAddress).transfer(
            (charitableMints.sub(charitableWithdrawals)).mul(0.02 ether)
        );
        charitableWithdrawals = charitableMints;
    }

    /**
     * @notice sets the address to send withdrawable funds to
     * @param _teamAddress the new destination address
     */
    function setTeamAddress(address payable _teamAddress) public onlyOwner {
        teamAddress = _teamAddress;
    }

    /**
     * @notice sets the address to send withdrawable charitable funds to
     * @param _charityAddress the new destination address
     */
    function setCharityAddress(address payable _charityAddress) public onlyOwner {
        charityAddress = _charityAddress;
    }

    /**
     * @notice sets the contracts locked state for general functions
     * @param _locked the updated state
     */
    function setSteakholderLock(bool _locked) external onlyOwner {
        steakholderLock = _locked;
    }

    /**
     * @notice sets the contracts locked state for steakholder functions
     * @param _locked the updated state
     */
    function setGeneralLock(bool _locked) external onlyOwner {
         generalLock = _locked;
    }

    function setSuffixPrefix(string calldata _prefix, string calldata _suffix) external onlyOwner {
        prefix = _prefix;
        suffix = _suffix;
    }

    function addReservations(address[] calldata addresses, uint256[] calldata quantities) external onlyOwner {
        require(addresses.length == quantities.length, "Mismatched inputs");
        for (uint i = 0; i < addresses.length; i++) {
            reservations[addresses[i]] = quantities[i];
        }
    }

    /************************/
    /******* INTERNAL *******/
    /************************/

    /**
     * @dev creates a random dog token and transfers it to the sender
     * @param id ID of the dog to generate
     * @param charitable whether or not the owner made a donation
     */
    function createDog(uint256 id, bool charitable) internal {
        uint256 nonce;
        Dog memory dog = generateDog(id, charitable, nonce);
        while (traitMaps[structToBitmap(dog)] != 0) {
            nonce = nonce.add(1);
            dog = generateDog(id, charitable, nonce);
        }
        dogs[id] = dog;
        traitMaps[structToBitmap(dog)] = id;
        _safeMint(_msgSender(), id);
        emit TokenUpdated(id, structToBitmap(dog), 0, 0);
    }

    /**
     * @dev generates random traits for a Dog
     * @param id ID of the dog to generate
     * @param charitable whether or not the owner made a donation
     * @param nonce create entropy in case of duplicates
     */
    function generateDog(uint256 id, bool charitable, uint256 nonce) internal view returns (Dog memory) {
        // generate entropy using block values, sender, serial number, and nonce
        bytes32 hash = generator.generate(_msgSender(), id, nonce);
        
        Dog memory dog;
        dog.id = uint16(id);
        dog.level = 1;
        dog.breed = uint8(hash[31]) % 5;
        dog.background = randomTrait(
            concatBytes(hash[0], hash[1]), charitable, 1, 1, 3, 7, 0 // CHANGE FOR DEPLOYMENT
        );
        dog.skin = randomTrait(
            concatBytes(hash[2], hash[3]), charitable, 2, 3, 3, 3, 0 // CHANGE FOR DEPLOYMENT
        );
        dog.shirt = randomTrait(
            concatBytes(hash[4], hash[5]), charitable, 2, 6, 14, 11, 15 // CHANGE FOR DEPLOYMENT
        );
        dog.neck = randomTrait(
            concatBytes(hash[6], hash[7]), charitable, 1, 2, 7, 7, 70 // CHANGE FOR DEPLOYMENT
        );
        dog.mouth = randomTrait(
            concatBytes(hash[8], hash[9]), charitable, 2, 4, 14, 11, 0 // CHANGE FOR DEPLOYMENT
        );
        dog.eyes = randomTrait(
            concatBytes(hash[10], hash[11]), charitable, 2, 6, 14, 9, 0 // CHANGE FOR DEPLOYMENT
        );
        dog.head = randomTrait(
            concatBytes(hash[12], hash[13]), charitable, 2, 4, 15, 9, 30 // CHANGE FOR DEPLOYMENT
        );

        return dog;
    }

    function randomTrait(
        uint16 seed, 
        bool charitable, 
        uint8 legendaries,
        uint8 ultras,
        uint8 rares, 
        uint8 commons,
        uint16 nonePercent
    ) internal pure returns (uint8) {
        uint256 trait = uint256(0xFFFF) * (100 - nonePercent) / 100;
        if (seed > trait) {
            return 0;
        }
        uint256 base = !charitable ? trait / 300 : trait / 200; // 0.33 / 0.5 % chance
        if (seed < base) return uint8(seed % legendaries) + 1;

        base += !charitable ? trait / 50 : trait / 33; // 2 / 3 % chance
        if (seed < base) return legendaries + uint8(seed % ultras) + 1;

        base += !charitable ? trait / 5 : trait * 3 / 10; // 20 / 30 % chance
        if (seed < base) return legendaries + ultras + uint8(seed % rares) + 1;

        return legendaries + ultras + rares + uint8(seed % commons) + 1; // remainder
        
    }

    /**
     * @dev converts Dog struct to bitmap
     * @param dog struct representing Dog
     * @return bitmap the bitmap representation of the Dog
     */
    function structToBitmap(Dog memory dog) internal pure returns (uint256 bitmap) { 
        bitmap = uint256(dog.breed) << 16;
        bitmap |= uint256(dog.background) << 24;
        bitmap |= uint256(dog.skin) << 32;
        bitmap |= uint256(dog.shirt) << 40;
        bitmap |= uint256(dog.neck) << 48;
        bitmap |= uint256(dog.mouth) << 56;
        bitmap |= uint256(dog.eyes) << 64;
        bitmap |= uint256(dog.head) << 72;
    }

    function concatBytes(bytes1 u1, bytes1 u2) internal pure returns (uint16) {
        return uint16(uint8(u1)) << 8 | uint16(uint8(u2));
    }

    function unpackUint8(uint256 value, uint256 index) internal pure returns (uint8) {
        return uint8((value & (0xFF << index)) >> index);
    }

    function randomSteakID() internal returns (uint256) {
        uint256 remaining = STEAKS_RESERVED - steaksRedeemed;
        uint256 random = uint256(generator.generate(_msgSender(), steaksRedeemed, remaining)) % remaining;
        
        uint256 index = steakIndices[random] == 0 ? random : steakIndices[random];
        steakIndices[random] = steakIndices[remaining - 1] == 0 ? uint16(remaining - 1) : steakIndices[remaining - 1];
        return index + MAX_TEAM_DOGS + 1;
    }

    function randomReservationID() internal returns (uint256) {
        uint256 remaining = MAX_RESERVATIONS - reservationsRedeemed;
        uint256 random = uint256(generator.generate(_msgSender(), reservationsRedeemed, remaining)) % remaining;
        
        uint256 index = reservationIndices[random] == 0 ? random : reservationIndices[random];
        reservationIndices[random] = reservationIndices[remaining - 1] == 0 ? uint16(remaining - 1) : reservationIndices[remaining - 1];
        return index + MAX_TEAM_DOGS + STEAKS_RESERVED + 1;
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"uint256","name":"_MAX_DOGS","type":"uint256"},{"internalType":"string","name":"_prefix","type":"string"},{"internalType":"string","name":"_suffix","type":"string"},{"internalType":"address","name":"_proofOfSteakAddress","type":"address"},{"internalType":"address","name":"_generatorAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"traitMap","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"parent1","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"parent2","type":"uint256"}],"name":"TokenUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"traitMap","type":"uint256"}],"name":"TraitsBurned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"MAX_DOGS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_RESERVATIONS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_TEAM_DOGS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STEAKS_RESERVED","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"addresses","type":"address[]"},{"internalType":"uint256[]","name":"quantities","type":"uint256[]"}],"name":"addReservations","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"bool","name":"charitable","type":"bool"}],"name":"charitableCost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"charitableMints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"charitableWithdrawals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"charityAddress","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"dogId1","type":"uint256"},{"internalType":"uint256","name":"dogId2","type":"uint256"},{"internalType":"uint256","name":"traitMap","type":"uint256"}],"name":"combineDogs","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"devMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"generalLock","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"mintCost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"prefix","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proofOfSteak","outputs":[{"internalType":"contract IProofOfSteak","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"bool","name":"charitable","type":"bool"}],"name":"redeemReservation","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"steakId","type":"uint256"},{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"bool","name":"charitable","type":"bool"}],"name":"redeemSteak","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"reservations","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"reservationsRedeemed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"_charityAddress","type":"address"}],"name":"setCharityAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_locked","type":"bool"}],"name":"setGeneralLock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_locked","type":"bool"}],"name":"setSteakholderLock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"setSteaksReserved","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_prefix","type":"string"},{"internalType":"string","name":"_suffix","type":"string"}],"name":"setSuffixPrefix","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"_teamAddress","type":"address"}],"name":"setTeamAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"steakholderLock","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"steaksRedeemed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"suffix","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"teamAddress","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalReservations","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"traitMaps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawCharitable","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6080604052600c805461ff001960ff19909116600117166101001790553480156200002957600080fd5b50604051620055f0380380620055f0833981810160405260a08110156200004f57600080fd5b8151602083018051604051929492938301929190846401000000008211156200007757600080fd5b9083019060208201858111156200008d57600080fd5b8251640100000000811182820188101715620000a857600080fd5b82525081516020918201929091019080838360005b83811015620000d7578181015183820152602001620000bd565b50505050905090810190601f168015620001055780820380516001836020036101000a031916815260200191505b50604052602001805160405193929190846401000000008211156200012957600080fd5b9083019060208201858111156200013f57600080fd5b82516401000000008111828201881017156200015a57600080fd5b82525081516020918201929091019080838360005b83811015620001895781810151838201526020016200016f565b50505050905090810190601f168015620001b75780820380516001836020036101000a031916815260200191505b506040818152602083810151938201518383018352600e84526d111bd9dcc8155b98da185a5b995960921b8285015282518084019093526004835263444f475560e01b918301919091529294509192509060006200021d6001600160e01b03620003bf16565b600080546001600160a01b0319166001600160a01b0383169081178255604051929350917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35060018055620002866301ffc9a760e01b6001600160e01b03620003c416565b81516200029b90600890602085019062000449565b508051620002b190600990602084019062000449565b50620002cd6380ac58cd60e01b6001600160e01b03620003c416565b620002e8635b5e139f60e01b6001600160e01b03620003c416565b6200030363780e9d6360e01b6001600160e01b03620003c416565b5050601885905583516200031f90601e90602087019062000449565b5082516200033590601f90602086019062000449565b50601b80546001600160a01b0319166001600160a01b0384161790556200035b620003bf565b601c80546001600160a01b0319166001600160a01b039290921691909117905562000385620003bf565b601d80546001600160a01b039283166001600160a01b0319918216179091556020805493909216921691909117905550620004eb92505050565b335b90565b6001600160e01b0319808216141562000424576040805162461bcd60e51b815260206004820152601c60248201527f4552433136353a20696e76616c696420696e7465726661636520696400000000604482015290519081900360640190fd5b6001600160e01b0319166000908152600260205260409020805460ff19166001179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200048c57805160ff1916838001178555620004bc565b82800160010185558215620004bc579182015b82811115620004bc5782518255916020019190600101906200049f565b50620004ca929150620004ce565b5090565b620003c191905b80821115620004ca5760008155600101620004d5565b6150f580620004fb6000396000f3fe60806040526004361061031a5760003560e01c806370c14b15116101ab578063b88d4fde116100f7578063ed37226d11610095578063f7073c3a1161006f578063f7073c3a14610c9c578063f865b30014610cb1578063fd3dc53a14610cc6578063ffecd9d614610cf95761031a565b8063ed37226d14610c2f578063f2fde38b14610c44578063f60c0eb514610c775761031a565b8063ce32206c116100d1578063ce32206c14610bb5578063d2f4a00014610bca578063e985e9c514610bdf578063e9b0cd9614610c1a5761031a565b8063b88d4fde14610aa5578063c61cb00014610b76578063c87b56dd14610b8b5761031a565b80639004039111610164578063a82d09c31161013e578063a82d09c314610a51578063abf14aed14610a66578063adea8a9e14610a7b578063afcf2fc414610a905761031a565b806390040391146109cb57806395d89b4114610a01578063a22cb46514610a165761031a565b806370c14b1514610880578063715018a6146108ac57806375dadb32146108c15780637c69e207146108d65780637ef9420f146108eb5780638da5cb5b146109b65761031a565b8063363125711161026a578063470de6fe116102235780636352211e116101fd5780636352211e146107db5780636690864e146108055780636c0360eb1461083857806370a082311461084d5761031a565b8063470de6fe146107555780634f6ccce71461078757806354e9cd34146107b15761031a565b8063363125711461067c5780633959ce9c146106915780633ccfd60b146106a65780633db87cdf146106bb57806340cfe0b1146106e757806342842e0e146107125761031a565b8063184af126116102d7578063204298c0116102b1578063204298c01461050b57806323b872dd146105d657806327de8f27146106195780632f745c59146106435761031a565b8063184af126146104cc5780631b917efe146104e15780631c75f085146104f65761031a565b806301ffc9a71461031f57806306fdde0314610367578063081812fc146103f1578063095ea7b3146104375780630c9be46d1461047257806318160ddd146104a5575b600080fd5b34801561032b57600080fd5b506103536004803603602081101561034257600080fd5b50356001600160e01b031916610d23565b604080519115158252519081900360200190f35b34801561037357600080fd5b5061037c610d46565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103b657818101518382015260200161039e565b50505050905090810190601f1680156103e35780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156103fd57600080fd5b5061041b6004803603602081101561041457600080fd5b5035610ddd565b604080516001600160a01b039092168252519081900360200190f35b34801561044357600080fd5b506104706004803603604081101561045a57600080fd5b506001600160a01b038135169060200135610e3f565b005b34801561047e57600080fd5b506104706004803603602081101561049557600080fd5b50356001600160a01b0316610f1a565b3480156104b157600080fd5b506104ba610f9e565b60408051918252519081900360200190f35b3480156104d857600080fd5b506104ba610faf565b3480156104ed57600080fd5b5061041b610fb5565b34801561050257600080fd5b5061041b610fc4565b34801561051757600080fd5b506104706004803603604081101561052e57600080fd5b810190602081018135600160201b81111561054857600080fd5b82018360208201111561055a57600080fd5b803590602001918460208302840111600160201b8311171561057b57600080fd5b919390929091602081019035600160201b81111561059857600080fd5b8201836020820111156105aa57600080fd5b803590602001918460208302840111600160201b831117156105cb57600080fd5b509092509050610fd3565b3480156105e257600080fd5b50610470600480360360608110156105f957600080fd5b506001600160a01b038135811691602081013590911690604001356110dd565b34801561062557600080fd5b506104ba6004803603602081101561063c57600080fd5b5035611134565b34801561064f57600080fd5b506104ba6004803603604081101561066657600080fd5b506001600160a01b038135169060200135611154565b34801561068857600080fd5b50610353611183565b34801561069d57600080fd5b50610353611191565b3480156106b257600080fd5b5061047061119a565b3480156106c757600080fd5b50610470600480360360208110156106de57600080fd5b5035151561127a565b610470600480360360608110156106fd57600080fd5b508035906020810135906040013515156112ef565b34801561071e57600080fd5b506104706004803603606081101561073557600080fd5b506001600160a01b03813581169160208101359091169060400135611577565b34801561076157600080fd5b506104ba6004803603604081101561077857600080fd5b50803590602001351515611592565b34801561079357600080fd5b506104ba600480360360208110156107aa57600080fd5b50356115b7565b3480156107bd57600080fd5b50610470600480360360208110156107d457600080fd5b50356115d3565b3480156107e757600080fd5b5061041b600480360360208110156107fe57600080fd5b50356116ca565b34801561081157600080fd5b506104706004803603602081101561082857600080fd5b50356001600160a01b03166116f8565b34801561084457600080fd5b5061037c61177c565b34801561085957600080fd5b506104ba6004803603602081101561087057600080fd5b50356001600160a01b03166117dd565b34801561088c57600080fd5b50610470600480360360208110156108a357600080fd5b50351515611845565b3480156108b857600080fd5b506104706118c1565b3480156108cd57600080fd5b5061037c61196d565b3480156108e257600080fd5b506104706119fb565b3480156108f757600080fd5b506104706004803603604081101561090e57600080fd5b810190602081018135600160201b81111561092857600080fd5b82018360208201111561093a57600080fd5b803590602001918460018302840111600160201b8311171561095b57600080fd5b919390929091602081019035600160201b81111561097857600080fd5b82018360208201111561098a57600080fd5b803590602001918460018302840111600160201b831117156109ab57600080fd5b509092509050611af9565b3480156109c257600080fd5b5061041b611b74565b3480156109d757600080fd5b50610470600480360360608110156109ee57600080fd5b5080359060208101359060400135611b83565b348015610a0d57600080fd5b5061037c612923565b348015610a2257600080fd5b5061047060048036036040811015610a3957600080fd5b506001600160a01b0381351690602001351515612984565b348015610a5d57600080fd5b506104ba612a89565b348015610a7257600080fd5b506104ba612a8f565b348015610a8757600080fd5b506104ba612a95565b348015610a9c57600080fd5b5061041b612a9b565b348015610ab157600080fd5b5061047060048036036080811015610ac857600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b811115610b0257600080fd5b820183602082011115610b1457600080fd5b803590602001918460018302840111600160201b83111715610b3557600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612aaa945050505050565b348015610b8257600080fd5b506104ba612b08565b348015610b9757600080fd5b5061037c60048036036020811015610bae57600080fd5b5035612b0e565b348015610bc157600080fd5b506104ba612c80565b348015610bd657600080fd5b506104ba612c85565b348015610beb57600080fd5b5061035360048036036040811015610c0257600080fd5b506001600160a01b0381358116916020013516612c8b565b348015610c2657600080fd5b50610470612cb9565b348015610c3b57600080fd5b506104ba612d82565b348015610c5057600080fd5b5061047060048036036020811015610c6757600080fd5b50356001600160a01b0316612d88565b61047060048036036040811015610c8d57600080fd5b50803590602001351515612e8a565b348015610ca857600080fd5b5061037c6131d9565b348015610cbd57600080fd5b506104ba613233565b348015610cd257600080fd5b506104ba60048036036020811015610ce957600080fd5b50356001600160a01b0316613239565b348015610d0557600080fd5b506104ba60048036036020811015610d1c57600080fd5b503561324b565b6001600160e01b0319811660009081526002602052604090205460ff165b919050565b60088054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610dd25780601f10610da757610100808354040283529160200191610dd2565b820191906000526020600020905b815481529060010190602001808311610db557829003601f168201915b505050505090505b90565b6000610de88261325d565b610e235760405162461bcd60e51b815260040180806020018281038252602c815260200180614f82602c913960400191505060405180910390fd5b506000908152600660205260409020546001600160a01b031690565b6000610e4a826116ca565b9050806001600160a01b0316836001600160a01b03161415610e9d5760405162461bcd60e51b81526004018080602001828103825260218152602001806150266021913960400191505060405180910390fd5b806001600160a01b0316610eaf613270565b6001600160a01b03161480610ed05750610ed081610ecb613270565b612c8b565b610f0b5760405162461bcd60e51b8152600401808060200182810382526038815260200180614e8f6038913960400191505060405180910390fd5b610f158383613274565b505050565b610f22613270565b6001600160a01b0316610f33611b74565b6001600160a01b031614610f7c576040805162461bcd60e51b81526020600482018190526024820152600080516020614fae833981519152604482015290519081900360640190fd5b601d80546001600160a01b0319166001600160a01b0392909216919091179055565b6000610faa60046132e2565b905090565b600e5481565b601b546001600160a01b031681565b601c546001600160a01b031681565b610fdb613270565b6001600160a01b0316610fec611b74565b6001600160a01b031614611035576040805162461bcd60e51b81526020600482018190526024820152600080516020614fae833981519152604482015290519081900360640190fd5b82811461107d576040805162461bcd60e51b81526020600482015260116024820152704d69736d61746368656420696e7075747360781b604482015290519081900360640190fd5b60005b838110156110d65782828281811061109457fe5b90506020020135601560008787858181106110ab57fe5b602090810292909201356001600160a01b031683525081019190915260400160002055600101611080565b5050505050565b6110ee6110e8613270565b826132ed565b6111295760405162461bcd60e51b815260040180806020018281038252603181526020018061506c6031913960400191505060405180910390fd5b610f15838383613391565b600061114e8267011c37937e08000063ffffffff6134ef16565b92915050565b6001600160a01b038216600090815260036020526040812061117c908363ffffffff61354816565b9392505050565b600c54610100900460ff1681565b600c5460ff1681565b6111a2613270565b6001600160a01b03166111b3611b74565b6001600160a01b0316146111fc576040805162461bcd60e51b81526020600482018190526024820152600080516020614fae833981519152604482015290519081900360640190fd5b600061122c66470de4df820000611220600f54600e5461355490919063ffffffff16565b9063ffffffff6134ef16565b601c549091506001600160a01b03166108fc61124e478463ffffffff61355416565b6040518115909202916000818181858888f19350505050158015611276573d6000803e3d6000fd5b5050565b611282613270565b6001600160a01b0316611293611b74565b6001600160a01b0316146112dc576040805162461bcd60e51b81526020600482018190526024820152600080516020614fae833981519152604482015290519081900360640190fd5b600c805460ff1916911515919091179055565b60026001541415611347576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002600155600c54610100900460ff161561139e576040805162461bcd60e51b8152602060048201526012602482015271119d5b98dd1a5bdb881a5cc81b1bd8dad95960721b604482015290519081900360640190fd5b600082116113e8576040805162461bcd60e51b815260206004820152601260248201527143616e6e6f74206d696e74203020446f677360701b604482015290519081900360640190fd5b600a8211156114285760405162461bcd60e51b8152600401808060200182810382526027815260200180614d9a6027913960400191505060405180910390fd5b6114328282611592565b3414611485576040805162461bcd60e51b815260206004820152601b60248201527f496e636f72726563742063686172697461626c6520616d6f756e740000000000604482015290519081900360640190fd5b601b546001600160a01b0316632b83cccd61149e613270565b85856040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b031681526020018381526020018281526020019350505050600060405180830381600087803b1580156114f657600080fd5b505af115801561150a573d6000803e3d6000fd5b5060009250829150505b8381101561154f576115246135b1565b91506115308284613797565b60115461154490600163ffffffff6139e316565b601155600101611514565b50811561156d57600e54611569908463ffffffff6139e316565b600e555b5050600180555050565b610f1583838360405180602001604052806000815250612aaa565b6000816115a057600061117c565b61117c83662386f26fc1000063ffffffff6134ef16565b6000806115cb60048463ffffffff613a3d16565b509392505050565b6115db613270565b6001600160a01b03166115ec611b74565b6001600160a01b031614611635576040805162461bcd60e51b81526020600482018190526024820152600080516020614fae833981519152604482015290519081900360640190fd5b6010819055604080518281526020808402820101909152818015611663578160200160208202803683370190505b50805161167891601291602090910190614b83565b50606460105460185403036013819055506013546040519080825280602002602001820160405280156116b5578160200160208202803683370190505b50805161127691601791602090910190614b83565b600061114e82604051806060016040528060298152602001614ef1602991396004919063ffffffff613a5916565b611700613270565b6001600160a01b0316611711611b74565b6001600160a01b03161461175a576040805162461bcd60e51b81526020600482018190526024820152600080516020614fae833981519152604482015290519081900360640190fd5b601c80546001600160a01b0319166001600160a01b0392909216919091179055565b600b8054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610dd25780601f10610da757610100808354040283529160200191610dd2565b60006001600160a01b0382166118245760405162461bcd60e51b815260040180806020018281038252602a815260200180614ec7602a913960400191505060405180910390fd5b6001600160a01b038216600090815260036020526040902061114e906132e2565b61184d613270565b6001600160a01b031661185e611b74565b6001600160a01b0316146118a7576040805162461bcd60e51b81526020600482018190526024820152600080516020614fae833981519152604482015290519081900360640190fd5b600c80549115156101000261ff0019909216919091179055565b6118c9613270565b6001600160a01b03166118da611b74565b6001600160a01b031614611923576040805162461bcd60e51b81526020600482018190526024820152600080516020614fae833981519152604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b601e805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156119f35780601f106119c8576101008083540402835291602001916119f3565b820191906000526020600020905b8154815290600101906020018083116119d657829003601f168201915b505050505081565b611a03613270565b6001600160a01b0316611a14611b74565b6001600160a01b031614611a5d576040805162461bcd60e51b81526020600482018190526024820152600080516020614fae833981519152604482015290519081900360640190fd5b600d54606490611a7490600a63ffffffff6139e316565b1115611abe576040805162461bcd60e51b815260206004820152601460248201527343616e6e6f7420646576206d696e74206d6f726560601b604482015290519081900360640190fd5b60005b600a811015611af657600d54611ade90600163ffffffff6139e316565b600d819055611aee906001613797565b600101611ac1565b50565b611b01613270565b6001600160a01b0316611b12611b74565b6001600160a01b031614611b5b576040805162461bcd60e51b81526020600482018190526024820152600080516020614fae833981519152604482015290519081900360640190fd5b611b67601e8585614c2c565b506110d6601f8383614c2c565b6000546001600160a01b031690565b60026001541415611bdb576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002600155600c54610100900460ff1615611c32576040805162461bcd60e51b8152602060048201526012602482015271119d5b98dd1a5bdb881a5cc81b1bd8dad95960721b604482015290519081900360640190fd5b611c3a613270565b6001600160a01b0316611c4c846116ca565b6001600160a01b031614611c9d576040805162461bcd60e51b81526020600482015260136024820152724d757374206f776e20746865736520446f677360681b604482015290519081900360640190fd5b611ca5613270565b6001600160a01b0316611cb7836116ca565b6001600160a01b031614611d08576040805162461bcd60e51b81526020600482015260136024820152724d757374206f776e20746865736520446f677360681b604482015290519081900360640190fd5b6000838152601960209081526040808320815161014081018352815461ffff8116825260ff62010000820481169583019590955263010000008104851693820193909352600160201b830484166060820152600160281b830484166080820152600160301b8304841660a0820152600160381b8304841660c0820152600160401b8304841660e0820152600160481b83048416610100820152600160501b909204909216610120820152909190611dbe90613a66565b6000858152601960209081526040808320815161014081018352815461ffff8116825260ff62010000820481169583019590955263010000008104851693820193909352600160201b830484166060820152600160281b830484166080820152600160301b8304841660a0820152600160381b8304841660c0820152600160401b8304841660e0820152600160481b83048416610100820152600160501b90920490921661012082015292935091611e7590613a66565b845490915061ffff8087169116811480611e965750825461ffff8281169116145b611ed4576040805162461bcd60e51b815260206004820152600a602482015269125b9d985b1a5908125160b21b604482015290519081900360640190fd5b611edc614ca6565b5061ffff8082166000908152601960209081526040918290208251610140810184529054938416815260ff62010000850481169282019290925263010000008404821692810192909252600160201b830481166060830152600160281b830481166080830152600160301b8304811660a0830152600160381b8304811660c0830152600160401b8304811660e0830152600160481b83048116610100830152600160501b909204909116610120820152611f94614ca6565b611f9f886010613aec565b60ff9081166020840181905288546201000090049091161480611fd357506020820151855462010000900460ff9081169116145b612014576040805162461bcd60e51b815260206004820152600d60248201526c125b9d985b1a5908189c995959609a1b604482015290519081900360640190fd5b6020820151875462010000900460ff90811691161461203d57865462010000900460ff16612049565b845462010000900460ff165b60ff16602082015261205c886018613aec565b60ff9081166040840181905288546301000000900490911614806120925750604082015185546301000000900460ff9081169116145b6120d8576040805162461bcd60e51b8152602060048201526012602482015271125b9d985b1a5908189858dad9dc9bdd5b9960721b604482015290519081900360640190fd5b604082015187546301000000900460ff9081169116146121035786546301000000900460ff16612110565b84546301000000900460ff165b60ff166040820152612123886020613aec565b60ff908116606084018190528854600160201b90049091161480612159575060608201518554600160201b900460ff9081169116145b612199576040805162461bcd60e51b815260206004820152600c60248201526b24b73b30b634b21039b5b4b760a11b604482015290519081900360640190fd5b60608201518754600160201b900460ff9081169116146121c4578654600160201b900460ff166121d1565b8454600160201b900460ff165b60ff1660608201526121e4886028613aec565b60ff908116608084018190528854600160281b9004909116148061221a575060808201518554600160281b900460ff9081169116145b61225b576040805162461bcd60e51b815260206004820152600d60248201526c125b9d985b1a59081cda1a5c9d609a1b604482015290519081900360640190fd5b60808201518754600160281b900460ff908116911614612286578654600160281b900460ff16612293565b8454600160281b900460ff165b60ff1660808201526122a6886030613aec565b60ff90811660a084018190528854600160301b900490911614806122dc575060a08201518554600160301b900460ff9081169116145b61231c576040805162461bcd60e51b815260206004820152600c60248201526b496e76616c6964206e65636b60a01b604482015290519081900360640190fd5b60a08201518754600160301b900460ff908116911614612347578654600160301b900460ff16612354565b8454600160301b900460ff165b60ff1660a0820152612367886038613aec565b60ff90811660c084018190528854600160381b9004909116148061239d575060c08201518554600160381b900460ff9081169116145b6123de576040805162461bcd60e51b815260206004820152600d60248201526c092dcecc2d8d2c840dadeeae8d609b1b604482015290519081900360640190fd5b60c08201518754600160381b900460ff908116911614612409578654600160381b900460ff16612416565b8454600160381b900460ff165b60ff1660c0820152612429886040613aec565b60ff90811660e084018190528854600160401b9004909116148061245f575060e08201518554600160401b900460ff9081169116145b61249f576040805162461bcd60e51b815260206004820152600c60248201526b496e76616c6964206579657360a01b604482015290519081900360640190fd5b60e08201518754600160401b900460ff9081169116146124ca578654600160401b900460ff166124d7565b8454600160401b900460ff165b60ff1660e08201526124ea886048613aec565b60ff90811661010084018190528854600160481b9004909116148061252257506101008201518554600160481b900460ff9081169116145b612562576040805162461bcd60e51b815260206004820152600c60248201526b125b9d985b1a59081a19585960a21b604482015290519081900360640190fd5b6101008201518754600160481b900460ff90811691161461258e578654600160481b900460ff1661259b565b8454600160481b900460ff165b60ff1661010082015260006125af83613a66565b6000818152601a6020526040902054909150156125fd5760405162461bcd60e51b8152600401808060200182810382526025815260200180614f1a6025913960400191505060405180910390fd5b82516000828152601a6020526040902061ffff90911690558554885460ff600160501b928390048116929091041611612644578554600160501b900460ff16600101612654565b8754600160501b900460ff166001015b60ff166101208401528251885487546040805161ffff9485168152602081018690528484168c0160ff60501b600160501b95869004605090811b821692909201838501529584168b019490930490921b90931691909101606082015290517f637ff2b5b59467a49a47569696266ffdfb2d53df685d2dea16e47f9b4bd034149181900360800190a1875483517fc1a62151a475b0cd1e8aee926d72656f6ffb529a88b1d8bf912fb9a4d06d64839161ffff91821691161461271a57885461ffff16612721565b865461ffff165b61272a84613a66565b6040805161ffff909316835260208301919091528051918290030190a182601960008661ffff16815260200190815260200160002060008201518160000160006101000a81548161ffff021916908361ffff16021790555060208201518160000160026101000a81548160ff021916908360ff16021790555060408201518160000160036101000a81548160ff021916908360ff16021790555060608201518160000160046101000a81548160ff021916908360ff16021790555060808201518160000160056101000a81548160ff021916908360ff16021790555060a08201518160000160066101000a81548160ff021916908360ff16021790555060c08201518160000160076101000a81548160ff021916908360ff16021790555060e08201518160000160086101000a81548160ff021916908360ff1602179055506101008201518160000160096101000a81548160ff021916908360ff16021790555061012082015181600001600a6101000a81548160ff021916908360ff1602179055509050508760000160009054906101000a900461ffff1661ffff16836000015161ffff1614156128ea5785546128e59061ffff16613af9565b6128f9565b87546128f99061ffff16613af9565b505050600093845250601a6020526040808420849055908352822091909155505060018055505050565b60098054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610dd25780601f10610da757610100808354040283529160200191610dd2565b61298c613270565b6001600160a01b0316826001600160a01b031614156129f2576040805162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015290519081900360640190fd5b80600760006129ff613270565b6001600160a01b03908116825260208083019390935260409182016000908120918716808252919093529120805460ff191692151592909217909155612a43613270565b60408051841515815290516001600160a01b0392909216917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c319181900360200190a35050565b60165481565b600f5481565b60115481565b601d546001600160a01b031681565b612abb612ab5613270565b836132ed565b612af65760405162461bcd60e51b815260040180806020018281038252603181526020018061506c6031913960400191505060405180910390fd5b612b0284848484613bd2565b50505050565b60185481565b6060612b198261325d565b612b545760405162461bcd60e51b815260040180806020018281038252602f815260200180614ff7602f913960400191505060405180910390fd5b601e612b5f83613c24565b601f6040516020018084805460018160011615610100020316600290048015612bbf5780601f10612b9d576101008083540402835291820191612bbf565b820191906000526020600020905b815481529060010190602001808311612bab575b5050835160208501908083835b60208310612beb5780518252601f199092019160209182019101612bcc565b6001836020036101000a03801982511681845116808217855250505050505090500182805460018160011615610100020316600290048015612c645780601f10612c42576101008083540402835291820191612c64565b820191906000526020600020905b815481529060010190602001808311612c50575b505060408051601f198184030181529190529695505050505050565b606481565b60135481565b6001600160a01b03918216600090815260076020908152604080832093909416825291909152205460ff1690565b612cc1613270565b6001600160a01b0316612cd2611b74565b6001600160a01b031614612d1b576040805162461bcd60e51b81526020600482018190526024820152600080516020614fae833981519152604482015290519081900360640190fd5b601d54600f54600e546001600160a01b03909216916108fc91612d519166470de4df82000091611220919063ffffffff61355416565b6040518115909202916000818181858888f19350505050158015612d79573d6000803e3d6000fd5b50600e54600f55565b60145481565b612d90613270565b6001600160a01b0316612da1611b74565b6001600160a01b031614612dea576040805162461bcd60e51b81526020600482018190526024820152600080516020614fae833981519152604482015290519081900360640190fd5b6001600160a01b038116612e2f5760405162461bcd60e51b8152600401808060200182810382526026815260200180614df36026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b60026001541415612ee2576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002600155600c5460ff1615612f34576040805162461bcd60e51b8152602060048201526012602482015271119d5b98dd1a5bdb881a5cc81b1bd8dad95960721b604482015290519081900360640190fd5b60008211612f7e576040805162461bcd60e51b815260206004820152601260248201527143616e6e6f74206d696e74203020446f677360701b604482015290519081900360640190fd5b60156000612f8a613270565b6001600160a01b03166001600160a01b0316815260200190815260200160002054821115612fe95760405162461bcd60e51b815260040180806020018281038252602381526020018061509d6023913960400191505060405180910390fd5b600a8211156130295760405162461bcd60e51b81526004018080602001828103825260258152602001806150476025913960400191505060405180910390fd5b6018546130588361304c606461304c6010546016546139e390919063ffffffff16565b9063ffffffff6139e316565b11156130ab576040805162461bcd60e51b815260206004820152601d60248201527f4372656174696e67206d6f726520646f6773207468616e206c696d6974000000604482015290519081900360640190fd5b6130c16130b88383611592565b61304c84611134565b3414613114576040805162461bcd60e51b815260206004820152601860248201527f496e636f7272656374207061796d656e7420616d6f756e740000000000000000604482015290519081900360640190fd5b61314a8260156000613124613270565b6001600160a01b031681526020810191909152604001600020549063ffffffff61355416565b60156000613156613270565b6001600160a01b031681526020810191909152604001600090812091909155805b838110156131b257613187613ce8565b91506131938284613797565b6016546131a790600163ffffffff6139e316565b601655600101613177565b5081156131d057600e546131cc908463ffffffff6139e316565b600e555b50506001805550565b601f80546040805160206002600019610100600187161502019094169390930480850184900484028201840190925281815292918301828280156119f35780601f106119c8576101008083540402835291602001916119f3565b60105481565b60156020526000908152604090205481565b601a6020526000908152604090205481565b600061114e60048363ffffffff613ed216565b3390565b600081815260066020526040902080546001600160a01b0319166001600160a01b03841690811790915581906132a9826116ca565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600061114e82613ede565b60006132f88261325d565b6133335760405162461bcd60e51b815260040180806020018281038252602c815260200180614e63602c913960400191505060405180910390fd5b600061333e836116ca565b9050806001600160a01b0316846001600160a01b031614806133795750836001600160a01b031661336e84610ddd565b6001600160a01b0316145b8061338957506133898185612c8b565b949350505050565b826001600160a01b03166133a4826116ca565b6001600160a01b0316146133e95760405162461bcd60e51b8152600401808060200182810382526029815260200180614fce6029913960400191505060405180910390fd5b6001600160a01b03821661342e5760405162461bcd60e51b8152600401808060200182810382526024815260200180614e196024913960400191505060405180910390fd5b613439838383610f15565b613444600082613274565b6001600160a01b038316600090815260036020526040902061346c908263ffffffff613ee216565b506001600160a01b0382166000908152600360205260409020613495908263ffffffff613eee16565b506134a86004828463ffffffff613efa16565b5080826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b6000826134fe5750600061114e565b8282028284828161350b57fe5b041461117c5760405162461bcd60e51b8152600401808060200182810382526021815260200180614f616021913960400191505060405180910390fd5b600061117c8383613f10565b6000828211156135ab576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b60115460105460205460009290910390829082906001600160a01b031663bc94b39c6135db613270565b601154866040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001838152602001828152602001935050505060206040518083038186803b15801561363357600080fd5b505afa158015613647573d6000803e3d6000fd5b505050506040513d602081101561365d57600080fd5b50518161366657fe5b06905060006012828154811061367857fe5b60009182526020909120601082040154600f9091166002026101000a900461ffff16156136d357601282815481106136ac57fe5b60009182526020909120601082040154600f9091166002026101000a900461ffff166136d5565b815b9050601260018403815481106136e757fe5b60009182526020909120601082040154600f9091166002026101000a900461ffff1615613747576012600184038154811061371e57fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff1661374c565b600183035b6012838154811061375957fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff16021790555060648101600101935050505090565b60006137a1614ca6565b6137ac848484613f74565b90505b601a60006137bc83613a66565b8152602001908152602001600020546000146137f7576137e382600163ffffffff6139e316565b91506137f0848484613f74565b90506137af565b806019600086815260200190815260200160002060008201518160000160006101000a81548161ffff021916908361ffff16021790555060208201518160000160026101000a81548160ff021916908360ff16021790555060408201518160000160036101000a81548160ff021916908360ff16021790555060608201518160000160046101000a81548160ff021916908360ff16021790555060808201518160000160056101000a81548160ff021916908360ff16021790555060a08201518160000160066101000a81548160ff021916908360ff16021790555060c08201518160000160076101000a81548160ff021916908360ff16021790555060e08201518160000160086101000a81548160ff021916908360ff1602179055506101008201518160000160096101000a81548160ff021916908360ff16021790555061012082015181600001600a6101000a81548160ff021916908360ff16021790555090505083601a600061396a84613a66565b815260208101919091526040016000205561398c613986613270565b85614189565b7f637ff2b5b59467a49a47569696266ffdfb2d53df685d2dea16e47f9b4bd03414846139b783613a66565b60408051928352602083019190915260008282018190526060830152519081900360800190a150505050565b60008282018381101561117c576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000808080613a4c86866141a3565b9097909650945050505050565b600061338984848461421e565b60006010826020015160ff16901b90506018826040015160ff16901b811790506020826060015160ff16901b811790506028826080015160ff16901b8117905060308260a0015160ff16901b8117905060388260c0015160ff16901b8117905060408260e0015160ff16901b81179050604882610100015160ff16901b81179050919050565b60ff811b91909116901c90565b6000613b04826116ca565b9050613b1281600084610f15565b613b1d600083613274565b6000828152600a60205260409020546002600019610100600184161502019091160415613b5b576000828152600a60205260408120613b5b91614cfa565b6001600160a01b0381166000908152600360205260409020613b83908363ffffffff613ee216565b50613b9560048363ffffffff6142e816565b5060405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b613bdd848484613391565b613be9848484846142f4565b612b025760405162461bcd60e51b8152600401808060200182810382526032815260200180614dc16032913960400191505060405180910390fd5b606081613c4957506040805180820190915260018152600360fc1b6020820152610d41565b8160005b8115613c6157600101600a82049150613c4d565b6060816040519080825280601f01601f191660200182016040528015613c8e576020820181803683370190505b50859350905060001982015b8315613cdf57600a840660300160f81b82828060019003935081518110613cbd57fe5b60200101906001600160f81b031916908160001a905350600a84049350613c9a565b50949350505050565b60165460135460205460009290910390829082906001600160a01b031663bc94b39c613d12613270565b601654866040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001838152602001828152602001935050505060206040518083038186803b158015613d6a57600080fd5b505afa158015613d7e573d6000803e3d6000fd5b505050506040513d6020811015613d9457600080fd5b505181613d9d57fe5b069050600060178281548110613daf57fe5b60009182526020909120601082040154600f9091166002026101000a900461ffff1615613e0a5760178281548110613de357fe5b60009182526020909120601082040154600f9091166002026101000a900461ffff16613e0c565b815b905060176001840381548110613e1e57fe5b60009182526020909120601082040154600f9091166002026101000a900461ffff1615613e7e5760176001840381548110613e5557fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16613e83565b600183035b60178381548110613e9057fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff1602179055506010546064820101600101935050505090565b600061117c8383614474565b5490565b600061117c838361448c565b600061117c8383614552565b600061338984846001600160a01b03851661459c565b81546000908210613f525760405162461bcd60e51b8152600401808060200182810382526022815260200180614d786022913960400191505060405180910390fd5b826000018281548110613f6157fe5b9060005260206000200154905092915050565b613f7c614ca6565b6020546000906001600160a01b031663bc94b39c613f98613270565b87866040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001838152602001828152602001935050505060206040518083038186803b158015613fee57600080fd5b505afa158015614002573d6000803e3d6000fd5b505050506040513d602081101561401857600080fd5b50519050614024614ca6565b61ffff861681526001610120820152600560ff83160660ff16602082015261406b61405c8360001a60f81b8460015b1a60f81b614633565b86600180600360076000614644565b60ff1660408201526140976140888360021a60f81b846003614053565b86600260038060036000614644565b60ff1660608201526140c46140b48360041a60f81b846005614053565b8660026006600e600b600f614644565b60ff1660808201526140f06140e18360061a60f81b846007614053565b86600160026007806046614644565b60ff1660a082015261411d61410d8360081a60f81b846009614053565b8660026004600e600b6000614644565b60ff1660c082015261414a61413a83600a1a60f81b84600b614053565b8660026006600e60096000614644565b60ff1660e082015261417761416783600c1a60f81b84600d614053565b8660026004600f6009601e614644565b60ff1661010082015295945050505050565b61127682826040518060200160405280600081525061475c565b8154600090819083106141e75760405162461bcd60e51b8152600401808060200182810382526022815260200180614f3f6022913960400191505060405180910390fd5b60008460000184815481106141f857fe5b906000526020600020906002020190508060000154816001015492509250509250929050565b600082815260018401602052604081205482816142b95760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561427e578181015183820152602001614266565b50505050905090810190601f1680156142ab5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b508460000160018203815481106142cc57fe5b9060005260206000209060020201600101549150509392505050565b600061117c83836147ae565b6000614308846001600160a01b0316614882565b61431457506001613389565b606061443a630a85bd0160e11b614329613270565b88878760405160240180856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156143a257818101518382015260200161438a565b50505050905090810190601f1680156143cf5780820380516001836020036101000a031916815260200191505b5095505050505050604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050604051806060016040528060328152602001614dc1603291396001600160a01b038816919063ffffffff61488816565b9050600081806020019051602081101561445357600080fd5b50516001600160e01b031916630a85bd0160e11b1492505050949350505050565b60009081526001919091016020526040902054151590565b6000818152600183016020526040812054801561454857835460001980830191908101906000908790839081106144bf57fe5b90600052602060002001549050808760000184815481106144dc57fe5b60009182526020808320909101929092558281526001898101909252604090209084019055865487908061450c57fe5b6001900381819060005260206000200160009055905586600101600087815260200190815260200160002060009055600194505050505061114e565b600091505061114e565b600061455e8383614474565b6145945750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561114e565b50600061114e565b60008281526001840160205260408120548061460157505060408051808201825283815260208082018481528654600181810189556000898152848120955160029093029095019182559151908201558654868452818801909252929091205561117c565b8285600001600183038154811061461457fe5b906000526020600020906002020160010181905550600091505061117c565b60f81c60f09190911c61ff00161790565b600080606461ffff848203811602049050808961ffff16111561466b576000915050614751565b6000881561467c5760c88204614682565b61012c82045b9050808a61ffff1610156146ad578760ff168a61ffff16816146a057fe5b0660010192505050614751565b88156146bc57602182046146c1565b603282045b0161ffff8a168111156146ed578660ff168a61ffff16816146de57fe5b06880160010192505050614751565b88156146ff57600a6003830204614704565b600582045b0161ffff8a16811115614732578560ff168a61ffff168161472157fe5b068789010160010192505050614751565b8460ff168a61ffff168161474257fe5b0686888a010101600101925050505b979650505050505050565b6147668383614897565b61477360008484846142f4565b610f155760405162461bcd60e51b8152600401808060200182810382526032815260200180614dc16032913960400191505060405180910390fd5b6000818152600183016020526040812054801561454857835460001980830191908101906000908790839081106147e157fe5b906000526020600020906002020190508087600001848154811061480157fe5b60009182526020808320845460029093020191825560019384015491840191909155835482528983019052604090209084019055865487908061484057fe5b600082815260208082206002600019909401938402018281556001908101839055929093558881528982019092526040822091909155945061114e9350505050565b3b151590565b606061338984846000856149d1565b6001600160a01b0382166148f2576040805162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015290519081900360640190fd5b6148fb8161325d565b1561494d576040805162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015290519081900360640190fd5b61495960008383610f15565b6001600160a01b0382166000908152600360205260409020614981908263ffffffff613eee16565b506149946004828463ffffffff613efa16565b5060405181906001600160a01b038416906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b606082471015614a125760405162461bcd60e51b8152600401808060200182810382526026815260200180614e3d6026913960400191505060405180910390fd5b614a1b85614882565b614a6c576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b60208310614aab5780518252601f199092019160209182019101614a8c565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114614b0d576040519150601f19603f3d011682016040523d82523d6000602084013e614b12565b606091505b509150915061475182828660608315614b2c57508161117c565b825115614b3c5782518084602001fd5b60405162461bcd60e51b815260206004820181815284516024840152845185939192839260440191908501908083836000831561427e578181015183820152602001614266565b82805482825590600052602060002090600f01601090048101928215614c1c5791602002820160005b83821115614bec57835183826101000a81548161ffff021916908361ffff1602179055509260200192600201602081600101049283019260010302614bac565b8015614c1a5782816101000a81549061ffff0219169055600201602081600101049283019260010302614bec565b505b50614c28929150614d3e565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10614c6d5782800160ff19823516178555614c9a565b82800160010185558215614c9a579182015b82811115614c9a578235825591602001919060010190614c7f565b50614c28929150614d5d565b6040805161014081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081019190915290565b50805460018160011615610100020316600290046000825580601f10614d205750611af6565b601f016020900490600052602060002090810190611af69190614d5d565b610dda91905b80821115614c2857805461ffff19168155600101614d44565b610dda91905b80821115614c285760008155600101614d6356fe456e756d657261626c655365743a20696e646578206f7574206f6620626f756e647343616e6e6f742072656465656d206d6f7265207468616e20313020446f6773206174206f6e63654552433732313a207472616e7366657220746f206e6f6e20455243373231526563656976657220696d706c656d656e7465724f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573734552433732313a207472616e7366657220746f20746865207a65726f2061646472657373416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a20617070726f76652063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f76656420666f7220616c6c4552433732313a2062616c616e636520717565727920666f7220746865207a65726f20616464726573734552433732313a206f776e657220717565727920666f72206e6f6e6578697374656e7420746f6b656e5468697320747261697420636f6d62696e6174696f6e20616c726561647920657869737473456e756d657261626c654d61703a20696e646578206f7574206f6620626f756e6473536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774552433732313a20617070726f76656420717565727920666f72206e6f6e6578697374656e7420746f6b656e4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65724552433732313a207472616e73666572206f6620746f6b656e2074686174206973206e6f74206f776e4552433732314d657461646174613a2055524920717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a20617070726f76616c20746f2063757272656e74206f776e657243616e6e6f74206d696e74206d6f7265207468616e20313020646f6773206174206f6e63654552433732313a207472616e736665722063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f76656443616e6e6f742072656465656d206d6f7265207468616e207265736572766174696f6ea264697066735822122033f002e6ffb9d246416ef247601ad7f4505c7533882a94f9e8753846d94a7fd464736f6c63430006040033000000000000000000000000000000000000000000000000000000000000270f00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000cab65c60d9dc47e1d450c7e9074f73f1ff75f18100000000000000000000000044b6766a242f97edc835586a897f3925e2eaeb3b000000000000000000000000000000000000000000000000000000000000001568747470733a2f2f697066732e696f2f69706e732f000000000000000000000000000000000000000000000000000000000000000000000000000000000000152e646f6773756e636861696e65646e66742e636f6d0000000000000000000000

Deployed Bytecode

0x60806040526004361061031a5760003560e01c806370c14b15116101ab578063b88d4fde116100f7578063ed37226d11610095578063f7073c3a1161006f578063f7073c3a14610c9c578063f865b30014610cb1578063fd3dc53a14610cc6578063ffecd9d614610cf95761031a565b8063ed37226d14610c2f578063f2fde38b14610c44578063f60c0eb514610c775761031a565b8063ce32206c116100d1578063ce32206c14610bb5578063d2f4a00014610bca578063e985e9c514610bdf578063e9b0cd9614610c1a5761031a565b8063b88d4fde14610aa5578063c61cb00014610b76578063c87b56dd14610b8b5761031a565b80639004039111610164578063a82d09c31161013e578063a82d09c314610a51578063abf14aed14610a66578063adea8a9e14610a7b578063afcf2fc414610a905761031a565b806390040391146109cb57806395d89b4114610a01578063a22cb46514610a165761031a565b806370c14b1514610880578063715018a6146108ac57806375dadb32146108c15780637c69e207146108d65780637ef9420f146108eb5780638da5cb5b146109b65761031a565b8063363125711161026a578063470de6fe116102235780636352211e116101fd5780636352211e146107db5780636690864e146108055780636c0360eb1461083857806370a082311461084d5761031a565b8063470de6fe146107555780634f6ccce71461078757806354e9cd34146107b15761031a565b8063363125711461067c5780633959ce9c146106915780633ccfd60b146106a65780633db87cdf146106bb57806340cfe0b1146106e757806342842e0e146107125761031a565b8063184af126116102d7578063204298c0116102b1578063204298c01461050b57806323b872dd146105d657806327de8f27146106195780632f745c59146106435761031a565b8063184af126146104cc5780631b917efe146104e15780631c75f085146104f65761031a565b806301ffc9a71461031f57806306fdde0314610367578063081812fc146103f1578063095ea7b3146104375780630c9be46d1461047257806318160ddd146104a5575b600080fd5b34801561032b57600080fd5b506103536004803603602081101561034257600080fd5b50356001600160e01b031916610d23565b604080519115158252519081900360200190f35b34801561037357600080fd5b5061037c610d46565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103b657818101518382015260200161039e565b50505050905090810190601f1680156103e35780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156103fd57600080fd5b5061041b6004803603602081101561041457600080fd5b5035610ddd565b604080516001600160a01b039092168252519081900360200190f35b34801561044357600080fd5b506104706004803603604081101561045a57600080fd5b506001600160a01b038135169060200135610e3f565b005b34801561047e57600080fd5b506104706004803603602081101561049557600080fd5b50356001600160a01b0316610f1a565b3480156104b157600080fd5b506104ba610f9e565b60408051918252519081900360200190f35b3480156104d857600080fd5b506104ba610faf565b3480156104ed57600080fd5b5061041b610fb5565b34801561050257600080fd5b5061041b610fc4565b34801561051757600080fd5b506104706004803603604081101561052e57600080fd5b810190602081018135600160201b81111561054857600080fd5b82018360208201111561055a57600080fd5b803590602001918460208302840111600160201b8311171561057b57600080fd5b919390929091602081019035600160201b81111561059857600080fd5b8201836020820111156105aa57600080fd5b803590602001918460208302840111600160201b831117156105cb57600080fd5b509092509050610fd3565b3480156105e257600080fd5b50610470600480360360608110156105f957600080fd5b506001600160a01b038135811691602081013590911690604001356110dd565b34801561062557600080fd5b506104ba6004803603602081101561063c57600080fd5b5035611134565b34801561064f57600080fd5b506104ba6004803603604081101561066657600080fd5b506001600160a01b038135169060200135611154565b34801561068857600080fd5b50610353611183565b34801561069d57600080fd5b50610353611191565b3480156106b257600080fd5b5061047061119a565b3480156106c757600080fd5b50610470600480360360208110156106de57600080fd5b5035151561127a565b610470600480360360608110156106fd57600080fd5b508035906020810135906040013515156112ef565b34801561071e57600080fd5b506104706004803603606081101561073557600080fd5b506001600160a01b03813581169160208101359091169060400135611577565b34801561076157600080fd5b506104ba6004803603604081101561077857600080fd5b50803590602001351515611592565b34801561079357600080fd5b506104ba600480360360208110156107aa57600080fd5b50356115b7565b3480156107bd57600080fd5b50610470600480360360208110156107d457600080fd5b50356115d3565b3480156107e757600080fd5b5061041b600480360360208110156107fe57600080fd5b50356116ca565b34801561081157600080fd5b506104706004803603602081101561082857600080fd5b50356001600160a01b03166116f8565b34801561084457600080fd5b5061037c61177c565b34801561085957600080fd5b506104ba6004803603602081101561087057600080fd5b50356001600160a01b03166117dd565b34801561088c57600080fd5b50610470600480360360208110156108a357600080fd5b50351515611845565b3480156108b857600080fd5b506104706118c1565b3480156108cd57600080fd5b5061037c61196d565b3480156108e257600080fd5b506104706119fb565b3480156108f757600080fd5b506104706004803603604081101561090e57600080fd5b810190602081018135600160201b81111561092857600080fd5b82018360208201111561093a57600080fd5b803590602001918460018302840111600160201b8311171561095b57600080fd5b919390929091602081019035600160201b81111561097857600080fd5b82018360208201111561098a57600080fd5b803590602001918460018302840111600160201b831117156109ab57600080fd5b509092509050611af9565b3480156109c257600080fd5b5061041b611b74565b3480156109d757600080fd5b50610470600480360360608110156109ee57600080fd5b5080359060208101359060400135611b83565b348015610a0d57600080fd5b5061037c612923565b348015610a2257600080fd5b5061047060048036036040811015610a3957600080fd5b506001600160a01b0381351690602001351515612984565b348015610a5d57600080fd5b506104ba612a89565b348015610a7257600080fd5b506104ba612a8f565b348015610a8757600080fd5b506104ba612a95565b348015610a9c57600080fd5b5061041b612a9b565b348015610ab157600080fd5b5061047060048036036080811015610ac857600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b811115610b0257600080fd5b820183602082011115610b1457600080fd5b803590602001918460018302840111600160201b83111715610b3557600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612aaa945050505050565b348015610b8257600080fd5b506104ba612b08565b348015610b9757600080fd5b5061037c60048036036020811015610bae57600080fd5b5035612b0e565b348015610bc157600080fd5b506104ba612c80565b348015610bd657600080fd5b506104ba612c85565b348015610beb57600080fd5b5061035360048036036040811015610c0257600080fd5b506001600160a01b0381358116916020013516612c8b565b348015610c2657600080fd5b50610470612cb9565b348015610c3b57600080fd5b506104ba612d82565b348015610c5057600080fd5b5061047060048036036020811015610c6757600080fd5b50356001600160a01b0316612d88565b61047060048036036040811015610c8d57600080fd5b50803590602001351515612e8a565b348015610ca857600080fd5b5061037c6131d9565b348015610cbd57600080fd5b506104ba613233565b348015610cd257600080fd5b506104ba60048036036020811015610ce957600080fd5b50356001600160a01b0316613239565b348015610d0557600080fd5b506104ba60048036036020811015610d1c57600080fd5b503561324b565b6001600160e01b0319811660009081526002602052604090205460ff165b919050565b60088054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610dd25780601f10610da757610100808354040283529160200191610dd2565b820191906000526020600020905b815481529060010190602001808311610db557829003601f168201915b505050505090505b90565b6000610de88261325d565b610e235760405162461bcd60e51b815260040180806020018281038252602c815260200180614f82602c913960400191505060405180910390fd5b506000908152600660205260409020546001600160a01b031690565b6000610e4a826116ca565b9050806001600160a01b0316836001600160a01b03161415610e9d5760405162461bcd60e51b81526004018080602001828103825260218152602001806150266021913960400191505060405180910390fd5b806001600160a01b0316610eaf613270565b6001600160a01b03161480610ed05750610ed081610ecb613270565b612c8b565b610f0b5760405162461bcd60e51b8152600401808060200182810382526038815260200180614e8f6038913960400191505060405180910390fd5b610f158383613274565b505050565b610f22613270565b6001600160a01b0316610f33611b74565b6001600160a01b031614610f7c576040805162461bcd60e51b81526020600482018190526024820152600080516020614fae833981519152604482015290519081900360640190fd5b601d80546001600160a01b0319166001600160a01b0392909216919091179055565b6000610faa60046132e2565b905090565b600e5481565b601b546001600160a01b031681565b601c546001600160a01b031681565b610fdb613270565b6001600160a01b0316610fec611b74565b6001600160a01b031614611035576040805162461bcd60e51b81526020600482018190526024820152600080516020614fae833981519152604482015290519081900360640190fd5b82811461107d576040805162461bcd60e51b81526020600482015260116024820152704d69736d61746368656420696e7075747360781b604482015290519081900360640190fd5b60005b838110156110d65782828281811061109457fe5b90506020020135601560008787858181106110ab57fe5b602090810292909201356001600160a01b031683525081019190915260400160002055600101611080565b5050505050565b6110ee6110e8613270565b826132ed565b6111295760405162461bcd60e51b815260040180806020018281038252603181526020018061506c6031913960400191505060405180910390fd5b610f15838383613391565b600061114e8267011c37937e08000063ffffffff6134ef16565b92915050565b6001600160a01b038216600090815260036020526040812061117c908363ffffffff61354816565b9392505050565b600c54610100900460ff1681565b600c5460ff1681565b6111a2613270565b6001600160a01b03166111b3611b74565b6001600160a01b0316146111fc576040805162461bcd60e51b81526020600482018190526024820152600080516020614fae833981519152604482015290519081900360640190fd5b600061122c66470de4df820000611220600f54600e5461355490919063ffffffff16565b9063ffffffff6134ef16565b601c549091506001600160a01b03166108fc61124e478463ffffffff61355416565b6040518115909202916000818181858888f19350505050158015611276573d6000803e3d6000fd5b5050565b611282613270565b6001600160a01b0316611293611b74565b6001600160a01b0316146112dc576040805162461bcd60e51b81526020600482018190526024820152600080516020614fae833981519152604482015290519081900360640190fd5b600c805460ff1916911515919091179055565b60026001541415611347576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002600155600c54610100900460ff161561139e576040805162461bcd60e51b8152602060048201526012602482015271119d5b98dd1a5bdb881a5cc81b1bd8dad95960721b604482015290519081900360640190fd5b600082116113e8576040805162461bcd60e51b815260206004820152601260248201527143616e6e6f74206d696e74203020446f677360701b604482015290519081900360640190fd5b600a8211156114285760405162461bcd60e51b8152600401808060200182810382526027815260200180614d9a6027913960400191505060405180910390fd5b6114328282611592565b3414611485576040805162461bcd60e51b815260206004820152601b60248201527f496e636f72726563742063686172697461626c6520616d6f756e740000000000604482015290519081900360640190fd5b601b546001600160a01b0316632b83cccd61149e613270565b85856040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b031681526020018381526020018281526020019350505050600060405180830381600087803b1580156114f657600080fd5b505af115801561150a573d6000803e3d6000fd5b5060009250829150505b8381101561154f576115246135b1565b91506115308284613797565b60115461154490600163ffffffff6139e316565b601155600101611514565b50811561156d57600e54611569908463ffffffff6139e316565b600e555b5050600180555050565b610f1583838360405180602001604052806000815250612aaa565b6000816115a057600061117c565b61117c83662386f26fc1000063ffffffff6134ef16565b6000806115cb60048463ffffffff613a3d16565b509392505050565b6115db613270565b6001600160a01b03166115ec611b74565b6001600160a01b031614611635576040805162461bcd60e51b81526020600482018190526024820152600080516020614fae833981519152604482015290519081900360640190fd5b6010819055604080518281526020808402820101909152818015611663578160200160208202803683370190505b50805161167891601291602090910190614b83565b50606460105460185403036013819055506013546040519080825280602002602001820160405280156116b5578160200160208202803683370190505b50805161127691601791602090910190614b83565b600061114e82604051806060016040528060298152602001614ef1602991396004919063ffffffff613a5916565b611700613270565b6001600160a01b0316611711611b74565b6001600160a01b03161461175a576040805162461bcd60e51b81526020600482018190526024820152600080516020614fae833981519152604482015290519081900360640190fd5b601c80546001600160a01b0319166001600160a01b0392909216919091179055565b600b8054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610dd25780601f10610da757610100808354040283529160200191610dd2565b60006001600160a01b0382166118245760405162461bcd60e51b815260040180806020018281038252602a815260200180614ec7602a913960400191505060405180910390fd5b6001600160a01b038216600090815260036020526040902061114e906132e2565b61184d613270565b6001600160a01b031661185e611b74565b6001600160a01b0316146118a7576040805162461bcd60e51b81526020600482018190526024820152600080516020614fae833981519152604482015290519081900360640190fd5b600c80549115156101000261ff0019909216919091179055565b6118c9613270565b6001600160a01b03166118da611b74565b6001600160a01b031614611923576040805162461bcd60e51b81526020600482018190526024820152600080516020614fae833981519152604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b601e805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156119f35780601f106119c8576101008083540402835291602001916119f3565b820191906000526020600020905b8154815290600101906020018083116119d657829003601f168201915b505050505081565b611a03613270565b6001600160a01b0316611a14611b74565b6001600160a01b031614611a5d576040805162461bcd60e51b81526020600482018190526024820152600080516020614fae833981519152604482015290519081900360640190fd5b600d54606490611a7490600a63ffffffff6139e316565b1115611abe576040805162461bcd60e51b815260206004820152601460248201527343616e6e6f7420646576206d696e74206d6f726560601b604482015290519081900360640190fd5b60005b600a811015611af657600d54611ade90600163ffffffff6139e316565b600d819055611aee906001613797565b600101611ac1565b50565b611b01613270565b6001600160a01b0316611b12611b74565b6001600160a01b031614611b5b576040805162461bcd60e51b81526020600482018190526024820152600080516020614fae833981519152604482015290519081900360640190fd5b611b67601e8585614c2c565b506110d6601f8383614c2c565b6000546001600160a01b031690565b60026001541415611bdb576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002600155600c54610100900460ff1615611c32576040805162461bcd60e51b8152602060048201526012602482015271119d5b98dd1a5bdb881a5cc81b1bd8dad95960721b604482015290519081900360640190fd5b611c3a613270565b6001600160a01b0316611c4c846116ca565b6001600160a01b031614611c9d576040805162461bcd60e51b81526020600482015260136024820152724d757374206f776e20746865736520446f677360681b604482015290519081900360640190fd5b611ca5613270565b6001600160a01b0316611cb7836116ca565b6001600160a01b031614611d08576040805162461bcd60e51b81526020600482015260136024820152724d757374206f776e20746865736520446f677360681b604482015290519081900360640190fd5b6000838152601960209081526040808320815161014081018352815461ffff8116825260ff62010000820481169583019590955263010000008104851693820193909352600160201b830484166060820152600160281b830484166080820152600160301b8304841660a0820152600160381b8304841660c0820152600160401b8304841660e0820152600160481b83048416610100820152600160501b909204909216610120820152909190611dbe90613a66565b6000858152601960209081526040808320815161014081018352815461ffff8116825260ff62010000820481169583019590955263010000008104851693820193909352600160201b830484166060820152600160281b830484166080820152600160301b8304841660a0820152600160381b8304841660c0820152600160401b8304841660e0820152600160481b83048416610100820152600160501b90920490921661012082015292935091611e7590613a66565b845490915061ffff8087169116811480611e965750825461ffff8281169116145b611ed4576040805162461bcd60e51b815260206004820152600a602482015269125b9d985b1a5908125160b21b604482015290519081900360640190fd5b611edc614ca6565b5061ffff8082166000908152601960209081526040918290208251610140810184529054938416815260ff62010000850481169282019290925263010000008404821692810192909252600160201b830481166060830152600160281b830481166080830152600160301b8304811660a0830152600160381b8304811660c0830152600160401b8304811660e0830152600160481b83048116610100830152600160501b909204909116610120820152611f94614ca6565b611f9f886010613aec565b60ff9081166020840181905288546201000090049091161480611fd357506020820151855462010000900460ff9081169116145b612014576040805162461bcd60e51b815260206004820152600d60248201526c125b9d985b1a5908189c995959609a1b604482015290519081900360640190fd5b6020820151875462010000900460ff90811691161461203d57865462010000900460ff16612049565b845462010000900460ff165b60ff16602082015261205c886018613aec565b60ff9081166040840181905288546301000000900490911614806120925750604082015185546301000000900460ff9081169116145b6120d8576040805162461bcd60e51b8152602060048201526012602482015271125b9d985b1a5908189858dad9dc9bdd5b9960721b604482015290519081900360640190fd5b604082015187546301000000900460ff9081169116146121035786546301000000900460ff16612110565b84546301000000900460ff165b60ff166040820152612123886020613aec565b60ff908116606084018190528854600160201b90049091161480612159575060608201518554600160201b900460ff9081169116145b612199576040805162461bcd60e51b815260206004820152600c60248201526b24b73b30b634b21039b5b4b760a11b604482015290519081900360640190fd5b60608201518754600160201b900460ff9081169116146121c4578654600160201b900460ff166121d1565b8454600160201b900460ff165b60ff1660608201526121e4886028613aec565b60ff908116608084018190528854600160281b9004909116148061221a575060808201518554600160281b900460ff9081169116145b61225b576040805162461bcd60e51b815260206004820152600d60248201526c125b9d985b1a59081cda1a5c9d609a1b604482015290519081900360640190fd5b60808201518754600160281b900460ff908116911614612286578654600160281b900460ff16612293565b8454600160281b900460ff165b60ff1660808201526122a6886030613aec565b60ff90811660a084018190528854600160301b900490911614806122dc575060a08201518554600160301b900460ff9081169116145b61231c576040805162461bcd60e51b815260206004820152600c60248201526b496e76616c6964206e65636b60a01b604482015290519081900360640190fd5b60a08201518754600160301b900460ff908116911614612347578654600160301b900460ff16612354565b8454600160301b900460ff165b60ff1660a0820152612367886038613aec565b60ff90811660c084018190528854600160381b9004909116148061239d575060c08201518554600160381b900460ff9081169116145b6123de576040805162461bcd60e51b815260206004820152600d60248201526c092dcecc2d8d2c840dadeeae8d609b1b604482015290519081900360640190fd5b60c08201518754600160381b900460ff908116911614612409578654600160381b900460ff16612416565b8454600160381b900460ff165b60ff1660c0820152612429886040613aec565b60ff90811660e084018190528854600160401b9004909116148061245f575060e08201518554600160401b900460ff9081169116145b61249f576040805162461bcd60e51b815260206004820152600c60248201526b496e76616c6964206579657360a01b604482015290519081900360640190fd5b60e08201518754600160401b900460ff9081169116146124ca578654600160401b900460ff166124d7565b8454600160401b900460ff165b60ff1660e08201526124ea886048613aec565b60ff90811661010084018190528854600160481b9004909116148061252257506101008201518554600160481b900460ff9081169116145b612562576040805162461bcd60e51b815260206004820152600c60248201526b125b9d985b1a59081a19585960a21b604482015290519081900360640190fd5b6101008201518754600160481b900460ff90811691161461258e578654600160481b900460ff1661259b565b8454600160481b900460ff165b60ff1661010082015260006125af83613a66565b6000818152601a6020526040902054909150156125fd5760405162461bcd60e51b8152600401808060200182810382526025815260200180614f1a6025913960400191505060405180910390fd5b82516000828152601a6020526040902061ffff90911690558554885460ff600160501b928390048116929091041611612644578554600160501b900460ff16600101612654565b8754600160501b900460ff166001015b60ff166101208401528251885487546040805161ffff9485168152602081018690528484168c0160ff60501b600160501b95869004605090811b821692909201838501529584168b019490930490921b90931691909101606082015290517f637ff2b5b59467a49a47569696266ffdfb2d53df685d2dea16e47f9b4bd034149181900360800190a1875483517fc1a62151a475b0cd1e8aee926d72656f6ffb529a88b1d8bf912fb9a4d06d64839161ffff91821691161461271a57885461ffff16612721565b865461ffff165b61272a84613a66565b6040805161ffff909316835260208301919091528051918290030190a182601960008661ffff16815260200190815260200160002060008201518160000160006101000a81548161ffff021916908361ffff16021790555060208201518160000160026101000a81548160ff021916908360ff16021790555060408201518160000160036101000a81548160ff021916908360ff16021790555060608201518160000160046101000a81548160ff021916908360ff16021790555060808201518160000160056101000a81548160ff021916908360ff16021790555060a08201518160000160066101000a81548160ff021916908360ff16021790555060c08201518160000160076101000a81548160ff021916908360ff16021790555060e08201518160000160086101000a81548160ff021916908360ff1602179055506101008201518160000160096101000a81548160ff021916908360ff16021790555061012082015181600001600a6101000a81548160ff021916908360ff1602179055509050508760000160009054906101000a900461ffff1661ffff16836000015161ffff1614156128ea5785546128e59061ffff16613af9565b6128f9565b87546128f99061ffff16613af9565b505050600093845250601a6020526040808420849055908352822091909155505060018055505050565b60098054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610dd25780601f10610da757610100808354040283529160200191610dd2565b61298c613270565b6001600160a01b0316826001600160a01b031614156129f2576040805162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015290519081900360640190fd5b80600760006129ff613270565b6001600160a01b03908116825260208083019390935260409182016000908120918716808252919093529120805460ff191692151592909217909155612a43613270565b60408051841515815290516001600160a01b0392909216917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c319181900360200190a35050565b60165481565b600f5481565b60115481565b601d546001600160a01b031681565b612abb612ab5613270565b836132ed565b612af65760405162461bcd60e51b815260040180806020018281038252603181526020018061506c6031913960400191505060405180910390fd5b612b0284848484613bd2565b50505050565b60185481565b6060612b198261325d565b612b545760405162461bcd60e51b815260040180806020018281038252602f815260200180614ff7602f913960400191505060405180910390fd5b601e612b5f83613c24565b601f6040516020018084805460018160011615610100020316600290048015612bbf5780601f10612b9d576101008083540402835291820191612bbf565b820191906000526020600020905b815481529060010190602001808311612bab575b5050835160208501908083835b60208310612beb5780518252601f199092019160209182019101612bcc565b6001836020036101000a03801982511681845116808217855250505050505090500182805460018160011615610100020316600290048015612c645780601f10612c42576101008083540402835291820191612c64565b820191906000526020600020905b815481529060010190602001808311612c50575b505060408051601f198184030181529190529695505050505050565b606481565b60135481565b6001600160a01b03918216600090815260076020908152604080832093909416825291909152205460ff1690565b612cc1613270565b6001600160a01b0316612cd2611b74565b6001600160a01b031614612d1b576040805162461bcd60e51b81526020600482018190526024820152600080516020614fae833981519152604482015290519081900360640190fd5b601d54600f54600e546001600160a01b03909216916108fc91612d519166470de4df82000091611220919063ffffffff61355416565b6040518115909202916000818181858888f19350505050158015612d79573d6000803e3d6000fd5b50600e54600f55565b60145481565b612d90613270565b6001600160a01b0316612da1611b74565b6001600160a01b031614612dea576040805162461bcd60e51b81526020600482018190526024820152600080516020614fae833981519152604482015290519081900360640190fd5b6001600160a01b038116612e2f5760405162461bcd60e51b8152600401808060200182810382526026815260200180614df36026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b60026001541415612ee2576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002600155600c5460ff1615612f34576040805162461bcd60e51b8152602060048201526012602482015271119d5b98dd1a5bdb881a5cc81b1bd8dad95960721b604482015290519081900360640190fd5b60008211612f7e576040805162461bcd60e51b815260206004820152601260248201527143616e6e6f74206d696e74203020446f677360701b604482015290519081900360640190fd5b60156000612f8a613270565b6001600160a01b03166001600160a01b0316815260200190815260200160002054821115612fe95760405162461bcd60e51b815260040180806020018281038252602381526020018061509d6023913960400191505060405180910390fd5b600a8211156130295760405162461bcd60e51b81526004018080602001828103825260258152602001806150476025913960400191505060405180910390fd5b6018546130588361304c606461304c6010546016546139e390919063ffffffff16565b9063ffffffff6139e316565b11156130ab576040805162461bcd60e51b815260206004820152601d60248201527f4372656174696e67206d6f726520646f6773207468616e206c696d6974000000604482015290519081900360640190fd5b6130c16130b88383611592565b61304c84611134565b3414613114576040805162461bcd60e51b815260206004820152601860248201527f496e636f7272656374207061796d656e7420616d6f756e740000000000000000604482015290519081900360640190fd5b61314a8260156000613124613270565b6001600160a01b031681526020810191909152604001600020549063ffffffff61355416565b60156000613156613270565b6001600160a01b031681526020810191909152604001600090812091909155805b838110156131b257613187613ce8565b91506131938284613797565b6016546131a790600163ffffffff6139e316565b601655600101613177565b5081156131d057600e546131cc908463ffffffff6139e316565b600e555b50506001805550565b601f80546040805160206002600019610100600187161502019094169390930480850184900484028201840190925281815292918301828280156119f35780601f106119c8576101008083540402835291602001916119f3565b60105481565b60156020526000908152604090205481565b601a6020526000908152604090205481565b600061114e60048363ffffffff613ed216565b3390565b600081815260066020526040902080546001600160a01b0319166001600160a01b03841690811790915581906132a9826116ca565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600061114e82613ede565b60006132f88261325d565b6133335760405162461bcd60e51b815260040180806020018281038252602c815260200180614e63602c913960400191505060405180910390fd5b600061333e836116ca565b9050806001600160a01b0316846001600160a01b031614806133795750836001600160a01b031661336e84610ddd565b6001600160a01b0316145b8061338957506133898185612c8b565b949350505050565b826001600160a01b03166133a4826116ca565b6001600160a01b0316146133e95760405162461bcd60e51b8152600401808060200182810382526029815260200180614fce6029913960400191505060405180910390fd5b6001600160a01b03821661342e5760405162461bcd60e51b8152600401808060200182810382526024815260200180614e196024913960400191505060405180910390fd5b613439838383610f15565b613444600082613274565b6001600160a01b038316600090815260036020526040902061346c908263ffffffff613ee216565b506001600160a01b0382166000908152600360205260409020613495908263ffffffff613eee16565b506134a86004828463ffffffff613efa16565b5080826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b6000826134fe5750600061114e565b8282028284828161350b57fe5b041461117c5760405162461bcd60e51b8152600401808060200182810382526021815260200180614f616021913960400191505060405180910390fd5b600061117c8383613f10565b6000828211156135ab576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b60115460105460205460009290910390829082906001600160a01b031663bc94b39c6135db613270565b601154866040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001838152602001828152602001935050505060206040518083038186803b15801561363357600080fd5b505afa158015613647573d6000803e3d6000fd5b505050506040513d602081101561365d57600080fd5b50518161366657fe5b06905060006012828154811061367857fe5b60009182526020909120601082040154600f9091166002026101000a900461ffff16156136d357601282815481106136ac57fe5b60009182526020909120601082040154600f9091166002026101000a900461ffff166136d5565b815b9050601260018403815481106136e757fe5b60009182526020909120601082040154600f9091166002026101000a900461ffff1615613747576012600184038154811061371e57fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff1661374c565b600183035b6012838154811061375957fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff16021790555060648101600101935050505090565b60006137a1614ca6565b6137ac848484613f74565b90505b601a60006137bc83613a66565b8152602001908152602001600020546000146137f7576137e382600163ffffffff6139e316565b91506137f0848484613f74565b90506137af565b806019600086815260200190815260200160002060008201518160000160006101000a81548161ffff021916908361ffff16021790555060208201518160000160026101000a81548160ff021916908360ff16021790555060408201518160000160036101000a81548160ff021916908360ff16021790555060608201518160000160046101000a81548160ff021916908360ff16021790555060808201518160000160056101000a81548160ff021916908360ff16021790555060a08201518160000160066101000a81548160ff021916908360ff16021790555060c08201518160000160076101000a81548160ff021916908360ff16021790555060e08201518160000160086101000a81548160ff021916908360ff1602179055506101008201518160000160096101000a81548160ff021916908360ff16021790555061012082015181600001600a6101000a81548160ff021916908360ff16021790555090505083601a600061396a84613a66565b815260208101919091526040016000205561398c613986613270565b85614189565b7f637ff2b5b59467a49a47569696266ffdfb2d53df685d2dea16e47f9b4bd03414846139b783613a66565b60408051928352602083019190915260008282018190526060830152519081900360800190a150505050565b60008282018381101561117c576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000808080613a4c86866141a3565b9097909650945050505050565b600061338984848461421e565b60006010826020015160ff16901b90506018826040015160ff16901b811790506020826060015160ff16901b811790506028826080015160ff16901b8117905060308260a0015160ff16901b8117905060388260c0015160ff16901b8117905060408260e0015160ff16901b81179050604882610100015160ff16901b81179050919050565b60ff811b91909116901c90565b6000613b04826116ca565b9050613b1281600084610f15565b613b1d600083613274565b6000828152600a60205260409020546002600019610100600184161502019091160415613b5b576000828152600a60205260408120613b5b91614cfa565b6001600160a01b0381166000908152600360205260409020613b83908363ffffffff613ee216565b50613b9560048363ffffffff6142e816565b5060405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b613bdd848484613391565b613be9848484846142f4565b612b025760405162461bcd60e51b8152600401808060200182810382526032815260200180614dc16032913960400191505060405180910390fd5b606081613c4957506040805180820190915260018152600360fc1b6020820152610d41565b8160005b8115613c6157600101600a82049150613c4d565b6060816040519080825280601f01601f191660200182016040528015613c8e576020820181803683370190505b50859350905060001982015b8315613cdf57600a840660300160f81b82828060019003935081518110613cbd57fe5b60200101906001600160f81b031916908160001a905350600a84049350613c9a565b50949350505050565b60165460135460205460009290910390829082906001600160a01b031663bc94b39c613d12613270565b601654866040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001838152602001828152602001935050505060206040518083038186803b158015613d6a57600080fd5b505afa158015613d7e573d6000803e3d6000fd5b505050506040513d6020811015613d9457600080fd5b505181613d9d57fe5b069050600060178281548110613daf57fe5b60009182526020909120601082040154600f9091166002026101000a900461ffff1615613e0a5760178281548110613de357fe5b60009182526020909120601082040154600f9091166002026101000a900461ffff16613e0c565b815b905060176001840381548110613e1e57fe5b60009182526020909120601082040154600f9091166002026101000a900461ffff1615613e7e5760176001840381548110613e5557fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16613e83565b600183035b60178381548110613e9057fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff1602179055506010546064820101600101935050505090565b600061117c8383614474565b5490565b600061117c838361448c565b600061117c8383614552565b600061338984846001600160a01b03851661459c565b81546000908210613f525760405162461bcd60e51b8152600401808060200182810382526022815260200180614d786022913960400191505060405180910390fd5b826000018281548110613f6157fe5b9060005260206000200154905092915050565b613f7c614ca6565b6020546000906001600160a01b031663bc94b39c613f98613270565b87866040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001838152602001828152602001935050505060206040518083038186803b158015613fee57600080fd5b505afa158015614002573d6000803e3d6000fd5b505050506040513d602081101561401857600080fd5b50519050614024614ca6565b61ffff861681526001610120820152600560ff83160660ff16602082015261406b61405c8360001a60f81b8460015b1a60f81b614633565b86600180600360076000614644565b60ff1660408201526140976140888360021a60f81b846003614053565b86600260038060036000614644565b60ff1660608201526140c46140b48360041a60f81b846005614053565b8660026006600e600b600f614644565b60ff1660808201526140f06140e18360061a60f81b846007614053565b86600160026007806046614644565b60ff1660a082015261411d61410d8360081a60f81b846009614053565b8660026004600e600b6000614644565b60ff1660c082015261414a61413a83600a1a60f81b84600b614053565b8660026006600e60096000614644565b60ff1660e082015261417761416783600c1a60f81b84600d614053565b8660026004600f6009601e614644565b60ff1661010082015295945050505050565b61127682826040518060200160405280600081525061475c565b8154600090819083106141e75760405162461bcd60e51b8152600401808060200182810382526022815260200180614f3f6022913960400191505060405180910390fd5b60008460000184815481106141f857fe5b906000526020600020906002020190508060000154816001015492509250509250929050565b600082815260018401602052604081205482816142b95760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561427e578181015183820152602001614266565b50505050905090810190601f1680156142ab5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b508460000160018203815481106142cc57fe5b9060005260206000209060020201600101549150509392505050565b600061117c83836147ae565b6000614308846001600160a01b0316614882565b61431457506001613389565b606061443a630a85bd0160e11b614329613270565b88878760405160240180856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156143a257818101518382015260200161438a565b50505050905090810190601f1680156143cf5780820380516001836020036101000a031916815260200191505b5095505050505050604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050604051806060016040528060328152602001614dc1603291396001600160a01b038816919063ffffffff61488816565b9050600081806020019051602081101561445357600080fd5b50516001600160e01b031916630a85bd0160e11b1492505050949350505050565b60009081526001919091016020526040902054151590565b6000818152600183016020526040812054801561454857835460001980830191908101906000908790839081106144bf57fe5b90600052602060002001549050808760000184815481106144dc57fe5b60009182526020808320909101929092558281526001898101909252604090209084019055865487908061450c57fe5b6001900381819060005260206000200160009055905586600101600087815260200190815260200160002060009055600194505050505061114e565b600091505061114e565b600061455e8383614474565b6145945750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561114e565b50600061114e565b60008281526001840160205260408120548061460157505060408051808201825283815260208082018481528654600181810189556000898152848120955160029093029095019182559151908201558654868452818801909252929091205561117c565b8285600001600183038154811061461457fe5b906000526020600020906002020160010181905550600091505061117c565b60f81c60f09190911c61ff00161790565b600080606461ffff848203811602049050808961ffff16111561466b576000915050614751565b6000881561467c5760c88204614682565b61012c82045b9050808a61ffff1610156146ad578760ff168a61ffff16816146a057fe5b0660010192505050614751565b88156146bc57602182046146c1565b603282045b0161ffff8a168111156146ed578660ff168a61ffff16816146de57fe5b06880160010192505050614751565b88156146ff57600a6003830204614704565b600582045b0161ffff8a16811115614732578560ff168a61ffff168161472157fe5b068789010160010192505050614751565b8460ff168a61ffff168161474257fe5b0686888a010101600101925050505b979650505050505050565b6147668383614897565b61477360008484846142f4565b610f155760405162461bcd60e51b8152600401808060200182810382526032815260200180614dc16032913960400191505060405180910390fd5b6000818152600183016020526040812054801561454857835460001980830191908101906000908790839081106147e157fe5b906000526020600020906002020190508087600001848154811061480157fe5b60009182526020808320845460029093020191825560019384015491840191909155835482528983019052604090209084019055865487908061484057fe5b600082815260208082206002600019909401938402018281556001908101839055929093558881528982019092526040822091909155945061114e9350505050565b3b151590565b606061338984846000856149d1565b6001600160a01b0382166148f2576040805162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015290519081900360640190fd5b6148fb8161325d565b1561494d576040805162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015290519081900360640190fd5b61495960008383610f15565b6001600160a01b0382166000908152600360205260409020614981908263ffffffff613eee16565b506149946004828463ffffffff613efa16565b5060405181906001600160a01b038416906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b606082471015614a125760405162461bcd60e51b8152600401808060200182810382526026815260200180614e3d6026913960400191505060405180910390fd5b614a1b85614882565b614a6c576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b60208310614aab5780518252601f199092019160209182019101614a8c565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114614b0d576040519150601f19603f3d011682016040523d82523d6000602084013e614b12565b606091505b509150915061475182828660608315614b2c57508161117c565b825115614b3c5782518084602001fd5b60405162461bcd60e51b815260206004820181815284516024840152845185939192839260440191908501908083836000831561427e578181015183820152602001614266565b82805482825590600052602060002090600f01601090048101928215614c1c5791602002820160005b83821115614bec57835183826101000a81548161ffff021916908361ffff1602179055509260200192600201602081600101049283019260010302614bac565b8015614c1a5782816101000a81549061ffff0219169055600201602081600101049283019260010302614bec565b505b50614c28929150614d3e565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10614c6d5782800160ff19823516178555614c9a565b82800160010185558215614c9a579182015b82811115614c9a578235825591602001919060010190614c7f565b50614c28929150614d5d565b6040805161014081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081019190915290565b50805460018160011615610100020316600290046000825580601f10614d205750611af6565b601f016020900490600052602060002090810190611af69190614d5d565b610dda91905b80821115614c2857805461ffff19168155600101614d44565b610dda91905b80821115614c285760008155600101614d6356fe456e756d657261626c655365743a20696e646578206f7574206f6620626f756e647343616e6e6f742072656465656d206d6f7265207468616e20313020446f6773206174206f6e63654552433732313a207472616e7366657220746f206e6f6e20455243373231526563656976657220696d706c656d656e7465724f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573734552433732313a207472616e7366657220746f20746865207a65726f2061646472657373416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a20617070726f76652063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f76656420666f7220616c6c4552433732313a2062616c616e636520717565727920666f7220746865207a65726f20616464726573734552433732313a206f776e657220717565727920666f72206e6f6e6578697374656e7420746f6b656e5468697320747261697420636f6d62696e6174696f6e20616c726561647920657869737473456e756d657261626c654d61703a20696e646578206f7574206f6620626f756e6473536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774552433732313a20617070726f76656420717565727920666f72206e6f6e6578697374656e7420746f6b656e4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65724552433732313a207472616e73666572206f6620746f6b656e2074686174206973206e6f74206f776e4552433732314d657461646174613a2055524920717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a20617070726f76616c20746f2063757272656e74206f776e657243616e6e6f74206d696e74206d6f7265207468616e20313020646f6773206174206f6e63654552433732313a207472616e736665722063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f76656443616e6e6f742072656465656d206d6f7265207468616e207265736572766174696f6ea264697066735822122033f002e6ffb9d246416ef247601ad7f4505c7533882a94f9e8753846d94a7fd464736f6c63430006040033

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

000000000000000000000000000000000000000000000000000000000000270f00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000cab65c60d9dc47e1d450c7e9074f73f1ff75f18100000000000000000000000044b6766a242f97edc835586a897f3925e2eaeb3b000000000000000000000000000000000000000000000000000000000000001568747470733a2f2f697066732e696f2f69706e732f000000000000000000000000000000000000000000000000000000000000000000000000000000000000152e646f6773756e636861696e65646e66742e636f6d0000000000000000000000

-----Decoded View---------------
Arg [0] : _MAX_DOGS (uint256): 9999
Arg [1] : _prefix (string): https://ipfs.io/ipns/
Arg [2] : _suffix (string): .dogsunchainednft.com
Arg [3] : _proofOfSteakAddress (address): 0xCaB65C60D9DC47e1D450c7E9074f73f1Ff75f181
Arg [4] : _generatorAddress (address): 0x44B6766a242F97eDc835586a897f3925E2eaeB3b

-----Encoded View---------------
9 Constructor Arguments found :
Arg [0] : 000000000000000000000000000000000000000000000000000000000000270f
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [2] : 00000000000000000000000000000000000000000000000000000000000000e0
Arg [3] : 000000000000000000000000cab65c60d9dc47e1d450c7e9074f73f1ff75f181
Arg [4] : 00000000000000000000000044b6766a242f97edc835586a897f3925e2eaeb3b
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000015
Arg [6] : 68747470733a2f2f697066732e696f2f69706e732f0000000000000000000000
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000015
Arg [8] : 2e646f6773756e636861696e65646e66742e636f6d0000000000000000000000


Deployed Bytecode Sourcemap

70208:17927:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12:1:-1;9;2:12;15226:150:0;;5:9:-1;2:2;;;27:1;24;17:12;2:2;15226:150:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;15226:150:0;-1:-1:-1;;;;;;15226:150:0;;:::i;:::-;;;;;;;;;;;;;;;;;;56484:100;;5:9:-1;2:2;;;27:1;24;17:12;2:2;56484:100:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8::-1;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;56484:100:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;59270:221;;5:9:-1;2:2;;;27:1;24;17:12;2:2;59270:221:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;59270:221:0;;:::i;:::-;;;;-1:-1:-1;;;;;59270:221:0;;;;;;;;;;;;;;58800:404;;5:9:-1;2:2;;;27:1;24;17:12;2:2;58800:404:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;58800:404:0;;;;;;;;:::i;:::-;;81669:128;;5:9:-1;2:2;;;27:1;24;17:12;2:2;81669:128:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;81669:128:0;-1:-1:-1;;;;;81669:128:0;;:::i;58278:211::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;58278:211:0;;;:::i;:::-;;;;;;;;;;;;;;;;70742:30;;5:9:-1;2:2;;;27:1;24;17:12;2:2;70742:30:0;;;:::i;71288:33::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;71288:33:0;;;:::i;71366:34::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;71366:34:0;;;:::i;82450:314::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;82450:314:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;82450:314:0;;;;;;;;-1:-1:-1;;;11:28;;8:2;;;52:1;49;42:12;8:2;82450:314:0;;41:9:-1;34:4;18:14;14:25;11:40;8:2;;;64:1;61;54:12;8:2;82450:314:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;82450:314:0;;;;;;;;;;;-1:-1:-1;;;11:28;;8:2;;;52:1;49;42:12;8:2;82450:314:0;;41:9:-1;34:4;18:14;14:25;11:40;8:2;;;64:1;61;54:12;8:2;82450:314:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;-1:-1;82450:314:0;;-1:-1:-1;82450:314:0;-1:-1:-1;82450:314:0;:::i;60160:305::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;60160:305:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;60160:305:0;;;;;;;;;;;;;;;;;:::i;78950:155::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;78950:155:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;78950:155:0;;:::i;58040:162::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;58040:162:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;58040:162:0;;;;;;;;:::i;70365:34::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;70365:34:0;;;:::i;70328:30::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;70328:30:0;;;:::i;80688:244::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;80688:244:0;;;:::i;82180:98::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;82180:98:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;82180:98:0;;;;:::i;73013:758::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;73013:758:0;;;;;;;;;;;;;;:::i;60536:151::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;60536:151:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;60536:151:0;;;;;;;;;;;;;;;;;:::i;79113:200::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;79113:200:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;79113:200:0;;;;;;;;;:::i;58566:172::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;58566:172:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;58566:172:0;;:::i;79967:296::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;79967:296:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;79967:296:0;;:::i;56240:177::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;56240:177:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;56240:177:0;;:::i;81394:116::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;81394:116:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;81394:116:0;-1:-1:-1;;;;;81394:116:0;;:::i;57859:97::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;57859:97:0;;;:::i;55957:221::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;55957:221:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;55957:221:0;-1:-1:-1;;;;;55957:221:0;;:::i;81934:105::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;81934:105:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;81934:105:0;;;;:::i;2779:148::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;2779:148:0;;;:::i;71453:20::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;71453:20:0;;;:::i;80347:254::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;80347:254:0;;;:::i;82286:156::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;82286:156:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;82286:156:0;;;;;;;;-1:-1:-1;;;11:28;;8:2;;;52:1;49;42:12;8:2;82286:156:0;;41:9:-1;34:4;18:14;14:25;11:40;8:2;;;64:1;61;54:12;8:2;82286:156:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;82286:156:0;;;;;;;;;;;-1:-1:-1;;;11:28;;8:2;;;52:1;49;42:12;8:2;82286:156:0;;41:9:-1;34:4;18:14;14:25;11:40;8:2;;;64:1;61;54:12;8:2;82286:156:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;-1:-1;82286:156:0;;-1:-1:-1;82286:156:0;-1:-1:-1;82286:156:0;:::i;2128:87::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;2128:87:0;;;:::i;75344:3375::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;75344:3375:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;75344:3375:0;;;;;;;;;;;;:::i;56653:104::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;56653:104:0;;;:::i;59563:295::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;59563:295:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;59563:295:0;;;;;;;;;;:::i;71070:35::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;71070:35:0;;;:::i;70779:36::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;70779:36:0;;;:::i;70861:29::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;70861:29:0;;;:::i;71407:37::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;71407:37:0;;;:::i;60758:285::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;60758:285:0;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;;;;;60758:285:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;11:28;;8:2;;;52:1;49;42:12;8:2;60758:285:0;;41:9:-1;34:4;18:14;14:25;11:40;8:2;;;64:1;61;54:12;8:2;60758:285:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;60758:285:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;60758:285:0;;-1:-1:-1;60758:285:0;;-1:-1:-1;;;;;60758:285:0:i;71156:23::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;71156:23:0;;;:::i;79384:342::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;79384:342:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;79384:342:0;;:::i;70689:43::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;70689:43:0;;;:::i;70939:31::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;70939:31:0;;;:::i;59929:164::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;59929:164:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;59929:164:0;;;;;;;;;;:::i;81015:234::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;81015:234:0;;;:::i;70977:32::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;70977:32:0;;;:::i;3082:244::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;3082:244:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;3082:244:0;-1:-1:-1;;;;;3082:244:0;;:::i;73981:1133::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;73981:1133:0;;;;;;;;;:::i;71480:20::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;71480:20:0;;;:::i;70824:30::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;70824:30:0;;;:::i;71016:47::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;71016:47:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;71016:47:0;-1:-1:-1;;;;;71016:47:0;;:::i;71235:44::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;71235:44:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;71235:44:0;;:::i;15226:150::-;-1:-1:-1;;;;;;15335:33:0;;15311:4;15335:33;;;:20;:33;;;;;;;;15226:150;;;;:::o;56484:100::-;56571:5;56564:12;;;;;;;;-1:-1:-1;;56564:12:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56538:13;;56564:12;;56571:5;;56564:12;;56571:5;56564:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56484:100;;:::o;59270:221::-;59346:7;59374:16;59382:7;59374;:16::i;:::-;59366:73;;;;-1:-1:-1;;;59366:73:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;59459:24:0;;;;:15;:24;;;;;;-1:-1:-1;;;;;59459:24:0;;59270:221::o;58800:404::-;58881:13;58897:23;58912:7;58897:14;:23::i;:::-;58881:39;;58945:5;-1:-1:-1;;;;;58939:11:0;:2;-1:-1:-1;;;;;58939:11:0;;;58931:57;;;;-1:-1:-1;;;58931:57:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;59025:5;-1:-1:-1;;;;;59009:21:0;:12;:10;:12::i;:::-;-1:-1:-1;;;;;59009:21:0;;:69;;;;59034:44;59058:5;59065:12;:10;:12::i;:::-;59034:23;:44::i;:::-;59001:161;;;;-1:-1:-1;;;59001:161:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;59175:21;59184:2;59188:7;59175:8;:21::i;:::-;58800:404;;;:::o;81669:128::-;2359:12;:10;:12::i;:::-;-1:-1:-1;;;;;2348:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;2348:23:0;;2340:68;;;;;-1:-1:-1;;;2340:68:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;2340:68:0;;;;;;;;;;;;;;;81757:14:::1;:32:::0;;-1:-1:-1;;;;;;81757:32:0::1;-1:-1:-1::0;;;;;81757:32:0;;;::::1;::::0;;;::::1;::::0;;81669:128::o;58278:211::-;58339:7;58460:21;:12;:19;:21::i;:::-;58453:28;;58278:211;:::o;70742:30::-;;;;:::o;71288:33::-;;;-1:-1:-1;;;;;71288:33:0;;:::o;71366:34::-;;;-1:-1:-1;;;;;71366:34:0;;:::o;82450:314::-;2359:12;:10;:12::i;:::-;-1:-1:-1;;;;;2348:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;2348:23:0;;2340:68;;;;;-1:-1:-1;;;2340:68:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;2340:68:0;;;;;;;;;;;;;;;82574:37;;::::1;82566:67;;;::::0;;-1:-1:-1;;;82566:67:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;82566:67:0;;;;;;;;;;;;;::::1;;82649:6;82644:113;82661:20:::0;;::::1;82644:113;;;82732:10;;82743:1;82732:13;;;;;;;;;;;;;82703:12;:26;82716:9;;82726:1;82716:12;;;;;;;;::::0;;::::1;::::0;;;::::1;;-1:-1:-1::0;;;;;82716:12:0::1;82703:26:::0;;-1:-1:-1;82703:26:0;::::1;::::0;;;;;;-1:-1:-1;82703:26:0;:42;82683:3:::1;;82644:113;;;;82450:314:::0;;;;:::o;60160:305::-;60321:41;60340:12;:10;:12::i;:::-;60354:7;60321:18;:41::i;:::-;60313:103;;;;-1:-1:-1;;;60313:103:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;60429:28;60439:4;60445:2;60449:7;60429:9;:28::i;78950:155::-;79007:7;79034:24;:8;79047:10;79034:24;:12;:24;:::i;:::-;79027:31;78950:155;-1:-1:-1;;78950:155:0:o;58040:162::-;-1:-1:-1;;;;;58164:20:0;;58137:7;58164:20;;;:13;:20;;;;;:30;;58188:5;58164:30;:23;:30;:::i;:::-;58157:37;58040:162;-1:-1:-1;;;58040:162:0:o;70365:34::-;;;;;;;;;:::o;70328:30::-;;;;;;:::o;80688:244::-;2359:12;:10;:12::i;:::-;-1:-1:-1;;;;;2348:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;2348:23:0;;2340:68;;;;;-1:-1:-1;;;2340:68:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;2340:68:0;;;;;;;;;;;;;;;80736:20:::1;80759:60;80808:10;80760:42;80780:21;;80760:15;;:19;;:42;;;;:::i;:::-;80759:48:::0;:60:::1;:48;:60;:::i;:::-;80838:11;::::0;80736:83;;-1:-1:-1;;;;;;80838:11:0::1;80830:94;80874:39;:21;80736:83:::0;80874:39:::1;:25;:39;:::i;:::-;80830:94;::::0;;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;::::1;;;;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;80830:94:0;2419:1;80688:244::o:0;82180:98::-;2359:12;:10;:12::i;:::-;-1:-1:-1;;;;;2348:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;2348:23:0;;2340:68;;;;;-1:-1:-1;;;2340:68:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;2340:68:0;;;;;;;;;;;;;;;82249:11:::1;:21:::0;;-1:-1:-1;;82249:21:0::1;::::0;::::1;;::::0;;;::::1;::::0;;82180:98::o;73013:758::-;5081:1;5687:7;;:19;;5679:63;;;;;-1:-1:-1;;;5679:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;5081:1;5820:7;:18;72441:15:::1;::::0;::::1;::::0;::::1;;;72440:16;72432:47;;;::::0;;-1:-1:-1;;;72432:47:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;72432:47:0;;;;;;;;;;;;;::::1;;73170:1:::2;73159:8;:12;73151:43;;;::::0;;-1:-1:-1;;;73151:43:0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;73151:43:0;;;;;;;;;;;;;::::2;;73225:2;73213:8;:14;;73205:66;;;;-1:-1:-1::0;;;73205:66:0::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;73303:36;73318:8;73328:10;73303:14;:36::i;:::-;73290:9;:49;73282:89;;;::::0;;-1:-1:-1;;;73282:89:0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;::::2;::::0;;;;;;;;;;;;;::::2;;73382:12;::::0;-1:-1:-1;;;;;73382:12:0::2;:19;73402:12;:10;:12::i;:::-;73416:7;73425:8;73382:52;;;;;;;;;;;;;-1:-1:-1::0;;;;;73382:52:0::2;-1:-1:-1::0;;;;;73382:52:0::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24::::0;17:12:::2;2:2;73382:52:0;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::2;77:16;74:1;67:27;5:2;-1:-1:::0;73447:16:0::2;::::0;-1:-1:-1;73447:16:0;;-1:-1:-1;;73474:188:0::2;73495:8;73491:1;:12;73474:188;;;73536:15;:13;:15::i;:::-;73525:26;;73566:31;73576:8;73586:10;73566:9;:31::i;:::-;73629:14;::::0;:21:::2;::::0;73648:1:::2;73629:21;:18;:21;:::i;:::-;73612:14;:38:::0;73505:3:::2;;73474:188;;;;73678:10;73674:90;;;73723:15;::::0;:29:::2;::::0;73743:8;73723:29:::2;:19;:29;:::i;:::-;73705:15;:47:::0;73674:90:::2;-1:-1:-1::0;;5037:1:0;5999:22;;-1:-1:-1;;73013:758:0:o;60536:151::-;60640:39;60657:4;60663:2;60667:7;60640:39;;;;;;;;;;;;:16;:39::i;79113:200::-;79193:7;79220:10;:41;;79260:1;79220:41;;;79233:24;:8;79246:10;79233:24;:12;:24;:::i;58566:172::-;58641:7;;58683:22;:12;58699:5;58683:22;:15;:22;:::i;:::-;-1:-1:-1;58661:44:0;58566:172;-1:-1:-1;;;58566:172:0:o;79967:296::-;2359:12;:10;:12::i;:::-;-1:-1:-1;;;;;2348:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;2348:23:0;;2340:68;;;;;-1:-1:-1;;;2340:68:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;2340:68:0;;;;;;;;;;;;;;;80040:15:::1;:26:::0;;;80092:29:::1;::::0;;;;;::::1;::::0;;::::1;::::0;;;;;;80058:8;80092:29;::::1;;;;;;29:2:-1;21:6;17:15;125:4;109:14;101:6;88:42;144:17;::::0;-1:-1;80092:29:0::1;-1:-1:-1::0;80077:44:0;;::::1;::::0;:12:::1;::::0;:44:::1;::::0;;::::1;::::0;::::1;:::i;:::-;;70729:3;80162:15;;80151:8;;:26;:42;80132:16;:61;;;;80238:16;;80225:30;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;125:4;109:14;101:6;88:42;144:17;::::0;-1:-1;80225:30:0::1;-1:-1:-1::0;80204:51:0;;::::1;::::0;:18:::1;::::0;:51:::1;::::0;;::::1;::::0;::::1;:::i;56240:177::-:0;56312:7;56339:70;56356:7;56339:70;;;;;;;;;;;;;;;;;:12;;:70;;:16;:70;:::i;81394:116::-;2359:12;:10;:12::i;:::-;-1:-1:-1;;;;;2348:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;2348:23:0;;2340:68;;;;;-1:-1:-1;;;2340:68:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;2340:68:0;;;;;;;;;;;;;;;81476:11:::1;:26:::0;;-1:-1:-1;;;;;;81476:26:0::1;-1:-1:-1::0;;;;;81476:26:0;;;::::1;::::0;;;::::1;::::0;;81394:116::o;57859:97::-;57940:8;57933:15;;;;;;;;-1:-1:-1;;57933:15:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;57907:13;;57933:15;;57940:8;;57933:15;;57940:8;57933:15;;;;;;;;;;;;;;;;;;;;;;;;55957:221;56029:7;-1:-1:-1;;;;;56057:19:0;;56049:74;;;;-1:-1:-1;;;56049:74:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;56141:20:0;;;;;;:13;:20;;;;;:29;;:27;:29::i;81934:105::-;2359:12;:10;:12::i;:::-;-1:-1:-1;;;;;2348:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;2348:23:0;;2340:68;;;;;-1:-1:-1;;;2340:68:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;2340:68:0;;;;;;;;;;;;;;;82006:15:::1;:25:::0;;;::::1;;;;-1:-1:-1::0;;82006:25:0;;::::1;::::0;;;::::1;::::0;;81934:105::o;2779:148::-;2359:12;:10;:12::i;:::-;-1:-1:-1;;;;;2348:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;2348:23:0;;2340:68;;;;;-1:-1:-1;;;2340:68:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;2340:68:0;;;;;;;;;;;;;;;2886:1:::1;2870:6:::0;;2849:40:::1;::::0;-1:-1:-1;;;;;2870:6:0;;::::1;::::0;2849:40:::1;::::0;2886:1;;2849:40:::1;2917:1;2900:19:::0;;-1:-1:-1;;;;;;2900:19:0::1;::::0;;2779:148::o;71453:20::-;;;;;;;;;;;;;;;-1:-1:-1;;71453:20:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;80347:254::-;2359:12;:10;:12::i;:::-;-1:-1:-1;;;;;2348:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;2348:23:0;;2340:68;;;;;-1:-1:-1;;;2340:68:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;2340:68:0;;;;;;;;;;;;;;;80402:8:::1;::::0;70729:3:::1;::::0;80402:16:::1;::::0;80415:2:::1;80402:16;:12;:16;:::i;:::-;:33;;80394:66;;;::::0;;-1:-1:-1;;;80394:66:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;80394:66:0;;;;;;;;;;;;;::::1;;80476:6;80471:123;80492:2;80488:1;:6;80471:123;;;80527:8;::::0;:15:::1;::::0;80540:1:::1;80527:15;:12;:15;:::i;:::-;80516:8;:26:::0;;;80557:25:::1;::::0;80577:4:::1;80557:9;:25::i;:::-;80496:3;;80471:123;;;;80347:254::o:0;82286:156::-;2359:12;:10;:12::i;:::-;-1:-1:-1;;;;;2348:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;2348:23:0;;2340:68;;;;;-1:-1:-1;;;2340:68:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;2340:68:0;;;;;;;;;;;;;;;82391:16:::1;:6;82400:7:::0;;82391:16:::1;:::i;:::-;-1:-1:-1::0;82418:16:0::1;:6;82427:7:::0;;82418:16:::1;:::i;2128:87::-:0;2174:7;2201:6;-1:-1:-1;;;;;2201:6:0;2128:87;:::o;75344:3375::-;5081:1;5687:7;;:19;;5679:63;;;;;-1:-1:-1;;;5679:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;5081:1;5820:7;:18;72441:15:::1;::::0;::::1;::::0;::::1;;;72440:16;72432:47;;;::::0;;-1:-1:-1;;;72432:47:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;72432:47:0;;;;;;;;;;;;;::::1;;75499:12:::2;:10;:12::i;:::-;-1:-1:-1::0;;;;;75480:31:0::2;:15;75488:6;75480:7;:15::i;:::-;-1:-1:-1::0;;;;;75480:31:0::2;;75472:63;;;::::0;;-1:-1:-1;;;75472:63:0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;75472:63:0;;;;;;;;;;;;;::::2;;75573:12;:10;:12::i;:::-;-1:-1:-1::0;;;;;75554:31:0::2;:15;75562:6;75554:7;:15::i;:::-;-1:-1:-1::0;;;;;75554:31:0::2;;75546:63;;;::::0;;-1:-1:-1;;;75546:63:0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;75546:63:0;;;;;;;;;;;;;::::2;;75622:16;75641:12:::0;;;:4:::2;:12;::::0;;;;;;;75682:20;;::::2;::::0;::::2;::::0;;;;::::2;::::0;::::2;::::0;;::::2;::::0;;::::2;::::0;::::2;::::0;;::::2;::::0;;;;;;::::2;::::0;::::2;::::0;;;;;;;-1:-1:-1;;;75682:20:0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;75682:20:0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;75682:20:0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;75682:20:0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;75682:20:0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;75682:20:0;::::2;::::0;::::2;;::::0;;;-1:-1:-1;;;75682:20:0;;::::2;::::0;;::::2;::::0;;;;75641:12;;75622:16;75682:20:::2;::::0;:14:::2;:20::i;:::-;75713:16;75732:12:::0;;;:4:::2;:12;::::0;;;;;;;75773:20;;::::2;::::0;::::2;::::0;;;;::::2;::::0;::::2;::::0;;::::2;::::0;;::::2;::::0;::::2;::::0;;::::2;::::0;;;;;;::::2;::::0;::::2;::::0;;;;;;;-1:-1:-1;;;75773:20:0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;75773:20:0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;75773:20:0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;75773:20:0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;75773:20:0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;75773:20:0;::::2;::::0;::::2;;::::0;;;-1:-1:-1;;;75773:20:0;;::::2;::::0;;::::2;::::0;;;;75664:38;;-1:-1:-1;75732:12:0;75773:20:::2;::::0;:14:::2;:20::i;:::-;75868:7:::0;;75755:38;;-1:-1:-1;75836:6:0::2;75825:17:::0;;::::2;::::0;75868:7:::2;:13:::0;::::2;::::0;:30:::2;;-1:-1:-1::0;75885:7:0;;:13:::2;::::0;;::::2;:7:::0;::::2;:13;75868:30;75860:53;;;::::0;;-1:-1:-1;;;75860:53:0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;75860:53:0;;;;;;;;;;;;;::::2;;75926:17;;:::i;:::-;-1:-1:-1::0;75946:8:0::2;::::0;;::::2;;::::0;;;:4:::2;:8;::::0;;;;;;;;75926:28;;::::2;::::0;::::2;::::0;;;;;;::::2;::::0;;::::2;::::0;;::::2;::::0;::::2;::::0;;::::2;::::0;;;;;;::::2;::::0;::::2;::::0;;;;;;;-1:-1:-1;;;75926:28:0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;75926:28:0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;75926:28:0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;75926:28:0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;75926:28:0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;75926:28:0;::::2;::::0;::::2;;::::0;;;-1:-1:-1;;;75926:28:0;;::::2;::::0;;::::2;::::0;;;;75965:23:::2;;:::i;:::-;76016:25;76028:8;76038:2;76016:11;:25::i;:::-;76001:40;::::0;;::::2;:12;::::0;::::2;:40:::0;;;76068:10;;;;::::2;::::0;;::::2;:26;::::0;:56:::2;;-1:-1:-1::0;76112:12:0::2;::::0;::::2;::::0;76098:10;;;;::::2;:26;:10:::0;;::::2;:26:::0;::::2;;76068:56;76060:82;;;::::0;;-1:-1:-1;;;76060:82:0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;76060:82:0;;;;;;;;;;;;;::::2;;76188:12;::::0;::::2;::::0;76174:10;;;;::::2;:26;:10:::0;;::::2;:26:::0;::::2;;:52;;76216:10:::0;;;;::::2;;;76174:52;;;76203:10:::0;;;;::::2;;;76174:52;76153:73;;:18;::::0;::::2;:73:::0;76259:25:::2;76271:8:::0;76281:2:::2;76259:11;:25::i;:::-;76239:45;::::0;;::::2;:17;::::0;::::2;:45:::0;;;76316:15;;;;::::2;::::0;;::::2;:36;::::0;:76:::2;;-1:-1:-1::0;76375:17:0::2;::::0;::::2;::::0;76356:15;;;;::::2;:36;:15:::0;;::::2;:36:::0;::::2;;76316:76;76308:107;;;::::0;;-1:-1:-1;;;76308:107:0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;76308:107:0;;;;;;;;;;;;;::::2;;76471:17;::::0;::::2;::::0;76452:15;;;;::::2;:36;:15:::0;;::::2;:36:::0;::::2;;:72;;76509:15:::0;;;;::::2;;;76452:72;;;76491:15:::0;;;;::::2;;;76452:72;76426:98;;:23;::::0;::::2;:98:::0;76551:25:::2;76563:8:::0;76573:2:::2;76551:11;:25::i;:::-;76537:39;::::0;;::::2;:11;::::0;::::2;:39:::0;;;76603:9;;-1:-1:-1;;;76603:9:0;::::2;::::0;;::::2;:24;::::0;:52:::2;;-1:-1:-1::0;76644:11:0::2;::::0;::::2;::::0;76631:9;;-1:-1:-1;;;76631:9:0;::::2;:24;:9:::0;;::::2;:24:::0;::::2;;76603:52;76595:77;;;::::0;;-1:-1:-1;;;76595:77:0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;76595:77:0;;;;;;;;;;;;;::::2;;76716:11;::::0;::::2;::::0;76703:9;;-1:-1:-1;;;76703:9:0;::::2;:24;:9:::0;;::::2;:24:::0;::::2;;:48;;76742:9:::0;;-1:-1:-1;;;76742:9:0;::::2;;;76703:48;;;76730:9:::0;;-1:-1:-1;;;76730:9:0;::::2;;;76703:48;76683:68;;:17;::::0;::::2;:68:::0;76779:25:::2;76791:8:::0;76801:2:::2;76779:11;:25::i;:::-;76764:40;::::0;;::::2;:12;::::0;::::2;:40:::0;;;76832:10;;-1:-1:-1;;;76832:10:0;::::2;::::0;;::::2;:26;::::0;:56:::2;;-1:-1:-1::0;76876:12:0::2;::::0;::::2;::::0;76862:10;;-1:-1:-1;;;76862:10:0;::::2;:26;:10:::0;;::::2;:26:::0;::::2;;76832:56;76824:82;;;::::0;;-1:-1:-1;;;76824:82:0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;76824:82:0;;;;;;;;;;;;;::::2;;76952:12;::::0;::::2;::::0;76938:10;;-1:-1:-1;;;76938:10:0;::::2;:26;:10:::0;;::::2;:26:::0;::::2;;:52;;76980:10:::0;;-1:-1:-1;;;76980:10:0;::::2;;;76938:52;;;76967:10:::0;;-1:-1:-1;;;76967:10:0;::::2;;;76938:52;76917:73;;:18;::::0;::::2;:73:::0;77017:25:::2;77029:8:::0;77039:2:::2;77017:11;:25::i;:::-;77003:39;::::0;;::::2;:11;::::0;::::2;:39:::0;;;77069:9;;-1:-1:-1;;;77069:9:0;::::2;::::0;;::::2;:24;::::0;:52:::2;;-1:-1:-1::0;77110:11:0::2;::::0;::::2;::::0;77097:9;;-1:-1:-1;;;77097:9:0;::::2;:24;:9:::0;;::::2;:24:::0;::::2;;77069:52;77061:77;;;::::0;;-1:-1:-1;;;77061:77:0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;77061:77:0;;;;;;;;;;;;;::::2;;77182:11;::::0;::::2;::::0;77169:9;;-1:-1:-1;;;77169:9:0;::::2;:24;:9:::0;;::::2;:24:::0;::::2;;:48;;77208:9:::0;;-1:-1:-1;;;77208:9:0;::::2;;;77169:48;;;77196:9:::0;;-1:-1:-1;;;77196:9:0;::::2;;;77169:48;77149:68;;:17;::::0;::::2;:68:::0;77245:25:::2;77257:8:::0;77267:2:::2;77245:11;:25::i;:::-;77230:40;::::0;;::::2;:12;::::0;::::2;:40:::0;;;77298:10;;-1:-1:-1;;;77298:10:0;::::2;::::0;;::::2;:26;::::0;:56:::2;;-1:-1:-1::0;77342:12:0::2;::::0;::::2;::::0;77328:10;;-1:-1:-1;;;77328:10:0;::::2;:26;:10:::0;;::::2;:26:::0;::::2;;77298:56;77290:82;;;::::0;;-1:-1:-1;;;77290:82:0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;77290:82:0;;;;;;;;;;;;;::::2;;77418:12;::::0;::::2;::::0;77404:10;;-1:-1:-1;;;77404:10:0;::::2;:26;:10:::0;;::::2;:26:::0;::::2;;:52;;77446:10:::0;;-1:-1:-1;;;77446:10:0;::::2;;;77404:52;;;77433:10:::0;;-1:-1:-1;;;77433:10:0;::::2;;;77404:52;77383:73;;:18;::::0;::::2;:73:::0;77483:25:::2;77495:8:::0;77505:2:::2;77483:11;:25::i;:::-;77469:39;::::0;;::::2;:11;::::0;::::2;:39:::0;;;77535:9;;-1:-1:-1;;;77535:9:0;::::2;::::0;;::::2;:24;::::0;:52:::2;;-1:-1:-1::0;77576:11:0::2;::::0;::::2;::::0;77563:9;;-1:-1:-1;;;77563:9:0;::::2;:24;:9:::0;;::::2;:24:::0;::::2;;77535:52;77527:77;;;::::0;;-1:-1:-1;;;77527:77:0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;77527:77:0;;;;;;;;;;;;;::::2;;77648:11;::::0;::::2;::::0;77635:9;;-1:-1:-1;;;77635:9:0;::::2;:24;:9:::0;;::::2;:24:::0;::::2;;:48;;77674:9:::0;;-1:-1:-1;;;77674:9:0;::::2;;;77635:48;;;77662:9:::0;;-1:-1:-1;;;77662:9:0;::::2;;;77635:48;77615:68;;:17;::::0;::::2;:68:::0;77710:25:::2;77722:8:::0;77732:2:::2;77710:11;:25::i;:::-;77696:39;::::0;;::::2;:11;::::0;::::2;:39:::0;;;77762:9;;-1:-1:-1;;;77762:9:0;::::2;::::0;;::::2;:24;::::0;:52:::2;;-1:-1:-1::0;77803:11:0::2;::::0;::::2;::::0;77790:9;;-1:-1:-1;;;77790:9:0;::::2;:24;:9:::0;;::::2;:24:::0;::::2;;77762:52;77754:77;;;::::0;;-1:-1:-1;;;77754:77:0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;77754:77:0;;;;;;;;;;;;;::::2;;77875:11;::::0;::::2;::::0;77862:9;;-1:-1:-1;;;77862:9:0;::::2;:24;:9:::0;;::::2;:24:::0;::::2;;:48;;77901:9:::0;;-1:-1:-1;;;77901:9:0;::::2;;;77862:48;;;77889:9:::0;;-1:-1:-1;;;77889:9:0;::::2;;;77862:48;77842:68;;:17;::::0;::::2;:68:::0;77923:14:::2;77940:22;77955:6:::0;77940:14:::2;:22::i;:::-;77981:17;::::0;;;:9:::2;:17;::::0;;;;;77923:39;;-1:-1:-1;77981:22:0;77973:72:::2;;;;-1:-1:-1::0;;;77973:72:0::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;78076:9:::0;;::::2;78056:17:::0;;;:9:::2;:17;::::0;;;;:29:::2;::::0;;::::2;::::0;;78126:10;;78113;;78126::::2;-1:-1:-1::0;;;78126:10:0;;;::::2;::::0;::::2;78113::::0;;;::::2;;:23;:57;;78156:10:::0;;-1:-1:-1;;;78156:10:0;::::2;;;78169:1;78156:14;78113:57;;;78139:10:::0;;-1:-1:-1;;;78139:10:0;::::2;;;78152:1;78139:14;78113:57;78098:72;;:12;::::0;::::2;:72:::0;78215:9;;78291:10;;78354;;78188:195:::2;::::0;;78272:7:::2;78188:195:::0;;::::2;::::0;;::::2;::::0;::::2;::::0;;;78272:7;;::::2;78262:17:::0;::::2;-1:-1:-1::0;;;;;;78291:10:0;;;::::2;78306:2;78283:25:::0;;;;;78262:47;;;::::2;78188:195:::0;;;;78335:7;;::::2;78325:17:::0;::::2;78354:10:::0;;;::::2;78346:25:::0;;;;;;78325:47;;;::::2;78188:195:::0;;;;;;::::2;::::0;;;;;;;::::2;78425:7:::0;;78412:9;;78399:84:::2;::::0;78425:7:::2;78412:20:::0;;::::2;78425:7:::0;::::2;78412:20;:40;;78445:7:::0;;::::2;;78412:40;;;78435:7:::0;;::::2;;78412:40;78454:28;78469:12;78454:14;:28::i;:::-;78399:84;::::0;;::::2;::::0;;::::2;::::0;;::::2;::::0;::::2;::::0;;;;;;;;;;;;::::2;78507:6;78496:4;:8;78501:2;78496:8;;;;;;;;;;;;;:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;78543:4;:7;;;;;;;;;;;;78530:20;;:6;:9;;;:20;;;78526:114;;;78573:7:::0;;78567:14:::2;::::0;78573:7:::2;;78567:5;:14::i;:::-;78526:114;;;78620:7:::0;;78614:14:::2;::::0;78620:7:::2;;78614:5;:14::i;:::-;-1:-1:-1::0;;;78657:18:0::2;::::0;;;-1:-1:-1;78657:9:0::2;:18;::::0;;;;;78650:25;;;78693:18;;;;;78686:25;;;;-1:-1:-1;;5037:1:0;5999:22;;-1:-1:-1;;;75344:3375:0:o;56653:104::-;56742:7;56735:14;;;;;;;;-1:-1:-1;;56735:14:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56709:13;;56735:14;;56742:7;;56735:14;;56742:7;56735:14;;;;;;;;;;;;;;;;;;;;;;;;59563:295;59678:12;:10;:12::i;:::-;-1:-1:-1;;;;;59666:24:0;:8;-1:-1:-1;;;;;59666:24:0;;;59658:62;;;;;-1:-1:-1;;;59658:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;59778:8;59733:18;:32;59752:12;:10;:12::i;:::-;-1:-1:-1;;;;;59733:32:0;;;;;;;;;;;;;;;;;-1:-1:-1;59733:32:0;;;:42;;;;;;;;;;;;:53;;-1:-1:-1;;59733:53:0;;;;;;;;;;;59817:12;:10;:12::i;:::-;59802:48;;;;;;;;;;-1:-1:-1;;;;;59802:48:0;;;;;;;;;;;;;;59563:295;;:::o;71070:35::-;;;;:::o;70779:36::-;;;;:::o;70861:29::-;;;;:::o;71407:37::-;;;-1:-1:-1;;;;;71407:37:0;;:::o;60758:285::-;60890:41;60909:12;:10;:12::i;:::-;60923:7;60890:18;:41::i;:::-;60882:103;;;;-1:-1:-1;;;60882:103:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;60996:39;61010:4;61016:2;61020:7;61029:5;60996:13;:39::i;:::-;60758:285;;;;:::o;71156:23::-;;;;:::o;79384:342::-;79457:13;79491:16;79499:7;79491;:16::i;:::-;79483:76;;;;-1:-1:-1;;;79483:76:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;79682:6;79690:18;:7;:16;:18::i;:::-;79710:6;79665:52;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;79665:52:0;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;79665:52:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;79665:52:0;;;-1:-1:-1;;26:21;;;22:32;6:49;;79665:52:0;;;;79384:342;-1:-1:-1;;;;;;79384:342:0:o;70689:43::-;70729:3;70689:43;:::o;70939:31::-;;;;:::o;59929:164::-;-1:-1:-1;;;;;60050:25:0;;;60026:4;60050:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;59929:164::o;81015:234::-;2359:12;:10;:12::i;:::-;-1:-1:-1;;;;;2348:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;2348:23:0;;2340:68;;;;;-1:-1:-1;;;2340:68:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;2340:68:0;;;;;;;;;;;;;;;81081:14:::1;::::0;81141:21:::1;::::0;81121:15:::1;::::0;-1:-1:-1;;;;;81081:14:0;;::::1;::::0;81073:118:::1;::::0;81120:60:::1;::::0;81169:10:::1;::::0;81121:42:::1;::::0;:15;:42:::1;:19;:42;:::i;81120:60::-;81073:118;::::0;;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;::::1;;;;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;-1:-1:::0;81226:15:0::1;::::0;81202:21:::1;:39:::0;81015:234::o;70977:32::-;;;;:::o;3082:244::-;2359:12;:10;:12::i;:::-;-1:-1:-1;;;;;2348:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;2348:23:0;;2340:68;;;;;-1:-1:-1;;;2340:68:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;2340:68:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;3171:22:0;::::1;3163:73;;;;-1:-1:-1::0;;;3163:73:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3273:6;::::0;;3252:38:::1;::::0;-1:-1:-1;;;;;3252:38:0;;::::1;::::0;3273:6;::::1;::::0;3252:38:::1;::::0;::::1;3301:6;:17:::0;;-1:-1:-1;;;;;;3301:17:0::1;-1:-1:-1::0;;;;;3301:17:0;;;::::1;::::0;;;::::1;::::0;;3082:244::o;73981:1133::-;5081:1;5687:7;;:19;;5679:63;;;;;-1:-1:-1;;;5679:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;5081:1;5820:7;:18;72558:11:::1;::::0;::::1;;72557:12;72549:43;;;::::0;;-1:-1:-1;;;72549:43:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;72549:43:0;;;;;;;;;;;;;::::1;;74123:1:::2;74112:8;:12;74104:43;;;::::0;;-1:-1:-1;;;74104:43:0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;74104:43:0;;;;;;;;;;;;;::::2;;74178:12;:26;74191:12;:10;:12::i;:::-;-1:-1:-1::0;;;;;74178:26:0::2;-1:-1:-1::0;;;;;74178:26:0::2;;;;;;;;;;;;;74166:8;:38;;74158:86;;;;-1:-1:-1::0;;;74158:86:0::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;74275:2;74263:8;:14;;74255:64;;;;-1:-1:-1::0;;;74255:64:0::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;74485:8;;74352:116;74459:8;74352:88;70729:3;74352:55;74391:15;;74352:20;;:38;;:55;;;;:::i;:::-;:73:::0;:88:::2;:73;:88;:::i;:116::-;:141;;74330:220;;;::::0;;-1:-1:-1;;;74330:220:0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;::::2;::::0;;;;;;;;;;;;;::::2;;74582:60;74605:36;74620:8;74630:10;74605:14;:36::i;:::-;74582:18;74591:8;74582;:18::i;:60::-;74569:9;:73;74561:110;;;::::0;;-1:-1:-1;;;74561:110:0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;::::2;::::0;;;;;;;;;;;;;::::2;;74711:40;74742:8;74711:12;:26;74724:12;:10;:12::i;:::-;-1:-1:-1::0;;;;;74711:26:0::2;::::0;;::::2;::::0;::::2;::::0;;;;;;-1:-1:-1;74711:26:0;;;:40:::2;:30;:40;:::i;:::-;74682:12;:26;74695:12;:10;:12::i;:::-;-1:-1:-1::0;;;;;74682:26:0::2;::::0;;::::2;::::0;::::2;::::0;;;;;;-1:-1:-1;74682:26:0;;;:69;;;;-1:-1:-1;74799:206:0::2;74820:8;74816:1;:12;74799:206;;;74861:21;:19;:21::i;:::-;74850:32;;74897:31;74907:8;74917:10;74897:9;:31::i;:::-;74966:20;::::0;:27:::2;::::0;74991:1:::2;74966:27;:24;:27;:::i;:::-;74943:20;:50:::0;74830:3:::2;;74799:206;;;;75021:10;75017:90;;;75066:15;::::0;:29:::2;::::0;75086:8;75066:29:::2;:19;:29;:::i;:::-;75048:15;:47:::0;75017:90:::2;-1:-1:-1::0;;5037:1:0;5999:22;;-1:-1:-1;73981:1133:0:o;71480:20::-;;;;;;;;;-1:-1:-1;;71480:20:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;70824:30;;;;:::o;71016:47::-;;;;;;;;;;;;;:::o;71235:44::-;;;;;;;;;;;;;:::o;62510:127::-;62575:4;62599:30;:12;62621:7;62599:30;:21;:30;:::i;667:106::-;755:10;667:106;:::o;68528:192::-;68603:24;;;;:15;:24;;;;;:29;;-1:-1:-1;;;;;;68603:29:0;-1:-1:-1;;;;;68603:29:0;;;;;;;;:24;;68657:23;68603:24;68657:14;:23::i;:::-;-1:-1:-1;;;;;68648:46:0;;;;;;;;;;;68528:192;;:::o;49253:123::-;49322:7;49349:19;49357:3;49349:7;:19::i;62804:355::-;62897:4;62922:16;62930:7;62922;:16::i;:::-;62914:73;;;;-1:-1:-1;;;62914:73:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62998:13;63014:23;63029:7;63014:14;:23::i;:::-;62998:39;;63067:5;-1:-1:-1;;;;;63056:16:0;:7;-1:-1:-1;;;;;63056:16:0;;:51;;;;63100:7;-1:-1:-1;;;;;63076:31:0;:20;63088:7;63076:11;:20::i;:::-;-1:-1:-1;;;;;63076:31:0;;63056:51;:94;;;;63111:39;63135:5;63142:7;63111:23;:39::i;:::-;63048:103;62804:355;-1:-1:-1;;;;62804:355:0:o;65940:599::-;66065:4;-1:-1:-1;;;;;66038:31:0;:23;66053:7;66038:14;:23::i;:::-;-1:-1:-1;;;;;66038:31:0;;66030:85;;;;-1:-1:-1;;;66030:85:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;66152:16:0;;66144:65;;;;-1:-1:-1;;;66144:65:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;66222:39;66243:4;66249:2;66253:7;66222:20;:39::i;:::-;66326:29;66343:1;66347:7;66326:8;:29::i;:::-;-1:-1:-1;;;;;66368:19:0;;;;;;:13;:19;;;;;:35;;66395:7;66368:35;:26;:35;:::i;:::-;-1:-1:-1;;;;;;66414:17:0;;;;;;:13;:17;;;;;:30;;66436:7;66414:30;:21;:30;:::i;:::-;-1:-1:-1;66457:29:0;:12;66474:7;66483:2;66457:29;:16;:29;:::i;:::-;;66523:7;66519:2;-1:-1:-1;;;;;66504:27:0;66513:4;-1:-1:-1;;;;;66504:27:0;;;;;;;;;;;65940:599;;;:::o;19663:220::-;19721:7;19745:6;19741:20;;-1:-1:-1;19760:1:0;19753:8;;19741:20;19784:5;;;19788:1;19784;:5;:1;19808:5;;;;;:10;19800:56;;;;-1:-1:-1;;;19800:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;41048:137;41119:7;41154:22;41158:3;41170:5;41154:3;:22::i;19246:158::-;19304:7;19337:1;19332;:6;;19324:49;;;;;-1:-1:-1;;;19324:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;19391:5:0;;;19246:158::o;87081:488::-;87182:14;;87164:15;;87232:9;;87124:7;;87164:32;;;;87124:7;;87164:32;;-1:-1:-1;;;;;87232:9:0;:18;87251:12;:10;:12::i;:::-;87265:14;;87281:9;87232:59;;;;;;;;;;;;;-1:-1:-1;;;;;87232:59:0;-1:-1:-1;;;;;87232:59:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;87232:59:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;87232:59:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;87232:59:0;87224:80;;;;;;87207:97;;87325:13;87341:12;87354:6;87341:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:25;:57;;87378:12;87391:6;87378:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;87341:57;;;87369:6;87341:57;87325:73;;87432:12;87457:1;87445:9;:13;87432:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:32;:86;;87491:12;87516:1;87504:9;:13;87491:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;87432:86;;;87486:1;87474:9;:13;87432:86;87409:12;87422:6;87409:20;;;;;;;;;;;;;;;;;;;;;;;;;;:109;;;;;;;;;;;;;;;;;;70729:3;87536:5;:21;87560:1;87536:25;87529:32;;;;;87081:488;:::o;83070:475::-;83138:13;83162:14;;:::i;:::-;83179:34;83191:2;83195:10;83207:5;83179:11;:34::i;:::-;83162:51;;83224:146;83231:9;:30;83241:19;83256:3;83241:14;:19::i;:::-;83231:30;;;;;;;;;;;;83265:1;83231:35;83224:146;;83291:12;:5;83301:1;83291:12;:9;:12;:::i;:::-;83283:20;;83324:34;83336:2;83340:10;83352:5;83324:11;:34::i;:::-;83318:40;;83224:146;;;83391:3;83380:4;:8;83385:2;83380:8;;;;;;;;;;;:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;83438:2;83405:9;:30;83415:19;83430:3;83415:14;:19::i;:::-;83405:30;;;;;;;;;;;-1:-1:-1;83405:30:0;:35;83451:27;83461:12;:10;:12::i;:::-;83475:2;83451:9;:27::i;:::-;83494:43;83507:2;83511:19;83526:3;83511:14;:19::i;:::-;83494:43;;;;;;;;;;;;;83532:1;83494:43;;;;;;;;;;;;;;;;;;;83070:475;;;;:::o;18784:179::-;18842:7;18874:5;;;18898:6;;;;18890:46;;;;;-1:-1:-1;;;18890:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;49715:236;49795:7;;;;49855:22;49859:3;49871:5;49855:3;:22::i;:::-;49824:53;;;;-1:-1:-1;49715:236:0;-1:-1:-1;;;;;49715:236:0:o;51001:213::-;51108:7;51159:44;51164:3;51184;51190:12;51159:4;:44::i;86319:448::-;86382:14;86441:2;86427:3;:9;;;86419:18;;:24;;86410:33;;86491:2;86472:3;:14;;;86464:23;;:29;;86454:39;;;;86535:2;86522:3;:8;;;86514:17;;:23;;86504:33;;;;86580:2;86566:3;:9;;;86558:18;;:24;;86548:34;;;;86624:2;86611:3;:8;;;86603:17;;:23;;86593:33;;;;86669:2;86655:3;:9;;;86647:18;;:24;;86637:34;;;;86713:2;86700:3;:8;;;86692:17;;:23;;86682:33;;;;86757:2;86744:3;:8;;;86736:17;;:23;;86726:33;;;;86319:448;;;:::o;86925:148::-;87040:4;:13;;87031:23;;;;87030:34;;;86925:148::o;65058:545::-;65118:13;65134:23;65149:7;65134:14;:23::i;:::-;65118:39;;65188:48;65209:5;65224:1;65228:7;65188:20;:48::i;:::-;65277:29;65294:1;65298:7;65277:8;:29::i;:::-;65365:19;;;;:10;:19;;;;;65359:33;;-1:-1:-1;;65359:33:0;;;;;;;;;;;:38;65355:97;;65421:19;;;;:10;:19;;;;;65414:26;;;:::i;:::-;-1:-1:-1;;;;;65464:20:0;;;;;;:13;:20;;;;;:36;;65492:7;65464:36;:27;:36;:::i;:::-;-1:-1:-1;65513:28:0;:12;65533:7;65513:28;:19;:28;:::i;:::-;-1:-1:-1;65559:36:0;;65587:7;;65583:1;;-1:-1:-1;;;;;65559:36:0;;;;;65583:1;;65559:36;65058:545;;:::o;61925:272::-;62039:28;62049:4;62055:2;62059:7;62039:9;:28::i;:::-;62086:48;62109:4;62115:2;62119:7;62128:5;62086:22;:48::i;:::-;62078:111;;;;-1:-1:-1;;;62078:111:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;51461:746;51517:13;51738:10;51734:53;;-1:-1:-1;51765:10:0;;;;;;;;;;;;-1:-1:-1;;;51765:10:0;;;;;;51734:53;51812:5;51797:12;51853:78;51860:9;;51853:78;;51886:8;;51917:2;51909:10;;;;51853:78;;;51941:19;51973:6;51963:17;;;;;;;;;;;;;;;;;;;;;;;;;21:6:-1;;108:14;51963:17:0;87:42:-1;143:17;;-1:-1;51963:17:0;-1:-1:-1;52035:5:0;;-1:-1:-1;51941:39:0;-1:-1:-1;;;52007:10:0;;52051:117;52058:9;;52051:117;;52127:2;52120:4;:9;52115:2;:14;52102:29;;52084:6;52091:7;;;;;;;52084:15;;;;;;;;;;;:47;-1:-1:-1;;;;;52084:47:0;;;;;;;;-1:-1:-1;52154:2:0;52146:10;;;;52051:117;;;-1:-1:-1;52192:6:0;51461:746;-1:-1:-1;;;;51461:746:0:o;87577:555::-;87685:20;;87666:16;;87741:9;;87626:7;;87666:39;;;;87626:7;;87666:39;;-1:-1:-1;;;;;87741:9:0;:18;87760:12;:10;:12::i;:::-;87774:20;;87796:9;87741:65;;;;;;;;;;;;;-1:-1:-1;;;;;87741:65:0;-1:-1:-1;;;;;87741:65:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;87741:65:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;87741:65:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;87741:65:0;87733:86;;;;;;87716:103;;87840:13;87856:18;87875:6;87856:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:31;:69;;87899:18;87918:6;87899:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;87856:69;;;87890:6;87856:69;87840:85;;87965:18;87996:1;87984:9;:13;87965:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:38;:98;;88030:18;88061:1;88049:9;:13;88030:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;87965:98;;;88025:1;88013:9;:13;87965:98;87936:18;87955:6;87936:26;;;;;;;;;;;;;;;;;;;;;;;;;;:127;;;;;;;;;;;;;;;;;;88105:15;;70729:3;88081:5;:21;:39;88123:1;88081:43;88074:50;;;;;87577:555;:::o;49014:151::-;49098:4;49122:35;49132:3;49152;49122:9;:35::i;45832:110::-;45915:19;;45832:110::o;40135:137::-;40205:4;40229:35;40237:3;40257:5;40229:7;:35::i;39828:131::-;39895:4;39919:32;39924:3;39944:5;39919:4;:32::i;48437:185::-;48526:4;48550:64;48555:3;48575;-1:-1:-1;;;;;48589:23:0;;48550:4;:64::i;36086:204::-;36181:18;;36153:7;;36181:26;-1:-1:-1;36173:73:0;;;;-1:-1:-1;;;36173:73:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;36264:3;:11;;36276:5;36264:18;;;;;;;;;;;;;;;;36257:25;;36086:204;;;;:::o;83787:1414::-;83875:10;;:::i;:::-;83995:9;;83980:12;;-1:-1:-1;;;;;83995:9:0;:18;84014:12;:10;:12::i;:::-;84028:2;84032:5;83995:43;;;;;;;;;;;;;-1:-1:-1;;;;;83995:43:0;-1:-1:-1;;;;;83995:43:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;83995:43:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;83995:43:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;83995:43:0;;-1:-1:-1;84059:14:0;;:::i;:::-;84084:19;;;;;84126:1;84114:9;;;:13;84168:1;84156:8;;;84150:19;84138:31;;:9;;;:31;84197:118;84223:29;84235:4;84240:1;84235:7;;;84244:4;84249:1;84244:7;;;;84223:11;:29::i;:::-;84254:10;84266:1;84269;84272;84275;84278;84197:11;:118::i;:::-;84180:135;;:14;;;:135;84337:118;84363:29;84375:4;84380:1;84375:7;;;84384:4;84389:1;84384:7;;84363:29;84394:10;84406:1;84409;84412;84415;84418;84337:11;:118::i;:::-;84326:129;;:8;;;:129;84478:121;84504:29;84516:4;84521:1;84516:7;;;84525:4;84530:1;84525:7;;84504:29;84535:10;84547:1;84550;84553:2;84557;84561;84478:11;:121::i;:::-;84466:133;;:9;;;:133;84621:119;84647:29;84659:4;84664:1;84659:7;;;84668:4;84673:1;84668:7;;84647:29;84678:10;84690:1;84693;84696;84699;84702:2;84621:11;:119::i;:::-;84610:130;;:8;;;:130;84763:120;84789:29;84801:4;84806:1;84801:7;;;84810:4;84815:1;84810:7;;84789:29;84820:10;84832:1;84835;84838:2;84842;84846:1;84763:11;:120::i;:::-;84751:132;;:9;;;:132;84905:121;84931:31;84943:4;84948:2;84943:8;;;84953:4;84958:2;84953:8;;84931:31;84964:10;84976:1;84979;84982:2;84986:1;84989;84905:11;:121::i;:::-;84894:132;;:8;;;:132;85048:122;85074:31;85086:4;85091:2;85086:8;;;85096:4;85101:2;85096:8;;85074:31;85107:10;85119:1;85122;85125:2;85129:1;85132:2;85048:11;:122::i;:::-;85037:133;;:8;;;:133;:8;83787:1414;-1:-1:-1;;;;;83787:1414:0:o;63502:110::-;63578:26;63588:2;63592:7;63578:26;;;;;;;;;;;;:9;:26::i;46297:279::-;46401:19;;46364:7;;;;46401:27;-1:-1:-1;46393:74:0;;;;-1:-1:-1;;;46393:74:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;46480:22;46505:3;:12;;46518:5;46505:19;;;;;;;;;;;;;;;;;;46480:44;;46543:5;:10;;;46555:5;:12;;;46535:33;;;;;46297:279;;;;;:::o;47794:319::-;47888:7;47927:17;;;:12;;;:17;;;;;;47978:12;47963:13;47955:36;;;;-1:-1:-1;;;47955:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;47955:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;48045:3;:12;;48069:1;48058:8;:12;48045:26;;;;;;;;;;;;;;;;;;:33;;;48038:40;;;47794:319;;;;;:::o;48788:142::-;48865:4;48889:33;48897:3;48917;48889:7;:33::i;67805:604::-;67926:4;67953:15;:2;-1:-1:-1;;;;;67953:13:0;;:15::i;:::-;67948:60;;-1:-1:-1;67992:4:0;67985:11;;67948:60;68018:23;68044:252;-1:-1:-1;;;68157:12:0;:10;:12::i;:::-;68184:4;68203:7;68225:5;68060:181;;;;;;-1:-1:-1;;;;;68060:181:0;-1:-1:-1;;;;;68060:181:0;;;;;;-1:-1:-1;;;;;68060:181:0;-1:-1:-1;;;;;68060:181:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;68060:181:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;68060:181:0;;;;-1:-1:-1;;;;;68060:181:0;;38:4:-1;29:7;25:18;67:10;61:17;-1:-1;;;;;199:8;192:4;186;182:15;179:29;167:10;160:49;0:215;;;68060:181:0;68044:252;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;68044:15:0;;;:252;;:15;:252;:::i;:::-;68018:278;;68307:13;68334:10;68323:32;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;68323:32:0;-1:-1:-1;;;;;;68374:26:0;-1:-1:-1;;;68374:26:0;;-1:-1:-1;;;67805:604:0;;;;;;:::o;45612:125::-;45683:4;45707:17;;;:12;;;;;:17;;;;;;:22;;;45612:125::o;33788:1544::-;33854:4;33993:19;;;:12;;;:19;;;;;;34029:15;;34025:1300;;34464:18;;-1:-1:-1;;34415:14:0;;;;34464:22;;;;34391:21;;34464:3;;:22;;34751;;;;;;;;;;;;;;34731:42;;34897:9;34868:3;:11;;34880:13;34868:26;;;;;;;;;;;;;;;;;;;:38;;;;34974:23;;;35016:1;34974:12;;;:23;;;;;;35000:17;;;34974:43;;35126:17;;34974:3;;35126:17;;;;;;;;;;;;;;;;;;;;;;35221:3;:12;;:19;35234:5;35221:19;;;;;;;;;;;35214:26;;;35264:4;35257:11;;;;;;;;34025:1300;35308:5;35301:12;;;;;33198:414;33261:4;33283:21;33293:3;33298:5;33283:9;:21::i;:::-;33278:327;;-1:-1:-1;27:10;;39:1;23:18;;;45:23;;33321:11:0;:23;;;;;;;;;;;;;33504:18;;33482:19;;;:12;;;:19;;;;;;:40;;;;33537:11;;33278:327;-1:-1:-1;33588:5:0;33581:12;;43112:692;43188:4;43323:17;;;:12;;;:17;;;;;;43357:13;43353:444;;-1:-1:-1;;43442:38:0;;;;;;;;;;;;;;;;;;27:10:-1;;39:1;23:18;;;45:23;;43424:12:0;:57;;;;;;;;;;;;;;;;;;;;;;;;43639:19;;43619:17;;;:12;;;:17;;;;;;;:39;43673:11;;43353:444;43753:5;43717:3;:12;;43741:1;43730:8;:12;43717:26;;;;;;;;;;;;;;;;;;:33;;:41;;;;43780:5;43773:12;;;;;86775:142;86899:9;;86867:22;;;;;;;:42;;86775:142::o;85209:938::-;85437:5;;85511:3;85471:37;85490:17;;;85471:37;;;:43;85455:59;;85536:5;85529:4;:12;;;85525:53;;;85565:1;85558:8;;;;;85525:53;85588:12;85604:10;85603:11;:39;;85639:3;85631:5;:11;85603:39;;;85625:3;85617:5;:11;85603:39;85588:54;;85687:4;85680;:11;;;85676:53;;;85713:11;85706:18;;:4;:18;;;;;;;;85728:1;85700:29;85693:36;;;;;;85676:53;85751:10;85750:11;:37;;85785:2;85777:5;:10;85750:37;;;85772:2;85764:5;:10;85750:37;85742:45;85820:11;;;;-1:-1:-1;85816:62:0;;;85867:6;85860:13;;:4;:13;;;;;;;;85840:11;:34;85877:1;85840:38;85833:45;;;;;;85816:62;85900:10;85899:11;:40;;85937:2;85933:1;85925:9;;:14;85899:40;;;85921:1;85913:5;:9;85899:40;85891:48;85974:11;;;;-1:-1:-1;85970:70:0;;;86030:5;86023:12;;:4;:12;;;;;;;;86008:6;85994:11;:20;:42;86039:1;85994:46;85987:53;;;;;;85970:70;86104:7;86097:14;;:4;:14;;;;;;;;86083:5;86074:6;86060:11;:20;:28;:52;86115:1;86060:56;86053:63;;;;85209:938;;;;;;;;;;:::o;63839:250::-;63935:18;63941:2;63945:7;63935:5;:18::i;:::-;63972:54;64003:1;64007:2;64011:7;64020:5;63972:22;:54::i;:::-;63964:117;;;;-1:-1:-1;;;63964:117:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;43979:1549;44043:4;44178:17;;;:12;;;:17;;;;;;44212:13;;44208:1313;;44644:19;;-1:-1:-1;;44597:12:0;;;;44644:23;;;;44573:21;;44644:3;;:23;;44941;;;;;;;;;;;;;;;;44912:52;;45089:9;45059:3;:12;;45072:13;45059:27;;;;;;;;;;;;;;;;:39;;:27;;;;;:39;;;;;;;;;;;;;;;45179:14;;45166:28;;:12;;;:28;;;;;45197:17;;;45166:48;;45323:18;;45166:3;;45323:18;;;;;;;;;;;;;;-1:-1:-1;;45323:18:0;;;;;;;;;;;;;;;;;;;;;45419:17;;;:12;;;:17;;;;;;45412:24;;;;45323:18;-1:-1:-1;45453:11:0;;-1:-1:-1;;;;45453:11:0;24221:422;24588:20;24627:8;;;24221:422::o;27139:195::-;27242:12;27274:52;27296:6;27304:4;27310:1;27313:12;27274:21;:52::i;64425:404::-;-1:-1:-1;;;;;64505:16:0;;64497:61;;;;;-1:-1:-1;;;64497:61:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;64578:16;64586:7;64578;:16::i;:::-;64577:17;64569:58;;;;;-1:-1:-1;;;64569:58:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;64640:45;64669:1;64673:2;64677:7;64640:20;:45::i;:::-;-1:-1:-1;;;;;64698:17:0;;;;;;:13;:17;;;;;:30;;64720:7;64698:30;:21;:30;:::i;:::-;-1:-1:-1;64741:29:0;:12;64758:7;64767:2;64741:29;:16;:29;:::i;:::-;-1:-1:-1;64788:33:0;;64813:7;;-1:-1:-1;;;;;64788:33:0;;;64805:1;;64788:33;;64805:1;;64788:33;64425:404;;:::o;28191:530::-;28318:12;28376:5;28351:21;:30;;28343:81;;;;-1:-1:-1;;;28343:81:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;28443:18;28454:6;28443:10;:18::i;:::-;28435:60;;;;;-1:-1:-1;;;28435:60:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;28569:12;28583:23;28610:6;-1:-1:-1;;;;;28610:11:0;28630:5;28638:4;28610:33;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;28610:33:0;;;;;;;;;;;;;;;;;;;;;;;;;12:1:-1;19;14:27;;;;67:4;61:11;56:16;;134:4;130:9;123:4;105:16;101:27;97:43;94:1;90:51;84:4;77:65;157:16;154:1;147:27;211:16;208:1;201:4;198:1;194:12;179:49;5:228;;14:27;32:4;27:9;;5:228;;28568:75:0;;;;28661:52;28679:7;28688:10;28700:12;30846;30875:7;30871:595;;;-1:-1:-1;30906:10:0;30899:17;;30871:595;31020:17;;:21;31016:439;;31283:10;31277:17;31344:15;31331:10;31327:2;31323:19;31316:44;31231:148;31419:20;;-1:-1:-1;;;31419:20:0;;;;;;;;;;;;;;;;;31426:12;;31419:20;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;70208:17927:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;70208:17927:0;;;-1:-1:-1;70208:17927:0;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;70208:17927:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;70208:17927:0;;;-1:-1:-1;70208:17927:0;:::i;:::-;;;;;;;;;-1:-1:-1;70208:17927:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;-1:-1:-1;;70208:17927:0;;;;;;;;;;;;;;;;;;;;;;;;

Swarm Source

ipfs://33f002e6ffb9d246416ef247601ad7f4505c7533882a94f9e8753846d94a7fd4
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.