Contract 0x4772fb92e6606c87f7cddccdb880f7677768815c 3

 
Txn Hash Method
Block
From
To
Value [Txn Fee]
0x7a2310137107df03298b96ff47830053454b7e333be8062cf67ab45db3b41ee8Safe Transfer Fr...275329972022-09-30 5:36:146 hrs 51 mins ago0xf7200f7a475b53446a10421dea95299fa9319a85 IN  0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH0.00002295
0x8c1727dc70de08bfe2879cd113cb0d3a3c3c0efb2ecf46737b71c5e6005e771fSet Approval For...275052802022-09-30 1:38:0710 hrs 49 mins ago0x9401ff1ee5076e46ec2342954e5dc72184777970 IN  0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH0.00001987
0xe83d2ae08c20417808c32aa24e8579472b7312b395cdb9e91e4d53ec0aa60e8fSet Approval For...275048162022-09-30 1:33:2210 hrs 54 mins ago0x9401ff1ee5076e46ec2342954e5dc72184777970 IN  0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH0.00001988
0xa3ca80e5c415668ba15f0aa47e16068ea4e2c692fb70bbf4b172f2d5ecf851a4Set Approval For...275039032022-09-30 1:22:2811 hrs 5 mins ago0x90e23d451a716bf25987f055e3e57c1384337fde IN  0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH0.00019818
0x88fce64dc6a9b43daaeff76da1f15e01c72188dcec8de908bfbc6621a9d2e0a5Set Approval For...274656182022-09-29 18:12:0718 hrs 15 mins ago0x413a5b0399745d7fe0f55f51deedb87c43460d32 IN  0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH0.00003201
0xdd4454619d1f8e4dc68cc26dc9ad804780110858450dc124ebbf429735059300Set Approval For...274628962022-09-29 17:55:0418 hrs 32 mins ago0x45c2188ec89cce1f0d08b41ffe6c7efb7e72479f IN  0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH0.00003775
0xe28a9077fce897d45ffc3b5fd66e3a145ea2aea115714403a425b126424e1168Set Approval For...272815782022-09-28 20:01:471 day 16 hrs ago0x9c13dc78840be88b51b9e31afaa7e9705e3e4fe3 IN  0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH0.00003773
0x96a3a1aaf02c8792cdb5dee1d1682c3d9c637793fed20ba69b42de0b74e0b047Set Approval For...271689462022-09-28 8:52:082 days 3 hrs ago0x27160e7acde498a0d431035d79f57cf640e8a8a9 IN  0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH0.00001914
0x9374af4970532129615eb2afaff5b14902ff60ccbb034ef8d3c6c0f3504713ccSet Approval For...271149582022-09-28 3:59:092 days 8 hrs ago0xff209651029de229108553c3fd3115b570327de6 IN  0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH0.00002026
0x54562360fc28c8869151a2e01863f031db02ddf34dfe53a9cad6a9ea9b886838Safe Transfer Fr...270891562022-09-28 1:41:262 days 10 hrs ago0x564b97df9e25d570312a8ddeb32f7027a52fc558 IN  0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH0.00002196
0x697618674d37d9e6f0b57c0252a3ee2a7cfc36979022a753c94f48eb4cb8f1b6Safe Transfer Fr...270890032022-09-28 1:40:292 days 10 hrs ago0x564b97df9e25d570312a8ddeb32f7027a52fc558 IN  0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH0.00002296
0x62ce954fd1dca0682de719875db817bc2e35b4d97ebf97263de9805df49dd23dSafe Transfer Fr...270887612022-09-28 1:38:592 days 10 hrs ago0x564b97df9e25d570312a8ddeb32f7027a52fc558 IN  0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH0.00002256
0xf212460969c299030fb20c50c8fc23e3669303751788eeab751d5e04d473e630Set Approval For...270589722022-09-27 20:44:342 days 15 hrs ago0x2397a6621ba076e9d0afac4cc6eee8e5c0397603 IN  0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH0.00003345
0xfa2866b7a9e0a8037909c9606588e3c913654a94a190117d58e22cb0ef06606aSet Approval For...268033772022-09-26 12:37:013 days 23 hrs ago0x0000000000dfa724d4232675d9fa6c3f4945dccc IN  0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH0.00000969
0xbe6b45c96326c8124576e53a374caad3bb0b642139ae3dfe249e2fa2f5e85aadSet Approval For...266021332022-09-25 14:18:424 days 22 hrs ago0x87cfdc4bfae569088bc1bcc0dd3c19f53da54193 IN  0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH0.00001249
0xfa899f1832b265abc161ec7517de7e597ee473051a67a190cf77d0581ae1e151Set Approval For...265311852022-09-25 7:40:035 days 4 hrs ago0x9c2ce1e7e220ab4b7ea3e8f52d93b752cb2492f3 IN  0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH0.00000967
0x1462bf9a4020d3199bfa64ca91ad3e9fe997739b7c9afab0f8f3dd4628550642Set Approval For...265243262022-09-25 7:00:585 days 5 hrs ago0x406ae1cda2b34c0000295f6bd4e7266549a60f4f IN  0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH0.00000926
0x698cc43021c30d964306ea21693002c07ecbf5550d77524e8074f32bfdc5d46cSet Approval For...265240782022-09-25 6:59:355 days 5 hrs ago0x21408e4478f84a8e891758bde30bc1d421d3f33a IN  0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH0.00000944
0x62de4844b5f9203d37603a4ea0de24db6122c7d8d902f5954f486c845953988cSet Approval For...265235882022-09-25 6:56:325 days 5 hrs ago0x40e7992345b92366627024ae6ec8ed4ef4d68021 IN  0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH0.00000947
0xa122988ed269de9d3ed1c30cb2ff44b98ad2db5acbbd6a2868b23ad38b0cb8d0Set Approval For...264990532022-09-25 3:56:515 days 8 hrs ago0x0dd189d8a05d4c7308aa5e08dba80ed57b9a5fbd IN  0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH0.00001012
0x949da5884b683f3f57742b702fb3fd4c2861b5a8ebd1c5026416dd98eaeb0ad8Set Approval For...264659982022-09-24 22:36:225 days 13 hrs ago0x66634a5014e37b4c16592bdf2ea65254de0db675 IN  0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH0.00001438
0xe1968080329f8375d1773c8fe12121737767f10350413556fc044545ef837a77Set Approval For...263771352022-09-24 11:29:296 days 58 mins ago0x99fdd2a67ba5ec9fb98f451f0e88d0fbec1ee121 IN  0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH0.00001074
0x8bf335b7d27e3d66544fa56c379c9865b470dcaa6da00147d2947498dcd8e83cSet Approval For...263431352022-09-24 7:49:316 days 4 hrs ago0x79f37a3d42b19bca7a67c5a312aef3066619ae67 IN  0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH0.00000961
0x2e2c42b20100596b97191ca43f0e69025cfd3c70cfacf66bdac7e95ded6c83b0Set Approval For...263422462022-09-24 7:42:326 days 4 hrs ago0x88840c37e8fa21afe5c28f0c704f9dcbd1601a45 IN  0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH0.00000931
0xee471d2e396b3701a0015ae3fc78a2cacf1ae417cd0be8ec36d4a6806d5989bdSet Approval For...263097952022-09-24 3:57:066 days 8 hrs ago0xa3494ba0c42588d1e62df80c04147ae4252652ae IN  0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH0.00001016
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0xc9172cf07cb33fb67c4652a4d390dcf4dbd2c3840f718ff5775d4a2c3e4666b4275901042022-09-30 11:47:5140 mins ago 0x1e0049783f008a0085193e00003d00cd54003c71 0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH
0xbdabca9ea284b561e3bd83a639fdc97d2e493406dd3d48b0a4a3403a79114b0b275900082022-09-30 11:47:2140 mins ago 0x1e0049783f008a0085193e00003d00cd54003c71 0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH
0x68a401184143a60694e85d46d62d10513d6f526a1536eeccf4ebaffe5e99e060275899292022-09-30 11:46:5641 mins ago 0x1e0049783f008a0085193e00003d00cd54003c71 0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH
0x1f3d045c7e1396eb2a6e04d66e6d1b9ca8c8924cdcd2e9dd3ff9999b58501672275037372022-09-30 1:20:3611 hrs 7 mins ago 0x1e0049783f008a0085193e00003d00cd54003c71 0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH
0x71f8ff226e969d2c08cc08833a8c340b9d4dbdbed02a67044aa6ad3b397f1949275036412022-09-30 1:19:4411 hrs 8 mins ago 0x1e0049783f008a0085193e00003d00cd54003c71 0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH
0x91007f5942f7b5bed4081ebee73f23327f3cf9e8c3d3a138b80554b1b128af2b274553862022-09-29 16:50:5919 hrs 37 mins ago 0x1e0049783f008a0085193e00003d00cd54003c71 0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH
0xd853c48d2fa65033c5087c5360321f0bb4ea6bef0f66855039131561c6918c58274551572022-09-29 16:49:2619 hrs 38 mins ago 0x1e0049783f008a0085193e00003d00cd54003c71 0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH
0xad2ca2e9c680b173ccac0a805b9b4ccd2ae77fcd5a53366950a6ca89499f1aa8272411852022-09-28 15:02:031 day 21 hrs ago 0x998ef16ea4111094eb5ee72fc2c6f4e6e8647666 0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH
0xf5994f989b671e179a8b5787bf9f3e93c8f61a480adff9c2fe20ff570e5ba62d271697562022-09-28 8:56:152 days 3 hrs ago 0x1e0049783f008a0085193e00003d00cd54003c71 0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH
0x74010088fc3d54454f44935e50df79e034c849e4a632f628a9517bbcfe386e1f271689712022-09-28 8:52:142 days 3 hrs ago 0x1e0049783f008a0085193e00003d00cd54003c71 0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH
0x4e8ac1d818bada530eec192327a6e231bd8154995771af32f03cb627654d2bbe269203222022-09-27 4:18:463 days 8 hrs ago 0x1e0049783f008a0085193e00003d00cd54003c71 0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH
0xe194c84b82de90d45817bc465918ca5c7e2b8198febf195b10c5b9b705ed22cb265510552022-09-25 9:38:245 days 2 hrs ago 0x998ef16ea4111094eb5ee72fc2c6f4e6e8647666 0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH
0x941112a3206792502223a6c73873c14ccdf90366487acc34f58f36f2a73f87ff265256142022-09-25 7:08:435 days 5 hrs ago 0x1e0049783f008a0085193e00003d00cd54003c71 0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH
0xfe8bb625f17c83f0a6bc8bc43fdf48ff1487ca214e10673a04973b55480ea3ef265255532022-09-25 7:08:235 days 5 hrs ago 0x1e0049783f008a0085193e00003d00cd54003c71 0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH
0x6e4f5d166506c04e85b9fa6c0517df43131fac166af8d1e6a7d690c248e96026265255062022-09-25 7:08:035 days 5 hrs ago 0x1e0049783f008a0085193e00003d00cd54003c71 0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH
0xa99dddfeeee90a72119ed1b5ea7aef2f4fb2940dbffe2c919b3a7b1e538c3400265242732022-09-25 7:00:405 days 5 hrs ago 0x1e0049783f008a0085193e00003d00cd54003c71 0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH
0xb5af1b635e88dbc3867313c7b14e6bf91abc21105d3f804a4fc67950e06ae572265239222022-09-25 6:58:275 days 5 hrs ago 0x1e0049783f008a0085193e00003d00cd54003c71 0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH
0x3d166842648acfffab711fd3e5aa91bd83e4b15aea7cf7d1970645c567021412265234302022-09-25 6:55:345 days 5 hrs ago 0x1e0049783f008a0085193e00003d00cd54003c71 0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH
0xe0d79b1c52e527b58fc53b12a7eee256a8a0febfe451ab43deeecedc1e69b197265233862022-09-25 6:55:165 days 5 hrs ago 0x1e0049783f008a0085193e00003d00cd54003c71 0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH
0x7b38b9bbcb5530d7a5f734e66768fe1109fd5276168721bd6c2d6e1a7d87b173265055442022-09-25 4:50:155 days 7 hrs ago 0x998ef16ea4111094eb5ee72fc2c6f4e6e8647666 0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH
0x8ff318891cb583855ed14189a8c2be1aacaf94f5cee58054f9bd125febb33914264538622022-09-24 20:42:075 days 15 hrs ago 0x1e0049783f008a0085193e00003d00cd54003c71 0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH
0xe24aac700b96cdc9e9c08e64cb9c105138623e94f4da94f2a741ad205286fc62264538152022-09-24 20:41:435 days 15 hrs ago 0x1e0049783f008a0085193e00003d00cd54003c71 0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH
0xb455f203ef4279de5bbe3c3ff8fbf186695e2a56c9d2f1bbf15f96ef97cade13263771412022-09-24 11:29:336 days 58 mins ago 0x1e0049783f008a0085193e00003d00cd54003c71 0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH
0x9638a98951d297a2e0918aec2032e163204a4a00377c41f05e65d0d08b6b012c263217522022-09-24 5:28:236 days 6 hrs ago 0x1e0049783f008a0085193e00003d00cd54003c71 0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH
0xea0977d0099124fe35d19ed46f0b66af4cd797ca8135888f1aed3233edb8c287263217122022-09-24 5:28:006 days 7 hrs ago 0x1e0049783f008a0085193e00003d00cd54003c71 0x4772fb92e6606c87f7cddccdb880f7677768815c0 ETH
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Nfts

Compiler Version
v0.8.4+commit.c7e474f2

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Arbiscan on 2021-09-13
*/

// Sources flattened with hardhat v2.6.0 https://hardhat.org

// File contracts/erc721.sol

// SPDX-License-Identifier: MIT
pragma solidity 0.8.4;

/**
 * @dev ERC-721 non-fungible token standard.
 * See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md.
 */
interface ERC721 {
	/**
	 * @dev Emits when ownership of any NFT changes by any mechanism. This event emits when NFTs are
	 * created (`from` == 0) and destroyed (`to` == 0). Exception: during contract creation, any
	 * number of NFTs may be created and assigned without emitting Transfer. At the time of any
	 * transfer, the approved address for that NFT (if any) is reset to none.
	 */
	event Transfer(
		address indexed _from,
		address indexed _to,
		uint256 indexed _tokenId
	);

	/**
	 * @dev This emits when the approved address for an NFT is changed or reaffirmed. The zero
	 * address indicates there is no approved address. When a Transfer event emits, this also
	 * indicates that the approved address for that NFT (if any) is reset to none.
	 */
	event Approval(
		address indexed _owner,
		address indexed _approved,
		uint256 indexed _tokenId
	);

	/**
	 * @dev This emits when an operator is enabled or disabled for an owner. The operator can manage
	 * all NFTs of the owner.
	 */
	event ApprovalForAll(
		address indexed _owner,
		address indexed _operator,
		bool _approved
	);

	/**
	 * @notice Throws unless `msg.sender` is the current owner, an authorized operator, or the
	 * approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is
	 * the zero address. Throws if `_tokenId` is not a valid NFT. When transfer is complete, this
	 * function checks if `_to` is a smart contract (code size > 0). If so, it calls
	 * `onERC721Received` on `_to` and throws if the return value is not
	 * `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`.
	 * @dev Transfers the ownership of an NFT from one address to another address. This function can
	 * be changed to payable.
	 * @param _from The current owner of the NFT.
	 * @param _to The new owner.
	 * @param _tokenId The NFT to transfer.
	 * @param _data Additional data with no specified format, sent in call to `_to`.
	 */
	function safeTransferFrom(
		address _from,
		address _to,
		uint256 _tokenId,
		bytes calldata _data
	) external;

	/**
	 * @notice This works identically to the other function with an extra data parameter, except this
	 * function just sets data to ""
	 * @dev Transfers the ownership of an NFT from one address to another address. This function can
	 * be changed to payable.
	 * @param _from The current owner of the NFT.
	 * @param _to The new owner.
	 * @param _tokenId The NFT to transfer.
	 */
	function safeTransferFrom(
		address _from,
		address _to,
		uint256 _tokenId
	) external;

	/**
	 * @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else
	 * they may be permanently lost.
	 * @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved
	 * address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero
	 * address. Throws if `_tokenId` is not a valid NFT.  This function can be changed to payable.
	 * @param _from The current owner of the NFT.
	 * @param _to The new owner.
	 * @param _tokenId The NFT to transfer.
	 */
	function transferFrom(
		address _from,
		address _to,
		uint256 _tokenId
	) external;

	/**
	 * @notice The zero address indicates there is no approved address. Throws unless `msg.sender` is
	 * the current NFT owner, or an authorized operator of the current owner.
	 * @param _approved The new approved NFT controller.
	 * @dev Set or reaffirm the approved address for an NFT. This function can be changed to payable.
	 * @param _tokenId The NFT to approve.
	 */
	function approve(address _approved, uint256 _tokenId) external;

	/**
	 * @notice The contract MUST allow multiple operators per owner.
	 * @dev Enables or disables approval for a third party ("operator") to manage all of
	 * `msg.sender`'s assets. It also emits the ApprovalForAll event.
	 * @param _operator Address to add to the set of authorized operators.
	 * @param _approved True if the operators is approved, false to revoke approval.
	 */
	function setApprovalForAll(address _operator, bool _approved) external;

	/**
	 * @dev Returns the number of NFTs owned by `_owner`. NFTs assigned to the zero address are
	 * considered invalid, and this function throws for queries about the zero address.
	 * @notice Count all NFTs assigned to an owner.
	 * @param _owner Address for whom to query the balance.
	 * @return Balance of _owner.
	 */
	function balanceOf(address _owner) external view returns (uint256);

	/**
	 * @notice Find the owner of an NFT.
	 * @dev Returns the address of the owner of the NFT. NFTs assigned to the zero address are
	 * considered invalid, and queries about them do throw.
	 * @param _tokenId The identifier for an NFT.
	 * @return Address of _tokenId owner.
	 */
	function ownerOf(uint256 _tokenId) external view returns (address);

	/**
	 * @notice Throws if `_tokenId` is not a valid NFT.
	 * @dev Get the approved address for a single NFT.
	 * @param _tokenId The NFT to find the approved address for.
	 * @return Address that _tokenId is approved for.
	 */
	function getApproved(uint256 _tokenId) external view returns (address);

	/**
	 * @notice Query if an address is an authorized operator for another address.
	 * @dev Returns true if `_operator` is an approved operator for `_owner`, false otherwise.
	 * @param _owner The address that owns the NFTs.
	 * @param _operator The address that acts on behalf of the owner.
	 * @return True if approved for all, false otherwise.
	 */
	function isApprovedForAll(address _owner, address _operator)
		external
		view
		returns (bool);
}

// File contracts/erc721-token-receiver.solpragma solidity 0.8.4;

/**
 * @dev ERC-721 interface for accepting safe transfers.
 * See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md.
 */
interface ERC721TokenReceiver {
	/**
	 * @notice The contract address is always the message sender. A wallet/broker/auction application
	 * MUST implement the wallet interface if it will accept safe transfers.
	 * @dev Handle the receipt of a NFT. The ERC721 smart contract calls this function on the
	 * recipient after a `transfer`. This function MAY throw to revert and reject the transfer. Return
	 * of other than the magic value MUST result in the transaction being reverted.
	 * Returns `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` unless throwing.
	 * @param _operator The address which called `safeTransferFrom` function.
	 * @param _from The address which previously owned the token.
	 * @param _tokenId The NFT identifier which is being transferred.
	 * @param _data Additional data with no specified format.
	 * @return Returns `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`.
	 */
	function onERC721Received(
		address _operator,
		address _from,
		uint256 _tokenId,
		bytes calldata _data
	) external returns (bytes4);
}

// File contracts/erc165.solpragma solidity 0.8.4;

/**
 * @dev A standard for detecting smart contract interfaces.
 * See: https://eips.ethereum.org/EIPS/eip-165.
 */
interface ERC165 {
	/**
	 * @dev Checks if the smart contract includes a specific interface.
	 * This function uses less than 30,000 gas.
	 * @param _interfaceID The interface identifier, as specified in ERC-165.
	 * @return True if _interfaceID is supported, false otherwise.
	 */
	function supportsInterface(bytes4 _interfaceID)
		external
		view
		returns (bool);
}

// File contracts/supports-interface.sol

pragma solidity 0.8.4;
/**
 * @dev Implementation of standard for detect smart contract interfaces.
 */

contract SupportsInterface is ERC165 {
	/**
	 * @dev Mapping of supported intefraces. You must not set element 0xffffffff to true.
	 */
	mapping(bytes4 => bool) internal supportedInterfaces;

	/**
	 * @dev Contract constructor.
	 */
	constructor() {
		supportedInterfaces[0x01ffc9a7] = true; // ERC165
	}

	/**
	 * @dev Function to check which interfaces are suported by this contract.
	 * @param _interfaceID Id of the interface.
	 * @return True if _interfaceID is supported, false otherwise.
	 */
	function supportsInterface(bytes4 _interfaceID)
		external
		view
		override
		returns (bool)
	{
		return supportedInterfaces[_interfaceID];
	}
}

// File contracts/address-utils.sol
pragma solidity 0.8.4;

/**
 * @notice Based on:
 * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Address.sol
 * Requires EIP-1052.
 * @dev Utility library of inline functions on addresses.
 */
library AddressUtils {
	/**
	 * @dev Returns whether the target address is a contract.
	 * @param _addr Address to check.
	 * @return addressCheck True if _addr is a contract, false if not.
	 */
	function isContract(address _addr)
		internal
		view
		returns (bool addressCheck)
	{
		// This method relies in extcodesize, which returns 0 for contracts in
		// construction, since the code is only stored at the end of the
		// constructor execution.

		// According to EIP-1052, 0x0 is the value returned for not-yet created accounts
		// and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
		// for accounts without code, i.e. `keccak256('')`
		bytes32 codehash;
		bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
		assembly {
			codehash := extcodehash(_addr)
		} // solhint-disable-line
		addressCheck = (codehash != 0x0 && codehash != accountHash);
	}
}

// File contracts/nf-token.sol
pragma solidity 0.8.4;

/**
 * @dev Implementation of ERC-721 non-fungible token standard.
 */
contract NFToken is ERC721, SupportsInterface {
	using AddressUtils for address;

	/**
	 * @dev List of revert message codes. Implementing dApp should handle showing the correct message.
	 * Based on 0xcert framework error codes.
	 */
	string constant ZERO_ADDRESS = '003001';
	string constant NOT_VALID_NFT = '003002';
	string constant NOT_OWNER_OR_OPERATOR = '003003';
	string constant NOT_OWNER_APPROVED_OR_OPERATOR = '003004';
	string constant NOT_ABLE_TO_RECEIVE_NFT = '003005';
	string constant NFT_ALREADY_EXISTS = '003006';
	string constant NOT_OWNER = '003007';
	string constant IS_OWNER = '003008';

	/**
	 * @dev Magic value of a smart contract that can receive NFT.
	 * Equal to: bytes4(keccak256("onERC721Received(address,address,uint256,bytes)")).
	 */
	bytes4 internal constant MAGIC_ON_ERC721_RECEIVED = 0x150b7a02;

	/**
	 * @dev A mapping from NFT ID to the address that owns it.
	 */
	mapping(uint256 => address) internal idToOwner;

	/**
	 * @dev Mapping from NFT ID to approved address.
	 */
	mapping(uint256 => address) internal idToApproval;

	/**
	 * @dev Mapping from owner address to count of their tokens.
	 */
	mapping(address => uint256) private ownerToNFTokenCount;

	/**
	 * @dev Mapping from owner address to mapping of operator addresses.
	 */
	mapping(address => mapping(address => bool)) internal ownerToOperators;

	/**
	 * @dev Guarantees that the msg.sender is an owner or operator of the given NFT.
	 * @param _tokenId ID of the NFT to validate.
	 */
	modifier canOperate(uint256 _tokenId) {
		address tokenOwner = idToOwner[_tokenId];
		require(
			tokenOwner == msg.sender ||
				ownerToOperators[tokenOwner][msg.sender],
			NOT_OWNER_OR_OPERATOR
		);
		_;
	}

	/**
	 * @dev Guarantees that the msg.sender is allowed to transfer NFT.
	 * @param _tokenId ID of the NFT to transfer.
	 */
	modifier canTransfer(uint256 _tokenId) {
		address tokenOwner = idToOwner[_tokenId];
		require(
			tokenOwner == msg.sender ||
				idToApproval[_tokenId] == msg.sender ||
				ownerToOperators[tokenOwner][msg.sender],
			NOT_OWNER_APPROVED_OR_OPERATOR
		);
		_;
	}

	/**
	 * @dev Guarantees that _tokenId is a valid Token.
	 * @param _tokenId ID of the NFT to validate.
	 */
	modifier validNFToken(uint256 _tokenId) {
		require(idToOwner[_tokenId] != address(0), NOT_VALID_NFT);
		_;
	}

	/**
	 * @dev Contract constructor.
	 */
	constructor() {
		supportedInterfaces[0x80ac58cd] = true; // ERC721
	}

	/**
	 * @notice Throws unless `msg.sender` is the current owner, an authorized operator, or the
	 * approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is
	 * the zero address. Throws if `_tokenId` is not a valid NFT. When transfer is complete, this
	 * function checks if `_to` is a smart contract (code size > 0). If so, it calls
	 * `onERC721Received` on `_to` and throws if the return value is not
	 * `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`.
	 * @dev Transfers the ownership of an NFT from one address to another address. This function can
	 * be changed to payable.
	 * @param _from The current owner of the NFT.
	 * @param _to The new owner.
	 * @param _tokenId The NFT to transfer.
	 * @param _data Additional data with no specified format, sent in call to `_to`.
	 */
	function safeTransferFrom(
		address _from,
		address _to,
		uint256 _tokenId,
		bytes calldata _data
	) external override {
		_safeTransferFrom(_from, _to, _tokenId, _data);
	}

	/**
	 * @notice This works identically to the other function with an extra data parameter, except this
	 * function just sets data to "".
	 * @dev Transfers the ownership of an NFT from one address to another address. This function can
	 * be changed to payable.
	 * @param _from The current owner of the NFT.
	 * @param _to The new owner.
	 * @param _tokenId The NFT to transfer.
	 */
	function safeTransferFrom(
		address _from,
		address _to,
		uint256 _tokenId
	) external override {
		_safeTransferFrom(_from, _to, _tokenId, '');
	}

	/**
	 * @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else
	 * they may be permanently lost.
	 * @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved
	 * address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero
	 * address. Throws if `_tokenId` is not a valid NFT. This function can be changed to payable.
	 * @param _from The current owner of the NFT.
	 * @param _to The new owner.
	 * @param _tokenId The NFT to transfer.
	 */
	function transferFrom(
		address _from,
		address _to,
		uint256 _tokenId
	) external override canTransfer(_tokenId) validNFToken(_tokenId) {
		address tokenOwner = idToOwner[_tokenId];
		require(tokenOwner == _from, NOT_OWNER);
		require(_to != address(0), ZERO_ADDRESS);

		_transfer(_to, _tokenId);
	}

	/**
	 * @notice The zero address indicates there is no approved address. Throws unless `msg.sender` is
	 * the current NFT owner, or an authorized operator of the current owner.
	 * @dev Set or reaffirm the approved address for an NFT. This function can be changed to payable.
	 * @param _approved Address to be approved for the given NFT ID.
	 * @param _tokenId ID of the token to be approved.
	 */
	function approve(address _approved, uint256 _tokenId)
		external
		override
		canOperate(_tokenId)
		validNFToken(_tokenId)
	{
		address tokenOwner = idToOwner[_tokenId];
		require(_approved != tokenOwner, IS_OWNER);

		idToApproval[_tokenId] = _approved;
		emit Approval(tokenOwner, _approved, _tokenId);
	}

	/**
	 * @notice This works even if sender doesn't own any tokens at the time.
	 * @dev Enables or disables approval for a third party ("operator") to manage all of
	 * `msg.sender`'s assets. It also emits the ApprovalForAll event.
	 * @param _operator Address to add to the set of authorized operators.
	 * @param _approved True if the operators is approved, false to revoke approval.
	 */
	function setApprovalForAll(address _operator, bool _approved)
		external
		override
	{
		ownerToOperators[msg.sender][_operator] = _approved;
		emit ApprovalForAll(msg.sender, _operator, _approved);
	}

	/**
	 * @dev Returns the number of NFTs owned by `_owner`. NFTs assigned to the zero address are
	 * considered invalid, and this function throws for queries about the zero address.
	 * @param _owner Address for whom to query the balance.
	 * @return Balance of _owner.
	 */
	function balanceOf(address _owner)
		external
		view
		override
		returns (uint256)
	{
		require(_owner != address(0), ZERO_ADDRESS);
		return _getOwnerNFTCount(_owner);
	}

	/**
	 * @dev Returns the address of the owner of the NFT. NFTs assigned to the zero address are
	 * considered invalid, and queries about them do throw.
	 * @param _tokenId The identifier for an NFT.
	 * @return _owner Address of _tokenId owner.
	 */
	function ownerOf(uint256 _tokenId)
		external
		view
		override
		returns (address _owner)
	{
		_owner = idToOwner[_tokenId];
		require(_owner != address(0), NOT_VALID_NFT);
	}

	/**
	 * @notice Throws if `_tokenId` is not a valid NFT.
	 * @dev Get the approved address for a single NFT.
	 * @param _tokenId ID of the NFT to query the approval of.
	 * @return Address that _tokenId is approved for.
	 */
	function getApproved(uint256 _tokenId)
		external
		view
		override
		validNFToken(_tokenId)
		returns (address)
	{
		return idToApproval[_tokenId];
	}

	/**
	 * @dev Checks if `_operator` is an approved operator for `_owner`.
	 * @param _owner The address that owns the NFTs.
	 * @param _operator The address that acts on behalf of the owner.
	 * @return True if approved for all, false otherwise.
	 */
	function isApprovedForAll(address _owner, address _operator)
		external
		view
		override
		returns (bool)
	{
		return ownerToOperators[_owner][_operator];
	}

	/**
	 * @notice Does NO checks.
	 * @dev Actually performs the transfer.
	 * @param _to Address of a new owner.
	 * @param _tokenId The NFT that is being transferred.
	 */
	function _transfer(address _to, uint256 _tokenId) internal {
		address from = idToOwner[_tokenId];
		_clearApproval(_tokenId);

		_removeNFToken(from, _tokenId);
		_addNFToken(_to, _tokenId);

		emit Transfer(from, _to, _tokenId);
	}

	/**
	 * @notice This is an internal function which should be called from user-implemented external
	 * mint function. Its purpose is to show and properly initialize data structures when using this
	 * implementation.
	 * @dev Mints a new NFT.
	 * @param _to The address that will own the minted NFT.
	 * @param _tokenId of the NFT to be minted by the msg.sender.
	 */
	function _mint(address _to, uint256 _tokenId) internal virtual {
		require(_to != address(0), ZERO_ADDRESS);
		require(idToOwner[_tokenId] == address(0), NFT_ALREADY_EXISTS);

		_addNFToken(_to, _tokenId);

		emit Transfer(address(0), _to, _tokenId);
	}

	/**
	 * @notice This is an internal function which should be called from user-implemented external burn
	 * function. Its purpose is to show and properly initialize data structures when using this
	 * implementation. Also, note that this burn implementation allows the minter to re-mint a burned
	 * NFT.
	 * @dev Burns a NFT.
	 * @param _tokenId ID of the NFT to be burned.
	 */
	function _burn(uint256 _tokenId) internal virtual validNFToken(_tokenId) {
		address tokenOwner = idToOwner[_tokenId];
		_clearApproval(_tokenId);
		_removeNFToken(tokenOwner, _tokenId);
		emit Transfer(tokenOwner, address(0), _tokenId);
	}

	/**
	 * @notice Use and override this function with caution. Wrong usage can have serious consequences.
	 * @dev Removes a NFT from owner.
	 * @param _from Address from which we want to remove the NFT.
	 * @param _tokenId Which NFT we want to remove.
	 */
	function _removeNFToken(address _from, uint256 _tokenId) internal virtual {
		require(idToOwner[_tokenId] == _from, NOT_OWNER);
		ownerToNFTokenCount[_from] -= 1;
		delete idToOwner[_tokenId];
	}

	/**
	 * @notice Use and override this function with caution. Wrong usage can have serious consequences.
	 * @dev Assigns a new NFT to owner.
	 * @param _to Address to which we want to add the NFT.
	 * @param _tokenId Which NFT we want to add.
	 */
	function _addNFToken(address _to, uint256 _tokenId) internal virtual {
		require(idToOwner[_tokenId] == address(0), NFT_ALREADY_EXISTS);

		idToOwner[_tokenId] = _to;
		ownerToNFTokenCount[_to] += 1;
	}

	/**
	 * @dev Helper function that gets NFT count of owner. This is needed for overriding in enumerable
	 * extension to remove double storage (gas optimization) of owner NFT count.
	 * @param _owner Address for whom to query the count.
	 * @return Number of _owner NFTs.
	 */
	function _getOwnerNFTCount(address _owner)
		internal
		view
		virtual
		returns (uint256)
	{
		return ownerToNFTokenCount[_owner];
	}

	/**
	 * @dev Actually perform the safeTransferFrom.
	 * @param _from The current owner of the NFT.
	 * @param _to The new owner.
	 * @param _tokenId The NFT to transfer.
	 * @param _data Additional data with no specified format, sent in call to `_to`.
	 */
	function _safeTransferFrom(
		address _from,
		address _to,
		uint256 _tokenId,
		bytes memory _data
	) private canTransfer(_tokenId) validNFToken(_tokenId) {
		address tokenOwner = idToOwner[_tokenId];
		require(tokenOwner == _from, NOT_OWNER);
		require(_to != address(0), ZERO_ADDRESS);

		_transfer(_to, _tokenId);

		if (_to.isContract()) {
			bytes4 retval = ERC721TokenReceiver(_to).onERC721Received(
				msg.sender,
				_from,
				_tokenId,
				_data
			);
			require(
				retval == MAGIC_ON_ERC721_RECEIVED,
				NOT_ABLE_TO_RECEIVE_NFT
			);
		}
	}

	/**
	 * @dev Clears the current approval of a given NFT ID.
	 * @param _tokenId ID of the NFT to be transferred.
	 */
	function _clearApproval(uint256 _tokenId) private {
		delete idToApproval[_tokenId];
	}
}

// File contracts/erc721-enumerable.solpragma solidity 0.8.4;

/**
 * @dev Optional enumeration extension for ERC-721 non-fungible token standard.
 * See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md.
 */
interface ERC721Enumerable {
	/**
	 * @dev Returns a count of valid NFTs tracked by this contract, where each one of them has an
	 * assigned and queryable owner not equal to the zero address.
	 * @return Total supply of NFTs.
	 */
	function totalSupply() external view returns (uint256);

	/**
	 * @dev Returns the token identifier for the `_index`th NFT. Sort order is not specified.
	 * @param _index A counter less than `totalSupply()`.
	 * @return Token id.
	 */
	function tokenByIndex(uint256 _index) external view returns (uint256);

	/**
	 * @dev Returns the token identifier for the `_index`th NFT assigned to `_owner`. Sort order is
	 * not specified. It throws if `_index` >= `balanceOf(_owner)` or if `_owner` is the zero address,
	 * representing invalid NFTs.
	 * @param _owner An address where we are interested in NFTs owned by them.
	 * @param _index A counter less than `balanceOf(_owner)`.
	 * @return Token id.
	 */
	function tokenOfOwnerByIndex(address _owner, uint256 _index)
		external
		view
		returns (uint256);
}

// File contracts/nf-token-enumerable.solpragma solidity 0.8.4;

/**
 * @dev Optional enumeration implementation for ERC-721 non-fungible token standard.
 */
contract NFTokenEnumerable is NFToken, ERC721Enumerable {
	/**
	 * @dev List of revert message codes. Implementing dApp should handle showing the correct message.
	 * Based on 0xcert framework error codes.
	 */
	string constant INVALID_INDEX = '005007';

	/**
	 * @dev Array of all NFT IDs.
	 */
	uint256[] internal tokens;

	/**
	 * @dev Mapping from token ID to its index in global tokens array.
	 */
	mapping(uint256 => uint256) internal idToIndex;

	/**
	 * @dev Mapping from owner to list of owned NFT IDs.
	 */
	mapping(address => uint256[]) internal ownerToIds;

	/**
	 * @dev Mapping from NFT ID to its index in the owner tokens list.
	 */
	mapping(uint256 => uint256) internal idToOwnerIndex;

	/**
	 * @dev Contract constructor.
	 */
	constructor() {
		supportedInterfaces[0x780e9d63] = true; // ERC721Enumerable
	}

	/**
	 * @dev Returns the count of all existing NFTokens.
	 * @return Total supply of NFTs.
	 */
	function totalSupply() external view override returns (uint256) {
		return tokens.length;
	}

	/**
	 * @dev Returns NFT ID by its index.
	 * @param _index A counter less than `totalSupply()`.
	 * @return Token id.
	 */
	function tokenByIndex(uint256 _index)
		external
		view
		override
		returns (uint256)
	{
		require(_index < tokens.length, INVALID_INDEX);
		return tokens[_index];
	}

	/**
	 * @dev returns the n-th NFT ID from a list of owner's tokens.
	 * @param _owner Token owner's address.
	 * @param _index Index number representing n-th token in owner's list of tokens.
	 * @return Token id.
	 */
	function tokenOfOwnerByIndex(address _owner, uint256 _index)
		external
		view
		override
		returns (uint256)
	{
		require(_index < ownerToIds[_owner].length, INVALID_INDEX);
		return ownerToIds[_owner][_index];
	}

	/**
	 * @notice This is an internal function which should be called from user-implemented external
	 * mint function. Its purpose is to show and properly initialize data structures when using this
	 * implementation.
	 * @dev Mints a new NFT.
	 * @param _to The address that will own the minted NFT.
	 * @param _tokenId of the NFT to be minted by the msg.sender.
	 */
	function _mint(address _to, uint256 _tokenId) internal virtual override {
		super._mint(_to, _tokenId);
		tokens.push(_tokenId);
		idToIndex[_tokenId] = tokens.length - 1;
	}

	/**
	 * @notice This is an internal function which should be called from user-implemented external
	 * burn function. Its purpose is to show and properly initialize data structures when using this
	 * implementation. Also, note that this burn implementation allows the minter to re-mint a burned
	 * NFT.
	 * @dev Burns a NFT.
	 * @param _tokenId ID of the NFT to be burned.
	 */
	function _burn(uint256 _tokenId) internal virtual override {
		super._burn(_tokenId);

		uint256 tokenIndex = idToIndex[_tokenId];
		uint256 lastTokenIndex = tokens.length - 1;
		uint256 lastToken = tokens[lastTokenIndex];

		tokens[tokenIndex] = lastToken;

		tokens.pop();
		// This wastes gas if you are burning the last token but saves a little gas if you are not.
		idToIndex[lastToken] = tokenIndex;
		idToIndex[_tokenId] = 0;
	}

	/**
	 * @notice Use and override this function with caution. Wrong usage can have serious consequences.
	 * @dev Removes a NFT from an address.
	 * @param _from Address from wich we want to remove the NFT.
	 * @param _tokenId Which NFT we want to remove.
	 */
	function _removeNFToken(address _from, uint256 _tokenId)
		internal
		virtual
		override
	{
		require(idToOwner[_tokenId] == _from, NOT_OWNER);
		delete idToOwner[_tokenId];

		uint256 tokenToRemoveIndex = idToOwnerIndex[_tokenId];
		uint256 lastTokenIndex = ownerToIds[_from].length - 1;

		if (lastTokenIndex != tokenToRemoveIndex) {
			uint256 lastToken = ownerToIds[_from][lastTokenIndex];
			ownerToIds[_from][tokenToRemoveIndex] = lastToken;
			idToOwnerIndex[lastToken] = tokenToRemoveIndex;
		}

		ownerToIds[_from].pop();
	}

	/**
	 * @notice Use and override this function with caution. Wrong usage can have serious consequences.
	 * @dev Assigns a new NFT to an address.
	 * @param _to Address to wich we want to add the NFT.
	 * @param _tokenId Which NFT we want to add.
	 */
	function _addNFToken(address _to, uint256 _tokenId)
		internal
		virtual
		override
	{
		require(idToOwner[_tokenId] == address(0), NFT_ALREADY_EXISTS);
		idToOwner[_tokenId] = _to;

		ownerToIds[_to].push(_tokenId);
		idToOwnerIndex[_tokenId] = ownerToIds[_to].length - 1;
	}

	/**
	 * @dev Helper function that gets NFT count of owner. This is needed for overriding in enumerable
	 * extension to remove double storage(gas optimization) of owner NFT count.
	 * @param _owner Address for whom to query the count.
	 * @return Number of _owner NFTs.
	 */
	function _getOwnerNFTCount(address _owner)
		internal
		view
		virtual
		override
		returns (uint256)
	{
		return ownerToIds[_owner].length;
	}
}

// File contracts/erc721-metadata.sol

pragma solidity 0.8.4;
/**
 * @dev Optional metadata extension for ERC-721 non-fungible token standard.
 * See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md.
 */

interface ERC721Metadata {
	/**
	 * @dev Returns a descriptive name for a collection of NFTs in this contract.
	 * @return _name Representing name.
	 */
	function name() external view returns (string memory _name);

	/**
	 * @dev Returns a abbreviated name for a collection of NFTs in this contract.
	 * @return _symbol Representing symbol.
	 */
	function symbol() external view returns (string memory _symbol);

	/**
	 * @dev Returns a distinct Uniform Resource Identifier (URI) for a given asset. It Throws if
	 * `_tokenId` is not a valid NFT. URIs are defined in RFC3986. The URI may point to a JSON file
	 * that conforms to the "ERC721 Metadata JSON Schema".
	 * @return URI of _tokenId.
	 */
	function tokenURI(uint256 _tokenId) external view returns (string memory);
}

// File contracts/nf-token-metadata.sol
pragma solidity 0.8.4;

/**
 * @dev Optional metadata implementation for ERC-721 non-fungible token standard.
 */
contract NFTokenMetadata is NFToken, ERC721Metadata {
	/**
	 * @dev A descriptive name for a collection of NFTs.
	 */
	string internal nftName;

	/**
	 * @dev An abbreviated name for NFTokens.
	 */
	string internal nftSymbol;

	/**
	 * @dev Mapping from NFT ID to metadata uri.
	 */
	mapping(uint256 => string) internal idToUri;

	/**
	 * @notice When implementing this contract don't forget to set nftName and nftSymbol.
	 * @dev Contract constructor.
	 */
	constructor() {
		supportedInterfaces[0x5b5e139f] = true; // ERC721Metadata
	}

	/**
	 * @dev Returns a descriptive name for a collection of NFTokens.
	 * @return _name Representing name.
	 */
	function name() external view override returns (string memory _name) {
		_name = nftName;
	}

	/**
	 * @dev Returns an abbreviated name for NFTokens.
	 * @return _symbol Representing symbol.
	 */
	function symbol() external view override returns (string memory _symbol) {
		_symbol = nftSymbol;
	}

	/**
	 * @dev A distinct URI (RFC 3986) for a given NFT.
	 * @param _tokenId Id for which we want uri.
	 * @return URI of _tokenId.
	 */
	function tokenURI(uint256 _tokenId)
		external
		view
		override
		validNFToken(_tokenId)
		returns (string memory)
	{
		return idToUri[_tokenId];
	}

	/**
	 * @notice This is an internal function which should be called from user-implemented external
	 * burn function. Its purpose is to show and properly initialize data structures when using this
	 * implementation. Also, note that this burn implementation allows the minter to re-mint a burned
	 * NFT.
	 * @dev Burns a NFT.
	 * @param _tokenId ID of the NFT to be burned.
	 */
	function _burn(uint256 _tokenId) internal virtual override {
		super._burn(_tokenId);

		delete idToUri[_tokenId];
	}

	/**
	 * @notice This is an internal function which should be called from user-implemented external
	 * function. Its purpose is to show and properly initialize data structures when using this
	 * implementation.
	 * @dev Set a distinct URI (RFC 3986) for a given NFT ID.
	 * @param _tokenId Id for which we want URI.
	 * @param _uri String representing RFC 3986 URI.
	 */
	function _setTokenUri(uint256 _tokenId, string memory _uri)
		internal
		validNFToken(_tokenId)
	{
		idToUri[_tokenId] = _uri;
	}
}

// File contracts/NFTokenMetadataEnumerable.sol
pragma solidity 0.8.4;

/**
 * @dev Optional metadata implementation for ERC-721 non-fungible token standard.
 */
abstract contract NFTokenEnumerableMetadata is
	NFToken,
	ERC721Metadata,
	ERC721Enumerable
{
	/**
	 * @dev A descriptive name for a collection of NFTs.
	 */
	string internal nftName;

	/**
	 * @dev An abbreviated name for NFTokens.
	 */
	string internal nftSymbol;

	/**
	 * @dev Mapping from NFT ID to metadata uri.
	 */
	mapping(uint256 => string) internal idToUri;

	/**
	 * @dev List of revert message codes. Implementing dApp should handle showing the correct message.
	 * Based on 0xcert framework error codes.
	 */
	string constant INVALID_INDEX = '005007';

	/**
	 * @dev Array of all NFT IDs.
	 */
	uint256[] internal tokens;

	/**
	 * @dev Mapping from token ID to its index in global tokens array.
	 */
	mapping(uint256 => uint256) internal idToIndex;

	/**
	 * @dev Mapping from owner to list of owned NFT IDs.
	 */
	mapping(address => uint256[]) internal ownerToIds;

	/**
	 * @dev Mapping from NFT ID to its index in the owner tokens list.
	 */
	mapping(uint256 => uint256) internal idToOwnerIndex;

	/**
	 * @notice When implementing this contract don't forget to set nftName and nftSymbol.
	 * @dev Contract constructor.
	 */
	constructor() {
		supportedInterfaces[0x780e9d63] = true; // ERC721Enumerable
		supportedInterfaces[0x5b5e139f] = true; // ERC721Metadata
	}

	/**
	 * @dev Returns a descriptive name for a collection of NFTokens.
	 * @return _name Representing name.
	 */
	function name() external view override returns (string memory _name) {
		_name = nftName;
	}

	/**
	 * @dev Returns an abbreviated name for NFTokens.
	 * @return _symbol Representing symbol.
	 */
	function symbol() external view override returns (string memory _symbol) {
		_symbol = nftSymbol;
	}

	/**
	 * @dev A distinct URI (RFC 3986) for a given NFT.
	 * @param _tokenId Id for which we want uri.
	 * @return URI of _tokenId.
	 */
	function tokenURI(uint256 _tokenId)
		external
		view
		override
		validNFToken(_tokenId)
		returns (string memory)
	{
		return idToUri[_tokenId];
	}

	/**
	 * @notice This is an internal function which should be called from user-implemented external
	 * function. Its purpose is to show and properly initialize data structures when using this
	 * implementation.
	 * @dev Set a distinct URI (RFC 3986) for a given NFT ID.
	 * @param _tokenId Id for which we want URI.
	 * @param _uri String representing RFC 3986 URI.
	 */
	function _setTokenUri(uint256 _tokenId, string memory _uri)
		internal
		validNFToken(_tokenId)
	{
		idToUri[_tokenId] = _uri;
	}

	/**
	 * @dev Returns the count of all existing NFTokens.
	 * @return Total supply of NFTs.
	 */
	function totalSupply() external view override returns (uint256) {
		return tokens.length;
	}

	/**
	 * @dev Returns NFT ID by its index.
	 * @param _index A counter less than `totalSupply()`.
	 * @return Token id.
	 */
	function tokenByIndex(uint256 _index)
		external
		view
		override
		returns (uint256)
	{
		require(_index < tokens.length, INVALID_INDEX);
		return tokens[_index];
	}

	/**
	 * @dev returns the n-th NFT ID from a list of owner's tokens.
	 * @param _owner Token owner's address.
	 * @param _index Index number representing n-th token in owner's list of tokens.
	 * @return Token id.
	 */
	function tokenOfOwnerByIndex(address _owner, uint256 _index)
		external
		view
		override
		returns (uint256)
	{
		require(_index < ownerToIds[_owner].length, INVALID_INDEX);
		return ownerToIds[_owner][_index];
	}

	/**
	 * @notice This is an internal function which should be called from user-implemented external
	 * mint function. Its purpose is to show and properly initialize data structures when using this
	 * implementation.
	 * @dev Mints a new NFT.
	 * @param _to The address that will own the minted NFT.
	 * @param _tokenId of the NFT to be minted by the msg.sender.
	 */
	function _mint(address _to, uint256 _tokenId) internal virtual override {
		super._mint(_to, _tokenId);
		tokens.push(_tokenId);
		idToIndex[_tokenId] = tokens.length - 1;
	}

	/**
	 * @notice This is an internal function which should be called from user-implemented external
	 * burn function. Its purpose is to show and properly initialize data structures when using this
	 * implementation. Also, note that this burn implementation allows the minter to re-mint a burned
	 * NFT.
	 * @dev Burns a NFT.
	 * @param _tokenId ID of the NFT to be burned.
	 */
	function _burn(uint256 _tokenId) internal virtual override {
		super._burn(_tokenId);

		uint256 tokenIndex = idToIndex[_tokenId];
		uint256 lastTokenIndex = tokens.length - 1;
		uint256 lastToken = tokens[lastTokenIndex];

		tokens[tokenIndex] = lastToken;

		tokens.pop();
		delete idToUri[_tokenId];
		// This wastes gas if you are burning the last token but saves a little gas if you are not.
		idToIndex[lastToken] = tokenIndex;
		idToIndex[_tokenId] = 0;
	}

	/**
	 * @notice Use and override this function with caution. Wrong usage can have serious consequences.
	 * @dev Removes a NFT from an address.
	 * @param _from Address from wich we want to remove the NFT.
	 * @param _tokenId Which NFT we want to remove.
	 */
	function _removeNFToken(address _from, uint256 _tokenId)
		internal
		virtual
		override
	{
		require(idToOwner[_tokenId] == _from, NOT_OWNER);
		delete idToOwner[_tokenId];

		uint256 tokenToRemoveIndex = idToOwnerIndex[_tokenId];
		uint256 lastTokenIndex = ownerToIds[_from].length - 1;

		if (lastTokenIndex != tokenToRemoveIndex) {
			uint256 lastToken = ownerToIds[_from][lastTokenIndex];
			ownerToIds[_from][tokenToRemoveIndex] = lastToken;
			idToOwnerIndex[lastToken] = tokenToRemoveIndex;
		}

		ownerToIds[_from].pop();
	}

	/**
	 * @notice Use and override this function with caution. Wrong usage can have serious consequences.
	 * @dev Assigns a new NFT to an address.
	 * @param _to Address to wich we want to add the NFT.
	 * @param _tokenId Which NFT we want to add.
	 */
	function _addNFToken(address _to, uint256 _tokenId)
		internal
		virtual
		override
	{
		require(idToOwner[_tokenId] == address(0), NFT_ALREADY_EXISTS);
		idToOwner[_tokenId] = _to;

		ownerToIds[_to].push(_tokenId);
		idToOwnerIndex[_tokenId] = ownerToIds[_to].length - 1;
	}

	/**
	 * @dev Helper function that gets NFT count of owner. This is needed for overriding in enumerable
	 * extension to remove double storage(gas optimization) of owner NFT count.
	 * @param _owner Address for whom to query the count.
	 * @return Number of _owner NFTs.
	 */
	function _getOwnerNFTs(address _owner)
		internal
		view
		virtual
		returns (uint256[] memory)
	{
		return ownerToIds[_owner];
	}

	/**
	 * @dev Helper function that gets NFT count of owner. This is needed for overriding in enumerable
	 * extension to remove double storage(gas optimization) of owner NFT count.
	 * @param _owner Address for whom to query the count.
	 * @return Number of _owner NFTs.
	 */
	function _getOwnerNFTCount(address _owner)
		internal
		view
		virtual
		override
		returns (uint256)
	{
		return ownerToIds[_owner].length;
	}
}

// File @openzeppelin/contracts/utils/[email protected] solidity 0.8.4;

/**
 * @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 @openzeppelin/contracts/access/[email protected] solidity 0.8.4;

/**
 * @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() {
		_setOwner(_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 {
		_setOwner(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'
		);
		_setOwner(newOwner);
	}

	function _setOwner(address newOwner) private {
		address oldOwner = _owner;
		_owner = newOwner;
		emit OwnershipTransferred(oldOwner, newOwner);
	}
}

// File @openzeppelin/contracts/utils/math/[email protected]

pragma solidity 0.8.4; // CAUTION

// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SafeMath` is no longer needed starting with Solidity 0.8. The compiler
 * now has built in overflow checking.
 */
library SafeMath {
	/**
	 * @dev Returns the addition of two unsigned integers, with an overflow flag.
	 *
	 * _Available since v3.4._
	 */
	function tryAdd(uint256 a, uint256 b)
		internal
		pure
		returns (bool, uint256)
	{
		unchecked {
			uint256 c = a + b;
			if (c < a) return (false, 0);
			return (true, c);
		}
	}

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

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

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

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

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

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

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

	/**
	 * @dev Returns the integer division of two unsigned integers, reverting on
	 * division by zero. The result is rounded towards zero.
	 *
	 * Counterpart to Solidity's `/` operator.
	 *
	 * Requirements:
	 *
	 * - The divisor cannot be zero.
	 */
	function div(uint256 a, uint256 b) internal pure returns (uint256) {
		return a / b;
	}

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

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

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

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

// File contracts/IReferral.sol
pragma solidity 0.8.4;

interface IReferral {
	/**
	 * @dev Record referral.
	 */
	function recordReferral(address user, address referrer) external;

	/**
	 * @dev Record referral share.
	 */
	function recordReferralShare(address referrer, uint256 share) external;

	/**
	 * @dev Get the referrer address that referred the user.
	 */
	function getReferrer(address user) external view returns (address);
}

// File contracts/Nfts.sol
pragma solidity 0.8.4;

contract Nfts is NFTokenEnumerableMetadata, Ownable {
	using SafeMath for uint256;

	uint256 public price = 0.05 ether; // 0.05 eth
	uint256 public maxSupply = 10_000;
	string public baseUri = 'https://api.arbipunks.com/';
	uint16 public refShare = 2000; // in basis points, so it's 20%
	IReferral public referralContract;

	event PriceUpdated(uint256 newPrice);
	event MaxSupplyUpdated(uint256 newMaxSupply);
	event BaseUriUpdated(string newBaseUri);
	event ReferralSharePaid(
		address indexed user,
		address indexed referrer,
		uint256 shareAmount
	);

	constructor() {
		nftName = 'ArbiPunks';
		nftSymbol = 'APUNKS';
	}

	function mint(address _referrer) external payable {
		require(msg.value >= price, 'Amount is less than price');
		require(maxSupply >= this.totalSupply(), 'Sold out');

		uint256 count = msg.value / price;

		if (
			msg.value > 0 &&
			address(referralContract) != address(0) &&
			_referrer != address(0) &&
			_referrer != msg.sender
		) {
			referralContract.recordReferral(msg.sender, _referrer);
		}

		for (uint256 i = 0; i < count; i++) {
			uint256 currentSupply = this.totalSupply();

			uint256 tokenId = currentSupply;
			address to = msg.sender;

			super._mint(to, tokenId);
			super._setTokenUri(
				tokenId,
				string(abi.encodePacked(baseUri, toString(tokenId), '.json'))
			);
			payReferral(msg.sender, msg.value);
		}
	}

	function getOwnerNFTs(address _owner)
		public
		view
		returns (uint256[] memory)
	{
		return super._getOwnerNFTs(_owner);
	}

	function withdraw() external onlyOwner {
		payable(msg.sender).transfer(address(this).balance);
	}

	function updatePrice(uint256 _newPrice) public onlyOwner {
		price = _newPrice;
		emit PriceUpdated(_newPrice);
	}

	function updateMaxSupply(uint256 _maxSupply) public onlyOwner {
		maxSupply = _maxSupply;
		emit MaxSupplyUpdated(_maxSupply);
	}

	function updateBaseUri(string memory _baseUri) public onlyOwner {
		baseUri = _baseUri;
		emit BaseUriUpdated(_baseUri);
	}

	// Update the referral contract address by the owner
	function setReferralAddress(IReferral _referralAddress) public onlyOwner {
		referralContract = _referralAddress;
	}

	// Update referral share rate by the owner
	function setRefShare(uint16 _refShare) public onlyOwner {
		refShare = _refShare;
	}

	// Pay referral share to the referrer who referred this user.
	function payReferral(address _to, uint256 _amount) internal {
		if (address(referralContract) != address(0) && refShare > 0) {
			address referrer = referralContract.getReferrer(_to);
			uint256 shareAmount = _amount.mul(refShare).div(10000);

			if (referrer != address(0) && shareAmount > 0) {
				payable(referrer).transfer(shareAmount);

				referralContract.recordReferralShare(referrer, shareAmount);
				emit ReferralSharePaid(_to, referrer, shareAmount);
			}
		}
	}

	function toString(uint256 value) internal pure returns (string memory) {
		// Inspired by OraclizeAPI's implementation - MIT license
		// 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);
	}
}

// File @openzeppelin/contracts/token/ERC20/[email protected] solidity 0.8.4;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
	/**
	 * @dev Returns the amount of tokens in existence.
	 */
	function totalSupply() external view returns (uint256);

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

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

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

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

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

	/**
	 * @dev Emitted when `value` tokens are moved from one account (`from`) to
	 * another (`to`).
	 *
	 * Note that `value` may be zero.
	 */
	event Transfer(address indexed from, address indexed to, uint256 value);

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

// File @openzeppelin/contracts/utils/[email protected] solidity 0.8.4;

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

		uint256 size;
		assembly {
			size := extcodesize(account)
		}
		return size > 0;
	}

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

		(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 @openzeppelin/contracts/token/ERC20/utils/[email protected]

pragma solidity 0.8.4;
/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */

library SafeERC20 {
	using Address for address;

	function safeTransfer(
		IERC20 token,
		address to,
		uint256 value
	) internal {
		_callOptionalReturn(
			token,
			abi.encodeWithSelector(token.transfer.selector, to, value)
		);
	}

	function safeTransferFrom(
		IERC20 token,
		address from,
		address to,
		uint256 value
	) internal {
		_callOptionalReturn(
			token,
			abi.encodeWithSelector(token.transferFrom.selector, from, to, value)
		);
	}

	/**
	 * @dev Deprecated. This function has issues similar to the ones found in
	 * {IERC20-approve}, and its usage is discouraged.
	 *
	 * Whenever possible, use {safeIncreaseAllowance} and
	 * {safeDecreaseAllowance} instead.
	 */
	function safeApprove(
		IERC20 token,
		address spender,
		uint256 value
	) internal {
		// safeApprove should only be called when setting an initial allowance,
		// or when resetting it to zero. To increase and decrease it, use
		// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
		require(
			(value == 0) || (token.allowance(address(this), spender) == 0),
			'SafeERC20: approve from non-zero to non-zero allowance'
		);
		_callOptionalReturn(
			token,
			abi.encodeWithSelector(token.approve.selector, spender, value)
		);
	}

	function safeIncreaseAllowance(
		IERC20 token,
		address spender,
		uint256 value
	) internal {
		uint256 newAllowance = token.allowance(address(this), spender) + value;
		_callOptionalReturn(
			token,
			abi.encodeWithSelector(
				token.approve.selector,
				spender,
				newAllowance
			)
		);
	}

	function safeDecreaseAllowance(
		IERC20 token,
		address spender,
		uint256 value
	) internal {
		unchecked {
			uint256 oldAllowance = token.allowance(address(this), spender);
			require(
				oldAllowance >= value,
				'SafeERC20: decreased allowance below zero'
			);
			uint256 newAllowance = oldAllowance - value;
			_callOptionalReturn(
				token,
				abi.encodeWithSelector(
					token.approve.selector,
					spender,
					newAllowance
				)
			);
		}
	}

	/**
	 * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
	 * on the return value: the return value is optional (but if data is returned, it must not be false).
	 * @param token The token targeted by the call.
	 * @param data The call data (encoded using abi.encode or one of its variants).
	 */
	function _callOptionalReturn(IERC20 token, bytes memory data) private {
		// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
		// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
		// the target address contains contract code and also asserts for success in the low-level call.

		bytes memory returndata = address(token).functionCall(
			data,
			'SafeERC20: low-level call failed'
		);
		if (returndata.length > 0) {
			// Return data is optional
			require(
				abi.decode(returndata, (bool)),
				'SafeERC20: ERC20 operation did not succeed'
			);
		}
	}
}

// File contracts/Referral.solpragma solidity 0.8.4;

contract Referral is IReferral, Ownable {
	using SafeERC20 for IERC20;

	mapping(address => bool) public operators;
	mapping(address => address) public referrers; // user address => referrer address
	mapping(address => uint256) public referralsCount; // referrer address => referrals count
	mapping(address => uint256) public totalReferralShares; // referrer address => total referral commissions

	event ReferralRecorded(address indexed user, address indexed referrer);
	event ReferralShareRecorded(address indexed referrer, uint256 commission);
	event OperatorUpdated(address indexed operator, bool indexed status);

	modifier onlyOperator() {
		require(operators[msg.sender], 'Operator: caller is not the operator');
		_;
	}

	function recordReferral(address _user, address _referrer)
		public
		override
		onlyOperator
	{
		if (
			_user != address(0) &&
			_referrer != address(0) &&
			_user != _referrer &&
			referrers[_user] == address(0)
		) {
			referrers[_user] = _referrer;
			referralsCount[_referrer] += 1;
			emit ReferralRecorded(_user, _referrer);
		}
	}

	function recordReferralShare(address _referrer, uint256 _share)
		public
		override
		onlyOperator
	{
		if (_referrer != address(0) && _share > 0) {
			totalReferralShares[_referrer] += _share;
			emit ReferralShareRecorded(_referrer, _share);
		}
	}

	// Get the referrer address that referred the user
	function getReferrer(address _user) public view override returns (address) {
		return referrers[_user];
	}

	// Update the status of the operator
	function updateOperator(address _operator, bool _status)
		external
		onlyOwner
	{
		operators[_operator] = _status;
		emit OperatorUpdated(_operator, _status);
	}

	function transferTokens(
		IERC20 _token,
		uint256 _amount,
		address _to
	) external onlyOwner {
		_token.safeTransfer(_to, _amount);
	}
}

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_owner","type":"address"},{"indexed":true,"internalType":"address","name":"_approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_owner","type":"address"},{"indexed":true,"internalType":"address","name":"_operator","type":"address"},{"indexed":false,"internalType":"bool","name":"_approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"newBaseUri","type":"string"}],"name":"BaseUriUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newMaxSupply","type":"uint256"}],"name":"MaxSupplyUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newPrice","type":"uint256"}],"name":"PriceUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"referrer","type":"address"},{"indexed":false,"internalType":"uint256","name":"shareAmount","type":"uint256"}],"name":"ReferralSharePaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":true,"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"_approved","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseUri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"getOwnerNFTs","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_referrer","type":"address"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"_name","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"price","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"refShare","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"referralContract","outputs":[{"internalType":"contract IReferral","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_operator","type":"address"},{"internalType":"bool","name":"_approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_refShare","type":"uint16"}],"name":"setRefShare","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IReferral","name":"_referralAddress","type":"address"}],"name":"setReferralAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"_interfaceID","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"_symbol","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_baseUri","type":"string"}],"name":"updateBaseUri","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxSupply","type":"uint256"}],"name":"updateMaxSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newPrice","type":"uint256"}],"name":"updatePrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

608060405266b1a2bc2ec50000600d55612710600e556040518060400160405280601a81526020017f68747470733a2f2f6170692e6172626970756e6b732e636f6d2f000000000000815250600f90805190602001906200006292919062000364565b506107d0601060006101000a81548161ffff021916908361ffff1602179055503480156200008f57600080fd5b5060016000806301ffc9a760e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548160ff02191690831515021790555060016000806380ac58cd60e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548160ff021916908315150217905550600160008063780e9d6360e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548160ff0219169083151502179055506001600080635b5e139f60e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548160ff021916908315150217905550620001f4620001e86200029660201b60201c565b6200029e60201b60201c565b6040518060400160405280600981526020017f4172626950756e6b730000000000000000000000000000000000000000000000815250600590805190602001906200024192919062000364565b506040518060400160405280600681526020017f4150554e4b530000000000000000000000000000000000000000000000000000815250600690805190602001906200028f92919062000364565b5062000479565b600033905090565b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600c60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b828054620003729062000414565b90600052602060002090601f016020900481019282620003965760008555620003e2565b82601f10620003b157805160ff1916838001178555620003e2565b82800160010185558215620003e2579182015b82811115620003e1578251825591602001919060010190620003c4565b5b509050620003f19190620003f5565b5090565b5b8082111562000410576000816000905550600101620003f6565b5090565b600060028204905060018216806200042d57607f821691505b602082108114156200044457620004436200044a565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b614a6b80620004896000396000f3fe6080604052600436106101e35760003560e01c8063715018a611610102578063a22cb46511610095578063d5abeb0111610064578063d5abeb01146106e3578063e985e9c51461070e578063f103b4331461074b578063f2fde38b14610774576101e3565b8063a22cb4651461062b578063b3caba5a14610654578063b88d4fde1461067d578063c87b56dd146106a6576101e3565b80638da5cb5b116100d15780638da5cb5b1461057f57806395d89b41146105aa5780639abc8320146105d5578063a035b1fe14610600576101e3565b8063715018a6146104d75780637dad19db146104ee5780638c017572146105195780638d6cc56d14610556576101e3565b80632f745c591161017a5780634f6ccce7116101495780634f6ccce7146104045780636352211e146104415780636a6278421461047e57806370a082311461049a576101e3565b80632f745c591461035e57806339f7e37f1461039b5780633ccfd60b146103c457806342842e0e146103db576101e3565b8063117d6507116101b6578063117d6507146102b657806318160ddd146102df5780631f4fc29c1461030a57806323b872dd14610335576101e3565b806301ffc9a7146101e857806306fdde0314610225578063081812fc14610250578063095ea7b31461028d575b600080fd5b3480156101f457600080fd5b5061020f600480360381019061020a9190613e28565b61079d565b60405161021c919061430a565b60405180910390f35b34801561023157600080fd5b5061023a610804565b6040516102479190614340565b60405180910390f35b34801561025c57600080fd5b5061027760048036038101906102729190613f0d565b610896565b604051610284919061422f565b60405180910390f35b34801561029957600080fd5b506102b460048036038101906102af9190613dec565b6109b1565b005b3480156102c257600080fd5b506102dd60048036038101906102d89190613ee4565b610d94565b005b3480156102eb57600080fd5b506102f4610e30565b60405161030191906143fd565b60405180910390f35b34801561031657600080fd5b5061031f610e3d565b60405161032c91906143e2565b60405180910390f35b34801561034157600080fd5b5061035c60048036038101906103579190613ce1565b610e51565b005b34801561036a57600080fd5b5061038560048036038101906103809190613dec565b6112a3565b60405161039291906143fd565b60405180910390f35b3480156103a757600080fd5b506103c260048036038101906103bd9190613ea3565b6113ec565b005b3480156103d057600080fd5b506103d96114b9565b005b3480156103e757600080fd5b5061040260048036038101906103fd9190613ce1565b61157e565b005b34801561041057600080fd5b5061042b60048036038101906104269190613f0d565b61159e565b60405161043891906143fd565b60405180910390f35b34801561044d57600080fd5b5061046860048036038101906104639190613f0d565b61166c565b604051610475919061422f565b60405180910390f35b61049860048036038101906104939190613c53565b611752565b005b3480156104a657600080fd5b506104c160048036038101906104bc9190613c53565b611aca565b6040516104ce91906143fd565b60405180910390f35b3480156104e357600080fd5b506104ec611b84565b005b3480156104fa57600080fd5b50610503611c0c565b6040516105109190614325565b60405180910390f35b34801561052557600080fd5b50610540600480360381019061053b9190613c53565b611c32565b60405161054d91906142e8565b60405180910390f35b34801561056257600080fd5b5061057d60048036038101906105789190613f0d565b611c44565b005b34801561058b57600080fd5b50610594611d01565b6040516105a1919061422f565b60405180910390f35b3480156105b657600080fd5b506105bf611d2b565b6040516105cc9190614340565b60405180910390f35b3480156105e157600080fd5b506105ea611dbd565b6040516105f79190614340565b60405180910390f35b34801561060c57600080fd5b50610615611e4b565b60405161062291906143fd565b60405180910390f35b34801561063757600080fd5b50610652600480360381019061064d9190613db0565b611e51565b005b34801561066057600080fd5b5061067b60048036038101906106769190613e7a565b611f4e565b005b34801561068957600080fd5b506106a4600480360381019061069f9190613d30565b61200e565b005b3480156106b257600080fd5b506106cd60048036038101906106c89190613f0d565b612065565b6040516106da9190614340565b60405180910390f35b3480156106ef57600080fd5b506106f86121e8565b60405161070591906143fd565b60405180910390f35b34801561071a57600080fd5b5061073560048036038101906107309190613ca5565b6121ee565b604051610742919061430a565b60405180910390f35b34801561075757600080fd5b50610772600480360381019061076d9190613f0d565b612282565b005b34801561078057600080fd5b5061079b60048036038101906107969190613c53565b61233f565b005b6000806000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900460ff169050919050565b6060600580546108139061470e565b80601f016020809104026020016040519081016040528092919081815260200182805461083f9061470e565b801561088c5780601f106108615761010080835404028352916020019161088c565b820191906000526020600020905b81548152906001019060200180831161086f57829003601f168201915b5050505050905090565b600081600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156040518060400160405280600681526020017f303033303032000000000000000000000000000000000000000000000000000081525090610974576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161096b9190614340565b60405180910390fd5b506002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16915050919050565b8060006001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161480610aaa5750600460008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b6040518060400160405280600681526020017f303033303033000000000000000000000000000000000000000000000000000081525090610b21576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b189190614340565b60405180910390fd5b5082600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156040518060400160405280600681526020017f303033303032000000000000000000000000000000000000000000000000000081525090610bfe576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bf59190614340565b60405180910390fd5b5060006001600086815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614156040518060400160405280600681526020017f303033303038000000000000000000000000000000000000000000000000000081525090610cde576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cd59190614340565b60405180910390fd5b50856002600087815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550848673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050505050565b610d9c612437565b73ffffffffffffffffffffffffffffffffffffffff16610dba611d01565b73ffffffffffffffffffffffffffffffffffffffff1614610e10576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e0790614382565b60405180910390fd5b80601060006101000a81548161ffff021916908361ffff16021790555050565b6000600880549050905090565b601060009054906101000a900461ffff1681565b8060006001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161480610f2257503373ffffffffffffffffffffffffffffffffffffffff166002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b80610fb35750600460008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b6040518060400160405280600681526020017f30303330303400000000000000000000000000000000000000000000000000008152509061102a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110219190614340565b60405180910390fd5b5082600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156040518060400160405280600681526020017f303033303032000000000000000000000000000000000000000000000000000081525090611107576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110fe9190614340565b60405180910390fd5b5060006001600086815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600681526020017f3030333030370000000000000000000000000000000000000000000000000000815250906111e6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111dd9190614340565b60405180910390fd5b50600073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614156040518060400160405280600681526020017f30303330303100000000000000000000000000000000000000000000000000008152509061128f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112869190614340565b60405180910390fd5b5061129a868661243f565b50505050505050565b6000600a60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905082106040518060400160405280600681526020017f303035303037000000000000000000000000000000000000000000000000000081525090611361576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113589190614340565b60405180910390fd5b50600a60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481106113d9577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154905092915050565b6113f4612437565b73ffffffffffffffffffffffffffffffffffffffff16611412611d01565b73ffffffffffffffffffffffffffffffffffffffff1614611468576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161145f90614382565b60405180910390fd5b80600f908051906020019061147e929190613a41565b507f24a9152dc695ecc801ad580886331ee12d7aac0fa2ae341a5ae3c2ccae36cb4f816040516114ae9190614340565b60405180910390a150565b6114c1612437565b73ffffffffffffffffffffffffffffffffffffffff166114df611d01565b73ffffffffffffffffffffffffffffffffffffffff1614611535576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161152c90614382565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff166108fc479081150290604051600060405180830381858888f1935050505015801561157b573d6000803e3d6000fd5b50565b611599838383604051806020016040528060008152506124f4565b505050565b600060088054905082106040518060400160405280600681526020017f30303530303700000000000000000000000000000000000000000000000000008152509061161f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116169190614340565b60405180910390fd5b506008828154811061165a577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001549050919050565b60006001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156040518060400160405280600681526020017f30303330303200000000000000000000000000000000000000000000000000008152509061174c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117439190614340565b60405180910390fd5b50919050565b600d54341015611797576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161178e906143a2565b60405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156117dd57600080fd5b505afa1580156117f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118159190613f36565b600e541015611859576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611850906143c2565b60405180910390fd5b6000600d54346118699190614555565b90506000341180156118ca5750600073ffffffffffffffffffffffffffffffffffffffff16601060029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b80156119035750600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b801561193b57503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b156119d057601060029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630c7f7b6b33846040518363ffffffff1660e01b815260040161199d92919061424a565b600060405180830381600087803b1580156119b757600080fd5b505af11580156119cb573d6000803e3d6000fd5b505050505b60005b81811015611ac55760003073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611a2357600080fd5b505afa158015611a37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a5b9190613f36565b905060008190506000339050611a718183612ac2565b611aa582600f611a8085612b22565b604051602001611a91929190614200565b604051602081830303815290604052612ccf565b611aaf3334612dd9565b5050508080611abd90614771565b9150506119d3565b505050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156040518060400160405280600681526020017f303033303031000000000000000000000000000000000000000000000000000081525090611b73576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b6a9190614340565b60405180910390fd5b50611b7d826130c4565b9050919050565b611b8c612437565b73ffffffffffffffffffffffffffffffffffffffff16611baa611d01565b73ffffffffffffffffffffffffffffffffffffffff1614611c00576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bf790614382565b60405180910390fd5b611c0a6000613110565b565b601060029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6060611c3d826131d6565b9050919050565b611c4c612437565b73ffffffffffffffffffffffffffffffffffffffff16611c6a611d01565b73ffffffffffffffffffffffffffffffffffffffff1614611cc0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cb790614382565b60405180910390fd5b80600d819055507f66cbca4f3c64fecf1dcb9ce094abcf7f68c3450a1d4e3a8e917dd621edb4ebe081604051611cf691906143fd565b60405180910390a150565b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b606060068054611d3a9061470e565b80601f0160208091040260200160405190810160405280929190818152602001828054611d669061470e565b8015611db35780601f10611d8857610100808354040283529160200191611db3565b820191906000526020600020905b815481529060010190602001808311611d9657829003601f168201915b5050505050905090565b600f8054611dca9061470e565b80601f0160208091040260200160405190810160405280929190818152602001828054611df69061470e565b8015611e435780601f10611e1857610100808354040283529160200191611e43565b820191906000526020600020905b815481529060010190602001808311611e2657829003601f168201915b505050505081565b600d5481565b80600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051611f42919061430a565b60405180910390a35050565b611f56612437565b73ffffffffffffffffffffffffffffffffffffffff16611f74611d01565b73ffffffffffffffffffffffffffffffffffffffff1614611fca576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fc190614382565b60405180910390fd5b80601060026101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b61205e85858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506124f4565b5050505050565b606081600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156040518060400160405280600681526020017f303033303032000000000000000000000000000000000000000000000000000081525090612143576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161213a9190614340565b60405180910390fd5b506007600084815260200190815260200160002080546121629061470e565b80601f016020809104026020016040519081016040528092919081815260200182805461218e9061470e565b80156121db5780601f106121b0576101008083540402835291602001916121db565b820191906000526020600020905b8154815290600101906020018083116121be57829003601f168201915b5050505050915050919050565b600e5481565b6000600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b61228a612437565b73ffffffffffffffffffffffffffffffffffffffff166122a8611d01565b73ffffffffffffffffffffffffffffffffffffffff16146122fe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122f590614382565b60405180910390fd5b80600e819055507f7810bd47de260c3e9ee10061cf438099dd12256c79485f12f94dbccc981e806c8160405161233491906143fd565b60405180910390a150565b612347612437565b73ffffffffffffffffffffffffffffffffffffffff16612365611d01565b73ffffffffffffffffffffffffffffffffffffffff16146123bb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123b290614382565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561242b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161242290614362565b60405180910390fd5b61243481613110565b50565b600033905090565b60006001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506124808261326d565b61248a81836132a6565b61249483836135df565b818373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b8160006001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614806125c557503373ffffffffffffffffffffffffffffffffffffffff166002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b806126565750600460008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b6040518060400160405280600681526020017f3030333030340000000000000000000000000000000000000000000000000000815250906126cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126c49190614340565b60405180910390fd5b5083600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156040518060400160405280600681526020017f3030333030320000000000000000000000000000000000000000000000000000815250906127aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127a19190614340565b60405180910390fd5b5060006001600087815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508773ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600681526020017f303033303037000000000000000000000000000000000000000000000000000081525090612889576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128809190614340565b60405180910390fd5b50600073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1614156040518060400160405280600681526020017f303033303031000000000000000000000000000000000000000000000000000081525090612932576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129299190614340565b60405180910390fd5b5061293d878761243f565b61295c8773ffffffffffffffffffffffffffffffffffffffff166137dc565b15612ab85760008773ffffffffffffffffffffffffffffffffffffffff1663150b7a02338b8a8a6040518563ffffffff1660e01b81526004016129a29493929190614273565b602060405180830381600087803b1580156129bc57600080fd5b505af11580156129d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129f49190613e51565b905063150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916146040518060400160405280600681526020017f303033303035000000000000000000000000000000000000000000000000000081525090612ab5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612aac9190614340565b60405180910390fd5b50505b5050505050505050565b612acc8282613827565b60088190806001815401808255809150506001900390600052602060002001600090919091909150556001600880549050612b0791906145e0565b60096000838152602001908152602001600020819055505050565b60606000821415612b6a576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050612cca565b600082905060005b60008214612b9c578080612b8590614771565b915050600a82612b959190614555565b9150612b72565b60008167ffffffffffffffff811115612bde577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015612c105781602001600182028036833780820191505090505b5090505b60008514612cc357600182612c2991906145e0565b9150600a85612c3891906147ba565b6030612c4491906144ff565b60f81b818381518110612c80577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a85612cbc9190614555565b9450612c14565b8093505050505b919050565b81600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156040518060400160405280600681526020017f303033303032000000000000000000000000000000000000000000000000000081525090612dab576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612da29190614340565b60405180910390fd5b5081600760008581526020019081526020016000209080519060200190612dd3929190613a41565b50505050565b600073ffffffffffffffffffffffffffffffffffffffff16601060029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614158015612e4c57506000601060009054906101000a900461ffff1661ffff16115b156130c0576000601060029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634a9fefc7846040518263ffffffff1660e01b8152600401612eae919061422f565b60206040518083038186803b158015612ec657600080fd5b505afa158015612eda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612efe9190613c7c565b90506000612f3d612710612f2f601060009054906101000a900461ffff1661ffff1686613a1590919063ffffffff16565b613a2b90919063ffffffff16565b9050600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614158015612f7c5750600081115b156130bd578173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015612fc7573d6000803e3d6000fd5b50601060029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630daf16ed83836040518363ffffffff1660e01b81526004016130259291906142bf565b600060405180830381600087803b15801561303f57600080fd5b505af1158015613053573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f3d7fe97a05338f5c0493489b396ff7334f8873465d8504b44641c554f3856f1c836040516130b491906143fd565b60405180910390a35b50505b5050565b6000600a60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490509050919050565b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600c60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6060600a60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060200260200160405190810160405280929190818152602001828054801561326157602002820191906000526020600020905b81548152602001906001019080831161324d575b50505050509050919050565b6002600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905550565b8173ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600681526020017f30303330303700000000000000000000000000000000000000000000000000008152509061337f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016133769190614340565b60405180910390fd5b506001600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556000600b600083815260200190815260200160002054905060006001600a60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905061341f91906145e0565b905081811461354e576000600a60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481106134a1577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154905080600a60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208481548110613526577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b906000526020600020018190555082600b600083815260200190815260200160002081905550505b600a60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806135c3577f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6001900381819060005260206000200160009055905550505050565b600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600681526020017f3030333030360000000000000000000000000000000000000000000000000000815250906136b9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016136b09190614340565b60405180910390fd5b50816001600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600a60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190806001815401808255809150506001900390600052602060002001600090919091909150556001600a60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490506137c191906145e0565b600b6000838152602001908152602001600020819055505050565b60008060007fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060001b9050833f91506000801b821415801561381e5750808214155b92505050919050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156040518060400160405280600681526020017f3030333030310000000000000000000000000000000000000000000000000000815250906138cf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016138c69190614340565b60405180910390fd5b50600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600681526020017f3030333030360000000000000000000000000000000000000000000000000000815250906139aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016139a19190614340565b60405180910390fd5b506139b582826135df565b808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050565b60008183613a239190614586565b905092915050565b60008183613a399190614555565b905092915050565b828054613a4d9061470e565b90600052602060002090601f016020900481019282613a6f5760008555613ab6565b82601f10613a8857805160ff1916838001178555613ab6565b82800160010185558215613ab6579182015b82811115613ab5578251825591602001919060010190613a9a565b5b509050613ac39190613ac7565b5090565b5b80821115613ae0576000816000905550600101613ac8565b5090565b6000613af7613af28461443d565b614418565b905082815260208101848484011115613b0f57600080fd5b613b1a8482856146cc565b509392505050565b600081359050613b31816149ab565b92915050565b600081519050613b46816149ab565b92915050565b600081359050613b5b816149c2565b92915050565b600081359050613b70816149d9565b92915050565b600081519050613b85816149d9565b92915050565b60008083601f840112613b9d57600080fd5b8235905067ffffffffffffffff811115613bb657600080fd5b602083019150836001820283011115613bce57600080fd5b9250929050565b600081359050613be4816149f0565b92915050565b600082601f830112613bfb57600080fd5b8135613c0b848260208601613ae4565b91505092915050565b600081359050613c2381614a07565b92915050565b600081359050613c3881614a1e565b92915050565b600081519050613c4d81614a1e565b92915050565b600060208284031215613c6557600080fd5b6000613c7384828501613b22565b91505092915050565b600060208284031215613c8e57600080fd5b6000613c9c84828501613b37565b91505092915050565b60008060408385031215613cb857600080fd5b6000613cc685828601613b22565b9250506020613cd785828601613b22565b9150509250929050565b600080600060608486031215613cf657600080fd5b6000613d0486828701613b22565b9350506020613d1586828701613b22565b9250506040613d2686828701613c29565b9150509250925092565b600080600080600060808688031215613d4857600080fd5b6000613d5688828901613b22565b9550506020613d6788828901613b22565b9450506040613d7888828901613c29565b935050606086013567ffffffffffffffff811115613d9557600080fd5b613da188828901613b8b565b92509250509295509295909350565b60008060408385031215613dc357600080fd5b6000613dd185828601613b22565b9250506020613de285828601613b4c565b9150509250929050565b60008060408385031215613dff57600080fd5b6000613e0d85828601613b22565b9250506020613e1e85828601613c29565b9150509250929050565b600060208284031215613e3a57600080fd5b6000613e4884828501613b61565b91505092915050565b600060208284031215613e6357600080fd5b6000613e7184828501613b76565b91505092915050565b600060208284031215613e8c57600080fd5b6000613e9a84828501613bd5565b91505092915050565b600060208284031215613eb557600080fd5b600082013567ffffffffffffffff811115613ecf57600080fd5b613edb84828501613bea565b91505092915050565b600060208284031215613ef657600080fd5b6000613f0484828501613c14565b91505092915050565b600060208284031215613f1f57600080fd5b6000613f2d84828501613c29565b91505092915050565b600060208284031215613f4857600080fd5b6000613f5684828501613c3e565b91505092915050565b6000613f6b83836141e2565b60208301905092915050565b613f8081614614565b82525050565b6000613f9182614493565b613f9b81856144c1565b9350613fa68361446e565b8060005b83811015613fd7578151613fbe8882613f5f565b9750613fc9836144b4565b925050600181019050613faa565b5085935050505092915050565b613fed81614626565b82525050565b6000613ffe8261449e565b61400881856144d2565b93506140188185602086016146db565b614021816148a7565b840191505092915050565b614035816146a8565b82525050565b6000614046826144a9565b61405081856144e3565b93506140608185602086016146db565b614069816148a7565b840191505092915050565b600061407f826144a9565b61408981856144f4565b93506140998185602086016146db565b80840191505092915050565b600081546140b28161470e565b6140bc81866144f4565b945060018216600081146140d757600181146140e85761411b565b60ff1983168652818601935061411b565b6140f18561447e565b60005b83811015614113578154818901526001820191506020810190506140f4565b838801955050505b50505092915050565b60006141316026836144e3565b915061413c826148b8565b604082019050919050565b60006141546005836144f4565b915061415f82614907565b600582019050919050565b60006141776020836144e3565b915061418282614930565b602082019050919050565b600061419a6019836144e3565b91506141a582614959565b602082019050919050565b60006141bd6008836144e3565b91506141c882614982565b602082019050919050565b6141dc81614670565b82525050565b6141eb8161469e565b82525050565b6141fa8161469e565b82525050565b600061420c82856140a5565b91506142188284614074565b915061422382614147565b91508190509392505050565b60006020820190506142446000830184613f77565b92915050565b600060408201905061425f6000830185613f77565b61426c6020830184613f77565b9392505050565b60006080820190506142886000830187613f77565b6142956020830186613f77565b6142a260408301856141f1565b81810360608301526142b48184613ff3565b905095945050505050565b60006040820190506142d46000830185613f77565b6142e160208301846141f1565b9392505050565b600060208201905081810360008301526143028184613f86565b905092915050565b600060208201905061431f6000830184613fe4565b92915050565b600060208201905061433a600083018461402c565b92915050565b6000602082019050818103600083015261435a818461403b565b905092915050565b6000602082019050818103600083015261437b81614124565b9050919050565b6000602082019050818103600083015261439b8161416a565b9050919050565b600060208201905081810360008301526143bb8161418d565b9050919050565b600060208201905081810360008301526143db816141b0565b9050919050565b60006020820190506143f760008301846141d3565b92915050565b600060208201905061441260008301846141f1565b92915050565b6000614422614433565b905061442e8282614740565b919050565b6000604051905090565b600067ffffffffffffffff82111561445857614457614878565b5b614461826148a7565b9050602081019050919050565b6000819050602082019050919050565b60008190508160005260206000209050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600061450a8261469e565b91506145158361469e565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0382111561454a576145496147eb565b5b828201905092915050565b60006145608261469e565b915061456b8361469e565b92508261457b5761457a61481a565b5b828204905092915050565b60006145918261469e565b915061459c8361469e565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156145d5576145d46147eb565b5b828202905092915050565b60006145eb8261469e565b91506145f68361469e565b925082821015614609576146086147eb565b5b828203905092915050565b600061461f8261467e565b9050919050565b60008115159050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600061466982614614565b9050919050565b600061ffff82169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006146b3826146ba565b9050919050565b60006146c58261467e565b9050919050565b82818337600083830152505050565b60005b838110156146f95780820151818401526020810190506146de565b83811115614708576000848401525b50505050565b6000600282049050600182168061472657607f821691505b6020821081141561473a57614739614849565b5b50919050565b614749826148a7565b810181811067ffffffffffffffff8211171561476857614767614878565b5b80604052505050565b600061477c8261469e565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156147af576147ae6147eb565b5b600182019050919050565b60006147c58261469e565b91506147d08361469e565b9250826147e0576147df61481a565b5b828206905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b7f2e6a736f6e000000000000000000000000000000000000000000000000000000600082015250565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b7f416d6f756e74206973206c657373207468616e20707269636500000000000000600082015250565b7f536f6c64206f7574000000000000000000000000000000000000000000000000600082015250565b6149b481614614565b81146149bf57600080fd5b50565b6149cb81614626565b81146149d657600080fd5b50565b6149e281614632565b81146149ed57600080fd5b50565b6149f98161465e565b8114614a0457600080fd5b50565b614a1081614670565b8114614a1b57600080fd5b50565b614a278161469e565b8114614a3257600080fd5b5056fea264697066735822122029a71587885fc4917d56b25cc11e39f6b22e88783bb02da93fd6aeb88c93d5f564736f6c63430008040033

Deployed ByteCode Sourcemap

49349:3522:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8545:150;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;33927:94;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;17552:159;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;15472:319;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;51630:86;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;35164:94;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;49579:29;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;14745:314;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;35798:222;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;51276:126;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;50912:100;;;;;;;;;;;;;:::i;:::-;;14024:156;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;35393:175;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;17131:184;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;50000:770;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;16688:180;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;42062:85;;;;;;;;;;;;;:::i;:::-;;49644:33;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;50775:132;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;51017:117;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;41471:78;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;34132:102;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;49523:52;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;49437:33;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;16194:207;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;51462:118;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;13439:184;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;34381:157;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;49486:33;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;17973:165;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;51139:132;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;42287:190;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;8545:150;8637:4;8657:19;:33;8677:12;8657:33;;;;;;;;;;;;;;;;;;;;;;;;;;;8650:40;;8545:150;;;:::o;33927:94::-;33975:19;34009:7;34001:15;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;33927:94;:::o;17552:159::-;17661:7;17639:8;12430:1;12399:33;;:9;:19;12409:8;12399:19;;;;;;;;;;;;;;;;;;;;;:33;;;;12434:13;;;;;;;;;;;;;;;;;12391:57;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;17684:12:::1;:22;17697:8;17684:22;;;;;;;;;;;;;;;;;;;;;17677:29;;17552:159:::0;;;;:::o;15472:319::-;15564:8;11648:18;11669:9;:19;11679:8;11669:19;;;;;;;;;;;;;;;;;;;;;11648:40;;11720:10;11706:24;;:10;:24;;;:73;;;;11739:16;:28;11756:10;11739:28;;;;;;;;;;;;;;;:40;11768:10;11739:40;;;;;;;;;;;;;;;;;;;;;;;;;11706:73;11785:21;;;;;;;;;;;;;;;;;11693:118;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;15590:8:::1;12430:1;12399:33;;:9;:19;12409:8;12399:19;;;;;;;;;;;;;;;;;;;;;:33;;;;12434:13;;;;;;;;;;;;;;;;::::0;12391:57:::1;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;15607:18:::2;15628:9;:19;15638:8;15628:19;;;;;;;;;;;;;;;;;;;;;15607:40;;15673:10;15660:23;;:9;:23;;;;15685:8;;;;;;;;;;;;;;;;::::0;15652:42:::2;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;15726:9;15701:12;:22;15714:8;15701:22;;;;;;;;;;;;:34;;;;;;;;;;;;;;;;;;15777:8;15766:9;15745:41;;15754:10;15745:41;;;;;;;;;;;;12453:1;11816::::1;15472:319:::0;;;;:::o;51630:86::-;41675:12;:10;:12::i;:::-;41664:23;;:7;:5;:7::i;:::-;:23;;;41656:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;51702:9:::1;51691:8;;:20;;;;;;;;;;;;;;;;;;51630:86:::0;:::o;35164:94::-;35219:7;35240:6;:13;;;;35233:20;;35164:94;:::o;49579:29::-;;;;;;;;;;;;;:::o;14745:314::-;14856:8;12000:18;12021:9;:19;12031:8;12021:19;;;;;;;;;;;;;;;;;;;;;12000:40;;12072:10;12058:24;;:10;:24;;;:69;;;;12117:10;12091:36;;:12;:22;12104:8;12091:22;;;;;;;;;;;;;;;;;;;;;:36;;;12058:69;:118;;;;12136:16;:28;12153:10;12136:28;;;;;;;;;;;;;;;:40;12165:10;12136:40;;;;;;;;;;;;;;;;;;;;;;;;;12058:118;12182:30;;;;;;;;;;;;;;;;;12045:172;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;14879:8:::1;12430:1;12399:33;;:9;:19;12409:8;12399:19;;;;;;;;;;;;;;;;;;;;;:33;;;;12434:13;;;;;;;;;;;;;;;;::::0;12391:57:::1;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;14894:18:::2;14915:9;:19;14925:8;14915:19;;;;;;;;;;;;;;;;;;;;;14894:40;;14961:5;14947:19;;:10;:19;;;14968:9;;;;;;;;;;;;;;;;::::0;14939:39:::2;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;15006:1;14991:17;;:3;:17;;;;15010:12;;;;;;;;;;;;;;;;::::0;14983:40:::2;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;15030:24;15040:3;15045:8;15030:9;:24::i;:::-;12453:1;12222::::1;14745:314:::0;;;;;:::o;35798:222::-;35903:7;35936:10;:18;35947:6;35936:18;;;;;;;;;;;;;;;:25;;;;35927:6;:34;35963:13;;;;;;;;;;;;;;;;;35919:58;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;35989:10;:18;36000:6;35989:18;;;;;;;;;;;;;;;36008:6;35989:26;;;;;;;;;;;;;;;;;;;;;;;;35982:33;;35798:222;;;;:::o;51276:126::-;41675:12;:10;:12::i;:::-;41664:23;;:7;:5;:7::i;:::-;:23;;;41656:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;51355:8:::1;51345:7;:18;;;;;;;;;;;;:::i;:::-;;51373:24;51388:8;51373:24;;;;;;:::i;:::-;;;;;;;;51276:126:::0;:::o;50912:100::-;41675:12;:10;:12::i;:::-;41664:23;;:7;:5;:7::i;:::-;:23;;;41656:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;50964:10:::1;50956:28;;:51;50985:21;50956:51;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;50912:100::o:0;14024:156::-;14132:43;14150:5;14157:3;14162:8;14132:43;;;;;;;;;;;;:17;:43::i;:::-;14024:156;;;:::o;35393:175::-;35475:7;35508:6;:13;;;;35499:6;:22;35523:13;;;;;;;;;;;;;;;;;35491:46;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;35549:6;35556;35549:14;;;;;;;;;;;;;;;;;;;;;;;;35542:21;;35393:175;;;:::o;17131:184::-;17210:14;17242:9;:19;17252:8;17242:19;;;;;;;;;;;;;;;;;;;;;17233:28;;17292:1;17274:20;;:6;:20;;;;17296:13;;;;;;;;;;;;;;;;;17266:44;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;17131:184;;;:::o;50000:770::-;50076:5;;50063:9;:18;;50055:56;;;;;;;;;;;;:::i;:::-;;;;;;;;;50137:4;:16;;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;50124:9;;:31;;50116:52;;;;;;;;;;;;:::i;:::-;;;;;;;;;50175:13;50203:5;;50191:9;:17;;;;:::i;:::-;50175:33;;50236:1;50224:9;:13;:60;;;;;50282:1;50245:39;;50253:16;;;;;;;;;;;50245:39;;;;50224:60;:91;;;;;50313:1;50292:23;;:9;:23;;;;50224:91;:122;;;;;50336:10;50323:23;;:9;:23;;;;50224:122;50215:203;;;50358:16;;;;;;;;;;;:31;;;50390:10;50402:9;50358:54;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;50215:203;50429:9;50424:342;50448:5;50444:1;:9;50424:342;;;50466:21;50490:4;:16;;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;50466:42;;50516:15;50534:13;50516:31;;50553:10;50566;50553:23;;50584:24;50596:2;50600:7;50584:11;:24::i;:::-;50614:106;50639:7;50677;50686:17;50695:7;50686:8;:17::i;:::-;50660:53;;;;;;;;;:::i;:::-;;;;;;;;;;;;;50614:18;:106::i;:::-;50726:34;50738:10;50750:9;50726:11;:34::i;:::-;50424:342;;;50455:3;;;;;:::i;:::-;;;;50424:342;;;;50000:770;;:::o;16688:180::-;16767:7;16809:1;16791:20;;:6;:20;;;;16813:12;;;;;;;;;;;;;;;;;16783:43;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;16838:25;16856:6;16838:17;:25::i;:::-;16831:32;;16688:180;;;:::o;42062:85::-;41675:12;:10;:12::i;:::-;41664:23;;:7;:5;:7::i;:::-;:23;;;41656:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;42121:21:::1;42139:1;42121:9;:21::i;:::-;42062:85::o:0;49644:33::-;;;;;;;;;;;;;:::o;50775:132::-;50843:16;50875:27;50895:6;50875:19;:27::i;:::-;50868:34;;50775:132;;;:::o;51017:117::-;41675:12;:10;:12::i;:::-;41664:23;;:7;:5;:7::i;:::-;:23;;;41656:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;51087:9:::1;51079:5;:17;;;;51106:23;51119:9;51106:23;;;;;;:::i;:::-;;;;;;;;51017:117:::0;:::o;41471:78::-;41517:7;41538:6;;;;;;;;;;;41531:13;;41471:78;:::o;34132:102::-;34182:21;34220:9;34210:19;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;34132:102;:::o;49523:52::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;49437:33::-;;;;:::o;16194:207::-;16329:9;16287:16;:28;16304:10;16287:28;;;;;;;;;;;;;;;:39;16316:9;16287:39;;;;;;;;;;;;;;;;:51;;;;;;;;;;;;;;;;;;16375:9;16348:48;;16363:10;16348:48;;;16386:9;16348:48;;;;;;:::i;:::-;;;;;;;;16194:207;;:::o;51462:118::-;41675:12;:10;:12::i;:::-;41664:23;;:7;:5;:7::i;:::-;:23;;;41656:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;51559:16:::1;51540;;:35;;;;;;;;;;;;;;;;;;51462:118:::0;:::o;13439:184::-;13572:46;13590:5;13597:3;13602:8;13612:5;;13572:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:17;:46::i;:::-;13439:184;;;;;:::o;34381:157::-;34487:13;34465:8;12430:1;12399:33;;:9;:19;12409:8;12399:19;;;;;;;;;;;;;;;;;;;;;:33;;;;12434:13;;;;;;;;;;;;;;;;;12391:57;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;34516:7:::1;:17;34524:8;34516:17;;;;;;;;;;;34509:24;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;34381:157:::0;;;;:::o;49486:33::-;;;;:::o;17973:165::-;18078:4;18098:16;:24;18115:6;18098:24;;;;;;;;;;;;;;;:35;18123:9;18098:35;;;;;;;;;;;;;;;;;;;;;;;;;18091:42;;17973:165;;;;:::o;51139:132::-;41675:12;:10;:12::i;:::-;41664:23;;:7;:5;:7::i;:::-;:23;;;41656:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;51218:10:::1;51206:9;:22;;;;51238:28;51255:10;51238:28;;;;;;:::i;:::-;;;;;;;;51139:132:::0;:::o;42287:190::-;41675:12;:10;:12::i;:::-;41664:23;;:7;:5;:7::i;:::-;:23;;;41656:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;42395:1:::1;42375:22;;:8;:22;;;;42362:86;;;;;;;;;;;;:::i;:::-;;;;;;;;;42453:19;42463:8;42453:9;:19::i;:::-;42287:190:::0;:::o;40314:89::-;40367:7;40388:10;40381:17;;40314:89;:::o;18322:241::-;18386:12;18401:9;:19;18411:8;18401:19;;;;;;;;;;;;;;;;;;;;;18386:34;;18425:24;18440:8;18425:14;:24::i;:::-;18456:30;18471:4;18477:8;18456:14;:30::i;:::-;18491:26;18503:3;18508:8;18491:11;:26::i;:::-;18549:8;18544:3;18529:29;;18538:4;18529:29;;;;;;;;;;;;18322:241;;;:::o;21478:581::-;21607:8;12000:18;12021:9;:19;12031:8;12021:19;;;;;;;;;;;;;;;;;;;;;12000:40;;12072:10;12058:24;;:10;:24;;;:69;;;;12117:10;12091:36;;:12;:22;12104:8;12091:22;;;;;;;;;;;;;;;;;;;;;:36;;;12058:69;:118;;;;12136:16;:28;12153:10;12136:28;;;;;;;;;;;;;;;:40;12165:10;12136:40;;;;;;;;;;;;;;;;;;;;;;;;;12058:118;12182:30;;;;;;;;;;;;;;;;;12045:172;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;21630:8:::1;12430:1;12399:33;;:9;:19;12409:8;12399:19;;;;;;;;;;;;;;;;;;;;;:33;;;;12434:13;;;;;;;;;;;;;;;;::::0;12391:57:::1;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;21645:18:::2;21666:9;:19;21676:8;21666:19;;;;;;;;;;;;;;;;;;;;;21645:40;;21712:5;21698:19;;:10;:19;;;21719:9;;;;;;;;;;;;;;;;::::0;21690:39:::2;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;21757:1;21742:17;;:3;:17;;;;21761:12;;;;;;;;;;;;;;;;::::0;21734:40:::2;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;21781:24;21791:3;21796:8;21781:9;:24::i;:::-;21816:16;:3;:14;;;:16::i;:::-;21812:243;;;21840:13;21876:3;21856:41;;;21904:10;21921:5;21933:8;21948:5;21856:103;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;21840:119;;10908:10;21989:24;;21979:34;;;:6;:34;;;;22020:23;;;;;;;;;;;;;;;;::::0;21965:84:::2;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;21812:243;;12453:1;12222::::1;21478:581:::0;;;;;;:::o;36402:178::-;36479:26;36491:3;36496:8;36479:11;:26::i;:::-;36510:6;36522:8;36510:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;36574:1;36558:6;:13;;;;:17;;;;:::i;:::-;36536:9;:19;36546:8;36536:19;;;;;;;;;;;:39;;;;36402:178;;:::o;52276:592::-;52332:13;52542:1;52533:5;:10;52529:38;;;52551:10;;;;;;;;;;;;;;;;;;;;;52529:38;52571:12;52586:5;52571:20;;52596:14;52615:54;52630:1;52622:4;:9;52615:54;;52639:8;;;;;:::i;:::-;;;;52661:2;52653:10;;;;;:::i;:::-;;;52615:54;;;52673:19;52705:6;52695:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;52673:39;;52717:121;52733:1;52724:5;:10;52717:121;;52752:1;52742:11;;;;;:::i;:::-;;;52810:2;52802:5;:10;;;;:::i;:::-;52789:2;:24;;;;:::i;:::-;52776:39;;52759:6;52766;52759:14;;;;;;;;;;;;;;;;;;;:56;;;;;;;;;;;52830:2;52821:11;;;;;:::i;:::-;;;52717:121;;;52856:6;52842:21;;;;;52276:592;;;;:::o;34924:134::-;35012:8;12430:1;12399:33;;:9;:19;12409:8;12399:19;;;;;;;;;;;;;;;;;;;;;:33;;;;12434:13;;;;;;;;;;;;;;;;;12391:57;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;35049:4:::1;35029:7;:17;35037:8;35029:17;;;;;;;;;;;:24;;;;;;;;;;;;:::i;:::-;;34924:134:::0;;;:::o;51785:486::-;51891:1;51854:39;;51862:16;;;;;;;;;;;51854:39;;;;:55;;;;;51908:1;51897:8;;;;;;;;;;;:12;;;51854:55;51850:417;;;51917:16;51936;;;;;;;;;;;:28;;;51965:3;51936:33;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;51917:52;;51975:19;51997:32;52023:5;51997:21;52009:8;;;;;;;;;;;51997:21;;:7;:11;;:21;;;;:::i;:::-;:25;;:32;;;;:::i;:::-;51975:54;;52061:1;52041:22;;:8;:22;;;;:41;;;;;52081:1;52067:11;:15;52041:41;52037:225;;;52099:8;52091:26;;:39;52118:11;52091:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;52139:16;;;;;;;;;;;:36;;;52176:8;52186:11;52139:59;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;52233:8;52210:45;;52228:3;52210:45;;;52243:11;52210:45;;;;;;:::i;:::-;;;;;;;;52037:225;51850:417;;;51785:486;;:::o;39537:151::-;39635:7;39658:10;:18;39669:6;39658:18;;;;;;;;;;;;;;;:25;;;;39651:32;;39537:151;;;:::o;42482:152::-;42532:16;42551:6;;;;;;;;;;;42532:25;;42571:8;42562:6;;:17;;;;;;;;;;;;;;;;;;42620:8;42589:40;;42610:8;42589:40;;;;;;;;;;;;42482:152;;:::o;39112:137::-;39194:16;39226:10;:18;39237:6;39226:18;;;;;;;;;;;;;;;39219:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;39112:137;;;:::o;22187:89::-;22249:12;:22;22262:8;22249:22;;;;;;;;;;;;22242:29;;;;;;;;;;;22187:89;:::o;37723:551::-;37853:5;37830:28;;:9;:19;37840:8;37830:19;;;;;;;;;;;;;;;;;;;;;:28;;;37860:9;;;;;;;;;;;;;;;;;37822:48;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;37882:9;:19;37892:8;37882:19;;;;;;;;;;;;37875:26;;;;;;;;;;;37908;37937:14;:24;37952:8;37937:24;;;;;;;;;;;;37908:53;;37966:22;38018:1;37991:10;:17;38002:5;37991:17;;;;;;;;;;;;;;;:24;;;;:28;;;;:::i;:::-;37966:53;;38048:18;38030:14;:36;38026:214;;38074:17;38094:10;:17;38105:5;38094:17;;;;;;;;;;;;;;;38112:14;38094:33;;;;;;;;;;;;;;;;;;;;;;;;38074:53;;38173:9;38133:10;:17;38144:5;38133:17;;;;;;;;;;;;;;;38151:18;38133:37;;;;;;;;;;;;;;;;;;;;;;;:49;;;;38216:18;38188:14;:25;38203:9;38188:25;;;;;;;;;;;:46;;;;38026:214;;38246:10;:17;38257:5;38246:17;;;;;;;;;;;;;;;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;37723:551;;;;:::o;38538:286::-;38671:1;38640:33;;:9;:19;38650:8;38640:19;;;;;;;;;;;;;;;;;;;;;:33;;;38675:18;;;;;;;;;;;;;;;;;38632:62;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;38721:3;38699:9;:19;38709:8;38699:19;;;;;;;;;;;;:25;;;;;;;;;;;;;;;;;;38731:10;:15;38742:3;38731:15;;;;;;;;;;;;;;;38752:8;38731:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38818:1;38793:10;:15;38804:3;38793:15;;;;;;;;;;;;;;;:22;;;;:26;;;;:::i;:::-;38766:14;:24;38781:8;38766:24;;;;;;;;;;;:53;;;;38538:286;;:::o;9180:749::-;9247:17;9673:16;9694:19;9716:66;9694:88;;;;9826:5;9814:18;9802:30;;9893:3;9881:15;;:8;:15;;:42;;;;;9912:11;9900:8;:23;;9881:42;9865:59;;9180:749;;;;;:::o;18945:260::-;19036:1;19021:17;;:3;:17;;;;19040:12;;;;;;;;;;;;;;;;;19013:40;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;19097:1;19066:33;;:9;:19;19076:8;19066:19;;;;;;;;;;;;;;;;;;;;;:33;;;19101:18;;;;;;;;;;;;;;;;;19058:62;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;19127:26;19139:3;19144:8;19127:11;:26::i;:::-;19191:8;19186:3;19165:35;;19182:1;19165:35;;;;;;;;;;;;18945:260;;:::o;45800:89::-;45858:7;45883:1;45879;:5;;;;:::i;:::-;45872:12;;45800:89;;;;:::o;46157:::-;46215:7;46240:1;46236;:5;;;;:::i;:::-;46229:12;;46157:89;;;;:::o;-1:-1:-1:-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;:::o;7:345:1:-;85:5;110:66;126:49;168:6;126:49;:::i;:::-;110:66;:::i;:::-;101:75;;199:6;192:5;185:21;237:4;230:5;226:16;275:3;266:6;261:3;257:16;254:25;251:2;;;292:1;289;282:12;251:2;305:41;339:6;334:3;329;305:41;:::i;:::-;91:261;;;;;;:::o;358:139::-;404:5;442:6;429:20;420:29;;458:33;485:5;458:33;:::i;:::-;410:87;;;;:::o;503:143::-;560:5;591:6;585:13;576:22;;607:33;634:5;607:33;:::i;:::-;566:80;;;;:::o;652:133::-;695:5;733:6;720:20;711:29;;749:30;773:5;749:30;:::i;:::-;701:84;;;;:::o;791:137::-;836:5;874:6;861:20;852:29;;890:32;916:5;890:32;:::i;:::-;842:86;;;;:::o;934:141::-;990:5;1021:6;1015:13;1006:22;;1037:32;1063:5;1037:32;:::i;:::-;996:79;;;;:::o;1094:351::-;1151:8;1161:6;1211:3;1204:4;1196:6;1192:17;1188:27;1178:2;;1229:1;1226;1219:12;1178:2;1265:6;1252:20;1242:30;;1295:18;1287:6;1284:30;1281:2;;;1327:1;1324;1317:12;1281:2;1364:4;1356:6;1352:17;1340:29;;1418:3;1410:4;1402:6;1398:17;1388:8;1384:32;1381:41;1378:2;;;1435:1;1432;1425:12;1378:2;1168:277;;;;;:::o;1451:175::-;1515:5;1553:6;1540:20;1531:29;;1569:51;1614:5;1569:51;:::i;:::-;1521:105;;;;:::o;1646:273::-;1702:5;1751:3;1744:4;1736:6;1732:17;1728:27;1718:2;;1769:1;1766;1759:12;1718:2;1809:6;1796:20;1834:79;1909:3;1901:6;1894:4;1886:6;1882:17;1834:79;:::i;:::-;1825:88;;1708:211;;;;;:::o;1925:137::-;1970:5;2008:6;1995:20;1986:29;;2024:32;2050:5;2024:32;:::i;:::-;1976:86;;;;:::o;2068:139::-;2114:5;2152:6;2139:20;2130:29;;2168:33;2195:5;2168:33;:::i;:::-;2120:87;;;;:::o;2213:143::-;2270:5;2301:6;2295:13;2286:22;;2317:33;2344:5;2317:33;:::i;:::-;2276:80;;;;:::o;2362:262::-;2421:6;2470:2;2458:9;2449:7;2445:23;2441:32;2438:2;;;2486:1;2483;2476:12;2438:2;2529:1;2554:53;2599:7;2590:6;2579:9;2575:22;2554:53;:::i;:::-;2544:63;;2500:117;2428:196;;;;:::o;2630:284::-;2700:6;2749:2;2737:9;2728:7;2724:23;2720:32;2717:2;;;2765:1;2762;2755:12;2717:2;2808:1;2833:64;2889:7;2880:6;2869:9;2865:22;2833:64;:::i;:::-;2823:74;;2779:128;2707:207;;;;:::o;2920:407::-;2988:6;2996;3045:2;3033:9;3024:7;3020:23;3016:32;3013:2;;;3061:1;3058;3051:12;3013:2;3104:1;3129:53;3174:7;3165:6;3154:9;3150:22;3129:53;:::i;:::-;3119:63;;3075:117;3231:2;3257:53;3302:7;3293:6;3282:9;3278:22;3257:53;:::i;:::-;3247:63;;3202:118;3003:324;;;;;:::o;3333:552::-;3410:6;3418;3426;3475:2;3463:9;3454:7;3450:23;3446:32;3443:2;;;3491:1;3488;3481:12;3443:2;3534:1;3559:53;3604:7;3595:6;3584:9;3580:22;3559:53;:::i;:::-;3549:63;;3505:117;3661:2;3687:53;3732:7;3723:6;3712:9;3708:22;3687:53;:::i;:::-;3677:63;;3632:118;3789:2;3815:53;3860:7;3851:6;3840:9;3836:22;3815:53;:::i;:::-;3805:63;;3760:118;3433:452;;;;;:::o;3891:829::-;3988:6;3996;4004;4012;4020;4069:3;4057:9;4048:7;4044:23;4040:33;4037:2;;;4086:1;4083;4076:12;4037:2;4129:1;4154:53;4199:7;4190:6;4179:9;4175:22;4154:53;:::i;:::-;4144:63;;4100:117;4256:2;4282:53;4327:7;4318:6;4307:9;4303:22;4282:53;:::i;:::-;4272:63;;4227:118;4384:2;4410:53;4455:7;4446:6;4435:9;4431:22;4410:53;:::i;:::-;4400:63;;4355:118;4540:2;4529:9;4525:18;4512:32;4571:18;4563:6;4560:30;4557:2;;;4603:1;4600;4593:12;4557:2;4639:64;4695:7;4686:6;4675:9;4671:22;4639:64;:::i;:::-;4621:82;;;;4483:230;4027:693;;;;;;;;:::o;4726:401::-;4791:6;4799;4848:2;4836:9;4827:7;4823:23;4819:32;4816:2;;;4864:1;4861;4854:12;4816:2;4907:1;4932:53;4977:7;4968:6;4957:9;4953:22;4932:53;:::i;:::-;4922:63;;4878:117;5034:2;5060:50;5102:7;5093:6;5082:9;5078:22;5060:50;:::i;:::-;5050:60;;5005:115;4806:321;;;;;:::o;5133:407::-;5201:6;5209;5258:2;5246:9;5237:7;5233:23;5229:32;5226:2;;;5274:1;5271;5264:12;5226:2;5317:1;5342:53;5387:7;5378:6;5367:9;5363:22;5342:53;:::i;:::-;5332:63;;5288:117;5444:2;5470:53;5515:7;5506:6;5495:9;5491:22;5470:53;:::i;:::-;5460:63;;5415:118;5216:324;;;;;:::o;5546:260::-;5604:6;5653:2;5641:9;5632:7;5628:23;5624:32;5621:2;;;5669:1;5666;5659:12;5621:2;5712:1;5737:52;5781:7;5772:6;5761:9;5757:22;5737:52;:::i;:::-;5727:62;;5683:116;5611:195;;;;:::o;5812:282::-;5881:6;5930:2;5918:9;5909:7;5905:23;5901:32;5898:2;;;5946:1;5943;5936:12;5898:2;5989:1;6014:63;6069:7;6060:6;6049:9;6045:22;6014:63;:::i;:::-;6004:73;;5960:127;5888:206;;;;:::o;6100:298::-;6177:6;6226:2;6214:9;6205:7;6201:23;6197:32;6194:2;;;6242:1;6239;6232:12;6194:2;6285:1;6310:71;6373:7;6364:6;6353:9;6349:22;6310:71;:::i;:::-;6300:81;;6256:135;6184:214;;;;:::o;6404:375::-;6473:6;6522:2;6510:9;6501:7;6497:23;6493:32;6490:2;;;6538:1;6535;6528:12;6490:2;6609:1;6598:9;6594:17;6581:31;6639:18;6631:6;6628:30;6625:2;;;6671:1;6668;6661:12;6625:2;6699:63;6754:7;6745:6;6734:9;6730:22;6699:63;:::i;:::-;6689:73;;6552:220;6480:299;;;;:::o;6785:260::-;6843:6;6892:2;6880:9;6871:7;6867:23;6863:32;6860:2;;;6908:1;6905;6898:12;6860:2;6951:1;6976:52;7020:7;7011:6;7000:9;6996:22;6976:52;:::i;:::-;6966:62;;6922:116;6850:195;;;;:::o;7051:262::-;7110:6;7159:2;7147:9;7138:7;7134:23;7130:32;7127:2;;;7175:1;7172;7165:12;7127:2;7218:1;7243:53;7288:7;7279:6;7268:9;7264:22;7243:53;:::i;:::-;7233:63;;7189:117;7117:196;;;;:::o;7319:284::-;7389:6;7438:2;7426:9;7417:7;7413:23;7409:32;7406:2;;;7454:1;7451;7444:12;7406:2;7497:1;7522:64;7578:7;7569:6;7558:9;7554:22;7522:64;:::i;:::-;7512:74;;7468:128;7396:207;;;;:::o;7609:179::-;7678:10;7699:46;7741:3;7733:6;7699:46;:::i;:::-;7777:4;7772:3;7768:14;7754:28;;7689:99;;;;:::o;7794:118::-;7881:24;7899:5;7881:24;:::i;:::-;7876:3;7869:37;7859:53;;:::o;7948:732::-;8067:3;8096:54;8144:5;8096:54;:::i;:::-;8166:86;8245:6;8240:3;8166:86;:::i;:::-;8159:93;;8276:56;8326:5;8276:56;:::i;:::-;8355:7;8386:1;8371:284;8396:6;8393:1;8390:13;8371:284;;;8472:6;8466:13;8499:63;8558:3;8543:13;8499:63;:::i;:::-;8492:70;;8585:60;8638:6;8585:60;:::i;:::-;8575:70;;8431:224;8418:1;8415;8411:9;8406:14;;8371:284;;;8375:14;8671:3;8664:10;;8072:608;;;;;;;:::o;8686:109::-;8767:21;8782:5;8767:21;:::i;:::-;8762:3;8755:34;8745:50;;:::o;8801:360::-;8887:3;8915:38;8947:5;8915:38;:::i;:::-;8969:70;9032:6;9027:3;8969:70;:::i;:::-;8962:77;;9048:52;9093:6;9088:3;9081:4;9074:5;9070:16;9048:52;:::i;:::-;9125:29;9147:6;9125:29;:::i;:::-;9120:3;9116:39;9109:46;;8891:270;;;;;:::o;9167:167::-;9272:55;9321:5;9272:55;:::i;:::-;9267:3;9260:68;9250:84;;:::o;9340:364::-;9428:3;9456:39;9489:5;9456:39;:::i;:::-;9511:71;9575:6;9570:3;9511:71;:::i;:::-;9504:78;;9591:52;9636:6;9631:3;9624:4;9617:5;9613:16;9591:52;:::i;:::-;9668:29;9690:6;9668:29;:::i;:::-;9663:3;9659:39;9652:46;;9432:272;;;;;:::o;9710:377::-;9816:3;9844:39;9877:5;9844:39;:::i;:::-;9899:89;9981:6;9976:3;9899:89;:::i;:::-;9892:96;;9997:52;10042:6;10037:3;10030:4;10023:5;10019:16;9997:52;:::i;:::-;10074:6;10069:3;10065:16;10058:23;;9820:267;;;;;:::o;10117:845::-;10220:3;10257:5;10251:12;10286:36;10312:9;10286:36;:::i;:::-;10338:89;10420:6;10415:3;10338:89;:::i;:::-;10331:96;;10458:1;10447:9;10443:17;10474:1;10469:137;;;;10620:1;10615:341;;;;10436:520;;10469:137;10553:4;10549:9;10538;10534:25;10529:3;10522:38;10589:6;10584:3;10580:16;10573:23;;10469:137;;10615:341;10682:38;10714:5;10682:38;:::i;:::-;10742:1;10756:154;10770:6;10767:1;10764:13;10756:154;;;10844:7;10838:14;10834:1;10829:3;10825:11;10818:35;10894:1;10885:7;10881:15;10870:26;;10792:4;10789:1;10785:12;10780:17;;10756:154;;;10939:6;10934:3;10930:16;10923:23;;10622:334;;10436:520;;10224:738;;;;;;:::o;10968:366::-;11110:3;11131:67;11195:2;11190:3;11131:67;:::i;:::-;11124:74;;11207:93;11296:3;11207:93;:::i;:::-;11325:2;11320:3;11316:12;11309:19;;11114:220;;;:::o;11340:400::-;11500:3;11521:84;11603:1;11598:3;11521:84;:::i;:::-;11514:91;;11614:93;11703:3;11614:93;:::i;:::-;11732:1;11727:3;11723:11;11716:18;;11504:236;;;:::o;11746:366::-;11888:3;11909:67;11973:2;11968:3;11909:67;:::i;:::-;11902:74;;11985:93;12074:3;11985:93;:::i;:::-;12103:2;12098:3;12094:12;12087:19;;11892:220;;;:::o;12118:366::-;12260:3;12281:67;12345:2;12340:3;12281:67;:::i;:::-;12274:74;;12357:93;12446:3;12357:93;:::i;:::-;12475:2;12470:3;12466:12;12459:19;;12264:220;;;:::o;12490:365::-;12632:3;12653:66;12717:1;12712:3;12653:66;:::i;:::-;12646:73;;12728:93;12817:3;12728:93;:::i;:::-;12846:2;12841:3;12837:12;12830:19;;12636:219;;;:::o;12861:115::-;12946:23;12963:5;12946:23;:::i;:::-;12941:3;12934:36;12924:52;;:::o;12982:108::-;13059:24;13077:5;13059:24;:::i;:::-;13054:3;13047:37;13037:53;;:::o;13096:118::-;13183:24;13201:5;13183:24;:::i;:::-;13178:3;13171:37;13161:53;;:::o;13220:695::-;13498:3;13520:92;13608:3;13599:6;13520:92;:::i;:::-;13513:99;;13629:95;13720:3;13711:6;13629:95;:::i;:::-;13622:102;;13741:148;13885:3;13741:148;:::i;:::-;13734:155;;13906:3;13899:10;;13502:413;;;;;:::o;13921:222::-;14014:4;14052:2;14041:9;14037:18;14029:26;;14065:71;14133:1;14122:9;14118:17;14109:6;14065:71;:::i;:::-;14019:124;;;;:::o;14149:332::-;14270:4;14308:2;14297:9;14293:18;14285:26;;14321:71;14389:1;14378:9;14374:17;14365:6;14321:71;:::i;:::-;14402:72;14470:2;14459:9;14455:18;14446:6;14402:72;:::i;:::-;14275:206;;;;;:::o;14487:640::-;14682:4;14720:3;14709:9;14705:19;14697:27;;14734:71;14802:1;14791:9;14787:17;14778:6;14734:71;:::i;:::-;14815:72;14883:2;14872:9;14868:18;14859:6;14815:72;:::i;:::-;14897;14965:2;14954:9;14950:18;14941:6;14897:72;:::i;:::-;15016:9;15010:4;15006:20;15001:2;14990:9;14986:18;14979:48;15044:76;15115:4;15106:6;15044:76;:::i;:::-;15036:84;;14687:440;;;;;;;:::o;15133:332::-;15254:4;15292:2;15281:9;15277:18;15269:26;;15305:71;15373:1;15362:9;15358:17;15349:6;15305:71;:::i;:::-;15386:72;15454:2;15443:9;15439:18;15430:6;15386:72;:::i;:::-;15259:206;;;;;:::o;15471:373::-;15614:4;15652:2;15641:9;15637:18;15629:26;;15701:9;15695:4;15691:20;15687:1;15676:9;15672:17;15665:47;15729:108;15832:4;15823:6;15729:108;:::i;:::-;15721:116;;15619:225;;;;:::o;15850:210::-;15937:4;15975:2;15964:9;15960:18;15952:26;;15988:65;16050:1;16039:9;16035:17;16026:6;15988:65;:::i;:::-;15942:118;;;;:::o;16066:258::-;16177:4;16215:2;16204:9;16200:18;16192:26;;16228:89;16314:1;16303:9;16299:17;16290:6;16228:89;:::i;:::-;16182:142;;;;:::o;16330:313::-;16443:4;16481:2;16470:9;16466:18;16458:26;;16530:9;16524:4;16520:20;16516:1;16505:9;16501:17;16494:47;16558:78;16631:4;16622:6;16558:78;:::i;:::-;16550:86;;16448:195;;;;:::o;16649:419::-;16815:4;16853:2;16842:9;16838:18;16830:26;;16902:9;16896:4;16892:20;16888:1;16877:9;16873:17;16866:47;16930:131;17056:4;16930:131;:::i;:::-;16922:139;;16820:248;;;:::o;17074:419::-;17240:4;17278:2;17267:9;17263:18;17255:26;;17327:9;17321:4;17317:20;17313:1;17302:9;17298:17;17291:47;17355:131;17481:4;17355:131;:::i;:::-;17347:139;;17245:248;;;:::o;17499:419::-;17665:4;17703:2;17692:9;17688:18;17680:26;;17752:9;17746:4;17742:20;17738:1;17727:9;17723:17;17716:47;17780:131;17906:4;17780:131;:::i;:::-;17772:139;;17670:248;;;:::o;17924:419::-;18090:4;18128:2;18117:9;18113:18;18105:26;;18177:9;18171:4;18167:20;18163:1;18152:9;18148:17;18141:47;18205:131;18331:4;18205:131;:::i;:::-;18197:139;;18095:248;;;:::o;18349:218::-;18440:4;18478:2;18467:9;18463:18;18455:26;;18491:69;18557:1;18546:9;18542:17;18533:6;18491:69;:::i;:::-;18445:122;;;;:::o;18573:222::-;18666:4;18704:2;18693:9;18689:18;18681:26;;18717:71;18785:1;18774:9;18770:17;18761:6;18717:71;:::i;:::-;18671:124;;;;:::o;18801:129::-;18835:6;18862:20;;:::i;:::-;18852:30;;18891:33;18919:4;18911:6;18891:33;:::i;:::-;18842:88;;;:::o;18936:75::-;18969:6;19002:2;18996:9;18986:19;;18976:35;:::o;19017:308::-;19079:4;19169:18;19161:6;19158:30;19155:2;;;19191:18;;:::i;:::-;19155:2;19229:29;19251:6;19229:29;:::i;:::-;19221:37;;19313:4;19307;19303:15;19295:23;;19084:241;;;:::o;19331:132::-;19398:4;19421:3;19413:11;;19451:4;19446:3;19442:14;19434:22;;19403:60;;;:::o;19469:141::-;19518:4;19541:3;19533:11;;19564:3;19561:1;19554:14;19598:4;19595:1;19585:18;19577:26;;19523:87;;;:::o;19616:114::-;19683:6;19717:5;19711:12;19701:22;;19690:40;;;:::o;19736:98::-;19787:6;19821:5;19815:12;19805:22;;19794:40;;;:::o;19840:99::-;19892:6;19926:5;19920:12;19910:22;;19899:40;;;:::o;19945:113::-;20015:4;20047;20042:3;20038:14;20030:22;;20020:38;;;:::o;20064:184::-;20163:11;20197:6;20192:3;20185:19;20237:4;20232:3;20228:14;20213:29;;20175:73;;;;:::o;20254:168::-;20337:11;20371:6;20366:3;20359:19;20411:4;20406:3;20402:14;20387:29;;20349:73;;;;:::o;20428:169::-;20512:11;20546:6;20541:3;20534:19;20586:4;20581:3;20577:14;20562:29;;20524:73;;;;:::o;20603:148::-;20705:11;20742:3;20727:18;;20717:34;;;;:::o;20757:305::-;20797:3;20816:20;20834:1;20816:20;:::i;:::-;20811:25;;20850:20;20868:1;20850:20;:::i;:::-;20845:25;;21004:1;20936:66;20932:74;20929:1;20926:81;20923:2;;;21010:18;;:::i;:::-;20923:2;21054:1;21051;21047:9;21040:16;;20801:261;;;;:::o;21068:185::-;21108:1;21125:20;21143:1;21125:20;:::i;:::-;21120:25;;21159:20;21177:1;21159:20;:::i;:::-;21154:25;;21198:1;21188:2;;21203:18;;:::i;:::-;21188:2;21245:1;21242;21238:9;21233:14;;21110:143;;;;:::o;21259:348::-;21299:7;21322:20;21340:1;21322:20;:::i;:::-;21317:25;;21356:20;21374:1;21356:20;:::i;:::-;21351:25;;21544:1;21476:66;21472:74;21469:1;21466:81;21461:1;21454:9;21447:17;21443:105;21440:2;;;21551:18;;:::i;:::-;21440:2;21599:1;21596;21592:9;21581:20;;21307:300;;;;:::o;21613:191::-;21653:4;21673:20;21691:1;21673:20;:::i;:::-;21668:25;;21707:20;21725:1;21707:20;:::i;:::-;21702:25;;21746:1;21743;21740:8;21737:2;;;21751:18;;:::i;:::-;21737:2;21796:1;21793;21789:9;21781:17;;21658:146;;;;:::o;21810:96::-;21847:7;21876:24;21894:5;21876:24;:::i;:::-;21865:35;;21855:51;;;:::o;21912:90::-;21946:7;21989:5;21982:13;21975:21;21964:32;;21954:48;;;:::o;22008:149::-;22044:7;22084:66;22077:5;22073:78;22062:89;;22052:105;;;:::o;22163:114::-;22218:7;22247:24;22265:5;22247:24;:::i;:::-;22236:35;;22226:51;;;:::o;22283:89::-;22319:7;22359:6;22352:5;22348:18;22337:29;;22327:45;;;:::o;22378:126::-;22415:7;22455:42;22448:5;22444:54;22433:65;;22423:81;;;:::o;22510:77::-;22547:7;22576:5;22565:16;;22555:32;;;:::o;22593:162::-;22661:9;22694:55;22743:5;22694:55;:::i;:::-;22681:68;;22671:84;;;:::o;22761:131::-;22829:9;22862:24;22880:5;22862:24;:::i;:::-;22849:37;;22839:53;;;:::o;22898:154::-;22982:6;22977:3;22972;22959:30;23044:1;23035:6;23030:3;23026:16;23019:27;22949:103;;;:::o;23058:307::-;23126:1;23136:113;23150:6;23147:1;23144:13;23136:113;;;23235:1;23230:3;23226:11;23220:18;23216:1;23211:3;23207:11;23200:39;23172:2;23169:1;23165:10;23160:15;;23136:113;;;23267:6;23264:1;23261:13;23258:2;;;23347:1;23338:6;23333:3;23329:16;23322:27;23258:2;23107:258;;;;:::o;23371:320::-;23415:6;23452:1;23446:4;23442:12;23432:22;;23499:1;23493:4;23489:12;23520:18;23510:2;;23576:4;23568:6;23564:17;23554:27;;23510:2;23638;23630:6;23627:14;23607:18;23604:38;23601:2;;;23657:18;;:::i;:::-;23601:2;23422:269;;;;:::o;23697:281::-;23780:27;23802:4;23780:27;:::i;:::-;23772:6;23768:40;23910:6;23898:10;23895:22;23874:18;23862:10;23859:34;23856:62;23853:2;;;23921:18;;:::i;:::-;23853:2;23961:10;23957:2;23950:22;23740:238;;;:::o;23984:233::-;24023:3;24046:24;24064:5;24046:24;:::i;:::-;24037:33;;24092:66;24085:5;24082:77;24079:2;;;24162:18;;:::i;:::-;24079:2;24209:1;24202:5;24198:13;24191:20;;24027:190;;;:::o;24223:176::-;24255:1;24272:20;24290:1;24272:20;:::i;:::-;24267:25;;24306:20;24324:1;24306:20;:::i;:::-;24301:25;;24345:1;24335:2;;24350:18;;:::i;:::-;24335:2;24391:1;24388;24384:9;24379:14;;24257:142;;;;:::o;24405:180::-;24453:77;24450:1;24443:88;24550:4;24547:1;24540:15;24574:4;24571:1;24564:15;24591:180;24639:77;24636:1;24629:88;24736:4;24733:1;24726:15;24760:4;24757:1;24750:15;24777:180;24825:77;24822:1;24815:88;24922:4;24919:1;24912:15;24946:4;24943:1;24936:15;24963:180;25011:77;25008:1;25001:88;25108:4;25105:1;25098:15;25132:4;25129:1;25122:15;25149:102;25190:6;25241:2;25237:7;25232:2;25225:5;25221:14;25217:28;25207:38;;25197:54;;;:::o;25257:225::-;25397:34;25393:1;25385:6;25381:14;25374:58;25466:8;25461:2;25453:6;25449:15;25442:33;25363:119;:::o;25488:155::-;25628:7;25624:1;25616:6;25612:14;25605:31;25594:49;:::o;25649:182::-;25789:34;25785:1;25777:6;25773:14;25766:58;25755:76;:::o;25837:175::-;25977:27;25973:1;25965:6;25961:14;25954:51;25943:69;:::o;26018:158::-;26158:10;26154:1;26146:6;26142:14;26135:34;26124:52;:::o;26182:122::-;26255:24;26273:5;26255:24;:::i;:::-;26248:5;26245:35;26235:2;;26294:1;26291;26284:12;26235:2;26225:79;:::o;26310:116::-;26380:21;26395:5;26380:21;:::i;:::-;26373:5;26370:32;26360:2;;26416:1;26413;26406:12;26360:2;26350:76;:::o;26432:120::-;26504:23;26521:5;26504:23;:::i;:::-;26497:5;26494:34;26484:2;;26542:1;26539;26532:12;26484:2;26474:78;:::o;26558:158::-;26649:42;26685:5;26649:42;:::i;:::-;26642:5;26639:53;26629:2;;26706:1;26703;26696:12;26629:2;26619:97;:::o;26722:120::-;26794:23;26811:5;26794:23;:::i;:::-;26787:5;26784:34;26774:2;;26832:1;26829;26822:12;26774:2;26764:78;:::o;26848:122::-;26921:24;26939:5;26921:24;:::i;:::-;26914:5;26911:35;26901:2;;26960:1;26957;26950:12;26901:2;26891:79;:::o

Metadata Hash

29a71587885fc4917d56b25cc11e39f6b22e88783bb02da93fd6aeb88c93d5f5
Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.