- Contract name:
- YayoNFT
- Optimization enabled
- false
- Compiler version
- v0.8.16+commit.07a7930e
- EVM Version
- default
- Verified at
- 2023-02-19T05:17:50.252325Z
Contract source code
// File: external/openzeppelin/utils/Context.sol // MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^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 meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } } // File: external/openzeppelin/access/Ownable.sol // MIT // OpenZeppelin Contracts v4.4.1 (access/Ownable.sol) pragma solidity ^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() { _transferOwnership(_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 { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } } // File: external/openzeppelin/utils/Strings.sol // MIT // OpenZeppelin Contracts v4.4.1 (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; /** * @dev Converts a `uint256` to its ASCII `string` decimal 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); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } } // File: external/openzeppelin/utils/introspection/IERC165.sol // MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^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: external/openzeppelin/token/ERC721/IERC721.sol // MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol) pragma solidity ^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: external/openzeppelin/token/ERC721/IERC721Receiver.sol // MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721Receiver.sol) pragma solidity ^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: external/openzeppelin/token/ERC721/extensions/IERC721Metadata.sol // MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol) pragma solidity ^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: external/openzeppelin/utils/Address.sol // MIT // OpenZeppelin Contracts v4.4.1 (utils/Address.sol) pragma solidity ^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 * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 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"); (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"); (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"); (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"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal 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 assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } } // File: external/openzeppelin/utils/introspection/ERC165.sol // MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } } // File: external/openzeppelin/token/ERC721/ERC721.sol // MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/ERC721.sol) pragma solidity ^0.8.0; /** * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including * the Metadata extension, but not including the Enumerable extension, which is available separately as * {ERC721Enumerable}. */ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata { using Address for address; using Strings for uint256; // Token name string private _name; // Token symbol string private _symbol; // Mapping from token ID to owner address mapping(uint256 => address) private _owners; // Mapping owner address to token count mapping(address => uint256) private _balances; // 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; /** * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC721).interfaceId || interfaceId == type(IERC721Metadata).interfaceId || super.supportsInterface(interfaceId); } /** * @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 _balances[owner]; } /** * @dev See {IERC721-ownerOf}. */ function ownerOf(uint256 tokenId) public view virtual override returns (address) { address owner = _owners[tokenId]; require(owner != address(0), "ERC721: owner query for nonexistent token"); return owner; } /** * @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 baseURI = _baseURI(); return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : ""; } /** * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each * token will be the concatenation of the `baseURI` and the `tokenId`. Empty * by default, can be overriden in child contracts. */ function _baseURI() internal view virtual returns (string memory) { return ""; } /** * @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 || 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 { _setApprovalForAll(_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 _owners[tokenId] != address(0); } /** * @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 || isApprovedForAll(owner, spender)); } /** * @dev Safely mints `tokenId` and transfers it to `to`. * * Requirements: * * - `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); _balances[to] += 1; _owners[tokenId] = to; emit Transfer(address(0), to, tokenId); _afterTokenTransfer(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); _beforeTokenTransfer(owner, address(0), tokenId); // Clear approvals _approve(address(0), tokenId); _balances[owner] -= 1; delete _owners[tokenId]; emit Transfer(owner, address(0), tokenId); _afterTokenTransfer(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 from incorrect 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); _balances[from] -= 1; _balances[to] += 1; _owners[tokenId] = to; emit Transfer(from, to, tokenId); _afterTokenTransfer(from, to, tokenId); } /** * @dev Approve `to` to operate on `tokenId` * * Emits a {Approval} event. */ function _approve(address to, uint256 tokenId) internal virtual { _tokenApprovals[tokenId] = to; emit Approval(ERC721.ownerOf(tokenId), to, tokenId); } /** * @dev Approve `operator` to operate on all of `owner` tokens * * Emits a {ApprovalForAll} event. */ function _setApprovalForAll( address owner, address operator, bool approved ) internal virtual { require(owner != operator, "ERC721: approve to caller"); _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @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()) { try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) { return retval == IERC721Receiver.onERC721Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { revert("ERC721: transfer to non ERC721Receiver implementer"); } else { assembly { revert(add(32, reason), mload(reason)) } } } } else { return true; } } /** * @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` and `to` are never both zero. * * 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 {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 tokenId ) internal virtual {} } // File: external/openzeppelin/token/ERC721/extensions/IERC721Enumerable.sol // MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Enumerable.sol) pragma solidity ^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: external/openzeppelin/token/ERC721/extensions/ERC721Enumerable.sol // MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721Enumerable.sol) pragma solidity ^0.8.0; /** * @dev This implements an optional extension of {ERC721} defined in the EIP that adds * enumerability of all the token ids in the contract as well as all token ids owned by each * account. */ abstract contract ERC721Enumerable is ERC721, IERC721Enumerable { // Mapping from owner to list of owned token IDs mapping(address => mapping(uint256 => uint256)) private _ownedTokens; // Mapping from token ID to index of the owner tokens list mapping(uint256 => uint256) private _ownedTokensIndex; // Array with all token ids, used for enumeration uint256[] private _allTokens; // Mapping from token id to position in the allTokens array mapping(uint256 => uint256) private _allTokensIndex; /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) { return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}. */ function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) { require(index < ERC721.balanceOf(owner), "ERC721Enumerable: owner index out of bounds"); return _ownedTokens[owner][index]; } /** * @dev See {IERC721Enumerable-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _allTokens.length; } /** * @dev See {IERC721Enumerable-tokenByIndex}. */ function tokenByIndex(uint256 index) public view virtual override returns (uint256) { require(index < ERC721Enumerable.totalSupply(), "ERC721Enumerable: global index out of bounds"); return _allTokens[index]; } /** * @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 override { super._beforeTokenTransfer(from, to, tokenId); if (from == address(0)) { _addTokenToAllTokensEnumeration(tokenId); } else if (from != to) { _removeTokenFromOwnerEnumeration(from, tokenId); } if (to == address(0)) { _removeTokenFromAllTokensEnumeration(tokenId); } else if (to != from) { _addTokenToOwnerEnumeration(to, tokenId); } } /** * @dev Private function to add a token to this extension's ownership-tracking data structures. * @param to address representing the new owner of the given token ID * @param tokenId uint256 ID of the token to be added to the tokens list of the given address */ function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private { uint256 length = ERC721.balanceOf(to); _ownedTokens[to][length] = tokenId; _ownedTokensIndex[tokenId] = length; } /** * @dev Private function to add a token to this extension's token tracking data structures. * @param tokenId uint256 ID of the token to be added to the tokens list */ function _addTokenToAllTokensEnumeration(uint256 tokenId) private { _allTokensIndex[tokenId] = _allTokens.length; _allTokens.push(tokenId); } /** * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for * gas optimizations e.g. when performing a transfer operation (avoiding double writes). * This has O(1) time complexity, but alters the order of the _ownedTokens array. * @param from address representing the previous owner of the given token ID * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address */ function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private { // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and // then delete the last slot (swap and pop). uint256 lastTokenIndex = ERC721.balanceOf(from) - 1; uint256 tokenIndex = _ownedTokensIndex[tokenId]; // When the token to delete is the last token, the swap operation is unnecessary if (tokenIndex != lastTokenIndex) { uint256 lastTokenId = _ownedTokens[from][lastTokenIndex]; _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index } // This also deletes the contents at the last position of the array delete _ownedTokensIndex[tokenId]; delete _ownedTokens[from][lastTokenIndex]; } /** * @dev Private function to remove a token from this extension's token tracking data structures. * This has O(1) time complexity, but alters the order of the _allTokens array. * @param tokenId uint256 ID of the token to be removed from the tokens list */ function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private { // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and // then delete the last slot (swap and pop). uint256 lastTokenIndex = _allTokens.length - 1; uint256 tokenIndex = _allTokensIndex[tokenId]; // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding // an 'if' statement (like in _removeTokenFromOwnerEnumeration) uint256 lastTokenId = _allTokens[lastTokenIndex]; _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index // This also deletes the contents at the last position of the array delete _allTokensIndex[tokenId]; _allTokens.pop(); } } // File: external/openzeppelin/interfaces/IERC721Enumerable.sol // MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC721Enumerable.sol) pragma solidity ^0.8.0; // File: main.sol //Copyleft (ɔ) Remilia Corporation All Rights Reversed // pragma solidity >=0.4.16 <0.9.0; pragma solidity >=0.8.0; contract YayoNFT is ERC721Enumerable, Ownable { string private __baseURI; function _baseURI() internal view virtual override returns (string memory) { return __baseURI; } function _setBaseURI(string memory baseURI_) internal virtual { __baseURI = baseURI_; } function setBaseURI(string memory baseURI) public onlyOwner { _setBaseURI(baseURI); } string private __contractURI; function _contractURI() internal view virtual returns (string memory) { return __contractURI; } function _setContractURI(string memory contractURI_) internal virtual { __contractURI = contractURI_; } function setContractURI(string memory contractURI) public onlyOwner { _setContractURI(contractURI); } bool private started = false; uint256 private mask = 0x000000000000000000000000000000000000000000000000ffffffffffffffff; uint8[] private shift = [ 8 * 0, 8 * 8, 8 * 16, 8 * 24 ]; // Hardcode into a literal in one tx if possible? uint256[] private packed; function CheckPacked( uint256 user, uint256 i, uint8 j ) public view returns ( bool ) { return ( ( packed[i] >> shift[j] ) & mask ) == ( user & mask ); } function ErasePacked( uint256 i, uint8 j ) private { packed[i] = packed[i] & ( ~( mask << shift[j] ) ); } function Withdraw() public onlyOwner { payable( msg.sender ).transfer( address( this ).balance ); } function StartMint() public onlyOwner { require( !started, "You've already started the minting." ); started = true; } function AddWhitelist( uint256[] memory wl_add ) public onlyOwner { for(uint256 i = 0; i < wl_add.length; i++){ packed.push(wl_add[i]); } } uint256 private price_adj = 100; function AdjustPrices(uint256 percent) public onlyOwner { price_adj = percent; } mapping( address => uint256 ) public mintCounter; uint256 constant price = 250 ether; uint256 constant whitelist_discount_price = 150 ether; uint256 constant bulk_discount_price = 200 ether; uint256 constant supply = 4000; uint256 constant reserve = 200; uint256 constant max_whitelist_mints = 5; uint256 ct_supply = supply - reserve; uint256 ct_reserve = reserve; mapping( address => uint256 ) public mintCounterYAYO; function AddYAYO( address[] memory wl_add ) public onlyOwner { for(uint256 i = 0; i < wl_add.length; i++){ mintCounterYAYO[ wl_add[i] ] = 1; } } function CheckYAYO() public view returns (bool) { return mintCounterYAYO[ msg.sender ] != 0; } function MintYAYO() public { uint256 n = totalSupply(); require( started, "Minting has not started yet." ); require( mintCounterYAYO[ msg.sender ] == 1, "Not on YAYO Holder Whitelist!"); require( n < supply, "We're out! Stay tuned for more REMILIA productions ~.o" ); require( ct_supply != 0, "We're out! Stay tuned for more REMILIA productions ~.o" ); _safeMint( msg.sender, n + 1 ); ct_supply = ct_supply - 1; mintCounterYAYO[ msg.sender ] = 0; } function MintWhitelist( uint256 i, uint8 j ) public payable { uint256 pay = (whitelist_discount_price * price_adj) / 100; uint256 n = totalSupply(); require( started, "Minting has not started yet." ); require( mintCounter[ msg.sender ] < max_whitelist_mints, "Maximum whitelist discount mints reached." ); require( msg.value == pay, "Incorrect amount of wei sent." ); require( n < supply, "We're out! Stay tuned for more REMILIA productions ~.o" ); require( ct_supply != 0, "We're out! Stay tuned for more REMILIA productions ~.o" ); require( CheckPacked( uint256( uint160( msg.sender ) ), i, j ), "Oops! Looks like you're not cool enough for this." ); _safeMint( msg.sender, n + 1 ); ct_supply = ct_supply - 1; mintCounter[ msg.sender ] = mintCounter[ msg.sender ] + 1; } function MintMain() public payable { uint256 pay = (price * price_adj) / 100; uint256 n = totalSupply(); require( started, "Minting has not started yet." ); require( n < supply, "We're out! Stay tuned for more REMILIA productions ~.o" ); require( ct_supply != 0, "We're out! Stay tuned for more REMILIA productions ~.o" ); require( msg.value == pay, "Incorrect amount of wei sent." ); _safeMint( msg.sender, n + 1 ); ct_supply = ct_supply - 1; } function MintBulk() public payable { uint256 pay = (bulk_discount_price * 10 * price_adj) / 100; uint256 n = totalSupply(); require( started, "Minting has not started yet." ); require( n < supply, "We're out! Stay tuned for more REMILIA productions ~.o" ); require( ct_supply >= 10, "We're out! Stay tuned for more REMILIA productions ~.o" ); require( msg.value == pay, "Incorrect amount of wei sent." ); //mint 10 at once _safeMint( msg.sender, n + 1); _safeMint( msg.sender, n + 2); _safeMint( msg.sender, n + 3); _safeMint( msg.sender, n + 4); _safeMint( msg.sender, n + 5); _safeMint( msg.sender, n + 6); _safeMint( msg.sender, n + 7); _safeMint( msg.sender, n + 8); _safeMint( msg.sender, n + 9); _safeMint( msg.sender, n + 10); ct_supply = ct_supply - 10; } function MintReserve() public onlyOwner { uint256 n = totalSupply(); require( started, "Minting has not started yet." ); require( n < supply, "We're out! Stay tuned for more REMILIA productions ~.o" ); require( ct_reserve >= 10, "We're out! Stay tuned for more REMILIA productions ~.o" ); //mint 10 at once _safeMint( msg.sender, n + 1); _safeMint( msg.sender, n + 2); _safeMint( msg.sender, n + 3); _safeMint( msg.sender, n + 4); _safeMint( msg.sender, n + 5); _safeMint( msg.sender, n + 6); _safeMint( msg.sender, n + 7); _safeMint( msg.sender, n + 8); _safeMint( msg.sender, n + 9); _safeMint( msg.sender, n + 10); ct_reserve = ct_reserve - 10; } constructor() ERC721( "YAYO NFT", "YAYO" ) { } }
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[]},{"type":"event","name":"Approval","inputs":[{"type":"address","name":"owner","internalType":"address","indexed":true},{"type":"address","name":"approved","internalType":"address","indexed":true},{"type":"uint256","name":"tokenId","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"ApprovalForAll","inputs":[{"type":"address","name":"owner","internalType":"address","indexed":true},{"type":"address","name":"operator","internalType":"address","indexed":true},{"type":"bool","name":"approved","internalType":"bool","indexed":false}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Transfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"tokenId","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"AddWhitelist","inputs":[{"type":"uint256[]","name":"wl_add","internalType":"uint256[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"AddYAYO","inputs":[{"type":"address[]","name":"wl_add","internalType":"address[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"AdjustPrices","inputs":[{"type":"uint256","name":"percent","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"CheckPacked","inputs":[{"type":"uint256","name":"user","internalType":"uint256"},{"type":"uint256","name":"i","internalType":"uint256"},{"type":"uint8","name":"j","internalType":"uint8"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"CheckYAYO","inputs":[]},{"type":"function","stateMutability":"payable","outputs":[],"name":"MintBulk","inputs":[]},{"type":"function","stateMutability":"payable","outputs":[],"name":"MintMain","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"MintReserve","inputs":[]},{"type":"function","stateMutability":"payable","outputs":[],"name":"MintWhitelist","inputs":[{"type":"uint256","name":"i","internalType":"uint256"},{"type":"uint8","name":"j","internalType":"uint8"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"MintYAYO","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"StartMint","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"Withdraw","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"approve","inputs":[{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"balanceOf","inputs":[{"type":"address","name":"owner","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"getApproved","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isApprovedForAll","inputs":[{"type":"address","name":"owner","internalType":"address"},{"type":"address","name":"operator","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"mintCounter","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"mintCounterYAYO","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"name","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"ownerOf","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"safeTransferFrom","inputs":[{"type":"address","name":"from","internalType":"address"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"safeTransferFrom","inputs":[{"type":"address","name":"from","internalType":"address"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"bytes","name":"_data","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setApprovalForAll","inputs":[{"type":"address","name":"operator","internalType":"address"},{"type":"bool","name":"approved","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setBaseURI","inputs":[{"type":"string","name":"baseURI","internalType":"string"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setContractURI","inputs":[{"type":"string","name":"contractURI","internalType":"string"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"supportsInterface","inputs":[{"type":"bytes4","name":"interfaceId","internalType":"bytes4"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"symbol","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"tokenByIndex","inputs":[{"type":"uint256","name":"index","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"tokenOfOwnerByIndex","inputs":[{"type":"address","name":"owner","internalType":"address"},{"type":"uint256","name":"index","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"tokenURI","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalSupply","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferFrom","inputs":[{"type":"address","name":"from","internalType":"address"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]}]
Contract Creation Code
0x60806040526000600d60006101000a81548160ff02191690831515021790555067ffffffffffffffff600e556040518060800160405280600060ff168152602001604060ff168152602001608060ff16815260200160c060ff16815250600f9060046200006e92919062000221565b50606460115560c8610fa062000085919062000327565b60135560c86014553480156200009a57600080fd5b506040518060400160405280600881526020017f5941594f204e46540000000000000000000000000000000000000000000000008152506040518060400160405280600481526020017f5941594f000000000000000000000000000000000000000000000000000000008152508160009081620001189190620005d2565b5080600190816200012a9190620005d2565b5050506200014d620001416200015360201b60201c565b6200015b60201b60201c565b620006b9565b600033905090565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b82805482825590600052602060002090601f01602090048101928215620002bc5791602002820160005b838211156200028b57835183826101000a81548160ff021916908360ff16021790555092602001926001016020816000010492830192600103026200024b565b8015620002ba5782816101000a81549060ff02191690556001016020816000010492830192600103026200028b565b505b509050620002cb9190620002cf565b5090565b5b80821115620002ea576000816000905550600101620002d0565b5090565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006200033482620002ee565b91506200034183620002ee565b92508282039050818111156200035c576200035b620002f8565b5b92915050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680620003e457607f821691505b602082108103620003fa57620003f96200039c565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302620004647fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8262000425565b62000470868362000425565b95508019841693508086168417925050509392505050565b6000819050919050565b6000620004b3620004ad620004a784620002ee565b62000488565b620002ee565b9050919050565b6000819050919050565b620004cf8362000492565b620004e7620004de82620004ba565b84845462000432565b825550505050565b600090565b620004fe620004ef565b6200050b818484620004c4565b505050565b5b81811015620005335762000527600082620004f4565b60018101905062000511565b5050565b601f82111562000582576200054c8162000400565b620005578462000415565b8101602085101562000567578190505b6200057f620005768562000415565b83018262000510565b50505b505050565b600082821c905092915050565b6000620005a76000198460080262000587565b1980831691505092915050565b6000620005c2838362000594565b9150826002028217905092915050565b620005dd8262000362565b67ffffffffffffffff811115620005f957620005f86200036d565b5b620006058254620003cb565b6200061282828562000537565b600060209050601f8311600181146200064a576000841562000635578287015190505b620006418582620005b4565b865550620006b1565b601f1984166200065a8662000400565b60005b8281101562000684578489015182556001820191506020850194506020810190506200065d565b86831015620006a45784890151620006a0601f89168262000594565b8355505b6001600288020188555050505b505050505050565b61524080620006c96000396000f3fe6080604052600436106102035760003560e01c806370a0823111610118578063afde90c2116100a0578063c9db64e01161006f578063c9db64e014610732578063d667ac3814610749578063e985e9c514610774578063f2fde38b146107b1578063fd3bb04e146107da57610203565b8063afde90c214610666578063b88d4fde146106a3578063b984c60b146106cc578063c87b56dd146106f557610203565b8063938e3d7b116100e7578063938e3d7b1461059557806395d89b41146105be5780639f402f3b146105e9578063a22cb46514610600578063afc48eef1461062957610203565b806370a08231146104ed578063715018a61461052a5780638da5cb5b146105415780639378ff6f1461056c57610203565b80632c645cc91161019b57806342842e0e1161016a57806342842e0e1461040a5780634f6ccce71461043357806355f804b31461047057806357ea89b6146104995780636352211e146104b057610203565b80632c645cc91461037e5780632f745c59146103a757806330be9111146103e4578063351ea4b61461040057610203565b8063095ea7b3116101d7578063095ea7b3146102c457806318160ddd146102ed5780631cdce9fe1461031857806323b872dd1461035557610203565b8062a173d21461020857806301ffc9a71461021f57806306fdde031461025c578063081812fc14610287575b600080fd5b34801561021457600080fd5b5061021d6107e4565b005b34801561022b57600080fd5b5061024660048036038101906102419190613568565b6109bd565b60405161025391906135b0565b60405180910390f35b34801561026857600080fd5b50610271610a37565b60405161027e919061365b565b60405180910390f35b34801561029357600080fd5b506102ae60048036038101906102a991906136b3565b610ac9565b6040516102bb9190613721565b60405180910390f35b3480156102d057600080fd5b506102eb60048036038101906102e69190613768565b610b4e565b005b3480156102f957600080fd5b50610302610c65565b60405161030f91906137b7565b60405180910390f35b34801561032457600080fd5b5061033f600480360381019061033a91906137d2565b610c72565b60405161034c91906137b7565b60405180910390f35b34801561036157600080fd5b5061037c600480360381019061037791906137ff565b610c8a565b005b34801561038a57600080fd5b506103a560048036038101906103a0919061399a565b610cea565b005b3480156103b357600080fd5b506103ce60048036038101906103c99190613768565b610de8565b6040516103db91906137b7565b60405180910390f35b6103fe60048036038101906103f99190613a1c565b610e8d565b005b61040861117c565b005b34801561041657600080fd5b50610431600480360381019061042c91906137ff565b6113cb565b005b34801561043f57600080fd5b5061045a600480360381019061045591906136b3565b6113eb565b60405161046791906137b7565b60405180910390f35b34801561047c57600080fd5b5061049760048036038101906104929190613b11565b61145c565b005b3480156104a557600080fd5b506104ae6114e4565b005b3480156104bc57600080fd5b506104d760048036038101906104d291906136b3565b6115a9565b6040516104e49190613721565b60405180910390f35b3480156104f957600080fd5b50610514600480360381019061050f91906137d2565b61165a565b60405161052191906137b7565b60405180910390f35b34801561053657600080fd5b5061053f611711565b005b34801561054d57600080fd5b50610556611799565b6040516105639190613721565b60405180910390f35b34801561057857600080fd5b50610593600480360381019061058e91906136b3565b6117c3565b005b3480156105a157600080fd5b506105bc60048036038101906105b79190613b11565b611849565b005b3480156105ca57600080fd5b506105d36118d1565b6040516105e0919061365b565b60405180910390f35b3480156105f557600080fd5b506105fe611963565b005b34801561060c57600080fd5b5061062760048036038101906106229190613b86565b611a4c565b005b34801561063557600080fd5b50610650600480360381019061064b91906137d2565b611a62565b60405161065d91906137b7565b60405180910390f35b34801561067257600080fd5b5061068d60048036038101906106889190613bc6565b611a7a565b60405161069a91906135b0565b60405180910390f35b3480156106af57600080fd5b506106ca60048036038101906106c59190613cba565b611aea565b005b3480156106d857600080fd5b506106f360048036038101906106ee9190613e00565b611b4c565b005b34801561070157600080fd5b5061071c600480360381019061071791906136b3565b611c2e565b604051610729919061365b565b60405180910390f35b34801561073e57600080fd5b50610747611cd5565b005b34801561075557600080fd5b5061075e611f2a565b60405161076b91906135b0565b60405180910390f35b34801561078057600080fd5b5061079b60048036038101906107969190613e49565b611f74565b6040516107a891906135b0565b60405180910390f35b3480156107bd57600080fd5b506107d860048036038101906107d391906137d2565b612008565b005b6107e26120ff565b005b60006107ee610c65565b9050600d60009054906101000a900460ff1661083f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161083690613ed5565b60405180910390fd5b6001601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054146108c1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108b890613f41565b60405180910390fd5b610fa08110610905576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108fc90613fd3565b60405180910390fd5b60006013540361094a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161094190613fd3565b60405180910390fd5b6109603360018361095b9190614022565b61227b565b600160135461096f9190614056565b6013819055506000601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555050565b60007f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610a305750610a2f82612299565b5b9050919050565b606060008054610a46906140b9565b80601f0160208091040260200160405190810160405280929190818152602001828054610a72906140b9565b8015610abf5780601f10610a9457610100808354040283529160200191610abf565b820191906000526020600020905b815481529060010190602001808311610aa257829003601f168201915b5050505050905090565b6000610ad48261237b565b610b13576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b0a9061415c565b60405180910390fd5b6004600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000610b59826115a9565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610bc9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bc0906141ee565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16610be86123e7565b73ffffffffffffffffffffffffffffffffffffffff161480610c175750610c1681610c116123e7565b611f74565b5b610c56576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c4d90614280565b60405180910390fd5b610c6083836123ef565b505050565b6000600880549050905090565b60126020528060005260406000206000915090505481565b610c9b610c956123e7565b826124a8565b610cda576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cd190614312565b60405180910390fd5b610ce5838383612586565b505050565b610cf26123e7565b73ffffffffffffffffffffffffffffffffffffffff16610d10611799565b73ffffffffffffffffffffffffffffffffffffffff1614610d66576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d5d9061437e565b60405180910390fd5b60005b8151811015610de457600160156000848481518110610d8b57610d8a61439e565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508080610ddc906143cd565b915050610d69565b5050565b6000610df38361165a565b8210610e34576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e2b90614487565b60405180910390fd5b600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002054905092915050565b60006064601154680821ab0d4414980000610ea891906144a7565b610eb29190614530565b90506000610ebe610c65565b9050600d60009054906101000a900460ff16610f0f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f0690613ed5565b60405180910390fd5b6005601260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410610f91576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f88906145d3565b60405180910390fd5b813414610fd3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fca9061463f565b60405180910390fd5b610fa08110611017576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161100e90613fd3565b60405180910390fd5b60006013540361105c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161105390613fd3565b60405180910390fd5b61107d3373ffffffffffffffffffffffffffffffffffffffff168585611a7a565b6110bc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110b3906146d1565b60405180910390fd5b6110d2336001836110cd9190614022565b61227b565b60016013546110e19190614056565b6013819055506001601260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546111339190614022565b601260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555050505050565b60006064601154600a680ad78ebc5ac620000061119991906144a7565b6111a391906144a7565b6111ad9190614530565b905060006111b9610c65565b9050600d60009054906101000a900460ff1661120a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161120190613ed5565b60405180910390fd5b610fa0811061124e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161124590613fd3565b60405180910390fd5b600a6013541015611294576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161128b90613fd3565b60405180910390fd5b8134146112d6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112cd9061463f565b60405180910390fd5b6112ec336001836112e79190614022565b61227b565b611302336002836112fd9190614022565b61227b565b611318336003836113139190614022565b61227b565b61132e336004836113299190614022565b61227b565b6113443360058361133f9190614022565b61227b565b61135a336006836113559190614022565b61227b565b6113703360078361136b9190614022565b61227b565b611386336008836113819190614022565b61227b565b61139c336009836113979190614022565b61227b565b6113b233600a836113ad9190614022565b61227b565b600a6013546113c19190614056565b6013819055505050565b6113e683838360405180602001604052806000815250611aea565b505050565b60006113f5610c65565b8210611436576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161142d90614763565b60405180910390fd5b6008828154811061144a5761144961439e565b5b90600052602060002001549050919050565b6114646123e7565b73ffffffffffffffffffffffffffffffffffffffff16611482611799565b73ffffffffffffffffffffffffffffffffffffffff16146114d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114cf9061437e565b60405180910390fd5b6114e1816127ec565b50565b6114ec6123e7565b73ffffffffffffffffffffffffffffffffffffffff1661150a611799565b73ffffffffffffffffffffffffffffffffffffffff1614611560576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115579061437e565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff166108fc479081150290604051600060405180830381858888f193505050501580156115a6573d6000803e3d6000fd5b50565b6000806002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611651576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611648906147f5565b60405180910390fd5b80915050919050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036116ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116c190614887565b60405180910390fd5b600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6117196123e7565b73ffffffffffffffffffffffffffffffffffffffff16611737611799565b73ffffffffffffffffffffffffffffffffffffffff161461178d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117849061437e565b60405180910390fd5b61179760006127ff565b565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6117cb6123e7565b73ffffffffffffffffffffffffffffffffffffffff166117e9611799565b73ffffffffffffffffffffffffffffffffffffffff161461183f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118369061437e565b60405180910390fd5b8060118190555050565b6118516123e7565b73ffffffffffffffffffffffffffffffffffffffff1661186f611799565b73ffffffffffffffffffffffffffffffffffffffff16146118c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118bc9061437e565b60405180910390fd5b6118ce816128c5565b50565b6060600180546118e0906140b9565b80601f016020809104026020016040519081016040528092919081815260200182805461190c906140b9565b80156119595780601f1061192e57610100808354040283529160200191611959565b820191906000526020600020905b81548152906001019060200180831161193c57829003601f168201915b5050505050905090565b61196b6123e7565b73ffffffffffffffffffffffffffffffffffffffff16611989611799565b73ffffffffffffffffffffffffffffffffffffffff16146119df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119d69061437e565b60405180910390fd5b600d60009054906101000a900460ff1615611a2f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a2690614919565b60405180910390fd5b6001600d60006101000a81548160ff021916908315150217905550565b611a5e611a576123e7565b83836128d8565b5050565b60156020528060005260406000206000915090505481565b6000600e548416600e54600f8460ff1681548110611a9b57611a9a61439e565b5b90600052602060002090602091828204019190069054906101000a900460ff1660ff1660108681548110611ad257611ad161439e565b5b9060005260206000200154901c161490509392505050565b611afb611af56123e7565b836124a8565b611b3a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b3190614312565b60405180910390fd5b611b4684848484612a44565b50505050565b611b546123e7565b73ffffffffffffffffffffffffffffffffffffffff16611b72611799565b73ffffffffffffffffffffffffffffffffffffffff1614611bc8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bbf9061437e565b60405180910390fd5b60005b8151811015611c2a576010828281518110611be957611be861439e565b5b602002602001015190806001815401808255809150506001900390600052602060002001600090919091909150558080611c22906143cd565b915050611bcb565b5050565b6060611c398261237b565b611c78576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c6f906149ab565b60405180910390fd5b6000611c82612aa0565b90506000815111611ca25760405180602001604052806000815250611ccd565b80611cac84612b32565b604051602001611cbd929190614a07565b6040516020818303038152906040525b915050919050565b611cdd6123e7565b73ffffffffffffffffffffffffffffffffffffffff16611cfb611799565b73ffffffffffffffffffffffffffffffffffffffff1614611d51576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d489061437e565b60405180910390fd5b6000611d5b610c65565b9050600d60009054906101000a900460ff16611dac576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611da390613ed5565b60405180910390fd5b610fa08110611df0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611de790613fd3565b60405180910390fd5b600a6014541015611e36576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e2d90613fd3565b60405180910390fd5b611e4c33600183611e479190614022565b61227b565b611e6233600283611e5d9190614022565b61227b565b611e7833600383611e739190614022565b61227b565b611e8e33600483611e899190614022565b61227b565b611ea433600583611e9f9190614022565b61227b565b611eba33600683611eb59190614022565b61227b565b611ed033600783611ecb9190614022565b61227b565b611ee633600883611ee19190614022565b61227b565b611efc33600983611ef79190614022565b61227b565b611f1233600a83611f0d9190614022565b61227b565b600a601454611f219190614056565b60148190555050565b600080601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541415905090565b6000600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b6120106123e7565b73ffffffffffffffffffffffffffffffffffffffff1661202e611799565b73ffffffffffffffffffffffffffffffffffffffff1614612084576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161207b9061437e565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036120f3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120ea90614a9d565b60405180910390fd5b6120fc816127ff565b50565b60006064601154680d8d726b7177a8000061211a91906144a7565b6121249190614530565b90506000612130610c65565b9050600d60009054906101000a900460ff16612181576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161217890613ed5565b60405180910390fd5b610fa081106121c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121bc90613fd3565b60405180910390fd5b60006013540361220a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161220190613fd3565b60405180910390fd5b81341461224c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122439061463f565b60405180910390fd5b6122623360018361225d9190614022565b61227b565b60016013546122719190614056565b6013819055505050565b612295828260405180602001604052806000815250612c92565b5050565b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061236457507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80612374575061237382612ced565b5b9050919050565b60008073ffffffffffffffffffffffffffffffffffffffff166002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b600033905090565b816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16612462836115a9565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60006124b38261237b565b6124f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124e990614b2f565b60405180910390fd5b60006124fd836115a9565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16148061256c57508373ffffffffffffffffffffffffffffffffffffffff1661255484610ac9565b73ffffffffffffffffffffffffffffffffffffffff16145b8061257d575061257c8185611f74565b5b91505092915050565b8273ffffffffffffffffffffffffffffffffffffffff166125a6826115a9565b73ffffffffffffffffffffffffffffffffffffffff16146125fc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125f390614bc1565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361266b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161266290614c53565b60405180910390fd5b612676838383612d57565b6126816000826123ef565b6001600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546126d19190614056565b925050819055506001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546127289190614022565b92505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46127e7838383612e69565b505050565b80600b90816127fb9190614e1f565b5050565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b80600c90816128d49190614e1f565b5050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612946576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161293d90614f3d565b60405180910390fd5b80600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051612a3791906135b0565b60405180910390a3505050565b612a4f848484612586565b612a5b84848484612e6e565b612a9a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a9190614fcf565b60405180910390fd5b50505050565b6060600b8054612aaf906140b9565b80601f0160208091040260200160405190810160405280929190818152602001828054612adb906140b9565b8015612b285780601f10612afd57610100808354040283529160200191612b28565b820191906000526020600020905b815481529060010190602001808311612b0b57829003601f168201915b5050505050905090565b606060008203612b79576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050612c8d565b600082905060005b60008214612bab578080612b94906143cd565b915050600a82612ba49190614530565b9150612b81565b60008167ffffffffffffffff811115612bc757612bc6613857565b5b6040519080825280601f01601f191660200182016040528015612bf95781602001600182028036833780820191505090505b5090505b60008514612c8657600182612c129190614056565b9150600a85612c219190614fef565b6030612c2d9190614022565b60f81b818381518110612c4357612c4261439e565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a85612c7f9190614530565b9450612bfd565b8093505050505b919050565b612c9c8383612ff5565b612ca96000848484612e6e565b612ce8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612cdf90614fcf565b60405180910390fd5b505050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b612d628383836131ce565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612da457612d9f816131d3565b612de3565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614612de257612de1838261321c565b5b5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612e2557612e2081613389565b612e64565b8273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614612e6357612e62828261345a565b5b5b505050565b505050565b6000612e8f8473ffffffffffffffffffffffffffffffffffffffff166134d9565b15612fe8578373ffffffffffffffffffffffffffffffffffffffff1663150b7a02612eb86123e7565b8786866040518563ffffffff1660e01b8152600401612eda9493929190615075565b6020604051808303816000875af1925050508015612f1657506040513d601f19601f82011682018060405250810190612f1391906150d6565b60015b612f98573d8060008114612f46576040519150601f19603f3d011682016040523d82523d6000602084013e612f4b565b606091505b506000815103612f90576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612f8790614fcf565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050612fed565b600190505b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603613064576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161305b9061514f565b60405180910390fd5b61306d8161237b565b156130ad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016130a4906151bb565b60405180910390fd5b6130b960008383612d57565b6001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546131099190614022565b92505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46131ca60008383612e69565b5050565b505050565b6008805490506009600083815260200190815260200160002081905550600881908060018154018082558091505060019003906000526020600020016000909190919091505550565b600060016132298461165a565b6132339190614056565b9050600060076000848152602001908152602001600020549050818114613318576000600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002054905080600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002081905550816007600083815260200190815260200160002081905550505b6007600084815260200190815260200160002060009055600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000905550505050565b6000600160088054905061339d9190614056565b90506000600960008481526020019081526020016000205490506000600883815481106133cd576133cc61439e565b5b9060005260206000200154905080600883815481106133ef576133ee61439e565b5b90600052602060002001819055508160096000838152602001908152602001600020819055506009600085815260200190815260200160002060009055600880548061343e5761343d6151db565b5b6001900381819060005260206000200160009055905550505050565b60006134658361165a565b905081600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002081905550806007600084815260200190815260200160002081905550505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61354581613510565b811461355057600080fd5b50565b6000813590506135628161353c565b92915050565b60006020828403121561357e5761357d613506565b5b600061358c84828501613553565b91505092915050565b60008115159050919050565b6135aa81613595565b82525050565b60006020820190506135c560008301846135a1565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156136055780820151818401526020810190506135ea565b60008484015250505050565b6000601f19601f8301169050919050565b600061362d826135cb565b61363781856135d6565b93506136478185602086016135e7565b61365081613611565b840191505092915050565b600060208201905081810360008301526136758184613622565b905092915050565b6000819050919050565b6136908161367d565b811461369b57600080fd5b50565b6000813590506136ad81613687565b92915050565b6000602082840312156136c9576136c8613506565b5b60006136d78482850161369e565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061370b826136e0565b9050919050565b61371b81613700565b82525050565b60006020820190506137366000830184613712565b92915050565b61374581613700565b811461375057600080fd5b50565b6000813590506137628161373c565b92915050565b6000806040838503121561377f5761377e613506565b5b600061378d85828601613753565b925050602061379e8582860161369e565b9150509250929050565b6137b18161367d565b82525050565b60006020820190506137cc60008301846137a8565b92915050565b6000602082840312156137e8576137e7613506565b5b60006137f684828501613753565b91505092915050565b60008060006060848603121561381857613817613506565b5b600061382686828701613753565b935050602061383786828701613753565b92505060406138488682870161369e565b9150509250925092565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61388f82613611565b810181811067ffffffffffffffff821117156138ae576138ad613857565b5b80604052505050565b60006138c16134fc565b90506138cd8282613886565b919050565b600067ffffffffffffffff8211156138ed576138ec613857565b5b602082029050602081019050919050565b600080fd5b6000613916613911846138d2565b6138b7565b90508083825260208201905060208402830185811115613939576139386138fe565b5b835b81811015613962578061394e8882613753565b84526020840193505060208101905061393b565b5050509392505050565b600082601f83011261398157613980613852565b5b8135613991848260208601613903565b91505092915050565b6000602082840312156139b0576139af613506565b5b600082013567ffffffffffffffff8111156139ce576139cd61350b565b5b6139da8482850161396c565b91505092915050565b600060ff82169050919050565b6139f9816139e3565b8114613a0457600080fd5b50565b600081359050613a16816139f0565b92915050565b60008060408385031215613a3357613a32613506565b5b6000613a418582860161369e565b9250506020613a5285828601613a07565b9150509250929050565b600080fd5b600067ffffffffffffffff821115613a7c57613a7b613857565b5b613a8582613611565b9050602081019050919050565b82818337600083830152505050565b6000613ab4613aaf84613a61565b6138b7565b905082815260208101848484011115613ad057613acf613a5c565b5b613adb848285613a92565b509392505050565b600082601f830112613af857613af7613852565b5b8135613b08848260208601613aa1565b91505092915050565b600060208284031215613b2757613b26613506565b5b600082013567ffffffffffffffff811115613b4557613b4461350b565b5b613b5184828501613ae3565b91505092915050565b613b6381613595565b8114613b6e57600080fd5b50565b600081359050613b8081613b5a565b92915050565b60008060408385031215613b9d57613b9c613506565b5b6000613bab85828601613753565b9250506020613bbc85828601613b71565b9150509250929050565b600080600060608486031215613bdf57613bde613506565b5b6000613bed8682870161369e565b9350506020613bfe8682870161369e565b9250506040613c0f86828701613a07565b9150509250925092565b600067ffffffffffffffff821115613c3457613c33613857565b5b613c3d82613611565b9050602081019050919050565b6000613c5d613c5884613c19565b6138b7565b905082815260208101848484011115613c7957613c78613a5c565b5b613c84848285613a92565b509392505050565b600082601f830112613ca157613ca0613852565b5b8135613cb1848260208601613c4a565b91505092915050565b60008060008060808587031215613cd457613cd3613506565b5b6000613ce287828801613753565b9450506020613cf387828801613753565b9350506040613d048782880161369e565b925050606085013567ffffffffffffffff811115613d2557613d2461350b565b5b613d3187828801613c8c565b91505092959194509250565b600067ffffffffffffffff821115613d5857613d57613857565b5b602082029050602081019050919050565b6000613d7c613d7784613d3d565b6138b7565b90508083825260208201905060208402830185811115613d9f57613d9e6138fe565b5b835b81811015613dc85780613db4888261369e565b845260208401935050602081019050613da1565b5050509392505050565b600082601f830112613de757613de6613852565b5b8135613df7848260208601613d69565b91505092915050565b600060208284031215613e1657613e15613506565b5b600082013567ffffffffffffffff811115613e3457613e3361350b565b5b613e4084828501613dd2565b91505092915050565b60008060408385031215613e6057613e5f613506565b5b6000613e6e85828601613753565b9250506020613e7f85828601613753565b9150509250929050565b7f4d696e74696e6720686173206e6f742073746172746564207965742e00000000600082015250565b6000613ebf601c836135d6565b9150613eca82613e89565b602082019050919050565b60006020820190508181036000830152613eee81613eb2565b9050919050565b7f4e6f74206f6e205941594f20486f6c6465722057686974656c69737421000000600082015250565b6000613f2b601d836135d6565b9150613f3682613ef5565b602082019050919050565b60006020820190508181036000830152613f5a81613f1e565b9050919050565b7f5765277265206f75742120537461792074756e656420666f72206d6f7265205260008201527f454d494c49412070726f64756374696f6e73207e2e6f00000000000000000000602082015250565b6000613fbd6036836135d6565b9150613fc882613f61565b604082019050919050565b60006020820190508181036000830152613fec81613fb0565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061402d8261367d565b91506140388361367d565b92508282019050808211156140505761404f613ff3565b5b92915050565b60006140618261367d565b915061406c8361367d565b925082820390508181111561408457614083613ff3565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806140d157607f821691505b6020821081036140e4576140e361408a565b5b50919050565b7f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b6000614146602c836135d6565b9150614151826140ea565b604082019050919050565b6000602082019050818103600083015261417581614139565b9050919050565b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b60006141d86021836135d6565b91506141e38261417c565b604082019050919050565b60006020820190508181036000830152614207816141cb565b9050919050565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760008201527f6e6572206e6f7220617070726f76656420666f7220616c6c0000000000000000602082015250565b600061426a6038836135d6565b91506142758261420e565b604082019050919050565b600060208201905081810360008301526142998161425d565b9050919050565b7f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60008201527f776e6572206e6f7220617070726f766564000000000000000000000000000000602082015250565b60006142fc6031836135d6565b9150614307826142a0565b604082019050919050565b6000602082019050818103600083015261432b816142ef565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006143686020836135d6565b915061437382614332565b602082019050919050565b600060208201905081810360008301526143978161435b565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006143d88261367d565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361440a57614409613ff3565b5b600182019050919050565b7f455243373231456e756d657261626c653a206f776e657220696e646578206f7560008201527f74206f6620626f756e6473000000000000000000000000000000000000000000602082015250565b6000614471602b836135d6565b915061447c82614415565b604082019050919050565b600060208201905081810360008301526144a081614464565b9050919050565b60006144b28261367d565b91506144bd8361367d565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156144f6576144f5613ff3565b5b828202905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061453b8261367d565b91506145468361367d565b92508261455657614555614501565b5b828204905092915050565b7f4d6178696d756d2077686974656c69737420646973636f756e74206d696e747360008201527f20726561636865642e0000000000000000000000000000000000000000000000602082015250565b60006145bd6029836135d6565b91506145c882614561565b604082019050919050565b600060208201905081810360008301526145ec816145b0565b9050919050565b7f496e636f727265637420616d6f756e74206f66207765692073656e742e000000600082015250565b6000614629601d836135d6565b9150614634826145f3565b602082019050919050565b600060208201905081810360008301526146588161461c565b9050919050565b7f4f6f707321204c6f6f6b73206c696b6520796f75277265206e6f7420636f6f6c60008201527f20656e6f75676820666f7220746869732e000000000000000000000000000000602082015250565b60006146bb6031836135d6565b91506146c68261465f565b604082019050919050565b600060208201905081810360008301526146ea816146ae565b9050919050565b7f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60008201527f7574206f6620626f756e64730000000000000000000000000000000000000000602082015250565b600061474d602c836135d6565b9150614758826146f1565b604082019050919050565b6000602082019050818103600083015261477c81614740565b9050919050565b7f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460008201527f656e7420746f6b656e0000000000000000000000000000000000000000000000602082015250565b60006147df6029836135d6565b91506147ea82614783565b604082019050919050565b6000602082019050818103600083015261480e816147d2565b9050919050565b7f4552433732313a2062616c616e636520717565727920666f7220746865207a6560008201527f726f206164647265737300000000000000000000000000000000000000000000602082015250565b6000614871602a836135d6565b915061487c82614815565b604082019050919050565b600060208201905081810360008301526148a081614864565b9050919050565b7f596f7527766520616c7265616479207374617274656420746865206d696e746960008201527f6e672e0000000000000000000000000000000000000000000000000000000000602082015250565b60006149036023836135d6565b915061490e826148a7565b604082019050919050565b60006020820190508181036000830152614932816148f6565b9050919050565b7f4552433732314d657461646174613a2055524920717565727920666f72206e6f60008201527f6e6578697374656e7420746f6b656e0000000000000000000000000000000000602082015250565b6000614995602f836135d6565b91506149a082614939565b604082019050919050565b600060208201905081810360008301526149c481614988565b9050919050565b600081905092915050565b60006149e1826135cb565b6149eb81856149cb565b93506149fb8185602086016135e7565b80840191505092915050565b6000614a1382856149d6565b9150614a1f82846149d6565b91508190509392505050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000614a876026836135d6565b9150614a9282614a2b565b604082019050919050565b60006020820190508181036000830152614ab681614a7a565b9050919050565b7f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b6000614b19602c836135d6565b9150614b2482614abd565b604082019050919050565b60006020820190508181036000830152614b4881614b0c565b9050919050565b7f4552433732313a207472616e736665722066726f6d20696e636f72726563742060008201527f6f776e6572000000000000000000000000000000000000000000000000000000602082015250565b6000614bab6025836135d6565b9150614bb682614b4f565b604082019050919050565b60006020820190508181036000830152614bda81614b9e565b9050919050565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b6000614c3d6024836135d6565b9150614c4882614be1565b604082019050919050565b60006020820190508181036000830152614c6c81614c30565b9050919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302614cd57fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82614c98565b614cdf8683614c98565b95508019841693508086168417925050509392505050565b6000819050919050565b6000614d1c614d17614d128461367d565b614cf7565b61367d565b9050919050565b6000819050919050565b614d3683614d01565b614d4a614d4282614d23565b848454614ca5565b825550505050565b600090565b614d5f614d52565b614d6a818484614d2d565b505050565b5b81811015614d8e57614d83600082614d57565b600181019050614d70565b5050565b601f821115614dd357614da481614c73565b614dad84614c88565b81016020851015614dbc578190505b614dd0614dc885614c88565b830182614d6f565b50505b505050565b600082821c905092915050565b6000614df660001984600802614dd8565b1980831691505092915050565b6000614e0f8383614de5565b9150826002028217905092915050565b614e28826135cb565b67ffffffffffffffff811115614e4157614e40613857565b5b614e4b82546140b9565b614e56828285614d92565b600060209050601f831160018114614e895760008415614e77578287015190505b614e818582614e03565b865550614ee9565b601f198416614e9786614c73565b60005b82811015614ebf57848901518255600182019150602085019450602081019050614e9a565b86831015614edc5784890151614ed8601f891682614de5565b8355505b6001600288020188555050505b505050505050565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b6000614f276019836135d6565b9150614f3282614ef1565b602082019050919050565b60006020820190508181036000830152614f5681614f1a565b9050919050565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b6000614fb96032836135d6565b9150614fc482614f5d565b604082019050919050565b60006020820190508181036000830152614fe881614fac565b9050919050565b6000614ffa8261367d565b91506150058361367d565b92508261501557615014614501565b5b828206905092915050565b600081519050919050565b600082825260208201905092915050565b600061504782615020565b615051818561502b565b93506150618185602086016135e7565b61506a81613611565b840191505092915050565b600060808201905061508a6000830187613712565b6150976020830186613712565b6150a460408301856137a8565b81810360608301526150b6818461503c565b905095945050505050565b6000815190506150d08161353c565b92915050565b6000602082840312156150ec576150eb613506565b5b60006150fa848285016150c1565b91505092915050565b7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373600082015250565b60006151396020836135d6565b915061514482615103565b602082019050919050565b600060208201905081810360008301526151688161512c565b9050919050565b7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000600082015250565b60006151a5601c836135d6565b91506151b08261516f565b602082019050919050565b600060208201905081810360008301526151d481615198565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea2646970667358221220887fb454ea50b98ef908a2261b27828e97bcc71177334885d6f2a10697d8005b64736f6c63430008100033
Deployed ByteCode
0x6080604052600436106102035760003560e01c806370a0823111610118578063afde90c2116100a0578063c9db64e01161006f578063c9db64e014610732578063d667ac3814610749578063e985e9c514610774578063f2fde38b146107b1578063fd3bb04e146107da57610203565b8063afde90c214610666578063b88d4fde146106a3578063b984c60b146106cc578063c87b56dd146106f557610203565b8063938e3d7b116100e7578063938e3d7b1461059557806395d89b41146105be5780639f402f3b146105e9578063a22cb46514610600578063afc48eef1461062957610203565b806370a08231146104ed578063715018a61461052a5780638da5cb5b146105415780639378ff6f1461056c57610203565b80632c645cc91161019b57806342842e0e1161016a57806342842e0e1461040a5780634f6ccce71461043357806355f804b31461047057806357ea89b6146104995780636352211e146104b057610203565b80632c645cc91461037e5780632f745c59146103a757806330be9111146103e4578063351ea4b61461040057610203565b8063095ea7b3116101d7578063095ea7b3146102c457806318160ddd146102ed5780631cdce9fe1461031857806323b872dd1461035557610203565b8062a173d21461020857806301ffc9a71461021f57806306fdde031461025c578063081812fc14610287575b600080fd5b34801561021457600080fd5b5061021d6107e4565b005b34801561022b57600080fd5b5061024660048036038101906102419190613568565b6109bd565b60405161025391906135b0565b60405180910390f35b34801561026857600080fd5b50610271610a37565b60405161027e919061365b565b60405180910390f35b34801561029357600080fd5b506102ae60048036038101906102a991906136b3565b610ac9565b6040516102bb9190613721565b60405180910390f35b3480156102d057600080fd5b506102eb60048036038101906102e69190613768565b610b4e565b005b3480156102f957600080fd5b50610302610c65565b60405161030f91906137b7565b60405180910390f35b34801561032457600080fd5b5061033f600480360381019061033a91906137d2565b610c72565b60405161034c91906137b7565b60405180910390f35b34801561036157600080fd5b5061037c600480360381019061037791906137ff565b610c8a565b005b34801561038a57600080fd5b506103a560048036038101906103a0919061399a565b610cea565b005b3480156103b357600080fd5b506103ce60048036038101906103c99190613768565b610de8565b6040516103db91906137b7565b60405180910390f35b6103fe60048036038101906103f99190613a1c565b610e8d565b005b61040861117c565b005b34801561041657600080fd5b50610431600480360381019061042c91906137ff565b6113cb565b005b34801561043f57600080fd5b5061045a600480360381019061045591906136b3565b6113eb565b60405161046791906137b7565b60405180910390f35b34801561047c57600080fd5b5061049760048036038101906104929190613b11565b61145c565b005b3480156104a557600080fd5b506104ae6114e4565b005b3480156104bc57600080fd5b506104d760048036038101906104d291906136b3565b6115a9565b6040516104e49190613721565b60405180910390f35b3480156104f957600080fd5b50610514600480360381019061050f91906137d2565b61165a565b60405161052191906137b7565b60405180910390f35b34801561053657600080fd5b5061053f611711565b005b34801561054d57600080fd5b50610556611799565b6040516105639190613721565b60405180910390f35b34801561057857600080fd5b50610593600480360381019061058e91906136b3565b6117c3565b005b3480156105a157600080fd5b506105bc60048036038101906105b79190613b11565b611849565b005b3480156105ca57600080fd5b506105d36118d1565b6040516105e0919061365b565b60405180910390f35b3480156105f557600080fd5b506105fe611963565b005b34801561060c57600080fd5b5061062760048036038101906106229190613b86565b611a4c565b005b34801561063557600080fd5b50610650600480360381019061064b91906137d2565b611a62565b60405161065d91906137b7565b60405180910390f35b34801561067257600080fd5b5061068d60048036038101906106889190613bc6565b611a7a565b60405161069a91906135b0565b60405180910390f35b3480156106af57600080fd5b506106ca60048036038101906106c59190613cba565b611aea565b005b3480156106d857600080fd5b506106f360048036038101906106ee9190613e00565b611b4c565b005b34801561070157600080fd5b5061071c600480360381019061071791906136b3565b611c2e565b604051610729919061365b565b60405180910390f35b34801561073e57600080fd5b50610747611cd5565b005b34801561075557600080fd5b5061075e611f2a565b60405161076b91906135b0565b60405180910390f35b34801561078057600080fd5b5061079b60048036038101906107969190613e49565b611f74565b6040516107a891906135b0565b60405180910390f35b3480156107bd57600080fd5b506107d860048036038101906107d391906137d2565b612008565b005b6107e26120ff565b005b60006107ee610c65565b9050600d60009054906101000a900460ff1661083f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161083690613ed5565b60405180910390fd5b6001601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054146108c1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108b890613f41565b60405180910390fd5b610fa08110610905576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108fc90613fd3565b60405180910390fd5b60006013540361094a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161094190613fd3565b60405180910390fd5b6109603360018361095b9190614022565b61227b565b600160135461096f9190614056565b6013819055506000601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555050565b60007f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610a305750610a2f82612299565b5b9050919050565b606060008054610a46906140b9565b80601f0160208091040260200160405190810160405280929190818152602001828054610a72906140b9565b8015610abf5780601f10610a9457610100808354040283529160200191610abf565b820191906000526020600020905b815481529060010190602001808311610aa257829003601f168201915b5050505050905090565b6000610ad48261237b565b610b13576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b0a9061415c565b60405180910390fd5b6004600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000610b59826115a9565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610bc9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bc0906141ee565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16610be86123e7565b73ffffffffffffffffffffffffffffffffffffffff161480610c175750610c1681610c116123e7565b611f74565b5b610c56576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c4d90614280565b60405180910390fd5b610c6083836123ef565b505050565b6000600880549050905090565b60126020528060005260406000206000915090505481565b610c9b610c956123e7565b826124a8565b610cda576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cd190614312565b60405180910390fd5b610ce5838383612586565b505050565b610cf26123e7565b73ffffffffffffffffffffffffffffffffffffffff16610d10611799565b73ffffffffffffffffffffffffffffffffffffffff1614610d66576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d5d9061437e565b60405180910390fd5b60005b8151811015610de457600160156000848481518110610d8b57610d8a61439e565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508080610ddc906143cd565b915050610d69565b5050565b6000610df38361165a565b8210610e34576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e2b90614487565b60405180910390fd5b600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002054905092915050565b60006064601154680821ab0d4414980000610ea891906144a7565b610eb29190614530565b90506000610ebe610c65565b9050600d60009054906101000a900460ff16610f0f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f0690613ed5565b60405180910390fd5b6005601260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410610f91576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f88906145d3565b60405180910390fd5b813414610fd3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fca9061463f565b60405180910390fd5b610fa08110611017576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161100e90613fd3565b60405180910390fd5b60006013540361105c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161105390613fd3565b60405180910390fd5b61107d3373ffffffffffffffffffffffffffffffffffffffff168585611a7a565b6110bc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110b3906146d1565b60405180910390fd5b6110d2336001836110cd9190614022565b61227b565b60016013546110e19190614056565b6013819055506001601260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546111339190614022565b601260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555050505050565b60006064601154600a680ad78ebc5ac620000061119991906144a7565b6111a391906144a7565b6111ad9190614530565b905060006111b9610c65565b9050600d60009054906101000a900460ff1661120a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161120190613ed5565b60405180910390fd5b610fa0811061124e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161124590613fd3565b60405180910390fd5b600a6013541015611294576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161128b90613fd3565b60405180910390fd5b8134146112d6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112cd9061463f565b60405180910390fd5b6112ec336001836112e79190614022565b61227b565b611302336002836112fd9190614022565b61227b565b611318336003836113139190614022565b61227b565b61132e336004836113299190614022565b61227b565b6113443360058361133f9190614022565b61227b565b61135a336006836113559190614022565b61227b565b6113703360078361136b9190614022565b61227b565b611386336008836113819190614022565b61227b565b61139c336009836113979190614022565b61227b565b6113b233600a836113ad9190614022565b61227b565b600a6013546113c19190614056565b6013819055505050565b6113e683838360405180602001604052806000815250611aea565b505050565b60006113f5610c65565b8210611436576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161142d90614763565b60405180910390fd5b6008828154811061144a5761144961439e565b5b90600052602060002001549050919050565b6114646123e7565b73ffffffffffffffffffffffffffffffffffffffff16611482611799565b73ffffffffffffffffffffffffffffffffffffffff16146114d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114cf9061437e565b60405180910390fd5b6114e1816127ec565b50565b6114ec6123e7565b73ffffffffffffffffffffffffffffffffffffffff1661150a611799565b73ffffffffffffffffffffffffffffffffffffffff1614611560576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115579061437e565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff166108fc479081150290604051600060405180830381858888f193505050501580156115a6573d6000803e3d6000fd5b50565b6000806002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611651576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611648906147f5565b60405180910390fd5b80915050919050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036116ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116c190614887565b60405180910390fd5b600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6117196123e7565b73ffffffffffffffffffffffffffffffffffffffff16611737611799565b73ffffffffffffffffffffffffffffffffffffffff161461178d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117849061437e565b60405180910390fd5b61179760006127ff565b565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6117cb6123e7565b73ffffffffffffffffffffffffffffffffffffffff166117e9611799565b73ffffffffffffffffffffffffffffffffffffffff161461183f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118369061437e565b60405180910390fd5b8060118190555050565b6118516123e7565b73ffffffffffffffffffffffffffffffffffffffff1661186f611799565b73ffffffffffffffffffffffffffffffffffffffff16146118c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118bc9061437e565b60405180910390fd5b6118ce816128c5565b50565b6060600180546118e0906140b9565b80601f016020809104026020016040519081016040528092919081815260200182805461190c906140b9565b80156119595780601f1061192e57610100808354040283529160200191611959565b820191906000526020600020905b81548152906001019060200180831161193c57829003601f168201915b5050505050905090565b61196b6123e7565b73ffffffffffffffffffffffffffffffffffffffff16611989611799565b73ffffffffffffffffffffffffffffffffffffffff16146119df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119d69061437e565b60405180910390fd5b600d60009054906101000a900460ff1615611a2f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a2690614919565b60405180910390fd5b6001600d60006101000a81548160ff021916908315150217905550565b611a5e611a576123e7565b83836128d8565b5050565b60156020528060005260406000206000915090505481565b6000600e548416600e54600f8460ff1681548110611a9b57611a9a61439e565b5b90600052602060002090602091828204019190069054906101000a900460ff1660ff1660108681548110611ad257611ad161439e565b5b9060005260206000200154901c161490509392505050565b611afb611af56123e7565b836124a8565b611b3a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b3190614312565b60405180910390fd5b611b4684848484612a44565b50505050565b611b546123e7565b73ffffffffffffffffffffffffffffffffffffffff16611b72611799565b73ffffffffffffffffffffffffffffffffffffffff1614611bc8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bbf9061437e565b60405180910390fd5b60005b8151811015611c2a576010828281518110611be957611be861439e565b5b602002602001015190806001815401808255809150506001900390600052602060002001600090919091909150558080611c22906143cd565b915050611bcb565b5050565b6060611c398261237b565b611c78576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c6f906149ab565b60405180910390fd5b6000611c82612aa0565b90506000815111611ca25760405180602001604052806000815250611ccd565b80611cac84612b32565b604051602001611cbd929190614a07565b6040516020818303038152906040525b915050919050565b611cdd6123e7565b73ffffffffffffffffffffffffffffffffffffffff16611cfb611799565b73ffffffffffffffffffffffffffffffffffffffff1614611d51576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d489061437e565b60405180910390fd5b6000611d5b610c65565b9050600d60009054906101000a900460ff16611dac576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611da390613ed5565b60405180910390fd5b610fa08110611df0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611de790613fd3565b60405180910390fd5b600a6014541015611e36576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e2d90613fd3565b60405180910390fd5b611e4c33600183611e479190614022565b61227b565b611e6233600283611e5d9190614022565b61227b565b611e7833600383611e739190614022565b61227b565b611e8e33600483611e899190614022565b61227b565b611ea433600583611e9f9190614022565b61227b565b611eba33600683611eb59190614022565b61227b565b611ed033600783611ecb9190614022565b61227b565b611ee633600883611ee19190614022565b61227b565b611efc33600983611ef79190614022565b61227b565b611f1233600a83611f0d9190614022565b61227b565b600a601454611f219190614056565b60148190555050565b600080601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541415905090565b6000600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b6120106123e7565b73ffffffffffffffffffffffffffffffffffffffff1661202e611799565b73ffffffffffffffffffffffffffffffffffffffff1614612084576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161207b9061437e565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036120f3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120ea90614a9d565b60405180910390fd5b6120fc816127ff565b50565b60006064601154680d8d726b7177a8000061211a91906144a7565b6121249190614530565b90506000612130610c65565b9050600d60009054906101000a900460ff16612181576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161217890613ed5565b60405180910390fd5b610fa081106121c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121bc90613fd3565b60405180910390fd5b60006013540361220a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161220190613fd3565b60405180910390fd5b81341461224c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122439061463f565b60405180910390fd5b6122623360018361225d9190614022565b61227b565b60016013546122719190614056565b6013819055505050565b612295828260405180602001604052806000815250612c92565b5050565b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061236457507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80612374575061237382612ced565b5b9050919050565b60008073ffffffffffffffffffffffffffffffffffffffff166002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b600033905090565b816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16612462836115a9565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60006124b38261237b565b6124f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124e990614b2f565b60405180910390fd5b60006124fd836115a9565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16148061256c57508373ffffffffffffffffffffffffffffffffffffffff1661255484610ac9565b73ffffffffffffffffffffffffffffffffffffffff16145b8061257d575061257c8185611f74565b5b91505092915050565b8273ffffffffffffffffffffffffffffffffffffffff166125a6826115a9565b73ffffffffffffffffffffffffffffffffffffffff16146125fc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125f390614bc1565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361266b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161266290614c53565b60405180910390fd5b612676838383612d57565b6126816000826123ef565b6001600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546126d19190614056565b925050819055506001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546127289190614022565b92505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46127e7838383612e69565b505050565b80600b90816127fb9190614e1f565b5050565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b80600c90816128d49190614e1f565b5050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612946576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161293d90614f3d565b60405180910390fd5b80600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051612a3791906135b0565b60405180910390a3505050565b612a4f848484612586565b612a5b84848484612e6e565b612a9a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a9190614fcf565b60405180910390fd5b50505050565b6060600b8054612aaf906140b9565b80601f0160208091040260200160405190810160405280929190818152602001828054612adb906140b9565b8015612b285780601f10612afd57610100808354040283529160200191612b28565b820191906000526020600020905b815481529060010190602001808311612b0b57829003601f168201915b5050505050905090565b606060008203612b79576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050612c8d565b600082905060005b60008214612bab578080612b94906143cd565b915050600a82612ba49190614530565b9150612b81565b60008167ffffffffffffffff811115612bc757612bc6613857565b5b6040519080825280601f01601f191660200182016040528015612bf95781602001600182028036833780820191505090505b5090505b60008514612c8657600182612c129190614056565b9150600a85612c219190614fef565b6030612c2d9190614022565b60f81b818381518110612c4357612c4261439e565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a85612c7f9190614530565b9450612bfd565b8093505050505b919050565b612c9c8383612ff5565b612ca96000848484612e6e565b612ce8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612cdf90614fcf565b60405180910390fd5b505050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b612d628383836131ce565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612da457612d9f816131d3565b612de3565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614612de257612de1838261321c565b5b5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612e2557612e2081613389565b612e64565b8273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614612e6357612e62828261345a565b5b5b505050565b505050565b6000612e8f8473ffffffffffffffffffffffffffffffffffffffff166134d9565b15612fe8578373ffffffffffffffffffffffffffffffffffffffff1663150b7a02612eb86123e7565b8786866040518563ffffffff1660e01b8152600401612eda9493929190615075565b6020604051808303816000875af1925050508015612f1657506040513d601f19601f82011682018060405250810190612f1391906150d6565b60015b612f98573d8060008114612f46576040519150601f19603f3d011682016040523d82523d6000602084013e612f4b565b606091505b506000815103612f90576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612f8790614fcf565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050612fed565b600190505b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603613064576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161305b9061514f565b60405180910390fd5b61306d8161237b565b156130ad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016130a4906151bb565b60405180910390fd5b6130b960008383612d57565b6001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546131099190614022565b92505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46131ca60008383612e69565b5050565b505050565b6008805490506009600083815260200190815260200160002081905550600881908060018154018082558091505060019003906000526020600020016000909190919091505550565b600060016132298461165a565b6132339190614056565b9050600060076000848152602001908152602001600020549050818114613318576000600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002054905080600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002081905550816007600083815260200190815260200160002081905550505b6007600084815260200190815260200160002060009055600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000905550505050565b6000600160088054905061339d9190614056565b90506000600960008481526020019081526020016000205490506000600883815481106133cd576133cc61439e565b5b9060005260206000200154905080600883815481106133ef576133ee61439e565b5b90600052602060002001819055508160096000838152602001908152602001600020819055506009600085815260200190815260200160002060009055600880548061343e5761343d6151db565b5b6001900381819060005260206000200160009055905550505050565b60006134658361165a565b905081600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002081905550806007600084815260200190815260200160002081905550505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61354581613510565b811461355057600080fd5b50565b6000813590506135628161353c565b92915050565b60006020828403121561357e5761357d613506565b5b600061358c84828501613553565b91505092915050565b60008115159050919050565b6135aa81613595565b82525050565b60006020820190506135c560008301846135a1565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156136055780820151818401526020810190506135ea565b60008484015250505050565b6000601f19601f8301169050919050565b600061362d826135cb565b61363781856135d6565b93506136478185602086016135e7565b61365081613611565b840191505092915050565b600060208201905081810360008301526136758184613622565b905092915050565b6000819050919050565b6136908161367d565b811461369b57600080fd5b50565b6000813590506136ad81613687565b92915050565b6000602082840312156136c9576136c8613506565b5b60006136d78482850161369e565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061370b826136e0565b9050919050565b61371b81613700565b82525050565b60006020820190506137366000830184613712565b92915050565b61374581613700565b811461375057600080fd5b50565b6000813590506137628161373c565b92915050565b6000806040838503121561377f5761377e613506565b5b600061378d85828601613753565b925050602061379e8582860161369e565b9150509250929050565b6137b18161367d565b82525050565b60006020820190506137cc60008301846137a8565b92915050565b6000602082840312156137e8576137e7613506565b5b60006137f684828501613753565b91505092915050565b60008060006060848603121561381857613817613506565b5b600061382686828701613753565b935050602061383786828701613753565b92505060406138488682870161369e565b9150509250925092565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61388f82613611565b810181811067ffffffffffffffff821117156138ae576138ad613857565b5b80604052505050565b60006138c16134fc565b90506138cd8282613886565b919050565b600067ffffffffffffffff8211156138ed576138ec613857565b5b602082029050602081019050919050565b600080fd5b6000613916613911846138d2565b6138b7565b90508083825260208201905060208402830185811115613939576139386138fe565b5b835b81811015613962578061394e8882613753565b84526020840193505060208101905061393b565b5050509392505050565b600082601f83011261398157613980613852565b5b8135613991848260208601613903565b91505092915050565b6000602082840312156139b0576139af613506565b5b600082013567ffffffffffffffff8111156139ce576139cd61350b565b5b6139da8482850161396c565b91505092915050565b600060ff82169050919050565b6139f9816139e3565b8114613a0457600080fd5b50565b600081359050613a16816139f0565b92915050565b60008060408385031215613a3357613a32613506565b5b6000613a418582860161369e565b9250506020613a5285828601613a07565b9150509250929050565b600080fd5b600067ffffffffffffffff821115613a7c57613a7b613857565b5b613a8582613611565b9050602081019050919050565b82818337600083830152505050565b6000613ab4613aaf84613a61565b6138b7565b905082815260208101848484011115613ad057613acf613a5c565b5b613adb848285613a92565b509392505050565b600082601f830112613af857613af7613852565b5b8135613b08848260208601613aa1565b91505092915050565b600060208284031215613b2757613b26613506565b5b600082013567ffffffffffffffff811115613b4557613b4461350b565b5b613b5184828501613ae3565b91505092915050565b613b6381613595565b8114613b6e57600080fd5b50565b600081359050613b8081613b5a565b92915050565b60008060408385031215613b9d57613b9c613506565b5b6000613bab85828601613753565b9250506020613bbc85828601613b71565b9150509250929050565b600080600060608486031215613bdf57613bde613506565b5b6000613bed8682870161369e565b9350506020613bfe8682870161369e565b9250506040613c0f86828701613a07565b9150509250925092565b600067ffffffffffffffff821115613c3457613c33613857565b5b613c3d82613611565b9050602081019050919050565b6000613c5d613c5884613c19565b6138b7565b905082815260208101848484011115613c7957613c78613a5c565b5b613c84848285613a92565b509392505050565b600082601f830112613ca157613ca0613852565b5b8135613cb1848260208601613c4a565b91505092915050565b60008060008060808587031215613cd457613cd3613506565b5b6000613ce287828801613753565b9450506020613cf387828801613753565b9350506040613d048782880161369e565b925050606085013567ffffffffffffffff811115613d2557613d2461350b565b5b613d3187828801613c8c565b91505092959194509250565b600067ffffffffffffffff821115613d5857613d57613857565b5b602082029050602081019050919050565b6000613d7c613d7784613d3d565b6138b7565b90508083825260208201905060208402830185811115613d9f57613d9e6138fe565b5b835b81811015613dc85780613db4888261369e565b845260208401935050602081019050613da1565b5050509392505050565b600082601f830112613de757613de6613852565b5b8135613df7848260208601613d69565b91505092915050565b600060208284031215613e1657613e15613506565b5b600082013567ffffffffffffffff811115613e3457613e3361350b565b5b613e4084828501613dd2565b91505092915050565b60008060408385031215613e6057613e5f613506565b5b6000613e6e85828601613753565b9250506020613e7f85828601613753565b9150509250929050565b7f4d696e74696e6720686173206e6f742073746172746564207965742e00000000600082015250565b6000613ebf601c836135d6565b9150613eca82613e89565b602082019050919050565b60006020820190508181036000830152613eee81613eb2565b9050919050565b7f4e6f74206f6e205941594f20486f6c6465722057686974656c69737421000000600082015250565b6000613f2b601d836135d6565b9150613f3682613ef5565b602082019050919050565b60006020820190508181036000830152613f5a81613f1e565b9050919050565b7f5765277265206f75742120537461792074756e656420666f72206d6f7265205260008201527f454d494c49412070726f64756374696f6e73207e2e6f00000000000000000000602082015250565b6000613fbd6036836135d6565b9150613fc882613f61565b604082019050919050565b60006020820190508181036000830152613fec81613fb0565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061402d8261367d565b91506140388361367d565b92508282019050808211156140505761404f613ff3565b5b92915050565b60006140618261367d565b915061406c8361367d565b925082820390508181111561408457614083613ff3565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806140d157607f821691505b6020821081036140e4576140e361408a565b5b50919050565b7f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b6000614146602c836135d6565b9150614151826140ea565b604082019050919050565b6000602082019050818103600083015261417581614139565b9050919050565b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b60006141d86021836135d6565b91506141e38261417c565b604082019050919050565b60006020820190508181036000830152614207816141cb565b9050919050565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760008201527f6e6572206e6f7220617070726f76656420666f7220616c6c0000000000000000602082015250565b600061426a6038836135d6565b91506142758261420e565b604082019050919050565b600060208201905081810360008301526142998161425d565b9050919050565b7f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60008201527f776e6572206e6f7220617070726f766564000000000000000000000000000000602082015250565b60006142fc6031836135d6565b9150614307826142a0565b604082019050919050565b6000602082019050818103600083015261432b816142ef565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006143686020836135d6565b915061437382614332565b602082019050919050565b600060208201905081810360008301526143978161435b565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006143d88261367d565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361440a57614409613ff3565b5b600182019050919050565b7f455243373231456e756d657261626c653a206f776e657220696e646578206f7560008201527f74206f6620626f756e6473000000000000000000000000000000000000000000602082015250565b6000614471602b836135d6565b915061447c82614415565b604082019050919050565b600060208201905081810360008301526144a081614464565b9050919050565b60006144b28261367d565b91506144bd8361367d565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156144f6576144f5613ff3565b5b828202905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061453b8261367d565b91506145468361367d565b92508261455657614555614501565b5b828204905092915050565b7f4d6178696d756d2077686974656c69737420646973636f756e74206d696e747360008201527f20726561636865642e0000000000000000000000000000000000000000000000602082015250565b60006145bd6029836135d6565b91506145c882614561565b604082019050919050565b600060208201905081810360008301526145ec816145b0565b9050919050565b7f496e636f727265637420616d6f756e74206f66207765692073656e742e000000600082015250565b6000614629601d836135d6565b9150614634826145f3565b602082019050919050565b600060208201905081810360008301526146588161461c565b9050919050565b7f4f6f707321204c6f6f6b73206c696b6520796f75277265206e6f7420636f6f6c60008201527f20656e6f75676820666f7220746869732e000000000000000000000000000000602082015250565b60006146bb6031836135d6565b91506146c68261465f565b604082019050919050565b600060208201905081810360008301526146ea816146ae565b9050919050565b7f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60008201527f7574206f6620626f756e64730000000000000000000000000000000000000000602082015250565b600061474d602c836135d6565b9150614758826146f1565b604082019050919050565b6000602082019050818103600083015261477c81614740565b9050919050565b7f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460008201527f656e7420746f6b656e0000000000000000000000000000000000000000000000602082015250565b60006147df6029836135d6565b91506147ea82614783565b604082019050919050565b6000602082019050818103600083015261480e816147d2565b9050919050565b7f4552433732313a2062616c616e636520717565727920666f7220746865207a6560008201527f726f206164647265737300000000000000000000000000000000000000000000602082015250565b6000614871602a836135d6565b915061487c82614815565b604082019050919050565b600060208201905081810360008301526148a081614864565b9050919050565b7f596f7527766520616c7265616479207374617274656420746865206d696e746960008201527f6e672e0000000000000000000000000000000000000000000000000000000000602082015250565b60006149036023836135d6565b915061490e826148a7565b604082019050919050565b60006020820190508181036000830152614932816148f6565b9050919050565b7f4552433732314d657461646174613a2055524920717565727920666f72206e6f60008201527f6e6578697374656e7420746f6b656e0000000000000000000000000000000000602082015250565b6000614995602f836135d6565b91506149a082614939565b604082019050919050565b600060208201905081810360008301526149c481614988565b9050919050565b600081905092915050565b60006149e1826135cb565b6149eb81856149cb565b93506149fb8185602086016135e7565b80840191505092915050565b6000614a1382856149d6565b9150614a1f82846149d6565b91508190509392505050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000614a876026836135d6565b9150614a9282614a2b565b604082019050919050565b60006020820190508181036000830152614ab681614a7a565b9050919050565b7f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b6000614b19602c836135d6565b9150614b2482614abd565b604082019050919050565b60006020820190508181036000830152614b4881614b0c565b9050919050565b7f4552433732313a207472616e736665722066726f6d20696e636f72726563742060008201527f6f776e6572000000000000000000000000000000000000000000000000000000602082015250565b6000614bab6025836135d6565b9150614bb682614b4f565b604082019050919050565b60006020820190508181036000830152614bda81614b9e565b9050919050565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b6000614c3d6024836135d6565b9150614c4882614be1565b604082019050919050565b60006020820190508181036000830152614c6c81614c30565b9050919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302614cd57fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82614c98565b614cdf8683614c98565b95508019841693508086168417925050509392505050565b6000819050919050565b6000614d1c614d17614d128461367d565b614cf7565b61367d565b9050919050565b6000819050919050565b614d3683614d01565b614d4a614d4282614d23565b848454614ca5565b825550505050565b600090565b614d5f614d52565b614d6a818484614d2d565b505050565b5b81811015614d8e57614d83600082614d57565b600181019050614d70565b5050565b601f821115614dd357614da481614c73565b614dad84614c88565b81016020851015614dbc578190505b614dd0614dc885614c88565b830182614d6f565b50505b505050565b600082821c905092915050565b6000614df660001984600802614dd8565b1980831691505092915050565b6000614e0f8383614de5565b9150826002028217905092915050565b614e28826135cb565b67ffffffffffffffff811115614e4157614e40613857565b5b614e4b82546140b9565b614e56828285614d92565b600060209050601f831160018114614e895760008415614e77578287015190505b614e818582614e03565b865550614ee9565b601f198416614e9786614c73565b60005b82811015614ebf57848901518255600182019150602085019450602081019050614e9a565b86831015614edc5784890151614ed8601f891682614de5565b8355505b6001600288020188555050505b505050505050565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b6000614f276019836135d6565b9150614f3282614ef1565b602082019050919050565b60006020820190508181036000830152614f5681614f1a565b9050919050565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b6000614fb96032836135d6565b9150614fc482614f5d565b604082019050919050565b60006020820190508181036000830152614fe881614fac565b9050919050565b6000614ffa8261367d565b91506150058361367d565b92508261501557615014614501565b5b828206905092915050565b600081519050919050565b600082825260208201905092915050565b600061504782615020565b615051818561502b565b93506150618185602086016135e7565b61506a81613611565b840191505092915050565b600060808201905061508a6000830187613712565b6150976020830186613712565b6150a460408301856137a8565b81810360608301526150b6818461503c565b905095945050505050565b6000815190506150d08161353c565b92915050565b6000602082840312156150ec576150eb613506565b5b60006150fa848285016150c1565b91505092915050565b7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373600082015250565b60006151396020836135d6565b915061514482615103565b602082019050919050565b600060208201905081810360008301526151688161512c565b9050919050565b7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000600082015250565b60006151a5601c836135d6565b91506151b08261516f565b602082019050919050565b600060208201905081810360008301526151d481615198565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea2646970667358221220887fb454ea50b98ef908a2261b27828e97bcc71177334885d6f2a10697d8005b64736f6c63430008100033