ERC-721
Overview
Max Total Supply
1,511 MF
Holders
576
Market
Volume (24H)
N/A
Min Price (24H)
N/A
Max Price (24H)
N/A
Other Info
Token Contract
Balance
2 MFLoading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
MovinFrens
Compiler Version
v0.8.17+commit.8df45f5f
Contract Source Code (Solidity Multiple files format)
// SPDX-License-Identifier: MIT pragma solidity >=0.8.9 <0.9.0; import './ERC721AQueryable.sol'; import './ERC721A.sol'; import './Ownable.sol'; import './MerkleProof.sol'; import './ReentrancyGuard.sol'; import './DefaultOperatorFilterer.sol'; contract MovinFrens is ERC721A, Ownable, ReentrancyGuard, DefaultOperatorFilterer { using Strings for uint256; bytes32 public merkleRoot; bytes32 public OGMerkelRoot; mapping(address => uint256) public whitelistClaimed; mapping(address => bool) public OGClaimed; mapping(address => uint256) public publicMinted; uint256 public maxPerUser; string public revealedURI = ''; string public uriSuffix = '.json'; string public hiddenMetadataUri; uint256 public cost; uint256 public maxSupply; uint256 public maxMintAmtPerTx; bool public revealed = false; uint256 public mintPhase; constructor( uint256 _cost, uint256 _MaxPerTxn, uint256 _MaxPerUser, uint256 _maxSupply, string memory _uri ) ERC721A("Movin Frens", "MF") { maxMintAmtPerTx = _MaxPerTxn; maxPerUser = _MaxPerUser; cost = _cost; maxSupply = _maxSupply; hiddenMetadataUri = _uri; } // modifiers modifier mintCompliance(uint256 _mintAmount) { require(_mintAmount > 0 && _mintAmount <= maxMintAmtPerTx, 'Invalid mint amount!'); require(totalSupply() + _mintAmount <= maxSupply, 'Max supply exceeded!'); _; } modifier mintPriceCompliance(uint256 _mintAmount) { require(msg.value >= cost * _mintAmount, 'Insufficient funds!'); _; } // Mints function whitelistMint(uint256 _mintAmount, bytes32[] calldata _merkleProof) public payable mintCompliance(_mintAmount) mintPriceCompliance(_mintAmount) { require(mintPhase == 2,'Whitelist Mint Phase is Not Active'); require((maxPerUser-whitelistClaimed[msg.sender])>=_mintAmount,"You have minted maximum allowed nfts or try to mint less"); bytes32 leaf = keccak256(abi.encodePacked(_msgSender())); require(MerkleProof.verify(_merkleProof, merkleRoot, leaf), 'Invalid proof!'); whitelistClaimed[_msgSender()] += _mintAmount; _safeMint(_msgSender(), _mintAmount); } function OGMint(bytes32[] calldata _merkleProof) public payable mintCompliance(1) { require(mintPhase == 1,'OG Mint Phase is Not Active'); require(!OGClaimed[msg.sender],"OG Mint Already Claimed"); bytes32 leaf = keccak256(abi.encodePacked(_msgSender())); require(MerkleProof.verify(_merkleProof, OGMerkelRoot, leaf), 'Invalid proof!'); OGClaimed[msg.sender] = true; _safeMint(_msgSender(), 1); } function mint(uint256 _mintAmount) public payable mintCompliance(_mintAmount) mintPriceCompliance(_mintAmount) { // require(publicEnabled, 'The contract is paused!'); require(publicMinted[msg.sender]+_mintAmount<=maxMintAmtPerTx,"You have minted maximum allowed nfts or try to mint less"); require(mintPhase == 3,'Public Mint Phase is Not Active'); publicMinted[msg.sender] += _mintAmount; _safeMint(_msgSender(), _mintAmount); } function mintForAddress(uint256 _mintAmount, address _receiver) public mintCompliance(_mintAmount) onlyOwner { _safeMint(_receiver, _mintAmount); } // internal function _startTokenId() internal view virtual override returns (uint256) { return 1; } // Cost , mint per address function setCost(uint256 _cost) public onlyOwner { // _cost in wei cost = _cost; } function setMintAmtPerTx(uint256 _amount) public onlyOwner { maxMintAmtPerTx = _amount; } function setMaxPerUser(uint256 _amount) public onlyOwner { maxPerUser = _amount; } // Token Base URI function tokenURI(uint256 _tokenId) public view virtual override returns (string memory) { require(_exists(_tokenId), 'ERC721Metadata: URI query for nonexistent token'); if (revealed == false) { return hiddenMetadataUri; } string memory currentBaseURI = _baseURI(); return bytes(currentBaseURI).length > 0 ? string(abi.encodePacked(currentBaseURI, _tokenId.toString(), uriSuffix)) : ''; } function setRevealed() public onlyOwner returns(string memory) { revealed = !revealed; return revealed?"NFTs Are Revealed":"NFTs Are Hidden"; } function setHiddenMetadataUri(string memory _hiddenMetadataUri) public onlyOwner { hiddenMetadataUri = _hiddenMetadataUri; } function setBaseUri(string memory _revealedURI) public onlyOwner { revealedURI = _revealedURI; } function setUriSuffix(string memory _uriSuffix) public onlyOwner { uriSuffix = _uriSuffix; } function _baseURI() internal view virtual override returns (string memory) { return revealedURI; } // set merkel roots function setWLRoot(bytes32 _merkleRoot) public onlyOwner { merkleRoot = _merkleRoot; } function setOGRoot(bytes32 _OGRoot) public onlyOwner { OGMerkelRoot = _OGRoot; } // set mint phase function setMintPhase(uint256 _phase) public onlyOwner returns(string memory) { require(_phase < 4, 'Invalid phase'); mintPhase = _phase; return(_phase == 1?'OG mint enabled':_phase == 2?'Whitelist mint enabled':_phase == 3?'Public mint enabled':'Mint not enabled'); } // check whitelisted / OG lists function isValidWL(bytes32[] memory proof, bytes32 leaf) public view returns (bool) { return MerkleProof.verify(proof, merkleRoot, leaf); } function isValidOG(bytes32[] memory proof, bytes32 leaf) public view returns (bool) { return MerkleProof.verify(proof, OGMerkelRoot, leaf); } // Withdraw Function function withdraw() public onlyOwner nonReentrant { // This will transfer the remaining contract balance to the owner. // Do not remove this otherwise you will not be able to withdraw the funds. // ============================================================================= (bool os, ) = payable(owner()).call{value: address(this).balance}(''); require(os); // ============================================================================= } // Overriding with opensea's open registry function transferFrom( address from, address to, uint256 tokenId ) public override onlyAllowedOperator { super.transferFrom(from, to, tokenId); } function safeTransferFrom( address from, address to, uint256 tokenId ) public override onlyAllowedOperator { super.safeTransferFrom(from, to, tokenId); } function safeTransferFrom( address from, address to, uint256 tokenId, bytes memory data ) public override onlyAllowedOperator { super.safeTransferFrom(from, to, tokenId, data); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import {OperatorFilterer} from "./OperatorFilterer.sol"; contract DefaultOperatorFilterer is OperatorFilterer { address constant DEFAULT_SUBSCRIPTION = address(0x3cc6CddA760b79bAfa08dF41ECFA224f810dCeB6); constructor() OperatorFilterer(DEFAULT_SUBSCRIPTION, true) {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ```solidity * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure * unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an * array of EnumerableSet. * ==== */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastValue; // Update the index for the moved value set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { bytes32[] memory store = _values(set._inner); bytes32[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values in the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // ERC721A Contracts v3.3.0 // Creator: Chiru Labs pragma solidity ^0.8.4; import './IERC721A.sol'; import './IERC721Receiver.sol'; import './Address.sol'; import './Context.sol'; import './Strings.sol'; import './ERC165.sol'; /** * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including * the Metadata extension. Built to optimize for lower gas during batch mints. * * Assumes serials are sequentially minted starting at _startTokenId() (defaults to 0, e.g. 0, 1, 2, 3..). * * Assumes that an owner cannot have more than 2**64 - 1 (max value of uint64) of supply. * * Assumes that the maximum token id cannot exceed 2**256 - 1 (max value of uint256). */ contract ERC721A is Context, ERC165, IERC721A { using Address for address; using Strings for uint256; // The tokenId of the next token to be minted. uint256 internal _currentIndex; // The number of tokens burned. uint256 internal _burnCounter; // Token name string private _name; // Token symbol string private _symbol; // Mapping from token ID to ownership details // An empty struct value does not necessarily mean the token is unowned. See _ownershipOf implementation for details. mapping(uint256 => TokenOwnership) internal _ownerships; // Mapping owner address to address data mapping(address => AddressData) private _addressData; // Mapping from token ID to approved address mapping(uint256 => address) private _tokenApprovals; // Mapping from owner to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; _currentIndex = _startTokenId(); } /** * To change the starting tokenId, please override this function. */ function _startTokenId() internal view virtual returns (uint256) { return 0; } /** * @dev Burned tokens are calculated here, use _totalMinted() if you want to count just minted tokens. */ function totalSupply() public view override returns (uint256) { // Counter underflow is impossible as _burnCounter cannot be incremented // more than _currentIndex - _startTokenId() times unchecked { return _currentIndex - _burnCounter - _startTokenId(); } } /** * Returns the total amount of tokens minted in the contract. */ function _totalMinted() internal view returns (uint256) { // Counter underflow is impossible as _currentIndex does not decrement, // and it is initialized to _startTokenId() unchecked { return _currentIndex - _startTokenId(); } } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC721).interfaceId || interfaceId == type(IERC721Metadata).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721-balanceOf}. */ function balanceOf(address owner) public view override returns (uint256) { if (owner == address(0)) revert BalanceQueryForZeroAddress(); return uint256(_addressData[owner].balance); } /** * Returns the number of tokens minted by `owner`. */ function _numberMinted(address owner) internal view returns (uint256) { return uint256(_addressData[owner].numberMinted); } /** * Returns the number of tokens burned by or on behalf of `owner`. */ function _numberBurned(address owner) internal view returns (uint256) { return uint256(_addressData[owner].numberBurned); } /** * Returns the auxillary data for `owner`. (e.g. number of whitelist mint slots used). */ function _getAux(address owner) internal view returns (uint64) { return _addressData[owner].aux; } /** * Sets the auxillary data for `owner`. (e.g. number of whitelist mint slots used). * If there are multiple variables, please pack them into a uint64. */ function _setAux(address owner, uint64 aux) internal { _addressData[owner].aux = aux; } /** * Gas spent here starts off proportional to the maximum mint batch size. * It gradually moves to O(1) as tokens get transferred around in the collection over time. */ function _ownershipOf(uint256 tokenId) internal view returns (TokenOwnership memory) { uint256 curr = tokenId; unchecked { if (_startTokenId() <= curr) if (curr < _currentIndex) { TokenOwnership memory ownership = _ownerships[curr]; if (!ownership.burned) { if (ownership.addr != address(0)) { return ownership; } // Invariant: // There will always be an ownership that has an address and is not burned // before an ownership that does not have an address and is not burned. // Hence, curr will not underflow. while (true) { curr--; ownership = _ownerships[curr]; if (ownership.addr != address(0)) { return ownership; } } } } } revert OwnerQueryForNonexistentToken(); } /** * @dev See {IERC721-ownerOf}. */ function ownerOf(uint256 tokenId) public view override returns (address) { return _ownershipOf(tokenId).addr; } /** * @dev See {IERC721Metadata-name}. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev See {IERC721Metadata-symbol}. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev See {IERC721Metadata-tokenURI}. */ function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { if (!_exists(tokenId)) revert URIQueryForNonexistentToken(); string memory baseURI = _baseURI(); return bytes(baseURI).length != 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : ''; } /** * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each * token will be the concatenation of the `baseURI` and the `tokenId`. Empty * by default, can be overriden in child contracts. */ function _baseURI() internal view virtual returns (string memory) { return ''; } /** * @dev See {IERC721-approve}. */ function approve(address to, uint256 tokenId) public override { address owner = ERC721A.ownerOf(tokenId); if (to == owner) revert ApprovalToCurrentOwner(); if (_msgSender() != owner) if(!isApprovedForAll(owner, _msgSender())) { revert ApprovalCallerNotOwnerNorApproved(); } _approve(to, tokenId, owner); } /** * @dev See {IERC721-getApproved}. */ function getApproved(uint256 tokenId) public view override returns (address) { if (!_exists(tokenId)) revert ApprovalQueryForNonexistentToken(); return _tokenApprovals[tokenId]; } /** * @dev See {IERC721-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { if (operator == _msgSender()) revert ApproveToCaller(); _operatorApprovals[_msgSender()][operator] = approved; emit ApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC721-isApprovedForAll}. */ function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev See {IERC721-transferFrom}. */ function transferFrom( address from, address to, uint256 tokenId ) public virtual override { _transfer(from, to, tokenId); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId ) public virtual override { safeTransferFrom(from, to, tokenId, ''); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes memory _data ) public virtual override { _transfer(from, to, tokenId); if (to.isContract()) if(!_checkContractOnERC721Received(from, to, tokenId, _data)) { revert TransferToNonERC721ReceiverImplementer(); } } /** * @dev Returns whether `tokenId` exists. * * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. * * Tokens start existing when they are minted (`_mint`), */ function _exists(uint256 tokenId) internal view returns (bool) { return _startTokenId() <= tokenId && tokenId < _currentIndex && !_ownerships[tokenId].burned; } /** * @dev Equivalent to `_safeMint(to, quantity, '')`. */ function _safeMint(address to, uint256 quantity) internal { _safeMint(to, quantity, ''); } /** * @dev Safely mints `quantity` tokens and transfers them to `to`. * * Requirements: * * - If `to` refers to a smart contract, it must implement * {IERC721Receiver-onERC721Received}, which is called for each safe transfer. * - `quantity` must be greater than 0. * * Emits a {Transfer} event. */ function _safeMint( address to, uint256 quantity, bytes memory _data ) internal { uint256 startTokenId = _currentIndex; if (to == address(0)) revert MintToZeroAddress(); if (quantity == 0) revert MintZeroQuantity(); _beforeTokenTransfers(address(0), to, startTokenId, quantity); // Overflows are incredibly unrealistic. // balance or numberMinted overflow if current value of either + quantity > 1.8e19 (2**64) - 1 // updatedIndex overflows if _currentIndex + quantity > 1.2e77 (2**256) - 1 unchecked { _addressData[to].balance += uint64(quantity); _addressData[to].numberMinted += uint64(quantity); _ownerships[startTokenId].addr = to; _ownerships[startTokenId].startTimestamp = uint64(block.timestamp); uint256 updatedIndex = startTokenId; uint256 end = updatedIndex + quantity; if (to.isContract()) { do { emit Transfer(address(0), to, updatedIndex); if (!_checkContractOnERC721Received(address(0), to, updatedIndex++, _data)) { revert TransferToNonERC721ReceiverImplementer(); } } while (updatedIndex < end); // Reentrancy protection if (_currentIndex != startTokenId) revert(); } else { do { emit Transfer(address(0), to, updatedIndex++); } while (updatedIndex < end); } _currentIndex = updatedIndex; } _afterTokenTransfers(address(0), to, startTokenId, quantity); } /** * @dev Mints `quantity` tokens and transfers them to `to`. * * Requirements: * * - `to` cannot be the zero address. * - `quantity` must be greater than 0. * * Emits a {Transfer} event. */ function _mint(address to, uint256 quantity) internal { uint256 startTokenId = _currentIndex; if (to == address(0)) revert MintToZeroAddress(); if (quantity == 0) revert MintZeroQuantity(); _beforeTokenTransfers(address(0), to, startTokenId, quantity); // Overflows are incredibly unrealistic. // balance or numberMinted overflow if current value of either + quantity > 1.8e19 (2**64) - 1 // updatedIndex overflows if _currentIndex + quantity > 1.2e77 (2**256) - 1 unchecked { _addressData[to].balance += uint64(quantity); _addressData[to].numberMinted += uint64(quantity); _ownerships[startTokenId].addr = to; _ownerships[startTokenId].startTimestamp = uint64(block.timestamp); uint256 updatedIndex = startTokenId; uint256 end = updatedIndex + quantity; do { emit Transfer(address(0), to, updatedIndex++); } while (updatedIndex < end); _currentIndex = updatedIndex; } _afterTokenTransfers(address(0), to, startTokenId, quantity); } /** * @dev Transfers `tokenId` from `from` to `to`. * * Requirements: * * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * * Emits a {Transfer} event. */ function _transfer( address from, address to, uint256 tokenId ) private { TokenOwnership memory prevOwnership = _ownershipOf(tokenId); if (prevOwnership.addr != from) revert TransferFromIncorrectOwner(); bool isApprovedOrOwner = (_msgSender() == from || isApprovedForAll(from, _msgSender()) || getApproved(tokenId) == _msgSender()); if (!isApprovedOrOwner) revert TransferCallerNotOwnerNorApproved(); if (to == address(0)) revert TransferToZeroAddress(); _beforeTokenTransfers(from, to, tokenId, 1); // Clear approvals from the previous owner _approve(address(0), tokenId, from); // Underflow of the sender's balance is impossible because we check for // ownership above and the recipient's balance can't realistically overflow. // Counter overflow is incredibly unrealistic as tokenId would have to be 2**256. unchecked { _addressData[from].balance -= 1; _addressData[to].balance += 1; TokenOwnership storage currSlot = _ownerships[tokenId]; currSlot.addr = to; currSlot.startTimestamp = uint64(block.timestamp); // If the ownership slot of tokenId+1 is not explicitly set, that means the transfer initiator owns it. // Set the slot of tokenId+1 explicitly in storage to maintain correctness for ownerOf(tokenId+1) calls. uint256 nextTokenId = tokenId + 1; TokenOwnership storage nextSlot = _ownerships[nextTokenId]; if (nextSlot.addr == address(0)) { // This will suffice for checking _exists(nextTokenId), // as a burned slot cannot contain the zero address. if (nextTokenId != _currentIndex) { nextSlot.addr = from; nextSlot.startTimestamp = prevOwnership.startTimestamp; } } } emit Transfer(from, to, tokenId); _afterTokenTransfers(from, to, tokenId, 1); } /** * @dev Equivalent to `_burn(tokenId, false)`. */ function _burn(uint256 tokenId) internal virtual { _burn(tokenId, false); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId, bool approvalCheck) internal virtual { TokenOwnership memory prevOwnership = _ownershipOf(tokenId); address from = prevOwnership.addr; if (approvalCheck) { bool isApprovedOrOwner = (_msgSender() == from || isApprovedForAll(from, _msgSender()) || getApproved(tokenId) == _msgSender()); if (!isApprovedOrOwner) revert TransferCallerNotOwnerNorApproved(); } _beforeTokenTransfers(from, address(0), tokenId, 1); // Clear approvals from the previous owner _approve(address(0), tokenId, from); // Underflow of the sender's balance is impossible because we check for // ownership above and the recipient's balance can't realistically overflow. // Counter overflow is incredibly unrealistic as tokenId would have to be 2**256. unchecked { AddressData storage addressData = _addressData[from]; addressData.balance -= 1; addressData.numberBurned += 1; // Keep track of who burned the token, and the timestamp of burning. TokenOwnership storage currSlot = _ownerships[tokenId]; currSlot.addr = from; currSlot.startTimestamp = uint64(block.timestamp); currSlot.burned = true; // If the ownership slot of tokenId+1 is not explicitly set, that means the burn initiator owns it. // Set the slot of tokenId+1 explicitly in storage to maintain correctness for ownerOf(tokenId+1) calls. uint256 nextTokenId = tokenId + 1; TokenOwnership storage nextSlot = _ownerships[nextTokenId]; if (nextSlot.addr == address(0)) { // This will suffice for checking _exists(nextTokenId), // as a burned slot cannot contain the zero address. if (nextTokenId != _currentIndex) { nextSlot.addr = from; nextSlot.startTimestamp = prevOwnership.startTimestamp; } } } emit Transfer(from, address(0), tokenId); _afterTokenTransfers(from, address(0), tokenId, 1); // Overflow not possible, as _burnCounter cannot be exceed _currentIndex times. unchecked { _burnCounter++; } } /** * @dev Approve `to` to operate on `tokenId` * * Emits a {Approval} event. */ function _approve( address to, uint256 tokenId, address owner ) private { _tokenApprovals[tokenId] = to; emit Approval(owner, to, tokenId); } /** * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target contract. * * @param from address representing the previous owner of the given token ID * @param to target address that will receive the tokens * @param tokenId uint256 ID of the token to be transferred * @param _data bytes optional data to send along with the call * @return bool whether the call correctly returned the expected magic value */ function _checkContractOnERC721Received( address from, address to, uint256 tokenId, bytes memory _data ) private returns (bool) { try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) { return retval == IERC721Receiver(to).onERC721Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { revert TransferToNonERC721ReceiverImplementer(); } else { assembly { revert(add(32, reason), mload(reason)) } } } } /** * @dev Hook that is called before a set of serially-ordered token ids are about to be transferred. This includes minting. * And also called before burning one token. * * startTokenId - the first token id to be transferred * quantity - the amount to be transferred * * Calling conditions: * * - When `from` and `to` are both non-zero, `from`'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, `tokenId` will be burned by `from`. * - `from` and `to` are never both zero. */ function _beforeTokenTransfers( address from, address to, uint256 startTokenId, uint256 quantity ) internal virtual {} /** * @dev Hook that is called after a set of serially-ordered token ids have been transferred. This includes * minting. * And also called after one token has been burned. * * startTokenId - the first token id to be transferred * quantity - the amount to be transferred * * Calling conditions: * * - When `from` and `to` are both non-zero, `from`'s `tokenId` has been * transferred to `to`. * - When `from` is zero, `tokenId` has been minted for `to`. * - When `to` is zero, `tokenId` has been burned by `from`. * - `from` and `to` are never both zero. */ function _afterTokenTransfers( address from, address to, uint256 startTokenId, uint256 quantity ) internal virtual {} }
// SPDX-License-Identifier: MIT // ERC721A Contracts v3.3.0 // Creator: Chiru Labs pragma solidity ^0.8.4; import './IERC721AQueryable.sol'; import './ERC721A.sol'; /** * @title ERC721A Queryable * @dev ERC721A subclass with convenience query functions. */ abstract contract ERC721AQueryable is ERC721A, IERC721AQueryable { /** * @dev Returns the `TokenOwnership` struct at `tokenId` without reverting. * * If the `tokenId` is out of bounds: * - `addr` = `address(0)` * - `startTimestamp` = `0` * - `burned` = `false` * * If the `tokenId` is burned: * - `addr` = `<Address of owner before token was burned>` * - `startTimestamp` = `<Timestamp when token was burned>` * - `burned = `true` * * Otherwise: * - `addr` = `<Address of owner>` * - `startTimestamp` = `<Timestamp of start of ownership>` * - `burned = `false` */ function explicitOwnershipOf(uint256 tokenId) public view override returns (TokenOwnership memory) { TokenOwnership memory ownership; if (tokenId < _startTokenId() || tokenId >= _currentIndex) { return ownership; } ownership = _ownerships[tokenId]; if (ownership.burned) { return ownership; } return _ownershipOf(tokenId); } /** * @dev Returns an array of `TokenOwnership` structs at `tokenIds` in order. * See {ERC721AQueryable-explicitOwnershipOf} */ function explicitOwnershipsOf(uint256[] memory tokenIds) external view override returns (TokenOwnership[] memory) { unchecked { uint256 tokenIdsLength = tokenIds.length; TokenOwnership[] memory ownerships = new TokenOwnership[](tokenIdsLength); for (uint256 i; i != tokenIdsLength; ++i) { ownerships[i] = explicitOwnershipOf(tokenIds[i]); } return ownerships; } } /** * @dev Returns an array of token IDs owned by `owner`, * in the range [`start`, `stop`) * (i.e. `start <= tokenId < stop`). * * This function allows for tokens to be queried if the collection * grows too big for a single call of {ERC721AQueryable-tokensOfOwner}. * * Requirements: * * - `start` < `stop` */ function tokensOfOwnerIn( address owner, uint256 start, uint256 stop ) external view override returns (uint256[] memory) { unchecked { if (start >= stop) revert InvalidQueryRange(); uint256 tokenIdsIdx; uint256 stopLimit = _currentIndex; // Set `start = max(start, _startTokenId())`. if (start < _startTokenId()) { start = _startTokenId(); } // Set `stop = min(stop, _currentIndex)`. if (stop > stopLimit) { stop = stopLimit; } uint256 tokenIdsMaxLength = balanceOf(owner); // Set `tokenIdsMaxLength = min(balanceOf(owner), stop - start)`, // to cater for cases where `balanceOf(owner)` is too big. if (start < stop) { uint256 rangeLength = stop - start; if (rangeLength < tokenIdsMaxLength) { tokenIdsMaxLength = rangeLength; } } else { tokenIdsMaxLength = 0; } uint256[] memory tokenIds = new uint256[](tokenIdsMaxLength); if (tokenIdsMaxLength == 0) { return tokenIds; } // We need to call `explicitOwnershipOf(start)`, // because the slot at `start` may not be initialized. TokenOwnership memory ownership = explicitOwnershipOf(start); address currOwnershipAddr; // If the starting slot exists (i.e. not burned), initialize `currOwnershipAddr`. // `ownership.address` will not be zero, as `start` is clamped to the valid token ID range. if (!ownership.burned) { currOwnershipAddr = ownership.addr; } for (uint256 i = start; i != stop && tokenIdsIdx != tokenIdsMaxLength; ++i) { ownership = _ownerships[i]; if (ownership.burned) { continue; } if (ownership.addr != address(0)) { currOwnershipAddr = ownership.addr; } if (currOwnershipAddr == owner) { tokenIds[tokenIdsIdx++] = i; } } // Downsize the array to fit. assembly { mstore(tokenIds, tokenIdsIdx) } return tokenIds; } } /** * @dev Returns an array of token IDs owned by `owner`. * * This function scans the ownership mapping and is O(totalSupply) in complexity. * It is meant to be called off-chain. * * See {ERC721AQueryable-tokensOfOwnerIn} for splitting the scan into * multiple smaller scans if the collection is large enough to cause * an out-of-gas error (10K pfp collections should be fine). */ function tokensOfOwner(address owner) external view override returns (uint256[] memory) { unchecked { uint256 tokenIdsIdx; address currOwnershipAddr; uint256 tokenIdsLength = balanceOf(owner); uint256[] memory tokenIds = new uint256[](tokenIdsLength); TokenOwnership memory ownership; for (uint256 i = _startTokenId(); tokenIdsIdx != tokenIdsLength; ++i) { ownership = _ownerships[i]; if (ownership.burned) { continue; } if (ownership.addr != address(0)) { currOwnershipAddr = ownership.addr; } if (currOwnershipAddr == owner) { tokenIds[tokenIdsIdx++] = i; } } return tokenIds; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT // ERC721A Contracts v3.3.0 // Creator: Chiru Labs pragma solidity ^0.8.4; import './IERC721.sol'; import './IERC721Metadata.sol'; /** * @dev Interface of an ERC721A compliant contract. */ interface IERC721A is IERC721, IERC721Metadata { /** * The caller must own the token or be an approved operator. */ error ApprovalCallerNotOwnerNorApproved(); /** * The token does not exist. */ error ApprovalQueryForNonexistentToken(); /** * The caller cannot approve to their own address. */ error ApproveToCaller(); /** * The caller cannot approve to the current owner. */ error ApprovalToCurrentOwner(); /** * Cannot query the balance for the zero address. */ error BalanceQueryForZeroAddress(); /** * Cannot mint to the zero address. */ error MintToZeroAddress(); /** * The quantity of tokens minted must be more than zero. */ error MintZeroQuantity(); /** * The token does not exist. */ error OwnerQueryForNonexistentToken(); /** * The caller must own the token or be an approved operator. */ error TransferCallerNotOwnerNorApproved(); /** * The token must be owned by `from`. */ error TransferFromIncorrectOwner(); /** * Cannot safely transfer to a contract that does not implement the ERC721Receiver interface. */ error TransferToNonERC721ReceiverImplementer(); /** * Cannot transfer to the zero address. */ error TransferToZeroAddress(); /** * The token does not exist. */ error URIQueryForNonexistentToken(); // Compiler will pack this into a single 256bit word. struct TokenOwnership { // The address of the owner. address addr; // Keeps track of the start time of ownership with minimal overhead for tokenomics. uint64 startTimestamp; // Whether the token has been burned. bool burned; } // Compiler will pack this into a single 256bit word. struct AddressData { // Realistically, 2**64-1 is more than enough. uint64 balance; // Keeps track of mint count with minimal overhead for tokenomics. uint64 numberMinted; // Keeps track of burn count with minimal overhead for tokenomics. uint64 numberBurned; // For miscellaneous variable(s) pertaining to the address // (e.g. number of whitelist mint slots used). // If there are multiple variables, please pack them into a uint64. uint64 aux; } /** * @dev Returns the total amount of tokens stored by the contract. * * Burned tokens are calculated here, use `_totalMinted()` if you want to count just minted tokens. */ function totalSupply() external view returns (uint256); }
// SPDX-License-Identifier: MIT // ERC721A Contracts v3.3.0 // Creator: Chiru Labs pragma solidity ^0.8.4; import './IERC721A.sol'; /** * @dev Interface of an ERC721AQueryable compliant contract. */ interface IERC721AQueryable is IERC721A { /** * Invalid query range (`start` >= `stop`). */ error InvalidQueryRange(); /** * @dev Returns the `TokenOwnership` struct at `tokenId` without reverting. * * If the `tokenId` is out of bounds: * - `addr` = `address(0)` * - `startTimestamp` = `0` * - `burned` = `false` * * If the `tokenId` is burned: * - `addr` = `<Address of owner before token was burned>` * - `startTimestamp` = `<Timestamp when token was burned>` * - `burned = `true` * * Otherwise: * - `addr` = `<Address of owner>` * - `startTimestamp` = `<Timestamp of start of ownership>` * - `burned = `false` */ function explicitOwnershipOf(uint256 tokenId) external view returns (TokenOwnership memory); /** * @dev Returns an array of `TokenOwnership` structs at `tokenIds` in order. * See {ERC721AQueryable-explicitOwnershipOf} */ function explicitOwnershipsOf(uint256[] memory tokenIds) external view returns (TokenOwnership[] memory); /** * @dev Returns an array of token IDs owned by `owner`, * in the range [`start`, `stop`) * (i.e. `start <= tokenId < stop`). * * This function allows for tokens to be queried if the collection * grows too big for a single call of {ERC721AQueryable-tokensOfOwner}. * * Requirements: * * - `start` < `stop` */ function tokensOfOwnerIn( address owner, uint256 start, uint256 stop ) external view returns (uint256[] memory); /** * @dev Returns an array of token IDs owned by `owner`. * * This function scans the ownership mapping and is O(totalSupply) in complexity. * It is meant to be called off-chain. * * See {ERC721AQueryable-tokensOfOwnerIn} for splitting the scan into * multiple smaller scans if the collection is large enough to cause * an out-of-gas error (10K pfp collections should be fine). */ function tokensOfOwner(address owner) external view returns (uint256[] memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol) pragma solidity ^0.8.0; import "./IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Metadata is IERC721 { /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import {EnumerableSet} from "./EnumerableSet.sol"; interface IOperatorFilterRegistry { function isOperatorAllowed(address registrant, address operator) external returns (bool); function register(address registrant) external; function registerAndSubscribe(address registrant, address subscription) external; function registerAndCopyEntries(address registrant, address registrantToCopy) external; function updateOperator(address registrant, address operator, bool filtered) external; function updateOperators(address registrant, address[] calldata operators, bool filtered) external; function updateCodeHash(address registrant, bytes32 codehash, bool filtered) external; function updateCodeHashes(address registrant, bytes32[] calldata codeHashes, bool filtered) external; function subscribe(address registrant, address registrantToSubscribe) external; function unsubscribe(address registrant, bool copyExistingEntries) external; function subscriptionOf(address addr) external returns (address registrant); function subscribers(address registrant) external returns (address[] memory); function subscriberAt(address registrant, uint256 index) external returns (address); function copyEntriesOf(address registrant, address registrantToCopy) external; function isOperatorFiltered(address registrant, address operator) external returns (bool); function isCodeHashOfFiltered(address registrant, address operatorWithCode) external returns (bool); function isCodeHashFiltered(address registrant, bytes32 codeHash) external returns (bool); function filteredOperators(address addr) external returns (address[] memory); function filteredCodeHashes(address addr) external returns (bytes32[] memory); function filteredOperatorAt(address registrant, uint256 index) external returns (address); function filteredCodeHashAt(address registrant, uint256 index) external returns (bytes32); function isRegistered(address addr) external returns (bool); function codeHashOf(address addr) external returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (utils/cryptography/MerkleProof.sol) pragma solidity ^0.8.0; /** * @dev These functions deal with verification of Merkle Trees proofs. * * The proofs can be generated using the JavaScript library * https://github.com/miguelmota/merkletreejs[merkletreejs]. * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled. * * See `test/utils/cryptography/MerkleProof.test.js` for some examples. */ library MerkleProof { /** * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree * defined by `root`. For this, a `proof` must be provided, containing * sibling hashes on the branch from the leaf to the root of the tree. Each * pair of leaves and each pair of pre-images are assumed to be sorted. */ function verify( bytes32[] memory proof, bytes32 root, bytes32 leaf ) internal pure returns (bool) { return processProof(proof, leaf) == root; } /** * @dev Returns the rebuilt hash obtained by traversing a Merklee tree up * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt * hash matches the root of the tree. When processing the proof, the pairs * of leafs & pre-images are assumed to be sorted. * * _Available since v4.4._ */ function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { bytes32 proofElement = proof[i]; if (computedHash <= proofElement) { // Hash(current computed hash + current element of the proof) computedHash = _efficientHash(computedHash, proofElement); } else { // Hash(current element of the proof + current computed hash) computedHash = _efficientHash(proofElement, computedHash); } } return computedHash; } function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) { assembly { mstore(0x00, a) mstore(0x20, b) value := keccak256(0x00, 0x40) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import {IOperatorFilterRegistry} from "./IOperatorFilterRegistry.sol"; contract OperatorFilterer { error OperatorNotAllowed(address operator); IOperatorFilterRegistry constant operatorFilterRegistry = IOperatorFilterRegistry(0x000000000000AAeB6D7670E522A718067333cd4E); constructor(address subscriptionOrRegistrantToCopy, bool subscribe) { // If an inheriting token contract is deployed to a network without the registry deployed, the modifier // will not revert, but the contract will need to be registered with the registry once it is deployed in // order for the modifier to filter addresses. if (address(operatorFilterRegistry).code.length > 0) { if (subscribe) { operatorFilterRegistry.registerAndSubscribe(address(this), subscriptionOrRegistrantToCopy); } else { if (subscriptionOrRegistrantToCopy != address(0)) { operatorFilterRegistry.registerAndCopyEntries(address(this), subscriptionOrRegistrantToCopy); } else { operatorFilterRegistry.register(address(this)); } } } } modifier onlyAllowedOperator() virtual { // Check registry code length to facilitate testing in environments without a deployed registry. if (address(operatorFilterRegistry).code.length > 0) { if (!operatorFilterRegistry.isOperatorAllowed(address(this), msg.sender)) { revert OperatorNotAllowed(msg.sender); } } _; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import {IOperatorFilterRegistry} from "./IOperatorFilterRegistry.sol"; import {Ownable} from "./Ownable.sol"; import {EnumerableSet} from "./EnumerableSet.sol"; import {OperatorFilterRegistryErrorsAndEvents} from "./OperatorFilterRegistryErrorsAndEvents.sol"; /** * @title OperatorFilterRegistry * @notice Borrows heavily from the QQL BlacklistOperatorFilter contract: * https://github.com/qql-art/contracts/blob/main/contracts/BlacklistOperatorFilter.sol * @notice This contracts allows tokens or token owners to register specific addresses or codeHashes that may be * * restricted according to the isOperatorAllowed function. */ contract OperatorFilterRegistry is IOperatorFilterRegistry, OperatorFilterRegistryErrorsAndEvents { using EnumerableSet for EnumerableSet.AddressSet; using EnumerableSet for EnumerableSet.Bytes32Set; /// @dev initialized accounts have a nonzero codehash (see https://eips.ethereum.org/EIPS/eip-1052) /// Note that this will also be a smart contract's codehash when making calls from its constructor. bytes32 constant EOA_CODEHASH = keccak256(""); mapping(address => EnumerableSet.AddressSet) private _filteredOperators; mapping(address => EnumerableSet.Bytes32Set) private _filteredCodeHashes; mapping(address => address) private _registrations; mapping(address => EnumerableSet.AddressSet) private _subscribers; /** * @notice restricts method caller to the address or EIP-173 "owner()" */ modifier onlyAddressOrOwner(address addr) { if (msg.sender != addr) { try Ownable(addr).owner() returns (address owner) { if (msg.sender != owner) { revert OnlyAddressOrOwner(); } } catch (bytes memory reason) { if (reason.length == 0) { revert NotOwnable(); } else { /// @solidity memory-safe-assembly assembly { revert(add(32, reason), mload(reason)) } } } } _; } /** * @notice Returns true if operator is not filtered for a given token, either by address or codeHash. Also returns * true if supplied registrant address is not registered. */ function isOperatorAllowed(address registrant, address operator) external view returns (bool) { address registration = _registrations[registrant]; if (registration != address(0)) { EnumerableSet.AddressSet storage filteredOperatorsRef; EnumerableSet.Bytes32Set storage filteredCodeHashesRef; filteredOperatorsRef = _filteredOperators[registration]; filteredCodeHashesRef = _filteredCodeHashes[registration]; if (filteredOperatorsRef.contains(operator)) { revert AddressFiltered(operator); } if (operator.code.length > 0) { bytes32 codeHash = operator.codehash; if (filteredCodeHashesRef.contains(codeHash)) { revert CodeHashFiltered(operator, codeHash); } } } return true; } ////////////////// // AUTH METHODS // ////////////////// /** * @notice Registers an address with the registry. May be called by address itself or by EIP-173 owner. */ function register(address registrant) external onlyAddressOrOwner(registrant) { if (_registrations[registrant] != address(0)) { revert AlreadyRegistered(); } _registrations[registrant] = registrant; emit RegistrationUpdated(registrant, true); } /** * @notice Unregisters an address with the registry and removes its subscription. May be called by address itself or by EIP-173 owner. * Note that this does not remove any filtered addresses or codeHashes. * Also note that any subscriptions to this registrant will still be active and follow the existing filtered addresses and codehashes. */ function unregister(address registrant) external onlyAddressOrOwner(registrant) { address registration = _registrations[registrant]; if (registration == address(0)) { revert NotRegistered(registrant); } if (registration != registrant) { _subscribers[registration].remove(registrant); emit SubscriptionUpdated(registrant, registration, false); } _registrations[registrant] = address(0); emit RegistrationUpdated(registrant, false); } /** * @notice Registers an address with the registry and "subscribes" to another address's filtered operators and codeHashes. */ function registerAndSubscribe(address registrant, address subscription) external onlyAddressOrOwner(registrant) { address registration = _registrations[registrant]; if (registration != address(0)) { revert AlreadyRegistered(); } if (registrant == subscription) { revert CannotSubscribeToSelf(); } address subscriptionRegistration = _registrations[subscription]; if (subscriptionRegistration == address(0)) { revert NotRegistered(subscription); } if (subscriptionRegistration != subscription) { revert CannotSubscribeToRegistrantWithSubscription(subscription); } _registrations[registrant] = subscription; _subscribers[subscription].add(registrant); emit RegistrationUpdated(registrant, true); emit SubscriptionUpdated(registrant, subscription, true); } /** * @notice Registers an address with the registry and copies the filtered operators and codeHashes from another * address without subscribing. */ function registerAndCopyEntries(address registrant, address registrantToCopy) external onlyAddressOrOwner(registrant) { if (registrantToCopy == registrant) { revert CannotCopyFromSelf(); } address registration = _registrations[registrant]; if (registration != address(0)) { revert AlreadyRegistered(); } address registrantRegistration = _registrations[registrantToCopy]; if (registrantRegistration == address(0)) { revert NotRegistered(registrantToCopy); } _registrations[registrant] = registrant; emit RegistrationUpdated(registrant, true); _copyEntries(registrant, registrantToCopy); } /** * @notice Update an operator address for a registered address - when filtered is true, the operator is filtered. */ function updateOperator(address registrant, address operator, bool filtered) external onlyAddressOrOwner(registrant) { address registration = _registrations[registrant]; if (registration == address(0)) { revert NotRegistered(registrant); } if (registration != registrant) { revert CannotUpdateWhileSubscribed(registration); } EnumerableSet.AddressSet storage filteredOperatorsRef = _filteredOperators[registrant]; if (!filtered) { bool removed = filteredOperatorsRef.remove(operator); if (!removed) { revert AddressNotFiltered(operator); } } else { bool added = filteredOperatorsRef.add(operator); if (!added) { revert AddressAlreadyFiltered(operator); } } emit OperatorUpdated(registrant, operator, filtered); } /** * @notice Update a codeHash for a registered address - when filtered is true, the codeHash is filtered. */ function updateCodeHash(address registrant, bytes32 codeHash, bool filtered) external onlyAddressOrOwner(registrant) { if (codeHash == EOA_CODEHASH) { revert CannotFilterEOAs(); } address registration = _registrations[registrant]; if (registration == address(0)) { revert NotRegistered(registrant); } if (registration != registrant) { revert CannotUpdateWhileSubscribed(registration); } EnumerableSet.Bytes32Set storage filteredCodeHashesRef = _filteredCodeHashes[registrant]; if (!filtered) { bool removed = filteredCodeHashesRef.remove(codeHash); if (!removed) { revert CodeHashNotFiltered(codeHash); } } else { bool added = filteredCodeHashesRef.add(codeHash); if (!added) { revert CodeHashAlreadyFiltered(codeHash); } } emit CodeHashUpdated(registrant, codeHash, filtered); } /** * @notice Update multiple operators for a registered address - when filtered is true, the operators will be filtered. Reverts on duplicates. */ function updateOperators(address registrant, address[] calldata operators, bool filtered) external onlyAddressOrOwner(registrant) { address registration = _registrations[registrant]; if (registration == address(0)) { revert NotRegistered(registrant); } if (registration != registrant) { revert CannotUpdateWhileSubscribed(registration); } EnumerableSet.AddressSet storage filteredOperatorsRef = _filteredOperators[registrant]; uint256 operatorsLength = operators.length; unchecked { if (!filtered) { for (uint256 i = 0; i < operatorsLength; ++i) { address operator = operators[i]; bool removed = filteredOperatorsRef.remove(operator); if (!removed) { revert AddressNotFiltered(operator); } } } else { for (uint256 i = 0; i < operatorsLength; ++i) { address operator = operators[i]; bool added = filteredOperatorsRef.add(operator); if (!added) { revert AddressAlreadyFiltered(operator); } } } } emit OperatorsUpdated(registrant, operators, filtered); } /** * @notice Update multiple codeHashes for a registered address - when filtered is true, the codeHashes will be filtered. Reverts on duplicates. */ function updateCodeHashes(address registrant, bytes32[] calldata codeHashes, bool filtered) external onlyAddressOrOwner(registrant) { address registration = _registrations[registrant]; if (registration == address(0)) { revert NotRegistered(registrant); } if (registration != registrant) { revert CannotUpdateWhileSubscribed(registration); } EnumerableSet.Bytes32Set storage filteredCodeHashesRef = _filteredCodeHashes[registrant]; uint256 codeHashesLength = codeHashes.length; unchecked { if (!filtered) { for (uint256 i = 0; i < codeHashesLength; ++i) { bytes32 codeHash = codeHashes[i]; bool removed = filteredCodeHashesRef.remove(codeHash); if (!removed) { revert CodeHashNotFiltered(codeHash); } } } else { for (uint256 i = 0; i < codeHashesLength; ++i) { bytes32 codeHash = codeHashes[i]; if (codeHash == EOA_CODEHASH) { revert CannotFilterEOAs(); } bool added = filteredCodeHashesRef.add(codeHash); if (!added) { revert CodeHashAlreadyFiltered(codeHash); } } } } emit CodeHashesUpdated(registrant, codeHashes, filtered); } /** * @notice Subscribe an address to another registrant's filtered operators and codeHashes. Will remove previous * subscription if present. * Note that accounts with subscriptions may go on to subscribe to other accounts - in this case, * subscriptions will not be forwarded. Instead the former subscription's existing entries will still be * used. */ function subscribe(address registrant, address newSubscription) external onlyAddressOrOwner(registrant) { if (registrant == newSubscription) { revert CannotSubscribeToSelf(); } if (newSubscription == address(0)) { revert CannotSubscribeToZeroAddress(); } address registration = _registrations[registrant]; if (registration == address(0)) { revert NotRegistered(registrant); } if (registration == newSubscription) { revert AlreadySubscribed(newSubscription); } address newSubscriptionRegistration = _registrations[newSubscription]; if (newSubscriptionRegistration == address(0)) { revert NotRegistered(newSubscription); } if (newSubscriptionRegistration != newSubscription) { revert CannotSubscribeToRegistrantWithSubscription(newSubscription); } if (registration != registrant) { _subscribers[registration].remove(registrant); emit SubscriptionUpdated(registrant, registration, false); } _registrations[registrant] = newSubscription; _subscribers[newSubscription].add(registrant); emit SubscriptionUpdated(registrant, newSubscription, true); } /** * @notice Unsubscribe an address from its current subscribed registrant, and optionally copy its filtered operators and codeHashes. */ function unsubscribe(address registrant, bool copyExistingEntries) external onlyAddressOrOwner(registrant) { address registration = _registrations[registrant]; if (registration == address(0)) { revert NotRegistered(registrant); } if (registration == registrant) { revert NotSubscribed(); } _subscribers[registration].remove(registrant); _registrations[registrant] = registrant; emit SubscriptionUpdated(registrant, registration, false); if (copyExistingEntries) { _copyEntries(registrant, registration); } } /** * @notice Copy filtered operators and codeHashes from a different registrantToCopy to addr. */ function copyEntriesOf(address registrant, address registrantToCopy) external onlyAddressOrOwner(registrant) { if (registrant == registrantToCopy) { revert CannotCopyFromSelf(); } address registration = _registrations[registrant]; if (registration == address(0)) { revert NotRegistered(registrant); } if (registration != registrant) { revert CannotUpdateWhileSubscribed(registration); } address registrantRegistration = _registrations[registrantToCopy]; if (registrantRegistration == address(0)) { revert NotRegistered(registrantToCopy); } _copyEntries(registrant, registrantToCopy); } /// @dev helper to copy entries from registrantToCopy to registrant and emit events function _copyEntries(address registrant, address registrantToCopy) private { EnumerableSet.AddressSet storage filteredOperatorsRef = _filteredOperators[registrantToCopy]; EnumerableSet.Bytes32Set storage filteredCodeHashesRef = _filteredCodeHashes[registrantToCopy]; uint256 filteredOperatorsLength = filteredOperatorsRef.length(); uint256 filteredCodeHashesLength = filteredCodeHashesRef.length(); unchecked { for (uint256 i = 0; i < filteredOperatorsLength; ++i) { address operator = filteredOperatorsRef.at(i); bool added = _filteredOperators[registrant].add(operator); if (added) { emit OperatorUpdated(registrant, operator, true); } } for (uint256 i = 0; i < filteredCodeHashesLength; ++i) { bytes32 codehash = filteredCodeHashesRef.at(i); bool added = _filteredCodeHashes[registrant].add(codehash); if (added) { emit CodeHashUpdated(registrant, codehash, true); } } } } ////////////////// // VIEW METHODS // ////////////////// /** * @notice Get the subscription address of a given registrant, if any. */ function subscriptionOf(address registrant) external view returns (address subscription) { subscription = _registrations[registrant]; if (subscription == address(0)) { revert NotRegistered(registrant); } else if (subscription == registrant) { subscription = address(0); } } /** * @notice Get the set of addresses subscribed to a given registrant. * Note that order is not guaranteed as updates are made. */ function subscribers(address registrant) external view returns (address[] memory) { return _subscribers[registrant].values(); } /** * @notice Get the subscriber at a given index in the set of addresses subscribed to a given registrant. * Note that order is not guaranteed as updates are made. */ function subscriberAt(address registrant, uint256 index) external view returns (address) { return _subscribers[registrant].at(index); } /** * @notice Returns true if operator is filtered by a given address or its subscription. */ function isOperatorFiltered(address registrant, address operator) external view returns (bool) { address registration = _registrations[registrant]; if (registration != registrant) { return _filteredOperators[registration].contains(operator); } return _filteredOperators[registrant].contains(operator); } /** * @notice Returns true if a codeHash is filtered by a given address or its subscription. */ function isCodeHashFiltered(address registrant, bytes32 codeHash) external view returns (bool) { address registration = _registrations[registrant]; if (registration != registrant) { return _filteredCodeHashes[registration].contains(codeHash); } return _filteredCodeHashes[registrant].contains(codeHash); } /** * @notice Returns true if the hash of an address's code is filtered by a given address or its subscription. */ function isCodeHashOfFiltered(address registrant, address operatorWithCode) external view returns (bool) { bytes32 codeHash = operatorWithCode.codehash; address registration = _registrations[registrant]; if (registration != registrant) { return _filteredCodeHashes[registration].contains(codeHash); } return _filteredCodeHashes[registrant].contains(codeHash); } /** * @notice Returns true if an address has registered */ function isRegistered(address registrant) external view returns (bool) { return _registrations[registrant] != address(0); } /** * @notice Returns a list of filtered operators for a given address or its subscription. */ function filteredOperators(address registrant) external view returns (address[] memory) { address registration = _registrations[registrant]; if (registration != registrant) { return _filteredOperators[registration].values(); } return _filteredOperators[registrant].values(); } /** * @notice Returns the set of filtered codeHashes for a given address or its subscription. * Note that order is not guaranteed as updates are made. */ function filteredCodeHashes(address registrant) external view returns (bytes32[] memory) { address registration = _registrations[registrant]; if (registration != registrant) { return _filteredCodeHashes[registration].values(); } return _filteredCodeHashes[registrant].values(); } /** * @notice Returns the filtered operator at the given index of the set of filtered operators for a given address or * its subscription. * Note that order is not guaranteed as updates are made. */ function filteredOperatorAt(address registrant, uint256 index) external view returns (address) { address registration = _registrations[registrant]; if (registration != registrant) { return _filteredOperators[registration].at(index); } return _filteredOperators[registrant].at(index); } /** * @notice Returns the filtered codeHash at the given index of the list of filtered codeHashes for a given address or * its subscription. * Note that order is not guaranteed as updates are made. */ function filteredCodeHashAt(address registrant, uint256 index) external view returns (bytes32) { address registration = _registrations[registrant]; if (registration != registrant) { return _filteredCodeHashes[registration].at(index); } return _filteredCodeHashes[registrant].at(index); } /// @dev Convenience method to compute the code hash of an arbitrary contract function codeHashOf(address a) external view returns (bytes32) { return a.codehash; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; contract OperatorFilterRegistryErrorsAndEvents { error CannotFilterEOAs(); error AddressAlreadyFiltered(address operator); error AddressNotFiltered(address operator); error CodeHashAlreadyFiltered(bytes32 codeHash); error CodeHashNotFiltered(bytes32 codeHash); error OnlyAddressOrOwner(); error NotRegistered(address registrant); error AlreadyRegistered(); error AlreadySubscribed(address subscription); error NotSubscribed(); error CannotUpdateWhileSubscribed(address subscription); error CannotSubscribeToSelf(); error CannotSubscribeToZeroAddress(); error NotOwnable(); error AddressFiltered(address filtered); error CodeHashFiltered(address account, bytes32 codeHash); error CannotSubscribeToRegistrantWithSubscription(address registrant); error CannotCopyFromSelf(); event RegistrationUpdated(address indexed registrant, bool indexed registered); event OperatorUpdated(address indexed registrant, address indexed operator, bool indexed filtered); event OperatorsUpdated(address indexed registrant, address[] operators, bool indexed filtered); event CodeHashUpdated(address indexed registrant, bytes32 indexed codeHash, bool indexed filtered); event CodeHashesUpdated(address indexed registrant, bytes32[] codeHashes, bool indexed filtered); event SubscriptionUpdated(address indexed registrant, address indexed subscription, bool indexed subscribed); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/Ownable.sol) pragma solidity ^0.8.0; import "./Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (access/Ownable2Step.sol) pragma solidity ^0.8.0; import "./Ownable.sol"; /** * @dev Contract module which provides 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} and {acceptOwnership}. * * This module is used through inheritance. It will make available all functions * from parent (Ownable). */ abstract contract Ownable2Step is Ownable { address private _pendingOwner; event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); /** * @dev Returns the address of the pending owner. */ function pendingOwner() public view virtual returns (address) { return _pendingOwner; } /** * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual override onlyOwner { _pendingOwner = newOwner; emit OwnershipTransferStarted(owner(), newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner. * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual override { delete _pendingOwner; super._transferOwnership(newOwner); } /** * @dev The new owner accepts the ownership transfer. */ function acceptOwnership() public virtual { address sender = _msgSender(); require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner"); _transferOwnership(sender); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import {IOperatorFilterRegistry} from "./IOperatorFilterRegistry.sol"; import {Ownable2Step} from "./Ownable2Step.sol"; import './Context.sol'; /** * @title OwnedRegistrant * @notice Ownable contract that registers itself with the OperatorFilterRegistry and administers its own entries, * to facilitate a subscription whose ownership can be transferred. */ contract OwnedRegistrant is Ownable2Step { address constant registry = 0x000000000000AAeB6D7670E522A718067333cd4E; constructor(address _owner) { IOperatorFilterRegistry(registry).register(address(this)); transferOwnership(_owner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"uint256","name":"_cost","type":"uint256"},{"internalType":"uint256","name":"_MaxPerTxn","type":"uint256"},{"internalType":"uint256","name":"_MaxPerUser","type":"uint256"},{"internalType":"uint256","name":"_maxSupply","type":"uint256"},{"internalType":"string","name":"_uri","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ApprovalCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"ApprovalQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"ApprovalToCurrentOwner","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"BalanceQueryForZeroAddress","type":"error"},{"inputs":[],"name":"MintToZeroAddress","type":"error"},{"inputs":[],"name":"MintZeroQuantity","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"OperatorNotAllowed","type":"error"},{"inputs":[],"name":"OwnerQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"TransferCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferToNonERC721ReceiverImplementer","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"inputs":[],"name":"URIQueryForNonexistentToken","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":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":"","type":"address"}],"name":"OGClaimed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OGMerkelRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"_merkleProof","type":"bytes32[]"}],"name":"OGMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hiddenMetadataUri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"},{"internalType":"bytes32","name":"leaf","type":"bytes32"}],"name":"isValidOG","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"},{"internalType":"bytes32","name":"leaf","type":"bytes32"}],"name":"isValidWL","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxMintAmtPerTx","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxPerUser","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"merkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_mintAmount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_mintAmount","type":"uint256"},{"internalType":"address","name":"_receiver","type":"address"}],"name":"mintForAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"mintPhase","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"publicMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"revealed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"revealedURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_revealedURI","type":"string"}],"name":"setBaseUri","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_cost","type":"uint256"}],"name":"setCost","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_hiddenMetadataUri","type":"string"}],"name":"setHiddenMetadataUri","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"setMaxPerUser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"setMintAmtPerTx","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_phase","type":"uint256"}],"name":"setMintPhase","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_OGRoot","type":"bytes32"}],"name":"setOGRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setRevealed","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_uriSuffix","type":"string"}],"name":"setUriSuffix","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_merkleRoot","type":"bytes32"}],"name":"setWLRoot","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":"","type":"string"}],"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":[],"name":"uriSuffix","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"whitelistClaimed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_mintAmount","type":"uint256"},{"internalType":"bytes32[]","name":"_merkleProof","type":"bytes32[]"}],"name":"whitelistMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6080604052604051806020016040528060008152506010908162000024919062000722565b506040518060400160405280600581526020017f2e6a736f6e000000000000000000000000000000000000000000000000000000815250601190816200006b919062000722565b506000601660006101000a81548160ff0219169083151502179055503480156200009457600080fd5b506040516200611c3803806200611c8339818101604052810190620000ba91906200099e565b733cc6cdda760b79bafa08df41ecfa224f810dceb660016040518060400160405280600b81526020017f4d6f76696e204672656e730000000000000000000000000000000000000000008152506040518060400160405280600281526020017f4d4600000000000000000000000000000000000000000000000000000000000081525081600290816200014e919062000722565b50806003908162000160919062000722565b5062000171620003d160201b60201c565b6000819055505050620001996200018d620003da60201b60201c565b620003e260201b60201c565b600160098190555060006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b1115620003965780156200025c576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff16637d3e3dbe30846040518363ffffffff1660e01b81526004016200022292919062000a8a565b600060405180830381600087803b1580156200023d57600080fd5b505af115801562000252573d6000803e3d6000fd5b5050505062000395565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161462000316576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663a0af290330846040518363ffffffff1660e01b8152600401620002dc92919062000a8a565b600060405180830381600087803b158015620002f757600080fd5b505af11580156200030c573d6000803e3d6000fd5b5050505062000394565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff16634420e486306040518263ffffffff1660e01b81526004016200035f919062000ab7565b600060405180830381600087803b1580156200037a57600080fd5b505af11580156200038f573d6000803e3d6000fd5b505050505b5b5b50508360158190555082600f8190555084601381905550816014819055508060129081620003c5919062000722565b50505050505062000ad4565b60006001905090565b600033905090565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806200052a57607f821691505b60208210810362000540576200053f620004e2565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302620005aa7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826200056b565b620005b686836200056b565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b600062000603620005fd620005f784620005ce565b620005d8565b620005ce565b9050919050565b6000819050919050565b6200061f83620005e2565b620006376200062e826200060a565b84845462000578565b825550505050565b600090565b6200064e6200063f565b6200065b81848462000614565b505050565b5b8181101562000683576200067760008262000644565b60018101905062000661565b5050565b601f821115620006d2576200069c8162000546565b620006a7846200055b565b81016020851015620006b7578190505b620006cf620006c6856200055b565b83018262000660565b50505b505050565b600082821c905092915050565b6000620006f760001984600802620006d7565b1980831691505092915050565b6000620007128383620006e4565b9150826002028217905092915050565b6200072d82620004a8565b67ffffffffffffffff811115620007495762000748620004b3565b5b62000755825462000511565b6200076282828562000687565b600060209050601f8311600181146200079a576000841562000785578287015190505b62000791858262000704565b86555062000801565b601f198416620007aa8662000546565b60005b82811015620007d457848901518255600182019150602085019450602081019050620007ad565b86831015620007f45784890151620007f0601f891682620006e4565b8355505b6001600288020188555050505b505050505050565b6000604051905090565b600080fd5b600080fd5b6200082881620005ce565b81146200083457600080fd5b50565b60008151905062000848816200081d565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b620008748262000858565b810181811067ffffffffffffffff82111715620008965762000895620004b3565b5b80604052505050565b6000620008ab62000809565b9050620008b9828262000869565b919050565b600067ffffffffffffffff821115620008dc57620008db620004b3565b5b620008e78262000858565b9050602081019050919050565b60005b8381101562000914578082015181840152602081019050620008f7565b60008484015250505050565b6000620009376200093184620008be565b6200089f565b90508281526020810184848401111562000956576200095562000853565b5b62000963848285620008f4565b509392505050565b600082601f8301126200098357620009826200084e565b5b81516200099584826020860162000920565b91505092915050565b600080600080600060a08688031215620009bd57620009bc62000813565b5b6000620009cd8882890162000837565b9550506020620009e08882890162000837565b9450506040620009f38882890162000837565b935050606062000a068882890162000837565b925050608086015167ffffffffffffffff81111562000a2a5762000a2962000818565b5b62000a38888289016200096b565b9150509295509295909350565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600062000a728262000a45565b9050919050565b62000a848162000a65565b82525050565b600060408201905062000aa1600083018562000a79565b62000ab0602083018462000a79565b9392505050565b600060208201905062000ace600083018462000a79565b92915050565b6156388062000ae46000396000f3fe6080604052600436106102935760003560e01c80635503a0e81161015a578063a22cb465116100c1578063d5abeb011161007a578063d5abeb01146109eb578063db4bec4414610a16578063e985e9c514610a53578063efbd73f414610a90578063f2fde38b14610ab9578063f7e8d6ea14610ae257610293565b8063a22cb465146108ec578063a45ba8e714610915578063b11c7f8214610940578063b88d4fde14610969578063c87b56dd14610992578063d2cab056146109cf57610293565b8063813dcee711610113578063813dcee7146107eb5780638da5cb5b14610814578063943431bf1461083f57806395d89b411461087c578063a0712d68146108a7578063a0bcfc7f146108c357610293565b80635503a0e8146106dd5780635efe1a1f146107085780636352211e1461073157806369bf67e61461076e57806370a0823114610797578063715018a6146107d457610293565b80631d706965116101fe5780633ccfd60b116101b75780633ccfd60b146105f55780634030ca7e1461060c57806342842e0e1461063757806344a0d68a146106605780634fdd43cb1461068957806351830227146106b257610293565b80631d706965146104bf5780631dfcaa48146104fc57806323b872dd146105395780632eb4a7ab14610562578063302c41121461058d5780633bd64968146105ca57610293565b80631015805b116102505780631015805b146103ad57806313faede6146103ea578063162519621461041557806316ba10e01461044057806317881cbf1461046957806318160ddd1461049457610293565b80630186d1371461029857806301ffc9a7146102b457806306d586bb146102f157806306fdde031461031c578063081812fc14610347578063095ea7b314610384575b600080fd5b6102b260048036038101906102ad9190613eb8565b610b0d565b005b3480156102c057600080fd5b506102db60048036038101906102d69190613f5d565b610db8565b6040516102e89190613fa5565b60405180910390f35b3480156102fd57600080fd5b50610306610e9a565b6040516103139190613fd9565b60405180910390f35b34801561032857600080fd5b50610331610ea0565b60405161033e9190614084565b60405180910390f35b34801561035357600080fd5b5061036e600480360381019061036991906140d2565b610f32565b60405161037b9190614140565b60405180910390f35b34801561039057600080fd5b506103ab60048036038101906103a69190614187565b610fae565b005b3480156103b957600080fd5b506103d460048036038101906103cf91906141c7565b6110b2565b6040516103e19190613fd9565b60405180910390f35b3480156103f657600080fd5b506103ff6110ca565b60405161040c9190613fd9565b60405180910390f35b34801561042157600080fd5b5061042a6110d0565b6040516104379190613fd9565b60405180910390f35b34801561044c57600080fd5b5061046760048036038101906104629190614324565b6110d6565b005b34801561047557600080fd5b5061047e611165565b60405161048b9190613fd9565b60405180910390f35b3480156104a057600080fd5b506104a961116b565b6040516104b69190613fd9565b60405180910390f35b3480156104cb57600080fd5b506104e660048036038101906104e19190614466565b611182565b6040516104f39190613fa5565b60405180910390f35b34801561050857600080fd5b50610523600480360381019061051e91906141c7565b611199565b6040516105309190613fa5565b60405180910390f35b34801561054557600080fd5b50610560600480360381019061055b91906144c2565b6111b9565b005b34801561056e57600080fd5b506105776112c5565b6040516105849190614524565b60405180910390f35b34801561059957600080fd5b506105b460048036038101906105af9190614466565b6112cb565b6040516105c19190613fa5565b60405180910390f35b3480156105d657600080fd5b506105df6112e2565b6040516105ec9190614084565b60405180910390f35b34801561060157600080fd5b5061060a611415565b005b34801561061857600080fd5b50610621611566565b60405161062e9190614524565b60405180910390f35b34801561064357600080fd5b5061065e600480360381019061065991906144c2565b61156c565b005b34801561066c57600080fd5b50610687600480360381019061068291906140d2565b611678565b005b34801561069557600080fd5b506106b060048036038101906106ab9190614324565b6116fe565b005b3480156106be57600080fd5b506106c761178d565b6040516106d49190613fa5565b60405180910390f35b3480156106e957600080fd5b506106f26117a0565b6040516106ff9190614084565b60405180910390f35b34801561071457600080fd5b5061072f600480360381019061072a919061453f565b61182e565b005b34801561073d57600080fd5b50610758600480360381019061075391906140d2565b6118b4565b6040516107659190614140565b60405180910390f35b34801561077a57600080fd5b50610795600480360381019061079091906140d2565b6118ca565b005b3480156107a357600080fd5b506107be60048036038101906107b991906141c7565b611950565b6040516107cb9190613fd9565b60405180910390f35b3480156107e057600080fd5b506107e9611a1f565b005b3480156107f757600080fd5b50610812600480360381019061080d91906140d2565b611aa7565b005b34801561082057600080fd5b50610829611b2d565b6040516108369190614140565b60405180910390f35b34801561084b57600080fd5b50610866600480360381019061086191906140d2565b611b57565b6040516108739190614084565b60405180910390f35b34801561088857600080fd5b50610891611d28565b60405161089e9190614084565b60405180910390f35b6108c160048036038101906108bc91906140d2565b611dba565b005b3480156108cf57600080fd5b506108ea60048036038101906108e59190614324565b611ff4565b005b3480156108f857600080fd5b50610913600480360381019061090e9190614598565b612083565b005b34801561092157600080fd5b5061092a6121fa565b6040516109379190614084565b60405180910390f35b34801561094c57600080fd5b506109676004803603810190610962919061453f565b612288565b005b34801561097557600080fd5b50610990600480360381019061098b9190614679565b61230e565b005b34801561099e57600080fd5b506109b960048036038101906109b491906140d2565b61241c565b6040516109c69190614084565b60405180910390f35b6109e960048036038101906109e491906146fc565b612574565b005b3480156109f757600080fd5b50610a00612877565b604051610a0d9190613fd9565b60405180910390f35b348015610a2257600080fd5b50610a3d6004803603810190610a3891906141c7565b61287d565b604051610a4a9190613fd9565b60405180910390f35b348015610a5f57600080fd5b50610a7a6004803603810190610a75919061475c565b612895565b604051610a879190613fa5565b60405180910390f35b348015610a9c57600080fd5b50610ab76004803603810190610ab2919061479c565b612929565b005b348015610ac557600080fd5b50610ae06004803603810190610adb91906141c7565b612a5d565b005b348015610aee57600080fd5b50610af7612b54565b604051610b049190614084565b60405180910390f35b6001600081118015610b2157506015548111155b610b60576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b5790614828565b60405180910390fd5b60145481610b6c61116b565b610b769190614877565b1115610bb7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bae906148f7565b60405180910390fd5b600160175414610bfc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bf390614963565b60405180910390fd5b600d60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615610c89576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c80906149cf565b60405180910390fd5b6000610c93612be2565b604051602001610ca39190614a37565b604051602081830303815290604052805190602001209050610d09848480806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f82011690508083019250505050505050600b5483612bea565b610d48576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d3f90614a9e565b60405180910390fd5b6001600d60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550610db2610dab612be2565b6001612c01565b50505050565b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610e8357507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80610e935750610e9282612c1f565b5b9050919050565b600f5481565b606060028054610eaf90614aed565b80601f0160208091040260200160405190810160405280929190818152602001828054610edb90614aed565b8015610f285780601f10610efd57610100808354040283529160200191610f28565b820191906000526020600020905b815481529060010190602001808311610f0b57829003601f168201915b5050505050905090565b6000610f3d82612c89565b610f73576040517fcf4700e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6006600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000610fb9826118b4565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611020576040517f943f7b8c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1661103f612be2565b73ffffffffffffffffffffffffffffffffffffffff16146110a25761106b81611066612be2565b612895565b6110a1576040517fcfb3b94200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b6110ad838383612cd7565b505050565b600e6020528060005260406000206000915090505481565b60135481565b60155481565b6110de612be2565b73ffffffffffffffffffffffffffffffffffffffff166110fc611b2d565b73ffffffffffffffffffffffffffffffffffffffff1614611152576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161114990614b6a565b60405180910390fd5b80601190816111619190614d36565b5050565b60175481565b6000611175612d89565b6001546000540303905090565b600061119183600a5484612bea565b905092915050565b600d6020528060005260406000206000915054906101000a900460ff1681565b60006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b11156112b5576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430336040518363ffffffff1660e01b8152600401611230929190614e08565b6020604051808303816000875af115801561124f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112739190614e46565b6112b457336040517fede71dcc0000000000000000000000000000000000000000000000000000000081526004016112ab9190614140565b60405180910390fd5b5b6112c0838383612d92565b505050565b600a5481565b60006112da83600b5484612bea565b905092915050565b60606112ec612be2565b73ffffffffffffffffffffffffffffffffffffffff1661130a611b2d565b73ffffffffffffffffffffffffffffffffffffffff1614611360576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161135790614b6a565b60405180910390fd5b601660009054906101000a900460ff1615601660006101000a81548160ff021916908315150217905550601660009054906101000a900460ff166113d9576040518060400160405280600f81526020017f4e465473204172652048696464656e0000000000000000000000000000000000815250611410565b6040518060400160405280601181526020017f4e465473204172652052657665616c65640000000000000000000000000000008152505b905090565b61141d612be2565b73ffffffffffffffffffffffffffffffffffffffff1661143b611b2d565b73ffffffffffffffffffffffffffffffffffffffff1614611491576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161148890614b6a565b60405180910390fd5b6002600954036114d6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114cd90614ebf565b60405180910390fd5b600260098190555060006114e8611b2d565b73ffffffffffffffffffffffffffffffffffffffff164760405161150b90614f10565b60006040518083038185875af1925050503d8060008114611548576040519150601f19603f3d011682016040523d82523d6000602084013e61154d565b606091505b505090508061155b57600080fd5b506001600981905550565b600b5481565b60006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b1115611668576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430336040518363ffffffff1660e01b81526004016115e3929190614e08565b6020604051808303816000875af1158015611602573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116269190614e46565b61166757336040517fede71dcc00000000000000000000000000000000000000000000000000000000815260040161165e9190614140565b60405180910390fd5b5b611673838383612da2565b505050565b611680612be2565b73ffffffffffffffffffffffffffffffffffffffff1661169e611b2d565b73ffffffffffffffffffffffffffffffffffffffff16146116f4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116eb90614b6a565b60405180910390fd5b8060138190555050565b611706612be2565b73ffffffffffffffffffffffffffffffffffffffff16611724611b2d565b73ffffffffffffffffffffffffffffffffffffffff161461177a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161177190614b6a565b60405180910390fd5b80601290816117899190614d36565b5050565b601660009054906101000a900460ff1681565b601180546117ad90614aed565b80601f01602080910402602001604051908101604052809291908181526020018280546117d990614aed565b80156118265780601f106117fb57610100808354040283529160200191611826565b820191906000526020600020905b81548152906001019060200180831161180957829003601f168201915b505050505081565b611836612be2565b73ffffffffffffffffffffffffffffffffffffffff16611854611b2d565b73ffffffffffffffffffffffffffffffffffffffff16146118aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118a190614b6a565b60405180910390fd5b80600b8190555050565b60006118bf82612dc2565b600001519050919050565b6118d2612be2565b73ffffffffffffffffffffffffffffffffffffffff166118f0611b2d565b73ffffffffffffffffffffffffffffffffffffffff1614611946576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161193d90614b6a565b60405180910390fd5b8060158190555050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036119b7576040517f8f4eb60400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900467ffffffffffffffff1667ffffffffffffffff169050919050565b611a27612be2565b73ffffffffffffffffffffffffffffffffffffffff16611a45611b2d565b73ffffffffffffffffffffffffffffffffffffffff1614611a9b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a9290614b6a565b60405180910390fd5b611aa5600061304d565b565b611aaf612be2565b73ffffffffffffffffffffffffffffffffffffffff16611acd611b2d565b73ffffffffffffffffffffffffffffffffffffffff1614611b23576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b1a90614b6a565b60405180910390fd5b80600f8190555050565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6060611b61612be2565b73ffffffffffffffffffffffffffffffffffffffff16611b7f611b2d565b73ffffffffffffffffffffffffffffffffffffffff1614611bd5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bcc90614b6a565b60405180910390fd5b60048210611c18576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c0f90614f71565b60405180910390fd5b8160178190555060018214611cea5760028214611cae5760038214611c72576040518060400160405280601081526020017f4d696e74206e6f7420656e61626c656400000000000000000000000000000000815250611ca9565b6040518060400160405280601381526020017f5075626c6963206d696e7420656e61626c6564000000000000000000000000008152505b611ce5565b6040518060400160405280601681526020017f57686974656c697374206d696e7420656e61626c6564000000000000000000008152505b611d21565b6040518060400160405280600f81526020017f4f47206d696e7420656e61626c656400000000000000000000000000000000008152505b9050919050565b606060038054611d3790614aed565b80601f0160208091040260200160405190810160405280929190818152602001828054611d6390614aed565b8015611db05780601f10611d8557610100808354040283529160200191611db0565b820191906000526020600020905b815481529060010190602001808311611d9357829003601f168201915b5050505050905090565b80600081118015611dcd57506015548111155b611e0c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e0390614828565b60405180910390fd5b60145481611e1861116b565b611e229190614877565b1115611e63576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e5a906148f7565b60405180910390fd5b8180601354611e729190614f91565b341015611eb4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611eab9061501f565b60405180910390fd5b60155483600e60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054611f029190614877565b1115611f43576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f3a906150b1565b60405180910390fd5b600360175414611f88576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f7f9061511d565b60405180910390fd5b82600e60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254611fd79190614877565b92505081905550611fef611fe9612be2565b84612c01565b505050565b611ffc612be2565b73ffffffffffffffffffffffffffffffffffffffff1661201a611b2d565b73ffffffffffffffffffffffffffffffffffffffff1614612070576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161206790614b6a565b60405180910390fd5b806010908161207f9190614d36565b5050565b61208b612be2565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036120ef576040517fb06307db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600760006120fc612be2565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff166121a9612be2565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516121ee9190613fa5565b60405180910390a35050565b6012805461220790614aed565b80601f016020809104026020016040519081016040528092919081815260200182805461223390614aed565b80156122805780601f1061225557610100808354040283529160200191612280565b820191906000526020600020905b81548152906001019060200180831161226357829003601f168201915b505050505081565b612290612be2565b73ffffffffffffffffffffffffffffffffffffffff166122ae611b2d565b73ffffffffffffffffffffffffffffffffffffffff1614612304576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122fb90614b6a565b60405180910390fd5b80600a8190555050565b60006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b111561240a576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430336040518363ffffffff1660e01b8152600401612385929190614e08565b6020604051808303816000875af11580156123a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123c89190614e46565b61240957336040517fede71dcc0000000000000000000000000000000000000000000000000000000081526004016124009190614140565b60405180910390fd5b5b61241684848484613113565b50505050565b606061242782612c89565b612466576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161245d906151af565b60405180910390fd5b60001515601660009054906101000a900460ff16151503612513576012805461248e90614aed565b80601f01602080910402602001604051908101604052809291908181526020018280546124ba90614aed565b80156125075780601f106124dc57610100808354040283529160200191612507565b820191906000526020600020905b8154815290600101906020018083116124ea57829003601f168201915b5050505050905061256f565b600061251d61318b565b9050600081511161253d576040518060200160405280600081525061256b565b806125478461321d565b601160405160200161255b9392919061528e565b6040516020818303038152906040525b9150505b919050565b8260008111801561258757506015548111155b6125c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125bd90614828565b60405180910390fd5b601454816125d261116b565b6125dc9190614877565b111561261d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612614906148f7565b60405180910390fd5b838060135461262c9190614f91565b34101561266e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126659061501f565b60405180910390fd5b6002601754146126b3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126aa90615331565b60405180910390fd5b84600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054600f546127019190615351565b1015612742576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612739906150b1565b60405180910390fd5b600061274c612be2565b60405160200161275c9190614a37565b6040516020818303038152906040528051906020012090506127c2858580806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f82011690508083019250505050505050600a5483612bea565b612801576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127f890614a9e565b60405180910390fd5b85600c600061280e612be2565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546128579190614877565b9250508190555061286f612869612be2565b87612c01565b505050505050565b60145481565b600c6020528060005260406000206000915090505481565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b8160008111801561293c57506015548111155b61297b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161297290614828565b60405180910390fd5b6014548161298761116b565b6129919190614877565b11156129d2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129c9906148f7565b60405180910390fd5b6129da612be2565b73ffffffffffffffffffffffffffffffffffffffff166129f8611b2d565b73ffffffffffffffffffffffffffffffffffffffff1614612a4e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a4590614b6a565b60405180910390fd5b612a588284612c01565b505050565b612a65612be2565b73ffffffffffffffffffffffffffffffffffffffff16612a83611b2d565b73ffffffffffffffffffffffffffffffffffffffff1614612ad9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ad090614b6a565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612b48576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b3f906153f7565b60405180910390fd5b612b518161304d565b50565b60108054612b6190614aed565b80601f0160208091040260200160405190810160405280929190818152602001828054612b8d90614aed565b8015612bda5780601f10612baf57610100808354040283529160200191612bda565b820191906000526020600020905b815481529060010190602001808311612bbd57829003601f168201915b505050505081565b600033905090565b600082612bf7858461337d565b1490509392505050565b612c1b8282604051806020016040528060008152506133f2565b5050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b600081612c94612d89565b11158015612ca3575060005482105b8015612cd0575060046000838152602001908152602001600020600001601c9054906101000a900460ff16155b9050919050565b826006600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b60006001905090565b612d9d8383836137b2565b505050565b612dbd8383836040518060200160405280600081525061230e565b505050565b612dca613dfc565b600082905080612dd8612d89565b1161301657600054811015613015576000600460008381526020019081526020016000206040518060600160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160008201601c9054906101000a900460ff1615151515815250509050806040015161301357600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff1614612ef7578092505050613048565b5b60011561301257818060019003925050600460008381526020019081526020016000206040518060600160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160008201601c9054906101000a900460ff1615151515815250509050600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff161461300d578092505050613048565b612ef8565b5b505b5b6040517fdf2d9b4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b61311e8484846137b2565b61313d8373ffffffffffffffffffffffffffffffffffffffff16613c66565b156131855761314e84848484613c89565b613184576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b50505050565b60606010805461319a90614aed565b80601f01602080910402602001604051908101604052809291908181526020018280546131c690614aed565b80156132135780601f106131e857610100808354040283529160200191613213565b820191906000526020600020905b8154815290600101906020018083116131f657829003601f168201915b5050505050905090565b606060008203613264576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050613378565b600082905060005b6000821461329657808061327f90615417565b915050600a8261328f919061548e565b915061326c565b60008167ffffffffffffffff8111156132b2576132b16141f9565b5b6040519080825280601f01601f1916602001820160405280156132e45781602001600182028036833780820191505090505b5090505b60008514613371576001826132fd9190615351565b9150600a8561330c91906154bf565b60306133189190614877565b60f81b81838151811061332e5761332d6154f0565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a8561336a919061548e565b94506132e8565b8093505050505b919050565b60008082905060005b84518110156133e75760008582815181106133a4576133a36154f0565b5b602002602001015190508083116133c6576133bf8382613dd9565b92506133d3565b6133d08184613dd9565b92505b5080806133df90615417565b915050613386565b508091505092915050565b600080549050600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361345e576040517f2e07630000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008303613498576040517fb562e8dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6134a56000858386613df0565b82600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282829054906101000a900467ffffffffffffffff160192506101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555082600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160088282829054906101000a900467ffffffffffffffff160192506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550836004600083815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550426004600083815260200190815260200160002060000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506000819050600084820190506136668673ffffffffffffffffffffffffffffffffffffffff16613c66565b1561372b575b818673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46136db6000878480600101955087613c89565b613711576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80821061366c57826000541461372657600080fd5b613796565b5b818060010192508673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a480821061372c575b8160008190555050506137ac6000858386613df6565b50505050565b60006137bd82612dc2565b90508373ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff1614613828576040517fa114810000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008473ffffffffffffffffffffffffffffffffffffffff16613849612be2565b73ffffffffffffffffffffffffffffffffffffffff161480613878575061387785613872612be2565b612895565b5b806138bd5750613886612be2565b73ffffffffffffffffffffffffffffffffffffffff166138a584610f32565b73ffffffffffffffffffffffffffffffffffffffff16145b9050806138f6576040517f59c896be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361395c576040517fea553b3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6139698585856001613df0565b61397560008487612cd7565b6001600560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282829054906101000a900467ffffffffffffffff160392506101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506001600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282829054906101000a900467ffffffffffffffff160192506101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506000600460008581526020019081526020016000209050848160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550428160000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555060006001850190506000600460008381526020019081526020016000209050600073ffffffffffffffffffffffffffffffffffffffff168160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1603613bf4576000548214613bf357878160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555084602001518160000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505b5b505050828473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4613c5f8585856001613df6565b5050505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b60008373ffffffffffffffffffffffffffffffffffffffff1663150b7a02613caf612be2565b8786866040518563ffffffff1660e01b8152600401613cd19493929190615574565b6020604051808303816000875af1925050508015613d0d57506040513d601f19601f82011682018060405250810190613d0a91906155d5565b60015b613d86573d8060008114613d3d576040519150601f19603f3d011682016040523d82523d6000602084013e613d42565b606091505b506000815103613d7e576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050949350505050565b600082600052816020526040600020905092915050565b50505050565b50505050565b6040518060600160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600067ffffffffffffffff1681526020016000151581525090565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b60008083601f840112613e7857613e77613e53565b5b8235905067ffffffffffffffff811115613e9557613e94613e58565b5b602083019150836020820283011115613eb157613eb0613e5d565b5b9250929050565b60008060208385031215613ecf57613ece613e49565b5b600083013567ffffffffffffffff811115613eed57613eec613e4e565b5b613ef985828601613e62565b92509250509250929050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b613f3a81613f05565b8114613f4557600080fd5b50565b600081359050613f5781613f31565b92915050565b600060208284031215613f7357613f72613e49565b5b6000613f8184828501613f48565b91505092915050565b60008115159050919050565b613f9f81613f8a565b82525050565b6000602082019050613fba6000830184613f96565b92915050565b6000819050919050565b613fd381613fc0565b82525050565b6000602082019050613fee6000830184613fca565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561402e578082015181840152602081019050614013565b60008484015250505050565b6000601f19601f8301169050919050565b600061405682613ff4565b6140608185613fff565b9350614070818560208601614010565b6140798161403a565b840191505092915050565b6000602082019050818103600083015261409e818461404b565b905092915050565b6140af81613fc0565b81146140ba57600080fd5b50565b6000813590506140cc816140a6565b92915050565b6000602082840312156140e8576140e7613e49565b5b60006140f6848285016140bd565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061412a826140ff565b9050919050565b61413a8161411f565b82525050565b60006020820190506141556000830184614131565b92915050565b6141648161411f565b811461416f57600080fd5b50565b6000813590506141818161415b565b92915050565b6000806040838503121561419e5761419d613e49565b5b60006141ac85828601614172565b92505060206141bd858286016140bd565b9150509250929050565b6000602082840312156141dd576141dc613e49565b5b60006141eb84828501614172565b91505092915050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6142318261403a565b810181811067ffffffffffffffff821117156142505761424f6141f9565b5b80604052505050565b6000614263613e3f565b905061426f8282614228565b919050565b600067ffffffffffffffff82111561428f5761428e6141f9565b5b6142988261403a565b9050602081019050919050565b82818337600083830152505050565b60006142c76142c284614274565b614259565b9050828152602081018484840111156142e3576142e26141f4565b5b6142ee8482856142a5565b509392505050565b600082601f83011261430b5761430a613e53565b5b813561431b8482602086016142b4565b91505092915050565b60006020828403121561433a57614339613e49565b5b600082013567ffffffffffffffff81111561435857614357613e4e565b5b614364848285016142f6565b91505092915050565b600067ffffffffffffffff821115614388576143876141f9565b5b602082029050602081019050919050565b6000819050919050565b6143ac81614399565b81146143b757600080fd5b50565b6000813590506143c9816143a3565b92915050565b60006143e26143dd8461436d565b614259565b9050808382526020820190506020840283018581111561440557614404613e5d565b5b835b8181101561442e578061441a88826143ba565b845260208401935050602081019050614407565b5050509392505050565b600082601f83011261444d5761444c613e53565b5b813561445d8482602086016143cf565b91505092915050565b6000806040838503121561447d5761447c613e49565b5b600083013567ffffffffffffffff81111561449b5761449a613e4e565b5b6144a785828601614438565b92505060206144b8858286016143ba565b9150509250929050565b6000806000606084860312156144db576144da613e49565b5b60006144e986828701614172565b93505060206144fa86828701614172565b925050604061450b868287016140bd565b9150509250925092565b61451e81614399565b82525050565b60006020820190506145396000830184614515565b92915050565b60006020828403121561455557614554613e49565b5b6000614563848285016143ba565b91505092915050565b61457581613f8a565b811461458057600080fd5b50565b6000813590506145928161456c565b92915050565b600080604083850312156145af576145ae613e49565b5b60006145bd85828601614172565b92505060206145ce85828601614583565b9150509250929050565b600067ffffffffffffffff8211156145f3576145f26141f9565b5b6145fc8261403a565b9050602081019050919050565b600061461c614617846145d8565b614259565b905082815260208101848484011115614638576146376141f4565b5b6146438482856142a5565b509392505050565b600082601f8301126146605761465f613e53565b5b8135614670848260208601614609565b91505092915050565b6000806000806080858703121561469357614692613e49565b5b60006146a187828801614172565b94505060206146b287828801614172565b93505060406146c3878288016140bd565b925050606085013567ffffffffffffffff8111156146e4576146e3613e4e565b5b6146f08782880161464b565b91505092959194509250565b60008060006040848603121561471557614714613e49565b5b6000614723868287016140bd565b935050602084013567ffffffffffffffff81111561474457614743613e4e565b5b61475086828701613e62565b92509250509250925092565b6000806040838503121561477357614772613e49565b5b600061478185828601614172565b925050602061479285828601614172565b9150509250929050565b600080604083850312156147b3576147b2613e49565b5b60006147c1858286016140bd565b92505060206147d285828601614172565b9150509250929050565b7f496e76616c6964206d696e7420616d6f756e7421000000000000000000000000600082015250565b6000614812601483613fff565b915061481d826147dc565b602082019050919050565b6000602082019050818103600083015261484181614805565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061488282613fc0565b915061488d83613fc0565b92508282019050808211156148a5576148a4614848565b5b92915050565b7f4d617820737570706c7920657863656564656421000000000000000000000000600082015250565b60006148e1601483613fff565b91506148ec826148ab565b602082019050919050565b60006020820190508181036000830152614910816148d4565b9050919050565b7f4f47204d696e74205068617365206973204e6f74204163746976650000000000600082015250565b600061494d601b83613fff565b915061495882614917565b602082019050919050565b6000602082019050818103600083015261497c81614940565b9050919050565b7f4f47204d696e7420416c726561647920436c61696d6564000000000000000000600082015250565b60006149b9601783613fff565b91506149c482614983565b602082019050919050565b600060208201905081810360008301526149e8816149ac565b9050919050565b60008160601b9050919050565b6000614a07826149ef565b9050919050565b6000614a19826149fc565b9050919050565b614a31614a2c8261411f565b614a0e565b82525050565b6000614a438284614a20565b60148201915081905092915050565b7f496e76616c69642070726f6f6621000000000000000000000000000000000000600082015250565b6000614a88600e83613fff565b9150614a9382614a52565b602082019050919050565b60006020820190508181036000830152614ab781614a7b565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680614b0557607f821691505b602082108103614b1857614b17614abe565b5b50919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000614b54602083613fff565b9150614b5f82614b1e565b602082019050919050565b60006020820190508181036000830152614b8381614b47565b9050919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302614bec7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82614baf565b614bf68683614baf565b95508019841693508086168417925050509392505050565b6000819050919050565b6000614c33614c2e614c2984613fc0565b614c0e565b613fc0565b9050919050565b6000819050919050565b614c4d83614c18565b614c61614c5982614c3a565b848454614bbc565b825550505050565b600090565b614c76614c69565b614c81818484614c44565b505050565b5b81811015614ca557614c9a600082614c6e565b600181019050614c87565b5050565b601f821115614cea57614cbb81614b8a565b614cc484614b9f565b81016020851015614cd3578190505b614ce7614cdf85614b9f565b830182614c86565b50505b505050565b600082821c905092915050565b6000614d0d60001984600802614cef565b1980831691505092915050565b6000614d268383614cfc565b9150826002028217905092915050565b614d3f82613ff4565b67ffffffffffffffff811115614d5857614d576141f9565b5b614d628254614aed565b614d6d828285614ca9565b600060209050601f831160018114614da05760008415614d8e578287015190505b614d988582614d1a565b865550614e00565b601f198416614dae86614b8a565b60005b82811015614dd657848901518255600182019150602085019450602081019050614db1565b86831015614df35784890151614def601f891682614cfc565b8355505b6001600288020188555050505b505050505050565b6000604082019050614e1d6000830185614131565b614e2a6020830184614131565b9392505050565b600081519050614e408161456c565b92915050565b600060208284031215614e5c57614e5b613e49565b5b6000614e6a84828501614e31565b91505092915050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b6000614ea9601f83613fff565b9150614eb482614e73565b602082019050919050565b60006020820190508181036000830152614ed881614e9c565b9050919050565b600081905092915050565b50565b6000614efa600083614edf565b9150614f0582614eea565b600082019050919050565b6000614f1b82614eed565b9150819050919050565b7f496e76616c696420706861736500000000000000000000000000000000000000600082015250565b6000614f5b600d83613fff565b9150614f6682614f25565b602082019050919050565b60006020820190508181036000830152614f8a81614f4e565b9050919050565b6000614f9c82613fc0565b9150614fa783613fc0565b9250828202614fb581613fc0565b91508282048414831517614fcc57614fcb614848565b5b5092915050565b7f496e73756666696369656e742066756e64732100000000000000000000000000600082015250565b6000615009601383613fff565b915061501482614fd3565b602082019050919050565b6000602082019050818103600083015261503881614ffc565b9050919050565b7f596f752068617665206d696e746564206d6178696d756d20616c6c6f7765642060008201527f6e667473206f722074727920746f206d696e74206c6573730000000000000000602082015250565b600061509b603883613fff565b91506150a68261503f565b604082019050919050565b600060208201905081810360008301526150ca8161508e565b9050919050565b7f5075626c6963204d696e74205068617365206973204e6f742041637469766500600082015250565b6000615107601f83613fff565b9150615112826150d1565b602082019050919050565b60006020820190508181036000830152615136816150fa565b9050919050565b7f4552433732314d657461646174613a2055524920717565727920666f72206e6f60008201527f6e6578697374656e7420746f6b656e0000000000000000000000000000000000602082015250565b6000615199602f83613fff565b91506151a48261513d565b604082019050919050565b600060208201905081810360008301526151c88161518c565b9050919050565b600081905092915050565b60006151e582613ff4565b6151ef81856151cf565b93506151ff818560208601614010565b80840191505092915050565b6000815461521881614aed565b61522281866151cf565b9450600182166000811461523d576001811461525257615285565b60ff1983168652811515820286019350615285565b61525b85614b8a565b60005b8381101561527d5781548189015260018201915060208101905061525e565b838801955050505b50505092915050565b600061529a82866151da565b91506152a682856151da565b91506152b2828461520b565b9150819050949350505050565b7f57686974656c697374204d696e74205068617365206973204e6f74204163746960008201527f7665000000000000000000000000000000000000000000000000000000000000602082015250565b600061531b602283613fff565b9150615326826152bf565b604082019050919050565b6000602082019050818103600083015261534a8161530e565b9050919050565b600061535c82613fc0565b915061536783613fc0565b925082820390508181111561537f5761537e614848565b5b92915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b60006153e1602683613fff565b91506153ec82615385565b604082019050919050565b60006020820190508181036000830152615410816153d4565b9050919050565b600061542282613fc0565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361545457615453614848565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061549982613fc0565b91506154a483613fc0565b9250826154b4576154b361545f565b5b828204905092915050565b60006154ca82613fc0565b91506154d583613fc0565b9250826154e5576154e461545f565b5b828206905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600081519050919050565b600082825260208201905092915050565b60006155468261551f565b615550818561552a565b9350615560818560208601614010565b6155698161403a565b840191505092915050565b60006080820190506155896000830187614131565b6155966020830186614131565b6155a36040830185613fca565b81810360608301526155b5818461553b565b905095945050505050565b6000815190506155cf81613f31565b92915050565b6000602082840312156155eb576155ea613e49565b5b60006155f9848285016155c0565b9150509291505056fea2646970667358221220add2e9a9a9ecc75fccfddbb931297fe37b95c09a75f5e424258811881bc14a4764736f6c634300081100330000000000000000000000000000000000000000000000000058d15e17628000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000138800000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000002468747470733a2f2f697066732e6d6f76696e6672656e732e636f6d2f756e72657665616c00000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x6080604052600436106102935760003560e01c80635503a0e81161015a578063a22cb465116100c1578063d5abeb011161007a578063d5abeb01146109eb578063db4bec4414610a16578063e985e9c514610a53578063efbd73f414610a90578063f2fde38b14610ab9578063f7e8d6ea14610ae257610293565b8063a22cb465146108ec578063a45ba8e714610915578063b11c7f8214610940578063b88d4fde14610969578063c87b56dd14610992578063d2cab056146109cf57610293565b8063813dcee711610113578063813dcee7146107eb5780638da5cb5b14610814578063943431bf1461083f57806395d89b411461087c578063a0712d68146108a7578063a0bcfc7f146108c357610293565b80635503a0e8146106dd5780635efe1a1f146107085780636352211e1461073157806369bf67e61461076e57806370a0823114610797578063715018a6146107d457610293565b80631d706965116101fe5780633ccfd60b116101b75780633ccfd60b146105f55780634030ca7e1461060c57806342842e0e1461063757806344a0d68a146106605780634fdd43cb1461068957806351830227146106b257610293565b80631d706965146104bf5780631dfcaa48146104fc57806323b872dd146105395780632eb4a7ab14610562578063302c41121461058d5780633bd64968146105ca57610293565b80631015805b116102505780631015805b146103ad57806313faede6146103ea578063162519621461041557806316ba10e01461044057806317881cbf1461046957806318160ddd1461049457610293565b80630186d1371461029857806301ffc9a7146102b457806306d586bb146102f157806306fdde031461031c578063081812fc14610347578063095ea7b314610384575b600080fd5b6102b260048036038101906102ad9190613eb8565b610b0d565b005b3480156102c057600080fd5b506102db60048036038101906102d69190613f5d565b610db8565b6040516102e89190613fa5565b60405180910390f35b3480156102fd57600080fd5b50610306610e9a565b6040516103139190613fd9565b60405180910390f35b34801561032857600080fd5b50610331610ea0565b60405161033e9190614084565b60405180910390f35b34801561035357600080fd5b5061036e600480360381019061036991906140d2565b610f32565b60405161037b9190614140565b60405180910390f35b34801561039057600080fd5b506103ab60048036038101906103a69190614187565b610fae565b005b3480156103b957600080fd5b506103d460048036038101906103cf91906141c7565b6110b2565b6040516103e19190613fd9565b60405180910390f35b3480156103f657600080fd5b506103ff6110ca565b60405161040c9190613fd9565b60405180910390f35b34801561042157600080fd5b5061042a6110d0565b6040516104379190613fd9565b60405180910390f35b34801561044c57600080fd5b5061046760048036038101906104629190614324565b6110d6565b005b34801561047557600080fd5b5061047e611165565b60405161048b9190613fd9565b60405180910390f35b3480156104a057600080fd5b506104a961116b565b6040516104b69190613fd9565b60405180910390f35b3480156104cb57600080fd5b506104e660048036038101906104e19190614466565b611182565b6040516104f39190613fa5565b60405180910390f35b34801561050857600080fd5b50610523600480360381019061051e91906141c7565b611199565b6040516105309190613fa5565b60405180910390f35b34801561054557600080fd5b50610560600480360381019061055b91906144c2565b6111b9565b005b34801561056e57600080fd5b506105776112c5565b6040516105849190614524565b60405180910390f35b34801561059957600080fd5b506105b460048036038101906105af9190614466565b6112cb565b6040516105c19190613fa5565b60405180910390f35b3480156105d657600080fd5b506105df6112e2565b6040516105ec9190614084565b60405180910390f35b34801561060157600080fd5b5061060a611415565b005b34801561061857600080fd5b50610621611566565b60405161062e9190614524565b60405180910390f35b34801561064357600080fd5b5061065e600480360381019061065991906144c2565b61156c565b005b34801561066c57600080fd5b50610687600480360381019061068291906140d2565b611678565b005b34801561069557600080fd5b506106b060048036038101906106ab9190614324565b6116fe565b005b3480156106be57600080fd5b506106c761178d565b6040516106d49190613fa5565b60405180910390f35b3480156106e957600080fd5b506106f26117a0565b6040516106ff9190614084565b60405180910390f35b34801561071457600080fd5b5061072f600480360381019061072a919061453f565b61182e565b005b34801561073d57600080fd5b50610758600480360381019061075391906140d2565b6118b4565b6040516107659190614140565b60405180910390f35b34801561077a57600080fd5b50610795600480360381019061079091906140d2565b6118ca565b005b3480156107a357600080fd5b506107be60048036038101906107b991906141c7565b611950565b6040516107cb9190613fd9565b60405180910390f35b3480156107e057600080fd5b506107e9611a1f565b005b3480156107f757600080fd5b50610812600480360381019061080d91906140d2565b611aa7565b005b34801561082057600080fd5b50610829611b2d565b6040516108369190614140565b60405180910390f35b34801561084b57600080fd5b50610866600480360381019061086191906140d2565b611b57565b6040516108739190614084565b60405180910390f35b34801561088857600080fd5b50610891611d28565b60405161089e9190614084565b60405180910390f35b6108c160048036038101906108bc91906140d2565b611dba565b005b3480156108cf57600080fd5b506108ea60048036038101906108e59190614324565b611ff4565b005b3480156108f857600080fd5b50610913600480360381019061090e9190614598565b612083565b005b34801561092157600080fd5b5061092a6121fa565b6040516109379190614084565b60405180910390f35b34801561094c57600080fd5b506109676004803603810190610962919061453f565b612288565b005b34801561097557600080fd5b50610990600480360381019061098b9190614679565b61230e565b005b34801561099e57600080fd5b506109b960048036038101906109b491906140d2565b61241c565b6040516109c69190614084565b60405180910390f35b6109e960048036038101906109e491906146fc565b612574565b005b3480156109f757600080fd5b50610a00612877565b604051610a0d9190613fd9565b60405180910390f35b348015610a2257600080fd5b50610a3d6004803603810190610a3891906141c7565b61287d565b604051610a4a9190613fd9565b60405180910390f35b348015610a5f57600080fd5b50610a7a6004803603810190610a75919061475c565b612895565b604051610a879190613fa5565b60405180910390f35b348015610a9c57600080fd5b50610ab76004803603810190610ab2919061479c565b612929565b005b348015610ac557600080fd5b50610ae06004803603810190610adb91906141c7565b612a5d565b005b348015610aee57600080fd5b50610af7612b54565b604051610b049190614084565b60405180910390f35b6001600081118015610b2157506015548111155b610b60576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b5790614828565b60405180910390fd5b60145481610b6c61116b565b610b769190614877565b1115610bb7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bae906148f7565b60405180910390fd5b600160175414610bfc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bf390614963565b60405180910390fd5b600d60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615610c89576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c80906149cf565b60405180910390fd5b6000610c93612be2565b604051602001610ca39190614a37565b604051602081830303815290604052805190602001209050610d09848480806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f82011690508083019250505050505050600b5483612bea565b610d48576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d3f90614a9e565b60405180910390fd5b6001600d60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550610db2610dab612be2565b6001612c01565b50505050565b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610e8357507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80610e935750610e9282612c1f565b5b9050919050565b600f5481565b606060028054610eaf90614aed565b80601f0160208091040260200160405190810160405280929190818152602001828054610edb90614aed565b8015610f285780601f10610efd57610100808354040283529160200191610f28565b820191906000526020600020905b815481529060010190602001808311610f0b57829003601f168201915b5050505050905090565b6000610f3d82612c89565b610f73576040517fcf4700e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6006600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000610fb9826118b4565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611020576040517f943f7b8c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1661103f612be2565b73ffffffffffffffffffffffffffffffffffffffff16146110a25761106b81611066612be2565b612895565b6110a1576040517fcfb3b94200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b6110ad838383612cd7565b505050565b600e6020528060005260406000206000915090505481565b60135481565b60155481565b6110de612be2565b73ffffffffffffffffffffffffffffffffffffffff166110fc611b2d565b73ffffffffffffffffffffffffffffffffffffffff1614611152576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161114990614b6a565b60405180910390fd5b80601190816111619190614d36565b5050565b60175481565b6000611175612d89565b6001546000540303905090565b600061119183600a5484612bea565b905092915050565b600d6020528060005260406000206000915054906101000a900460ff1681565b60006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b11156112b5576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430336040518363ffffffff1660e01b8152600401611230929190614e08565b6020604051808303816000875af115801561124f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112739190614e46565b6112b457336040517fede71dcc0000000000000000000000000000000000000000000000000000000081526004016112ab9190614140565b60405180910390fd5b5b6112c0838383612d92565b505050565b600a5481565b60006112da83600b5484612bea565b905092915050565b60606112ec612be2565b73ffffffffffffffffffffffffffffffffffffffff1661130a611b2d565b73ffffffffffffffffffffffffffffffffffffffff1614611360576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161135790614b6a565b60405180910390fd5b601660009054906101000a900460ff1615601660006101000a81548160ff021916908315150217905550601660009054906101000a900460ff166113d9576040518060400160405280600f81526020017f4e465473204172652048696464656e0000000000000000000000000000000000815250611410565b6040518060400160405280601181526020017f4e465473204172652052657665616c65640000000000000000000000000000008152505b905090565b61141d612be2565b73ffffffffffffffffffffffffffffffffffffffff1661143b611b2d565b73ffffffffffffffffffffffffffffffffffffffff1614611491576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161148890614b6a565b60405180910390fd5b6002600954036114d6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114cd90614ebf565b60405180910390fd5b600260098190555060006114e8611b2d565b73ffffffffffffffffffffffffffffffffffffffff164760405161150b90614f10565b60006040518083038185875af1925050503d8060008114611548576040519150601f19603f3d011682016040523d82523d6000602084013e61154d565b606091505b505090508061155b57600080fd5b506001600981905550565b600b5481565b60006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b1115611668576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430336040518363ffffffff1660e01b81526004016115e3929190614e08565b6020604051808303816000875af1158015611602573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116269190614e46565b61166757336040517fede71dcc00000000000000000000000000000000000000000000000000000000815260040161165e9190614140565b60405180910390fd5b5b611673838383612da2565b505050565b611680612be2565b73ffffffffffffffffffffffffffffffffffffffff1661169e611b2d565b73ffffffffffffffffffffffffffffffffffffffff16146116f4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116eb90614b6a565b60405180910390fd5b8060138190555050565b611706612be2565b73ffffffffffffffffffffffffffffffffffffffff16611724611b2d565b73ffffffffffffffffffffffffffffffffffffffff161461177a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161177190614b6a565b60405180910390fd5b80601290816117899190614d36565b5050565b601660009054906101000a900460ff1681565b601180546117ad90614aed565b80601f01602080910402602001604051908101604052809291908181526020018280546117d990614aed565b80156118265780601f106117fb57610100808354040283529160200191611826565b820191906000526020600020905b81548152906001019060200180831161180957829003601f168201915b505050505081565b611836612be2565b73ffffffffffffffffffffffffffffffffffffffff16611854611b2d565b73ffffffffffffffffffffffffffffffffffffffff16146118aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118a190614b6a565b60405180910390fd5b80600b8190555050565b60006118bf82612dc2565b600001519050919050565b6118d2612be2565b73ffffffffffffffffffffffffffffffffffffffff166118f0611b2d565b73ffffffffffffffffffffffffffffffffffffffff1614611946576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161193d90614b6a565b60405180910390fd5b8060158190555050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036119b7576040517f8f4eb60400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900467ffffffffffffffff1667ffffffffffffffff169050919050565b611a27612be2565b73ffffffffffffffffffffffffffffffffffffffff16611a45611b2d565b73ffffffffffffffffffffffffffffffffffffffff1614611a9b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a9290614b6a565b60405180910390fd5b611aa5600061304d565b565b611aaf612be2565b73ffffffffffffffffffffffffffffffffffffffff16611acd611b2d565b73ffffffffffffffffffffffffffffffffffffffff1614611b23576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b1a90614b6a565b60405180910390fd5b80600f8190555050565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6060611b61612be2565b73ffffffffffffffffffffffffffffffffffffffff16611b7f611b2d565b73ffffffffffffffffffffffffffffffffffffffff1614611bd5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bcc90614b6a565b60405180910390fd5b60048210611c18576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c0f90614f71565b60405180910390fd5b8160178190555060018214611cea5760028214611cae5760038214611c72576040518060400160405280601081526020017f4d696e74206e6f7420656e61626c656400000000000000000000000000000000815250611ca9565b6040518060400160405280601381526020017f5075626c6963206d696e7420656e61626c6564000000000000000000000000008152505b611ce5565b6040518060400160405280601681526020017f57686974656c697374206d696e7420656e61626c6564000000000000000000008152505b611d21565b6040518060400160405280600f81526020017f4f47206d696e7420656e61626c656400000000000000000000000000000000008152505b9050919050565b606060038054611d3790614aed565b80601f0160208091040260200160405190810160405280929190818152602001828054611d6390614aed565b8015611db05780601f10611d8557610100808354040283529160200191611db0565b820191906000526020600020905b815481529060010190602001808311611d9357829003601f168201915b5050505050905090565b80600081118015611dcd57506015548111155b611e0c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e0390614828565b60405180910390fd5b60145481611e1861116b565b611e229190614877565b1115611e63576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e5a906148f7565b60405180910390fd5b8180601354611e729190614f91565b341015611eb4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611eab9061501f565b60405180910390fd5b60155483600e60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054611f029190614877565b1115611f43576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f3a906150b1565b60405180910390fd5b600360175414611f88576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f7f9061511d565b60405180910390fd5b82600e60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254611fd79190614877565b92505081905550611fef611fe9612be2565b84612c01565b505050565b611ffc612be2565b73ffffffffffffffffffffffffffffffffffffffff1661201a611b2d565b73ffffffffffffffffffffffffffffffffffffffff1614612070576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161206790614b6a565b60405180910390fd5b806010908161207f9190614d36565b5050565b61208b612be2565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036120ef576040517fb06307db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600760006120fc612be2565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff166121a9612be2565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516121ee9190613fa5565b60405180910390a35050565b6012805461220790614aed565b80601f016020809104026020016040519081016040528092919081815260200182805461223390614aed565b80156122805780601f1061225557610100808354040283529160200191612280565b820191906000526020600020905b81548152906001019060200180831161226357829003601f168201915b505050505081565b612290612be2565b73ffffffffffffffffffffffffffffffffffffffff166122ae611b2d565b73ffffffffffffffffffffffffffffffffffffffff1614612304576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122fb90614b6a565b60405180910390fd5b80600a8190555050565b60006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b111561240a576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430336040518363ffffffff1660e01b8152600401612385929190614e08565b6020604051808303816000875af11580156123a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123c89190614e46565b61240957336040517fede71dcc0000000000000000000000000000000000000000000000000000000081526004016124009190614140565b60405180910390fd5b5b61241684848484613113565b50505050565b606061242782612c89565b612466576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161245d906151af565b60405180910390fd5b60001515601660009054906101000a900460ff16151503612513576012805461248e90614aed565b80601f01602080910402602001604051908101604052809291908181526020018280546124ba90614aed565b80156125075780601f106124dc57610100808354040283529160200191612507565b820191906000526020600020905b8154815290600101906020018083116124ea57829003601f168201915b5050505050905061256f565b600061251d61318b565b9050600081511161253d576040518060200160405280600081525061256b565b806125478461321d565b601160405160200161255b9392919061528e565b6040516020818303038152906040525b9150505b919050565b8260008111801561258757506015548111155b6125c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125bd90614828565b60405180910390fd5b601454816125d261116b565b6125dc9190614877565b111561261d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612614906148f7565b60405180910390fd5b838060135461262c9190614f91565b34101561266e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126659061501f565b60405180910390fd5b6002601754146126b3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126aa90615331565b60405180910390fd5b84600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054600f546127019190615351565b1015612742576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612739906150b1565b60405180910390fd5b600061274c612be2565b60405160200161275c9190614a37565b6040516020818303038152906040528051906020012090506127c2858580806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f82011690508083019250505050505050600a5483612bea565b612801576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127f890614a9e565b60405180910390fd5b85600c600061280e612be2565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546128579190614877565b9250508190555061286f612869612be2565b87612c01565b505050505050565b60145481565b600c6020528060005260406000206000915090505481565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b8160008111801561293c57506015548111155b61297b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161297290614828565b60405180910390fd5b6014548161298761116b565b6129919190614877565b11156129d2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129c9906148f7565b60405180910390fd5b6129da612be2565b73ffffffffffffffffffffffffffffffffffffffff166129f8611b2d565b73ffffffffffffffffffffffffffffffffffffffff1614612a4e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a4590614b6a565b60405180910390fd5b612a588284612c01565b505050565b612a65612be2565b73ffffffffffffffffffffffffffffffffffffffff16612a83611b2d565b73ffffffffffffffffffffffffffffffffffffffff1614612ad9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ad090614b6a565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612b48576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b3f906153f7565b60405180910390fd5b612b518161304d565b50565b60108054612b6190614aed565b80601f0160208091040260200160405190810160405280929190818152602001828054612b8d90614aed565b8015612bda5780601f10612baf57610100808354040283529160200191612bda565b820191906000526020600020905b815481529060010190602001808311612bbd57829003601f168201915b505050505081565b600033905090565b600082612bf7858461337d565b1490509392505050565b612c1b8282604051806020016040528060008152506133f2565b5050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b600081612c94612d89565b11158015612ca3575060005482105b8015612cd0575060046000838152602001908152602001600020600001601c9054906101000a900460ff16155b9050919050565b826006600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b60006001905090565b612d9d8383836137b2565b505050565b612dbd8383836040518060200160405280600081525061230e565b505050565b612dca613dfc565b600082905080612dd8612d89565b1161301657600054811015613015576000600460008381526020019081526020016000206040518060600160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160008201601c9054906101000a900460ff1615151515815250509050806040015161301357600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff1614612ef7578092505050613048565b5b60011561301257818060019003925050600460008381526020019081526020016000206040518060600160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160008201601c9054906101000a900460ff1615151515815250509050600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff161461300d578092505050613048565b612ef8565b5b505b5b6040517fdf2d9b4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b61311e8484846137b2565b61313d8373ffffffffffffffffffffffffffffffffffffffff16613c66565b156131855761314e84848484613c89565b613184576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b50505050565b60606010805461319a90614aed565b80601f01602080910402602001604051908101604052809291908181526020018280546131c690614aed565b80156132135780601f106131e857610100808354040283529160200191613213565b820191906000526020600020905b8154815290600101906020018083116131f657829003601f168201915b5050505050905090565b606060008203613264576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050613378565b600082905060005b6000821461329657808061327f90615417565b915050600a8261328f919061548e565b915061326c565b60008167ffffffffffffffff8111156132b2576132b16141f9565b5b6040519080825280601f01601f1916602001820160405280156132e45781602001600182028036833780820191505090505b5090505b60008514613371576001826132fd9190615351565b9150600a8561330c91906154bf565b60306133189190614877565b60f81b81838151811061332e5761332d6154f0565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a8561336a919061548e565b94506132e8565b8093505050505b919050565b60008082905060005b84518110156133e75760008582815181106133a4576133a36154f0565b5b602002602001015190508083116133c6576133bf8382613dd9565b92506133d3565b6133d08184613dd9565b92505b5080806133df90615417565b915050613386565b508091505092915050565b600080549050600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361345e576040517f2e07630000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008303613498576040517fb562e8dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6134a56000858386613df0565b82600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282829054906101000a900467ffffffffffffffff160192506101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555082600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160088282829054906101000a900467ffffffffffffffff160192506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550836004600083815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550426004600083815260200190815260200160002060000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506000819050600084820190506136668673ffffffffffffffffffffffffffffffffffffffff16613c66565b1561372b575b818673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46136db6000878480600101955087613c89565b613711576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80821061366c57826000541461372657600080fd5b613796565b5b818060010192508673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a480821061372c575b8160008190555050506137ac6000858386613df6565b50505050565b60006137bd82612dc2565b90508373ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff1614613828576040517fa114810000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008473ffffffffffffffffffffffffffffffffffffffff16613849612be2565b73ffffffffffffffffffffffffffffffffffffffff161480613878575061387785613872612be2565b612895565b5b806138bd5750613886612be2565b73ffffffffffffffffffffffffffffffffffffffff166138a584610f32565b73ffffffffffffffffffffffffffffffffffffffff16145b9050806138f6576040517f59c896be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361395c576040517fea553b3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6139698585856001613df0565b61397560008487612cd7565b6001600560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282829054906101000a900467ffffffffffffffff160392506101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506001600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282829054906101000a900467ffffffffffffffff160192506101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506000600460008581526020019081526020016000209050848160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550428160000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555060006001850190506000600460008381526020019081526020016000209050600073ffffffffffffffffffffffffffffffffffffffff168160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1603613bf4576000548214613bf357878160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555084602001518160000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505b5b505050828473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4613c5f8585856001613df6565b5050505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b60008373ffffffffffffffffffffffffffffffffffffffff1663150b7a02613caf612be2565b8786866040518563ffffffff1660e01b8152600401613cd19493929190615574565b6020604051808303816000875af1925050508015613d0d57506040513d601f19601f82011682018060405250810190613d0a91906155d5565b60015b613d86573d8060008114613d3d576040519150601f19603f3d011682016040523d82523d6000602084013e613d42565b606091505b506000815103613d7e576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050949350505050565b600082600052816020526040600020905092915050565b50505050565b50505050565b6040518060600160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600067ffffffffffffffff1681526020016000151581525090565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b60008083601f840112613e7857613e77613e53565b5b8235905067ffffffffffffffff811115613e9557613e94613e58565b5b602083019150836020820283011115613eb157613eb0613e5d565b5b9250929050565b60008060208385031215613ecf57613ece613e49565b5b600083013567ffffffffffffffff811115613eed57613eec613e4e565b5b613ef985828601613e62565b92509250509250929050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b613f3a81613f05565b8114613f4557600080fd5b50565b600081359050613f5781613f31565b92915050565b600060208284031215613f7357613f72613e49565b5b6000613f8184828501613f48565b91505092915050565b60008115159050919050565b613f9f81613f8a565b82525050565b6000602082019050613fba6000830184613f96565b92915050565b6000819050919050565b613fd381613fc0565b82525050565b6000602082019050613fee6000830184613fca565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561402e578082015181840152602081019050614013565b60008484015250505050565b6000601f19601f8301169050919050565b600061405682613ff4565b6140608185613fff565b9350614070818560208601614010565b6140798161403a565b840191505092915050565b6000602082019050818103600083015261409e818461404b565b905092915050565b6140af81613fc0565b81146140ba57600080fd5b50565b6000813590506140cc816140a6565b92915050565b6000602082840312156140e8576140e7613e49565b5b60006140f6848285016140bd565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061412a826140ff565b9050919050565b61413a8161411f565b82525050565b60006020820190506141556000830184614131565b92915050565b6141648161411f565b811461416f57600080fd5b50565b6000813590506141818161415b565b92915050565b6000806040838503121561419e5761419d613e49565b5b60006141ac85828601614172565b92505060206141bd858286016140bd565b9150509250929050565b6000602082840312156141dd576141dc613e49565b5b60006141eb84828501614172565b91505092915050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6142318261403a565b810181811067ffffffffffffffff821117156142505761424f6141f9565b5b80604052505050565b6000614263613e3f565b905061426f8282614228565b919050565b600067ffffffffffffffff82111561428f5761428e6141f9565b5b6142988261403a565b9050602081019050919050565b82818337600083830152505050565b60006142c76142c284614274565b614259565b9050828152602081018484840111156142e3576142e26141f4565b5b6142ee8482856142a5565b509392505050565b600082601f83011261430b5761430a613e53565b5b813561431b8482602086016142b4565b91505092915050565b60006020828403121561433a57614339613e49565b5b600082013567ffffffffffffffff81111561435857614357613e4e565b5b614364848285016142f6565b91505092915050565b600067ffffffffffffffff821115614388576143876141f9565b5b602082029050602081019050919050565b6000819050919050565b6143ac81614399565b81146143b757600080fd5b50565b6000813590506143c9816143a3565b92915050565b60006143e26143dd8461436d565b614259565b9050808382526020820190506020840283018581111561440557614404613e5d565b5b835b8181101561442e578061441a88826143ba565b845260208401935050602081019050614407565b5050509392505050565b600082601f83011261444d5761444c613e53565b5b813561445d8482602086016143cf565b91505092915050565b6000806040838503121561447d5761447c613e49565b5b600083013567ffffffffffffffff81111561449b5761449a613e4e565b5b6144a785828601614438565b92505060206144b8858286016143ba565b9150509250929050565b6000806000606084860312156144db576144da613e49565b5b60006144e986828701614172565b93505060206144fa86828701614172565b925050604061450b868287016140bd565b9150509250925092565b61451e81614399565b82525050565b60006020820190506145396000830184614515565b92915050565b60006020828403121561455557614554613e49565b5b6000614563848285016143ba565b91505092915050565b61457581613f8a565b811461458057600080fd5b50565b6000813590506145928161456c565b92915050565b600080604083850312156145af576145ae613e49565b5b60006145bd85828601614172565b92505060206145ce85828601614583565b9150509250929050565b600067ffffffffffffffff8211156145f3576145f26141f9565b5b6145fc8261403a565b9050602081019050919050565b600061461c614617846145d8565b614259565b905082815260208101848484011115614638576146376141f4565b5b6146438482856142a5565b509392505050565b600082601f8301126146605761465f613e53565b5b8135614670848260208601614609565b91505092915050565b6000806000806080858703121561469357614692613e49565b5b60006146a187828801614172565b94505060206146b287828801614172565b93505060406146c3878288016140bd565b925050606085013567ffffffffffffffff8111156146e4576146e3613e4e565b5b6146f08782880161464b565b91505092959194509250565b60008060006040848603121561471557614714613e49565b5b6000614723868287016140bd565b935050602084013567ffffffffffffffff81111561474457614743613e4e565b5b61475086828701613e62565b92509250509250925092565b6000806040838503121561477357614772613e49565b5b600061478185828601614172565b925050602061479285828601614172565b9150509250929050565b600080604083850312156147b3576147b2613e49565b5b60006147c1858286016140bd565b92505060206147d285828601614172565b9150509250929050565b7f496e76616c6964206d696e7420616d6f756e7421000000000000000000000000600082015250565b6000614812601483613fff565b915061481d826147dc565b602082019050919050565b6000602082019050818103600083015261484181614805565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061488282613fc0565b915061488d83613fc0565b92508282019050808211156148a5576148a4614848565b5b92915050565b7f4d617820737570706c7920657863656564656421000000000000000000000000600082015250565b60006148e1601483613fff565b91506148ec826148ab565b602082019050919050565b60006020820190508181036000830152614910816148d4565b9050919050565b7f4f47204d696e74205068617365206973204e6f74204163746976650000000000600082015250565b600061494d601b83613fff565b915061495882614917565b602082019050919050565b6000602082019050818103600083015261497c81614940565b9050919050565b7f4f47204d696e7420416c726561647920436c61696d6564000000000000000000600082015250565b60006149b9601783613fff565b91506149c482614983565b602082019050919050565b600060208201905081810360008301526149e8816149ac565b9050919050565b60008160601b9050919050565b6000614a07826149ef565b9050919050565b6000614a19826149fc565b9050919050565b614a31614a2c8261411f565b614a0e565b82525050565b6000614a438284614a20565b60148201915081905092915050565b7f496e76616c69642070726f6f6621000000000000000000000000000000000000600082015250565b6000614a88600e83613fff565b9150614a9382614a52565b602082019050919050565b60006020820190508181036000830152614ab781614a7b565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680614b0557607f821691505b602082108103614b1857614b17614abe565b5b50919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000614b54602083613fff565b9150614b5f82614b1e565b602082019050919050565b60006020820190508181036000830152614b8381614b47565b9050919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302614bec7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82614baf565b614bf68683614baf565b95508019841693508086168417925050509392505050565b6000819050919050565b6000614c33614c2e614c2984613fc0565b614c0e565b613fc0565b9050919050565b6000819050919050565b614c4d83614c18565b614c61614c5982614c3a565b848454614bbc565b825550505050565b600090565b614c76614c69565b614c81818484614c44565b505050565b5b81811015614ca557614c9a600082614c6e565b600181019050614c87565b5050565b601f821115614cea57614cbb81614b8a565b614cc484614b9f565b81016020851015614cd3578190505b614ce7614cdf85614b9f565b830182614c86565b50505b505050565b600082821c905092915050565b6000614d0d60001984600802614cef565b1980831691505092915050565b6000614d268383614cfc565b9150826002028217905092915050565b614d3f82613ff4565b67ffffffffffffffff811115614d5857614d576141f9565b5b614d628254614aed565b614d6d828285614ca9565b600060209050601f831160018114614da05760008415614d8e578287015190505b614d988582614d1a565b865550614e00565b601f198416614dae86614b8a565b60005b82811015614dd657848901518255600182019150602085019450602081019050614db1565b86831015614df35784890151614def601f891682614cfc565b8355505b6001600288020188555050505b505050505050565b6000604082019050614e1d6000830185614131565b614e2a6020830184614131565b9392505050565b600081519050614e408161456c565b92915050565b600060208284031215614e5c57614e5b613e49565b5b6000614e6a84828501614e31565b91505092915050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b6000614ea9601f83613fff565b9150614eb482614e73565b602082019050919050565b60006020820190508181036000830152614ed881614e9c565b9050919050565b600081905092915050565b50565b6000614efa600083614edf565b9150614f0582614eea565b600082019050919050565b6000614f1b82614eed565b9150819050919050565b7f496e76616c696420706861736500000000000000000000000000000000000000600082015250565b6000614f5b600d83613fff565b9150614f6682614f25565b602082019050919050565b60006020820190508181036000830152614f8a81614f4e565b9050919050565b6000614f9c82613fc0565b9150614fa783613fc0565b9250828202614fb581613fc0565b91508282048414831517614fcc57614fcb614848565b5b5092915050565b7f496e73756666696369656e742066756e64732100000000000000000000000000600082015250565b6000615009601383613fff565b915061501482614fd3565b602082019050919050565b6000602082019050818103600083015261503881614ffc565b9050919050565b7f596f752068617665206d696e746564206d6178696d756d20616c6c6f7765642060008201527f6e667473206f722074727920746f206d696e74206c6573730000000000000000602082015250565b600061509b603883613fff565b91506150a68261503f565b604082019050919050565b600060208201905081810360008301526150ca8161508e565b9050919050565b7f5075626c6963204d696e74205068617365206973204e6f742041637469766500600082015250565b6000615107601f83613fff565b9150615112826150d1565b602082019050919050565b60006020820190508181036000830152615136816150fa565b9050919050565b7f4552433732314d657461646174613a2055524920717565727920666f72206e6f60008201527f6e6578697374656e7420746f6b656e0000000000000000000000000000000000602082015250565b6000615199602f83613fff565b91506151a48261513d565b604082019050919050565b600060208201905081810360008301526151c88161518c565b9050919050565b600081905092915050565b60006151e582613ff4565b6151ef81856151cf565b93506151ff818560208601614010565b80840191505092915050565b6000815461521881614aed565b61522281866151cf565b9450600182166000811461523d576001811461525257615285565b60ff1983168652811515820286019350615285565b61525b85614b8a565b60005b8381101561527d5781548189015260018201915060208101905061525e565b838801955050505b50505092915050565b600061529a82866151da565b91506152a682856151da565b91506152b2828461520b565b9150819050949350505050565b7f57686974656c697374204d696e74205068617365206973204e6f74204163746960008201527f7665000000000000000000000000000000000000000000000000000000000000602082015250565b600061531b602283613fff565b9150615326826152bf565b604082019050919050565b6000602082019050818103600083015261534a8161530e565b9050919050565b600061535c82613fc0565b915061536783613fc0565b925082820390508181111561537f5761537e614848565b5b92915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b60006153e1602683613fff565b91506153ec82615385565b604082019050919050565b60006020820190508181036000830152615410816153d4565b9050919050565b600061542282613fc0565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361545457615453614848565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061549982613fc0565b91506154a483613fc0565b9250826154b4576154b361545f565b5b828204905092915050565b60006154ca82613fc0565b91506154d583613fc0565b9250826154e5576154e461545f565b5b828206905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600081519050919050565b600082825260208201905092915050565b60006155468261551f565b615550818561552a565b9350615560818560208601614010565b6155698161403a565b840191505092915050565b60006080820190506155896000830187614131565b6155966020830186614131565b6155a36040830185613fca565b81810360608301526155b5818461553b565b905095945050505050565b6000815190506155cf81613f31565b92915050565b6000602082840312156155eb576155ea613e49565b5b60006155f9848285016155c0565b9150509291505056fea2646970667358221220add2e9a9a9ecc75fccfddbb931297fe37b95c09a75f5e424258811881bc14a4764736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000000000000000000058d15e17628000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000138800000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000002468747470733a2f2f697066732e6d6f76696e6672656e732e636f6d2f756e72657665616c00000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _cost (uint256): 25000000000000000
Arg [1] : _MaxPerTxn (uint256): 10
Arg [2] : _MaxPerUser (uint256): 5
Arg [3] : _maxSupply (uint256): 5000
Arg [4] : _uri (string): https://ipfs.movinfrens.com/unreveal
-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000058d15e17628000
Arg [1] : 000000000000000000000000000000000000000000000000000000000000000a
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000005
Arg [3] : 0000000000000000000000000000000000000000000000000000000000001388
Arg [4] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000024
Arg [6] : 68747470733a2f2f697066732e6d6f76696e6672656e732e636f6d2f756e7265
Arg [7] : 7665616c00000000000000000000000000000000000000000000000000000000
Deployed Bytecode Sourcemap
259:6669:15:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2233:430;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;2986:305:4;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;599:25:15;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;6101:100:4;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;7605:204;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;7167:372;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;547:47:15;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;742:19;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;795:30;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;4618:100;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;867:24;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2226:312:4;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;5398:153:15;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;501:41;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;6286:191;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;381:25;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;5559:155;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;4208:156;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;5750:480;;;;;;;;;;;;;:::i;:::-;;411:27;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;6485:199;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;3440:91;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;4370:132;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;832:28;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;664:33;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;4959:88;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;5909:125:4;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3537:97:15;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;3355:206:4;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1714:103:19;;;;;;;;;;;;;:::i;:::-;;3640:90:15;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;1063:87:19;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;5072:286:15;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;6270:104:4;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2669:457:15;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;4508:104;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;7881:287:4;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;702:31:15;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;4859:94;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;6692:233;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;3757:445;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1625:600;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;766:24;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;445:51;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;8239:164:4;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3134:155:15;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;1972:201:19;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;629:30:15;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2233:430;2312:1;1312;1298:11;:15;:49;;;;;1332:15;;1317:11;:30;;1298:49;1290:82;;;;;;;;;;;;:::i;:::-;;;;;;;;;1418:9;;1403:11;1387:13;:11;:13::i;:::-;:27;;;;:::i;:::-;:40;;1379:73;;;;;;;;;;;;:::i;:::-;;;;;;;;;2344:1:::1;2331:9;;:14;2323:53;;;;;;;;;;;;:::i;:::-;;;;;;;;;2392:9;:21;2402:10;2392:21;;;;;;;;;;;;;;;;;;;;;;;;;2391:22;2383:57;;;;;;;;;;;;:::i;:::-;;;;;;;;;2447:12;2489;:10;:12::i;:::-;2472:30;;;;;;;;:::i;:::-;;;;;;;;;;;;;2462:41;;;;;;2447:56;;2518:52;2537:12;;2518:52;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2551:12;;2565:4;2518:18;:52::i;:::-;2510:79;;;;;;;;;;;;:::i;:::-;;;;;;;;;2620:4;2596:9;:21;2606:10;2596:21;;;;;;;;;;;;;;;;:28;;;;;;;;;;;;;;;;;;2631:26;2641:12;:10;:12::i;:::-;2655:1;2631:9;:26::i;:::-;2315:348;2233:430:::0;;;:::o;2986:305:4:-;3088:4;3140:25;3125:40;;;:11;:40;;;;:105;;;;3197:33;3182:48;;;:11;:48;;;;3125:105;:158;;;;3247:36;3271:11;3247:23;:36::i;:::-;3125:158;3105:178;;2986:305;;;:::o;599:25:15:-;;;;:::o;6101:100:4:-;6155:13;6188:5;6181:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6101:100;:::o;7605:204::-;7673:7;7698:16;7706:7;7698;:16::i;:::-;7693:64;;7723:34;;;;;;;;;;;;;;7693:64;7777:15;:24;7793:7;7777:24;;;;;;;;;;;;;;;;;;;;;7770:31;;7605:204;;;:::o;7167:372::-;7240:13;7256:24;7272:7;7256:15;:24::i;:::-;7240:40;;7301:5;7295:11;;:2;:11;;;7291:48;;7315:24;;;;;;;;;;;;;;7291:48;7372:5;7356:21;;:12;:10;:12::i;:::-;:21;;;7352:139;;7383:37;7400:5;7407:12;:10;:12::i;:::-;7383:16;:37::i;:::-;7379:112;;7444:35;;;;;;;;;;;;;;7379:112;7352:139;7503:28;7512:2;7516:7;7525:5;7503:8;:28::i;:::-;7229:310;7167:372;;:::o;547:47:15:-;;;;;;;;;;;;;;;;;:::o;742:19::-;;;;:::o;795:30::-;;;;:::o;4618:100::-;1294:12:19;:10;:12::i;:::-;1283:23;;:7;:5;:7::i;:::-;:23;;;1275:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;4702:10:15::1;4690:9;:22;;;;;;:::i;:::-;;4618:100:::0;:::o;867:24::-;;;;:::o;2226:312:4:-;2279:7;2504:15;:13;:15::i;:::-;2489:12;;2473:13;;:28;:46;2466:53;;2226:312;:::o;5398:153:15:-;5476:4;5500:43;5519:5;5526:10;;5538:4;5500:18;:43::i;:::-;5493:50;;5398:153;;;;:::o;501:41::-;;;;;;;;;;;;;;;;;;;;;;:::o;6286:191::-;1484:1:18;310:42;1438:43;;;:47;1434:225;;;310:42;1507:40;;;1556:4;1563:10;1507:67;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1502:146;;1621:10;1602:30;;;;;;;;;;;:::i;:::-;;;;;;;;1502:146;1434:225;6432:37:15::1;6451:4;6457:2;6461:7;6432:18;:37::i;:::-;6286:191:::0;;;:::o;381:25::-;;;;:::o;5559:155::-;5637:4;5661:45;5680:5;5687:12;;5701:4;5661:18;:45::i;:::-;5654:52;;5559:155;;;;:::o;4208:156::-;4256:13;1294:12:19;:10;:12::i;:::-;1283:23;;:7;:5;:7::i;:::-;:23;;;1275:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;4290:8:15::1;;;;;;;;;;;4289:9;4278:8;;:20;;;;;;;;;;;;;;;;;;4312:8;;;;;;;;;;;:46;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;4305:53;;4208:156:::0;:::o;5750:480::-;1294:12:19;:10;:12::i;:::-;1283:23;;:7;:5;:7::i;:::-;:23;;;1275:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;1778:1:22::1;2376:7;;:19:::0;2368:63:::1;;;;;;;;;;;;:::i;:::-;;;;;;;;;1778:1;2509:7;:18;;;;6052:7:15::2;6073;:5;:7::i;:::-;6065:21;;6094;6065:55;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6051:69;;;6135:2;6127:11;;;::::0;::::2;;5800:430;1734:1:22::1;2688:7;:22;;;;5750:480:15:o:0;411:27::-;;;;:::o;6485:199::-;1484:1:18;310:42;1438:43;;;:47;1434:225;;;310:42;1507:40;;;1556:4;1563:10;1507:67;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1502:146;;1621:10;1602:30;;;;;;;;;;;:::i;:::-;;;;;;;;1502:146;1434:225;6635:41:15::1;6658:4;6664:2;6668:7;6635:22;:41::i;:::-;6485:199:::0;;;:::o;3440:91::-;1294:12:19;:10;:12::i;:::-;1283:23;;:7;:5;:7::i;:::-;:23;;;1275:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;3520:5:15::1;3513:4;:12;;;;3440:91:::0;:::o;4370:132::-;1294:12:19;:10;:12::i;:::-;1283:23;;:7;:5;:7::i;:::-;:23;;;1275:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;4478:18:15::1;4458:17;:38;;;;;;:::i;:::-;;4370:132:::0;:::o;832:28::-;;;;;;;;;;;;;:::o;664:33::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;4959:88::-;1294:12:19;:10;:12::i;:::-;1283:23;;:7;:5;:7::i;:::-;:23;;;1275:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;5034:7:15::1;5019:12;:22;;;;4959:88:::0;:::o;5909:125:4:-;5973:7;6000:21;6013:7;6000:12;:21::i;:::-;:26;;;5993:33;;5909:125;;;:::o;3537:97:15:-;1294:12:19;:10;:12::i;:::-;1283:23;;:7;:5;:7::i;:::-;:23;;;1275:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;3621:7:15::1;3603:15;:25;;;;3537:97:::0;:::o;3355:206:4:-;3419:7;3460:1;3443:19;;:5;:19;;;3439:60;;3471:28;;;;;;;;;;;;;;3439:60;3525:12;:19;3538:5;3525:19;;;;;;;;;;;;;;;:27;;;;;;;;;;;;3517:36;;3510:43;;3355:206;;;:::o;1714:103:19:-;1294:12;:10;:12::i;:::-;1283:23;;:7;:5;:7::i;:::-;:23;;;1275:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;1779:30:::1;1806:1;1779:18;:30::i;:::-;1714:103::o:0;3640:90:15:-;1294:12:19;:10;:12::i;:::-;1283:23;;:7;:5;:7::i;:::-;:23;;;1275:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;3717:7:15::1;3704:10;:20;;;;3640:90:::0;:::o;1063:87:19:-;1109:7;1136:6;;;;;;;;;;;1129:13;;1063:87;:::o;5072:286:15:-;5135:13;1294:12:19;:10;:12::i;:::-;1283:23;;:7;:5;:7::i;:::-;:23;;;1275:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;5174:1:15::1;5165:6;:10;5157:36;;;;;;;;;;;;:::i;:::-;;;;;;;;;5212:6;5200:9;:18;;;;5242:1;5232:6;:11;:119;;5272:1;5262:6;:11;:89;;5309:1;5299:6;:11;:52;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;5262:89;;;;;;;;;;;;;;;;;;;::::0;::::1;5232:119;;;;;;;;;;;;;;;;;;;::::0;::::1;5225:127;;5072:286:::0;;;:::o;6270:104:4:-;6326:13;6359:7;6352:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6270:104;:::o;2669:457:15:-;2734:11;1312:1;1298:11;:15;:49;;;;;1332:15;;1317:11;:30;;1298:49;1290:82;;;;;;;;;;;;:::i;:::-;;;;;;;;;1418:9;;1403:11;1387:13;:11;:13::i;:::-;:27;;;;:::i;:::-;:40;;1379:73;;;;;;;;;;;;:::i;:::-;;;;;;;;;2767:11:::1;1557;1550:4;;:18;;;;:::i;:::-;1537:9;:31;;1529:63;;;;;;;;;;;;:::i;:::-;;;;;;;;;2892:15:::2;;2879:11;2854:12;:24;2867:10;2854:24;;;;;;;;;;;;;;;;:36;;;;:::i;:::-;:53;;2846:121;;;;;;;;;;;;:::i;:::-;;;;;;;;;2995:1;2982:9;;:14;2974:57;;;;;;;;;;;;:::i;:::-;;;;;;;;;3066:11;3038:12;:24;3051:10;3038:24;;;;;;;;;;;;;;;;:39;;;;;;;:::i;:::-;;;;;;;;3084:36;3094:12;:10;:12::i;:::-;3108:11;3084:9;:36::i;:::-;1459:1:::1;2669:457:::0;;:::o;4508:104::-;1294:12:19;:10;:12::i;:::-;1283:23;;:7;:5;:7::i;:::-;:23;;;1275:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;4594:12:15::1;4580:11;:26;;;;;;:::i;:::-;;4508:104:::0;:::o;7881:287:4:-;7992:12;:10;:12::i;:::-;7980:24;;:8;:24;;;7976:54;;8013:17;;;;;;;;;;;;;;7976:54;8088:8;8043:18;:32;8062:12;:10;:12::i;:::-;8043:32;;;;;;;;;;;;;;;:42;8076:8;8043:42;;;;;;;;;;;;;;;;:53;;;;;;;;;;;;;;;;;;8141:8;8112:48;;8127:12;:10;:12::i;:::-;8112:48;;;8151:8;8112:48;;;;;;:::i;:::-;;;;;;;;7881:287;;:::o;702:31:15:-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;4859:94::-;1294:12:19;:10;:12::i;:::-;1283:23;;:7;:5;:7::i;:::-;:23;;;1275:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;4936:11:15::1;4923:10;:24;;;;4859:94:::0;:::o;6692:233::-;1484:1:18;310:42;1438:43;;;:47;1434:225;;;310:42;1507:40;;;1556:4;1563:10;1507:67;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1502:146;;1621:10;1602:30;;;;;;;;;;;:::i;:::-;;;;;;;;1502:146;1434:225;6870:47:15::1;6893:4;6899:2;6903:7;6912:4;6870:22;:47::i;:::-;6692:233:::0;;;;:::o;3757:445::-;3831:13;3861:17;3869:8;3861:7;:17::i;:::-;3853:77;;;;;;;;;;;;:::i;:::-;;;;;;;;;3955:5;3943:17;;:8;;;;;;;;;;;:17;;;3939:64;;3978:17;3971:24;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3939:64;4011:28;4042:10;:8;:10::i;:::-;4011:41;;4097:1;4072:14;4066:28;:32;:130;;;;;;;;;;;;;;;;;4134:14;4150:19;:8;:17;:19::i;:::-;4171:9;4117:64;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;4066:130;4059:137;;;3757:445;;;;:::o;1625:600::-;1732:11;1312:1;1298:11;:15;:49;;;;;1332:15;;1317:11;:30;;1298:49;1290:82;;;;;;;;;;;;:::i;:::-;;;;;;;;;1418:9;;1403:11;1387:13;:11;:13::i;:::-;:27;;;;:::i;:::-;:40;;1379:73;;;;;;;;;;;;:::i;:::-;;;;;;;;;1765:11:::1;1557;1550:4;;:18;;;;:::i;:::-;1537:9;:31;;1529:63;;;;;;;;;;;;:::i;:::-;;;;;;;;;1807:1:::2;1794:9;;:14;1786:60;;;;;;;;;;;;:::i;:::-;;;;;;;;;1904:11;1873:16;:28;1890:10;1873:28;;;;;;;;;;;;;;;;1862:10;;:39;;;;:::i;:::-;1861:54;;1853:122;;;;;;;;;;;;:::i;:::-;;;;;;;;;1982:12;2024;:10;:12::i;:::-;2007:30;;;;;;;;:::i;:::-;;;;;;;;;;;;;1997:41;;;;;;1982:56;;2053:50;2072:12;;2053:50;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2086:10;;2098:4;2053:18;:50::i;:::-;2045:77;;;;;;;;;;;;:::i;:::-;;;;;;;;;2165:11;2131:16;:30;2148:12;:10;:12::i;:::-;2131:30;;;;;;;;;;;;;;;;:45;;;;;;;:::i;:::-;;;;;;;;2183:36;2193:12;:10;:12::i;:::-;2207:11;2183:9;:36::i;:::-;1778:447;1459:1:::1;1625:600:::0;;;;:::o;766:24::-;;;;:::o;445:51::-;;;;;;;;;;;;;;;;;:::o;8239:164:4:-;8336:4;8360:18;:25;8379:5;8360:25;;;;;;;;;;;;;;;:35;8386:8;8360:35;;;;;;;;;;;;;;;;;;;;;;;;;8353:42;;8239:164;;;;:::o;3134:155:15:-;3220:11;1312:1;1298:11;:15;:49;;;;;1332:15;;1317:11;:30;;1298:49;1290:82;;;;;;;;;;;;:::i;:::-;;;;;;;;;1418:9;;1403:11;1387:13;:11;:13::i;:::-;:27;;;;:::i;:::-;:40;;1379:73;;;;;;;;;;;;:::i;:::-;;;;;;;;;1294:12:19::1;:10;:12::i;:::-;1283:23;;:7;:5;:7::i;:::-;:23;;;1275:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;3250:33:15::2;3260:9;3271:11;3250:9;:33::i;:::-;3134:155:::0;;;:::o;1972:201:19:-;1294:12;:10;:12::i;:::-;1283:23;;:7;:5;:7::i;:::-;:23;;;1275:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;2081:1:::1;2061:22;;:8;:22;;::::0;2053:73:::1;;;;;;;;;;;;:::i;:::-;;;;;;;;;2137:28;2156:8;2137:18;:28::i;:::-;1972:201:::0;:::o;629:30:15:-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;656:98:1:-;709:7;736:10;729:17;;656:98;:::o;883:190:14:-;1008:4;1061;1032:25;1045:5;1052:4;1032:12;:25::i;:::-;:33;1025:40;;883:190;;;;;:::o;9850:104:4:-;9919:27;9929:2;9933:8;9919:27;;;;;;;;;;;;:9;:27::i;:::-;9850:104;;:::o;854:157:3:-;939:4;978:25;963:40;;;:11;:40;;;;956:47;;854:157;;;:::o;9592:174:4:-;9649:4;9692:7;9673:15;:13;:15::i;:::-;:26;;:53;;;;;9713:13;;9703:7;:23;9673:53;:85;;;;;9731:11;:20;9743:7;9731:20;;;;;;;;;;;:27;;;;;;;;;;;;9730:28;9673:85;9666:92;;9592:174;;;:::o;18814:196::-;18956:2;18929:15;:24;18945:7;18929:24;;;;;;;;;;;;:29;;;;;;;;;;;;;;;;;;18994:7;18990:2;18974:28;;18983:5;18974:28;;;;;;;;;;;;18814:196;;;:::o;3309:95:15:-;3374:7;3397:1;3390:8;;3309:95;:::o;8470:170:4:-;8604:28;8614:4;8620:2;8624:7;8604:9;:28::i;:::-;8470:170;;;:::o;8711:185::-;8849:39;8866:4;8872:2;8876:7;8849:39;;;;;;;;;;;;:16;:39::i;:::-;8711:185;;;:::o;4736:1111::-;4798:21;;:::i;:::-;4832:12;4847:7;4832:22;;4915:4;4896:15;:13;:15::i;:::-;:23;4892:888;;4932:13;;4925:4;:20;4921:859;;;4966:31;5000:11;:17;5012:4;5000:17;;;;;;;;;;;4966:51;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5041:9;:16;;;5036:729;;5112:1;5086:28;;:9;:14;;;:28;;;5082:101;;5150:9;5143:16;;;;;;5082:101;5485:261;5492:4;5485:261;;;5525:6;;;;;;;;5570:11;:17;5582:4;5570:17;;;;;;;;;;;5558:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5644:1;5618:28;;:9;:14;;;:28;;;5614:109;;5686:9;5679:16;;;;;;5614:109;5485:261;;;5036:729;4947:833;4921:859;4892:888;5808:31;;;;;;;;;;;;;;4736:1111;;;;:::o;2333:191:19:-;2407:16;2426:6;;;;;;;;;;;2407:25;;2452:8;2443:6;;:17;;;;;;;;;;;;;;;;;;2507:8;2476:40;;2497:8;2476:40;;;;;;;;;;;;2396:128;2333:191;:::o;8967:370:4:-;9134:28;9144:4;9150:2;9154:7;9134:9;:28::i;:::-;9177:15;:2;:13;;;:15::i;:::-;9173:157;;;9198:56;9229:4;9235:2;9239:7;9248:5;9198:30;:56::i;:::-;9194:136;;9278:40;;;;;;;;;;;;;;9194:136;9173:157;8967:370;;;;:::o;4724:106:15:-;4784:13;4813:11;4806:18;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4724:106;:::o;342:723:23:-;398:13;628:1;619:5;:10;615:53;;646:10;;;;;;;;;;;;;;;;;;;;;615:53;678:12;693:5;678:20;;709:14;734:78;749:1;741:4;:9;734:78;;767:8;;;;;:::i;:::-;;;;798:2;790:10;;;;;:::i;:::-;;;734:78;;;822:19;854:6;844:17;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;822:39;;872:154;888:1;879:5;:10;872:154;;916:1;906:11;;;;;:::i;:::-;;;983:2;975:5;:10;;;;:::i;:::-;962:2;:24;;;;:::i;:::-;949:39;;932:6;939;932:14;;;;;;;;:::i;:::-;;;;;:56;;;;;;;;;;;1012:2;1003:11;;;;;:::i;:::-;;;872:154;;;1050:6;1036:21;;;;;342:723;;;;:::o;1435:675:14:-;1518:7;1538:20;1561:4;1538:27;;1581:9;1576:497;1600:5;:12;1596:1;:16;1576:497;;;1634:20;1657:5;1663:1;1657:8;;;;;;;;:::i;:::-;;;;;;;;1634:31;;1700:12;1684;:28;1680:382;;1827:42;1842:12;1856;1827:14;:42::i;:::-;1812:57;;1680:382;;;2004:42;2019:12;2033;2004:14;:42::i;:::-;1989:57;;1680:382;1619:454;1614:3;;;;;:::i;:::-;;;;1576:497;;;;2090:12;2083:19;;;1435:675;;;;:::o;10327:1749:4:-;10450:20;10473:13;;10450:36;;10515:1;10501:16;;:2;:16;;;10497:48;;10526:19;;;;;;;;;;;;;;10497:48;10572:1;10560:8;:13;10556:44;;10582:18;;;;;;;;;;;;;;10556:44;10613:61;10643:1;10647:2;10651:12;10665:8;10613:21;:61::i;:::-;10986:8;10951:12;:16;10964:2;10951:16;;;;;;;;;;;;;;;:24;;;:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11050:8;11010:12;:16;11023:2;11010:16;;;;;;;;;;;;;;;:29;;;:49;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11109:2;11076:11;:25;11088:12;11076:25;;;;;;;;;;;:30;;;:35;;;;;;;;;;;;;;;;;;11176:15;11126:11;:25;11138:12;11126:25;;;;;;;;;;;:40;;;:66;;;;;;;;;;;;;;;;;;11209:20;11232:12;11209:35;;11259:11;11288:8;11273:12;:23;11259:37;;11317:15;:2;:13;;;:15::i;:::-;11313:631;;;11353:313;11409:12;11405:2;11384:38;;11401:1;11384:38;;;;;;;;;;;;11450:69;11489:1;11493:2;11497:14;;;;;;11513:5;11450:30;:69::i;:::-;11445:174;;11555:40;;;;;;;;;;;;;;11445:174;11661:3;11646:12;:18;11353:313;;11747:12;11730:13;;:29;11726:43;;11761:8;;;11726:43;11313:631;;;11810:119;11866:14;;;;;;11862:2;11841:40;;11858:1;11841:40;;;;;;;;;;;;11924:3;11909:12;:18;11810:119;;11313:631;11974:12;11958:13;:28;;;;10926:1072;;12008:60;12037:1;12041:2;12045:12;12059:8;12008:20;:60::i;:::-;10439:1637;10327:1749;;;:::o;13762:2130::-;13877:35;13915:21;13928:7;13915:12;:21::i;:::-;13877:59;;13975:4;13953:26;;:13;:18;;;:26;;;13949:67;;13988:28;;;;;;;;;;;;;;13949:67;14029:22;14071:4;14055:20;;:12;:10;:12::i;:::-;:20;;;:73;;;;14092:36;14109:4;14115:12;:10;:12::i;:::-;14092:16;:36::i;:::-;14055:73;:126;;;;14169:12;:10;:12::i;:::-;14145:36;;:20;14157:7;14145:11;:20::i;:::-;:36;;;14055:126;14029:153;;14200:17;14195:66;;14226:35;;;;;;;;;;;;;;14195:66;14290:1;14276:16;;:2;:16;;;14272:52;;14301:23;;;;;;;;;;;;;;14272:52;14337:43;14359:4;14365:2;14369:7;14378:1;14337:21;:43::i;:::-;14445:35;14462:1;14466:7;14475:4;14445:8;:35::i;:::-;14806:1;14776:12;:18;14789:4;14776:18;;;;;;;;;;;;;;;:26;;;:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14850:1;14822:12;:16;14835:2;14822:16;;;;;;;;;;;;;;;:24;;;:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14868:31;14902:11;:20;14914:7;14902:20;;;;;;;;;;;14868:54;;14953:2;14937:8;:13;;;:18;;;;;;;;;;;;;;;;;;15003:15;14970:8;:23;;;:49;;;;;;;;;;;;;;;;;;15271:19;15303:1;15293:7;:11;15271:33;;15319:31;15353:11;:24;15365:11;15353:24;;;;;;;;;;;15319:58;;15421:1;15396:27;;:8;:13;;;;;;;;;;;;:27;;;15392:384;;15606:13;;15591:11;:28;15587:174;;15660:4;15644:8;:13;;;:20;;;;;;;;;;;;;;;;;;15713:13;:28;;;15687:8;:23;;;:54;;;;;;;;;;;;;;;;;;15587:174;15392:384;14751:1036;;;15823:7;15819:2;15804:27;;15813:4;15804:27;;;;;;;;;;;;15842:42;15863:4;15869:2;15873:7;15882:1;15842:20;:42::i;:::-;13866:2026;;13762:2130;;;:::o;1210:326:0:-;1270:4;1527:1;1505:7;:19;;;:23;1498:30;;1210:326;;;:::o;19502:667:4:-;19665:4;19702:2;19686:36;;;19723:12;:10;:12::i;:::-;19737:4;19743:7;19752:5;19686:72;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;19682:480;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19937:1;19920:6;:13;:18;19916:235;;19966:40;;;;;;;;;;;;;;19916:235;20109:6;20103:13;20094:6;20090:2;20086:15;20079:38;19682:480;19815:45;;;19805:55;;;:6;:55;;;;19798:62;;;19502:667;;;;;;:::o;2118:224:14:-;2186:13;2249:1;2243:4;2236:15;2278:1;2272:4;2265:15;2319:4;2313;2303:21;2294:30;;2118:224;;;;:::o;20817:159:4:-;;;;;:::o;21635:158::-;;;;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;7:75:24:-;40:6;73:2;67:9;57:19;;7:75;:::o;88:117::-;197:1;194;187:12;211:117;320:1;317;310:12;334:117;443:1;440;433:12;457:117;566:1;563;556:12;580:117;689:1;686;679:12;720:568;793:8;803:6;853:3;846:4;838:6;834:17;830:27;820:122;;861:79;;:::i;:::-;820:122;974:6;961:20;951:30;;1004:18;996:6;993:30;990:117;;;1026:79;;:::i;:::-;990:117;1140:4;1132:6;1128:17;1116:29;;1194:3;1186:4;1178:6;1174:17;1164:8;1160:32;1157:41;1154:128;;;1201:79;;:::i;:::-;1154:128;720:568;;;;;:::o;1294:559::-;1380:6;1388;1437:2;1425:9;1416:7;1412:23;1408:32;1405:119;;;1443:79;;:::i;:::-;1405:119;1591:1;1580:9;1576:17;1563:31;1621:18;1613:6;1610:30;1607:117;;;1643:79;;:::i;:::-;1607:117;1756:80;1828:7;1819:6;1808:9;1804:22;1756:80;:::i;:::-;1738:98;;;;1534:312;1294:559;;;;;:::o;1859:149::-;1895:7;1935:66;1928:5;1924:78;1913:89;;1859:149;;;:::o;2014:120::-;2086:23;2103:5;2086:23;:::i;:::-;2079:5;2076:34;2066:62;;2124:1;2121;2114:12;2066:62;2014:120;:::o;2140:137::-;2185:5;2223:6;2210:20;2201:29;;2239:32;2265:5;2239:32;:::i;:::-;2140:137;;;;:::o;2283:327::-;2341:6;2390:2;2378:9;2369:7;2365:23;2361:32;2358:119;;;2396:79;;:::i;:::-;2358:119;2516:1;2541:52;2585:7;2576:6;2565:9;2561:22;2541:52;:::i;:::-;2531:62;;2487:116;2283:327;;;;:::o;2616:90::-;2650:7;2693:5;2686:13;2679:21;2668:32;;2616:90;;;:::o;2712:109::-;2793:21;2808:5;2793:21;:::i;:::-;2788:3;2781:34;2712:109;;:::o;2827:210::-;2914:4;2952:2;2941:9;2937:18;2929:26;;2965:65;3027:1;3016:9;3012:17;3003:6;2965:65;:::i;:::-;2827:210;;;;:::o;3043:77::-;3080:7;3109:5;3098:16;;3043:77;;;:::o;3126:118::-;3213:24;3231:5;3213:24;:::i;:::-;3208:3;3201:37;3126:118;;:::o;3250:222::-;3343:4;3381:2;3370:9;3366:18;3358:26;;3394:71;3462:1;3451:9;3447:17;3438:6;3394:71;:::i;:::-;3250:222;;;;:::o;3478:99::-;3530:6;3564:5;3558:12;3548:22;;3478:99;;;:::o;3583:169::-;3667:11;3701:6;3696:3;3689:19;3741:4;3736:3;3732:14;3717:29;;3583:169;;;;:::o;3758:246::-;3839:1;3849:113;3863:6;3860:1;3857:13;3849:113;;;3948:1;3943:3;3939:11;3933:18;3929:1;3924:3;3920:11;3913:39;3885:2;3882:1;3878:10;3873:15;;3849:113;;;3996:1;3987:6;3982:3;3978:16;3971:27;3820:184;3758:246;;;:::o;4010:102::-;4051:6;4102:2;4098:7;4093:2;4086:5;4082:14;4078:28;4068:38;;4010:102;;;:::o;4118:377::-;4206:3;4234:39;4267:5;4234:39;:::i;:::-;4289:71;4353:6;4348:3;4289:71;:::i;:::-;4282:78;;4369:65;4427:6;4422:3;4415:4;4408:5;4404:16;4369:65;:::i;:::-;4459:29;4481:6;4459:29;:::i;:::-;4454:3;4450:39;4443:46;;4210:285;4118:377;;;;:::o;4501:313::-;4614:4;4652:2;4641:9;4637:18;4629:26;;4701:9;4695:4;4691:20;4687:1;4676:9;4672:17;4665:47;4729:78;4802:4;4793:6;4729:78;:::i;:::-;4721:86;;4501:313;;;;:::o;4820:122::-;4893:24;4911:5;4893:24;:::i;:::-;4886:5;4883:35;4873:63;;4932:1;4929;4922:12;4873:63;4820:122;:::o;4948:139::-;4994:5;5032:6;5019:20;5010:29;;5048:33;5075:5;5048:33;:::i;:::-;4948:139;;;;:::o;5093:329::-;5152:6;5201:2;5189:9;5180:7;5176:23;5172:32;5169:119;;;5207:79;;:::i;:::-;5169:119;5327:1;5352:53;5397:7;5388:6;5377:9;5373:22;5352:53;:::i;:::-;5342:63;;5298:117;5093:329;;;;:::o;5428:126::-;5465:7;5505:42;5498:5;5494:54;5483:65;;5428:126;;;:::o;5560:96::-;5597:7;5626:24;5644:5;5626:24;:::i;:::-;5615:35;;5560:96;;;:::o;5662:118::-;5749:24;5767:5;5749:24;:::i;:::-;5744:3;5737:37;5662:118;;:::o;5786:222::-;5879:4;5917:2;5906:9;5902:18;5894:26;;5930:71;5998:1;5987:9;5983:17;5974:6;5930:71;:::i;:::-;5786:222;;;;:::o;6014:122::-;6087:24;6105:5;6087:24;:::i;:::-;6080:5;6077:35;6067:63;;6126:1;6123;6116:12;6067:63;6014:122;:::o;6142:139::-;6188:5;6226:6;6213:20;6204:29;;6242:33;6269:5;6242:33;:::i;:::-;6142:139;;;;:::o;6287:474::-;6355:6;6363;6412:2;6400:9;6391:7;6387:23;6383:32;6380:119;;;6418:79;;:::i;:::-;6380:119;6538:1;6563:53;6608:7;6599:6;6588:9;6584:22;6563:53;:::i;:::-;6553:63;;6509:117;6665:2;6691:53;6736:7;6727:6;6716:9;6712:22;6691:53;:::i;:::-;6681:63;;6636:118;6287:474;;;;;:::o;6767:329::-;6826:6;6875:2;6863:9;6854:7;6850:23;6846:32;6843:119;;;6881:79;;:::i;:::-;6843:119;7001:1;7026:53;7071:7;7062:6;7051:9;7047:22;7026:53;:::i;:::-;7016:63;;6972:117;6767:329;;;;:::o;7102:117::-;7211:1;7208;7201:12;7225:180;7273:77;7270:1;7263:88;7370:4;7367:1;7360:15;7394:4;7391:1;7384:15;7411:281;7494:27;7516:4;7494:27;:::i;:::-;7486:6;7482:40;7624:6;7612:10;7609:22;7588:18;7576:10;7573:34;7570:62;7567:88;;;7635:18;;:::i;:::-;7567:88;7675:10;7671:2;7664:22;7454:238;7411:281;;:::o;7698:129::-;7732:6;7759:20;;:::i;:::-;7749:30;;7788:33;7816:4;7808:6;7788:33;:::i;:::-;7698:129;;;:::o;7833:308::-;7895:4;7985:18;7977:6;7974:30;7971:56;;;8007:18;;:::i;:::-;7971:56;8045:29;8067:6;8045:29;:::i;:::-;8037:37;;8129:4;8123;8119:15;8111:23;;7833:308;;;:::o;8147:146::-;8244:6;8239:3;8234;8221:30;8285:1;8276:6;8271:3;8267:16;8260:27;8147:146;;;:::o;8299:425::-;8377:5;8402:66;8418:49;8460:6;8418:49;:::i;:::-;8402:66;:::i;:::-;8393:75;;8491:6;8484:5;8477:21;8529:4;8522:5;8518:16;8567:3;8558:6;8553:3;8549:16;8546:25;8543:112;;;8574:79;;:::i;:::-;8543:112;8664:54;8711:6;8706:3;8701;8664:54;:::i;:::-;8383:341;8299:425;;;;;:::o;8744:340::-;8800:5;8849:3;8842:4;8834:6;8830:17;8826:27;8816:122;;8857:79;;:::i;:::-;8816:122;8974:6;8961:20;8999:79;9074:3;9066:6;9059:4;9051:6;9047:17;8999:79;:::i;:::-;8990:88;;8806:278;8744:340;;;;:::o;9090:509::-;9159:6;9208:2;9196:9;9187:7;9183:23;9179:32;9176:119;;;9214:79;;:::i;:::-;9176:119;9362:1;9351:9;9347:17;9334:31;9392:18;9384:6;9381:30;9378:117;;;9414:79;;:::i;:::-;9378:117;9519:63;9574:7;9565:6;9554:9;9550:22;9519:63;:::i;:::-;9509:73;;9305:287;9090:509;;;;:::o;9605:311::-;9682:4;9772:18;9764:6;9761:30;9758:56;;;9794:18;;:::i;:::-;9758:56;9844:4;9836:6;9832:17;9824:25;;9904:4;9898;9894:15;9886:23;;9605:311;;;:::o;9922:77::-;9959:7;9988:5;9977:16;;9922:77;;;:::o;10005:122::-;10078:24;10096:5;10078:24;:::i;:::-;10071:5;10068:35;10058:63;;10117:1;10114;10107:12;10058:63;10005:122;:::o;10133:139::-;10179:5;10217:6;10204:20;10195:29;;10233:33;10260:5;10233:33;:::i;:::-;10133:139;;;;:::o;10295:710::-;10391:5;10416:81;10432:64;10489:6;10432:64;:::i;:::-;10416:81;:::i;:::-;10407:90;;10517:5;10546:6;10539:5;10532:21;10580:4;10573:5;10569:16;10562:23;;10633:4;10625:6;10621:17;10613:6;10609:30;10662:3;10654:6;10651:15;10648:122;;;10681:79;;:::i;:::-;10648:122;10796:6;10779:220;10813:6;10808:3;10805:15;10779:220;;;10888:3;10917:37;10950:3;10938:10;10917:37;:::i;:::-;10912:3;10905:50;10984:4;10979:3;10975:14;10968:21;;10855:144;10839:4;10834:3;10830:14;10823:21;;10779:220;;;10783:21;10397:608;;10295:710;;;;;:::o;11028:370::-;11099:5;11148:3;11141:4;11133:6;11129:17;11125:27;11115:122;;11156:79;;:::i;:::-;11115:122;11273:6;11260:20;11298:94;11388:3;11380:6;11373:4;11365:6;11361:17;11298:94;:::i;:::-;11289:103;;11105:293;11028:370;;;;:::o;11404:684::-;11497:6;11505;11554:2;11542:9;11533:7;11529:23;11525:32;11522:119;;;11560:79;;:::i;:::-;11522:119;11708:1;11697:9;11693:17;11680:31;11738:18;11730:6;11727:30;11724:117;;;11760:79;;:::i;:::-;11724:117;11865:78;11935:7;11926:6;11915:9;11911:22;11865:78;:::i;:::-;11855:88;;11651:302;11992:2;12018:53;12063:7;12054:6;12043:9;12039:22;12018:53;:::i;:::-;12008:63;;11963:118;11404:684;;;;;:::o;12094:619::-;12171:6;12179;12187;12236:2;12224:9;12215:7;12211:23;12207:32;12204:119;;;12242:79;;:::i;:::-;12204:119;12362:1;12387:53;12432:7;12423:6;12412:9;12408:22;12387:53;:::i;:::-;12377:63;;12333:117;12489:2;12515:53;12560:7;12551:6;12540:9;12536:22;12515:53;:::i;:::-;12505:63;;12460:118;12617:2;12643:53;12688:7;12679:6;12668:9;12664:22;12643:53;:::i;:::-;12633:63;;12588:118;12094:619;;;;;:::o;12719:118::-;12806:24;12824:5;12806:24;:::i;:::-;12801:3;12794:37;12719:118;;:::o;12843:222::-;12936:4;12974:2;12963:9;12959:18;12951:26;;12987:71;13055:1;13044:9;13040:17;13031:6;12987:71;:::i;:::-;12843:222;;;;:::o;13071:329::-;13130:6;13179:2;13167:9;13158:7;13154:23;13150:32;13147:119;;;13185:79;;:::i;:::-;13147:119;13305:1;13330:53;13375:7;13366:6;13355:9;13351:22;13330:53;:::i;:::-;13320:63;;13276:117;13071:329;;;;:::o;13406:116::-;13476:21;13491:5;13476:21;:::i;:::-;13469:5;13466:32;13456:60;;13512:1;13509;13502:12;13456:60;13406:116;:::o;13528:133::-;13571:5;13609:6;13596:20;13587:29;;13625:30;13649:5;13625:30;:::i;:::-;13528:133;;;;:::o;13667:468::-;13732:6;13740;13789:2;13777:9;13768:7;13764:23;13760:32;13757:119;;;13795:79;;:::i;:::-;13757:119;13915:1;13940:53;13985:7;13976:6;13965:9;13961:22;13940:53;:::i;:::-;13930:63;;13886:117;14042:2;14068:50;14110:7;14101:6;14090:9;14086:22;14068:50;:::i;:::-;14058:60;;14013:115;13667:468;;;;;:::o;14141:307::-;14202:4;14292:18;14284:6;14281:30;14278:56;;;14314:18;;:::i;:::-;14278:56;14352:29;14374:6;14352:29;:::i;:::-;14344:37;;14436:4;14430;14426:15;14418:23;;14141:307;;;:::o;14454:423::-;14531:5;14556:65;14572:48;14613:6;14572:48;:::i;:::-;14556:65;:::i;:::-;14547:74;;14644:6;14637:5;14630:21;14682:4;14675:5;14671:16;14720:3;14711:6;14706:3;14702:16;14699:25;14696:112;;;14727:79;;:::i;:::-;14696:112;14817:54;14864:6;14859:3;14854;14817:54;:::i;:::-;14537:340;14454:423;;;;;:::o;14896:338::-;14951:5;15000:3;14993:4;14985:6;14981:17;14977:27;14967:122;;15008:79;;:::i;:::-;14967:122;15125:6;15112:20;15150:78;15224:3;15216:6;15209:4;15201:6;15197:17;15150:78;:::i;:::-;15141:87;;14957:277;14896:338;;;;:::o;15240:943::-;15335:6;15343;15351;15359;15408:3;15396:9;15387:7;15383:23;15379:33;15376:120;;;15415:79;;:::i;:::-;15376:120;15535:1;15560:53;15605:7;15596:6;15585:9;15581:22;15560:53;:::i;:::-;15550:63;;15506:117;15662:2;15688:53;15733:7;15724:6;15713:9;15709:22;15688:53;:::i;:::-;15678:63;;15633:118;15790:2;15816:53;15861:7;15852:6;15841:9;15837:22;15816:53;:::i;:::-;15806:63;;15761:118;15946:2;15935:9;15931:18;15918:32;15977:18;15969:6;15966:30;15963:117;;;15999:79;;:::i;:::-;15963:117;16104:62;16158:7;16149:6;16138:9;16134:22;16104:62;:::i;:::-;16094:72;;15889:287;15240:943;;;;;;;:::o;16189:704::-;16284:6;16292;16300;16349:2;16337:9;16328:7;16324:23;16320:32;16317:119;;;16355:79;;:::i;:::-;16317:119;16475:1;16500:53;16545:7;16536:6;16525:9;16521:22;16500:53;:::i;:::-;16490:63;;16446:117;16630:2;16619:9;16615:18;16602:32;16661:18;16653:6;16650:30;16647:117;;;16683:79;;:::i;:::-;16647:117;16796:80;16868:7;16859:6;16848:9;16844:22;16796:80;:::i;:::-;16778:98;;;;16573:313;16189:704;;;;;:::o;16899:474::-;16967:6;16975;17024:2;17012:9;17003:7;16999:23;16995:32;16992:119;;;17030:79;;:::i;:::-;16992:119;17150:1;17175:53;17220:7;17211:6;17200:9;17196:22;17175:53;:::i;:::-;17165:63;;17121:117;17277:2;17303:53;17348:7;17339:6;17328:9;17324:22;17303:53;:::i;:::-;17293:63;;17248:118;16899:474;;;;;:::o;17379:::-;17447:6;17455;17504:2;17492:9;17483:7;17479:23;17475:32;17472:119;;;17510:79;;:::i;:::-;17472:119;17630:1;17655:53;17700:7;17691:6;17680:9;17676:22;17655:53;:::i;:::-;17645:63;;17601:117;17757:2;17783:53;17828:7;17819:6;17808:9;17804:22;17783:53;:::i;:::-;17773:63;;17728:118;17379:474;;;;;:::o;17859:170::-;17999:22;17995:1;17987:6;17983:14;17976:46;17859:170;:::o;18035:366::-;18177:3;18198:67;18262:2;18257:3;18198:67;:::i;:::-;18191:74;;18274:93;18363:3;18274:93;:::i;:::-;18392:2;18387:3;18383:12;18376:19;;18035:366;;;:::o;18407:419::-;18573:4;18611:2;18600:9;18596:18;18588:26;;18660:9;18654:4;18650:20;18646:1;18635:9;18631:17;18624:47;18688:131;18814:4;18688:131;:::i;:::-;18680:139;;18407:419;;;:::o;18832:180::-;18880:77;18877:1;18870:88;18977:4;18974:1;18967:15;19001:4;18998:1;18991:15;19018:191;19058:3;19077:20;19095:1;19077:20;:::i;:::-;19072:25;;19111:20;19129:1;19111:20;:::i;:::-;19106:25;;19154:1;19151;19147:9;19140:16;;19175:3;19172:1;19169:10;19166:36;;;19182:18;;:::i;:::-;19166:36;19018:191;;;;:::o;19215:170::-;19355:22;19351:1;19343:6;19339:14;19332:46;19215:170;:::o;19391:366::-;19533:3;19554:67;19618:2;19613:3;19554:67;:::i;:::-;19547:74;;19630:93;19719:3;19630:93;:::i;:::-;19748:2;19743:3;19739:12;19732:19;;19391:366;;;:::o;19763:419::-;19929:4;19967:2;19956:9;19952:18;19944:26;;20016:9;20010:4;20006:20;20002:1;19991:9;19987:17;19980:47;20044:131;20170:4;20044:131;:::i;:::-;20036:139;;19763:419;;;:::o;20188:177::-;20328:29;20324:1;20316:6;20312:14;20305:53;20188:177;:::o;20371:366::-;20513:3;20534:67;20598:2;20593:3;20534:67;:::i;:::-;20527:74;;20610:93;20699:3;20610:93;:::i;:::-;20728:2;20723:3;20719:12;20712:19;;20371:366;;;:::o;20743:419::-;20909:4;20947:2;20936:9;20932:18;20924:26;;20996:9;20990:4;20986:20;20982:1;20971:9;20967:17;20960:47;21024:131;21150:4;21024:131;:::i;:::-;21016:139;;20743:419;;;:::o;21168:173::-;21308:25;21304:1;21296:6;21292:14;21285:49;21168:173;:::o;21347:366::-;21489:3;21510:67;21574:2;21569:3;21510:67;:::i;:::-;21503:74;;21586:93;21675:3;21586:93;:::i;:::-;21704:2;21699:3;21695:12;21688:19;;21347:366;;;:::o;21719:419::-;21885:4;21923:2;21912:9;21908:18;21900:26;;21972:9;21966:4;21962:20;21958:1;21947:9;21943:17;21936:47;22000:131;22126:4;22000:131;:::i;:::-;21992:139;;21719:419;;;:::o;22144:94::-;22177:8;22225:5;22221:2;22217:14;22196:35;;22144:94;;;:::o;22244:::-;22283:7;22312:20;22326:5;22312:20;:::i;:::-;22301:31;;22244:94;;;:::o;22344:100::-;22383:7;22412:26;22432:5;22412:26;:::i;:::-;22401:37;;22344:100;;;:::o;22450:157::-;22555:45;22575:24;22593:5;22575:24;:::i;:::-;22555:45;:::i;:::-;22550:3;22543:58;22450:157;;:::o;22613:256::-;22725:3;22740:75;22811:3;22802:6;22740:75;:::i;:::-;22840:2;22835:3;22831:12;22824:19;;22860:3;22853:10;;22613:256;;;;:::o;22875:164::-;23015:16;23011:1;23003:6;22999:14;22992:40;22875:164;:::o;23045:366::-;23187:3;23208:67;23272:2;23267:3;23208:67;:::i;:::-;23201:74;;23284:93;23373:3;23284:93;:::i;:::-;23402:2;23397:3;23393:12;23386:19;;23045:366;;;:::o;23417:419::-;23583:4;23621:2;23610:9;23606:18;23598:26;;23670:9;23664:4;23660:20;23656:1;23645:9;23641:17;23634:47;23698:131;23824:4;23698:131;:::i;:::-;23690:139;;23417:419;;;:::o;23842:180::-;23890:77;23887:1;23880:88;23987:4;23984:1;23977:15;24011:4;24008:1;24001:15;24028:320;24072:6;24109:1;24103:4;24099:12;24089:22;;24156:1;24150:4;24146:12;24177:18;24167:81;;24233:4;24225:6;24221:17;24211:27;;24167:81;24295:2;24287:6;24284:14;24264:18;24261:38;24258:84;;24314:18;;:::i;:::-;24258:84;24079:269;24028:320;;;:::o;24354:182::-;24494:34;24490:1;24482:6;24478:14;24471:58;24354:182;:::o;24542:366::-;24684:3;24705:67;24769:2;24764:3;24705:67;:::i;:::-;24698:74;;24781:93;24870:3;24781:93;:::i;:::-;24899:2;24894:3;24890:12;24883:19;;24542:366;;;:::o;24914:419::-;25080:4;25118:2;25107:9;25103:18;25095:26;;25167:9;25161:4;25157:20;25153:1;25142:9;25138:17;25131:47;25195:131;25321:4;25195:131;:::i;:::-;25187:139;;24914:419;;;:::o;25339:141::-;25388:4;25411:3;25403:11;;25434:3;25431:1;25424:14;25468:4;25465:1;25455:18;25447:26;;25339:141;;;:::o;25486:93::-;25523:6;25570:2;25565;25558:5;25554:14;25550:23;25540:33;;25486:93;;;:::o;25585:107::-;25629:8;25679:5;25673:4;25669:16;25648:37;;25585:107;;;;:::o;25698:393::-;25767:6;25817:1;25805:10;25801:18;25840:97;25870:66;25859:9;25840:97;:::i;:::-;25958:39;25988:8;25977:9;25958:39;:::i;:::-;25946:51;;26030:4;26026:9;26019:5;26015:21;26006:30;;26079:4;26069:8;26065:19;26058:5;26055:30;26045:40;;25774:317;;25698:393;;;;;:::o;26097:60::-;26125:3;26146:5;26139:12;;26097:60;;;:::o;26163:142::-;26213:9;26246:53;26264:34;26273:24;26291:5;26273:24;:::i;:::-;26264:34;:::i;:::-;26246:53;:::i;:::-;26233:66;;26163:142;;;:::o;26311:75::-;26354:3;26375:5;26368:12;;26311:75;;;:::o;26392:269::-;26502:39;26533:7;26502:39;:::i;:::-;26563:91;26612:41;26636:16;26612:41;:::i;:::-;26604:6;26597:4;26591:11;26563:91;:::i;:::-;26557:4;26550:105;26468:193;26392:269;;;:::o;26667:73::-;26712:3;26667:73;:::o;26746:189::-;26823:32;;:::i;:::-;26864:65;26922:6;26914;26908:4;26864:65;:::i;:::-;26799:136;26746:189;;:::o;26941:186::-;27001:120;27018:3;27011:5;27008:14;27001:120;;;27072:39;27109:1;27102:5;27072:39;:::i;:::-;27045:1;27038:5;27034:13;27025:22;;27001:120;;;26941:186;;:::o;27133:543::-;27234:2;27229:3;27226:11;27223:446;;;27268:38;27300:5;27268:38;:::i;:::-;27352:29;27370:10;27352:29;:::i;:::-;27342:8;27338:44;27535:2;27523:10;27520:18;27517:49;;;27556:8;27541:23;;27517:49;27579:80;27635:22;27653:3;27635:22;:::i;:::-;27625:8;27621:37;27608:11;27579:80;:::i;:::-;27238:431;;27223:446;27133:543;;;:::o;27682:117::-;27736:8;27786:5;27780:4;27776:16;27755:37;;27682:117;;;;:::o;27805:169::-;27849:6;27882:51;27930:1;27926:6;27918:5;27915:1;27911:13;27882:51;:::i;:::-;27878:56;27963:4;27957;27953:15;27943:25;;27856:118;27805:169;;;;:::o;27979:295::-;28055:4;28201:29;28226:3;28220:4;28201:29;:::i;:::-;28193:37;;28263:3;28260:1;28256:11;28250:4;28247:21;28239:29;;27979:295;;;;:::o;28279:1395::-;28396:37;28429:3;28396:37;:::i;:::-;28498:18;28490:6;28487:30;28484:56;;;28520:18;;:::i;:::-;28484:56;28564:38;28596:4;28590:11;28564:38;:::i;:::-;28649:67;28709:6;28701;28695:4;28649:67;:::i;:::-;28743:1;28767:4;28754:17;;28799:2;28791:6;28788:14;28816:1;28811:618;;;;29473:1;29490:6;29487:77;;;29539:9;29534:3;29530:19;29524:26;29515:35;;29487:77;29590:67;29650:6;29643:5;29590:67;:::i;:::-;29584:4;29577:81;29446:222;28781:887;;28811:618;28863:4;28859:9;28851:6;28847:22;28897:37;28929:4;28897:37;:::i;:::-;28956:1;28970:208;28984:7;28981:1;28978:14;28970:208;;;29063:9;29058:3;29054:19;29048:26;29040:6;29033:42;29114:1;29106:6;29102:14;29092:24;;29161:2;29150:9;29146:18;29133:31;;29007:4;29004:1;29000:12;28995:17;;28970:208;;;29206:6;29197:7;29194:19;29191:179;;;29264:9;29259:3;29255:19;29249:26;29307:48;29349:4;29341:6;29337:17;29326:9;29307:48;:::i;:::-;29299:6;29292:64;29214:156;29191:179;29416:1;29412;29404:6;29400:14;29396:22;29390:4;29383:36;28818:611;;;28781:887;;28371:1303;;;28279:1395;;:::o;29680:332::-;29801:4;29839:2;29828:9;29824:18;29816:26;;29852:71;29920:1;29909:9;29905:17;29896:6;29852:71;:::i;:::-;29933:72;30001:2;29990:9;29986:18;29977:6;29933:72;:::i;:::-;29680:332;;;;;:::o;30018:137::-;30072:5;30103:6;30097:13;30088:22;;30119:30;30143:5;30119:30;:::i;:::-;30018:137;;;;:::o;30161:345::-;30228:6;30277:2;30265:9;30256:7;30252:23;30248:32;30245:119;;;30283:79;;:::i;:::-;30245:119;30403:1;30428:61;30481:7;30472:6;30461:9;30457:22;30428:61;:::i;:::-;30418:71;;30374:125;30161:345;;;;:::o;30512:181::-;30652:33;30648:1;30640:6;30636:14;30629:57;30512:181;:::o;30699:366::-;30841:3;30862:67;30926:2;30921:3;30862:67;:::i;:::-;30855:74;;30938:93;31027:3;30938:93;:::i;:::-;31056:2;31051:3;31047:12;31040:19;;30699:366;;;:::o;31071:419::-;31237:4;31275:2;31264:9;31260:18;31252:26;;31324:9;31318:4;31314:20;31310:1;31299:9;31295:17;31288:47;31352:131;31478:4;31352:131;:::i;:::-;31344:139;;31071:419;;;:::o;31496:147::-;31597:11;31634:3;31619:18;;31496:147;;;;:::o;31649:114::-;;:::o;31769:398::-;31928:3;31949:83;32030:1;32025:3;31949:83;:::i;:::-;31942:90;;32041:93;32130:3;32041:93;:::i;:::-;32159:1;32154:3;32150:11;32143:18;;31769:398;;;:::o;32173:379::-;32357:3;32379:147;32522:3;32379:147;:::i;:::-;32372:154;;32543:3;32536:10;;32173:379;;;:::o;32558:163::-;32698:15;32694:1;32686:6;32682:14;32675:39;32558:163;:::o;32727:366::-;32869:3;32890:67;32954:2;32949:3;32890:67;:::i;:::-;32883:74;;32966:93;33055:3;32966:93;:::i;:::-;33084:2;33079:3;33075:12;33068:19;;32727:366;;;:::o;33099:419::-;33265:4;33303:2;33292:9;33288:18;33280:26;;33352:9;33346:4;33342:20;33338:1;33327:9;33323:17;33316:47;33380:131;33506:4;33380:131;:::i;:::-;33372:139;;33099:419;;;:::o;33524:410::-;33564:7;33587:20;33605:1;33587:20;:::i;:::-;33582:25;;33621:20;33639:1;33621:20;:::i;:::-;33616:25;;33676:1;33673;33669:9;33698:30;33716:11;33698:30;:::i;:::-;33687:41;;33877:1;33868:7;33864:15;33861:1;33858:22;33838:1;33831:9;33811:83;33788:139;;33907:18;;:::i;:::-;33788:139;33572:362;33524:410;;;;:::o;33940:169::-;34080:21;34076:1;34068:6;34064:14;34057:45;33940:169;:::o;34115:366::-;34257:3;34278:67;34342:2;34337:3;34278:67;:::i;:::-;34271:74;;34354:93;34443:3;34354:93;:::i;:::-;34472:2;34467:3;34463:12;34456:19;;34115:366;;;:::o;34487:419::-;34653:4;34691:2;34680:9;34676:18;34668:26;;34740:9;34734:4;34730:20;34726:1;34715:9;34711:17;34704:47;34768:131;34894:4;34768:131;:::i;:::-;34760:139;;34487:419;;;:::o;34912:243::-;35052:34;35048:1;35040:6;35036:14;35029:58;35121:26;35116:2;35108:6;35104:15;35097:51;34912:243;:::o;35161:366::-;35303:3;35324:67;35388:2;35383:3;35324:67;:::i;:::-;35317:74;;35400:93;35489:3;35400:93;:::i;:::-;35518:2;35513:3;35509:12;35502:19;;35161:366;;;:::o;35533:419::-;35699:4;35737:2;35726:9;35722:18;35714:26;;35786:9;35780:4;35776:20;35772:1;35761:9;35757:17;35750:47;35814:131;35940:4;35814:131;:::i;:::-;35806:139;;35533:419;;;:::o;35958:181::-;36098:33;36094:1;36086:6;36082:14;36075:57;35958:181;:::o;36145:366::-;36287:3;36308:67;36372:2;36367:3;36308:67;:::i;:::-;36301:74;;36384:93;36473:3;36384:93;:::i;:::-;36502:2;36497:3;36493:12;36486:19;;36145:366;;;:::o;36517:419::-;36683:4;36721:2;36710:9;36706:18;36698:26;;36770:9;36764:4;36760:20;36756:1;36745:9;36741:17;36734:47;36798:131;36924:4;36798:131;:::i;:::-;36790:139;;36517:419;;;:::o;36942:234::-;37082:34;37078:1;37070:6;37066:14;37059:58;37151:17;37146:2;37138:6;37134:15;37127:42;36942:234;:::o;37182:366::-;37324:3;37345:67;37409:2;37404:3;37345:67;:::i;:::-;37338:74;;37421:93;37510:3;37421:93;:::i;:::-;37539:2;37534:3;37530:12;37523:19;;37182:366;;;:::o;37554:419::-;37720:4;37758:2;37747:9;37743:18;37735:26;;37807:9;37801:4;37797:20;37793:1;37782:9;37778:17;37771:47;37835:131;37961:4;37835:131;:::i;:::-;37827:139;;37554:419;;;:::o;37979:148::-;38081:11;38118:3;38103:18;;37979:148;;;;:::o;38133:390::-;38239:3;38267:39;38300:5;38267:39;:::i;:::-;38322:89;38404:6;38399:3;38322:89;:::i;:::-;38315:96;;38420:65;38478:6;38473:3;38466:4;38459:5;38455:16;38420:65;:::i;:::-;38510:6;38505:3;38501:16;38494:23;;38243:280;38133:390;;;;:::o;38553:874::-;38656:3;38693:5;38687:12;38722:36;38748:9;38722:36;:::i;:::-;38774:89;38856:6;38851:3;38774:89;:::i;:::-;38767:96;;38894:1;38883:9;38879:17;38910:1;38905:166;;;;39085:1;39080:341;;;;38872:549;;38905:166;38989:4;38985:9;38974;38970:25;38965:3;38958:38;39051:6;39044:14;39037:22;39029:6;39025:35;39020:3;39016:45;39009:52;;38905:166;;39080:341;39147:38;39179:5;39147:38;:::i;:::-;39207:1;39221:154;39235:6;39232:1;39229:13;39221:154;;;39309:7;39303:14;39299:1;39294:3;39290:11;39283:35;39359:1;39350:7;39346:15;39335:26;;39257:4;39254:1;39250:12;39245:17;;39221:154;;;39404:6;39399:3;39395:16;39388:23;;39087:334;;38872:549;;38660:767;;38553:874;;;;:::o;39433:589::-;39658:3;39680:95;39771:3;39762:6;39680:95;:::i;:::-;39673:102;;39792:95;39883:3;39874:6;39792:95;:::i;:::-;39785:102;;39904:92;39992:3;39983:6;39904:92;:::i;:::-;39897:99;;40013:3;40006:10;;39433:589;;;;;;:::o;40028:221::-;40168:34;40164:1;40156:6;40152:14;40145:58;40237:4;40232:2;40224:6;40220:15;40213:29;40028:221;:::o;40255:366::-;40397:3;40418:67;40482:2;40477:3;40418:67;:::i;:::-;40411:74;;40494:93;40583:3;40494:93;:::i;:::-;40612:2;40607:3;40603:12;40596:19;;40255:366;;;:::o;40627:419::-;40793:4;40831:2;40820:9;40816:18;40808:26;;40880:9;40874:4;40870:20;40866:1;40855:9;40851:17;40844:47;40908:131;41034:4;40908:131;:::i;:::-;40900:139;;40627:419;;;:::o;41052:194::-;41092:4;41112:20;41130:1;41112:20;:::i;:::-;41107:25;;41146:20;41164:1;41146:20;:::i;:::-;41141:25;;41190:1;41187;41183:9;41175:17;;41214:1;41208:4;41205:11;41202:37;;;41219:18;;:::i;:::-;41202:37;41052:194;;;;:::o;41252:225::-;41392:34;41388:1;41380:6;41376:14;41369:58;41461:8;41456:2;41448:6;41444:15;41437:33;41252:225;:::o;41483:366::-;41625:3;41646:67;41710:2;41705:3;41646:67;:::i;:::-;41639:74;;41722:93;41811:3;41722:93;:::i;:::-;41840:2;41835:3;41831:12;41824:19;;41483:366;;;:::o;41855:419::-;42021:4;42059:2;42048:9;42044:18;42036:26;;42108:9;42102:4;42098:20;42094:1;42083:9;42079:17;42072:47;42136:131;42262:4;42136:131;:::i;:::-;42128:139;;41855:419;;;:::o;42280:233::-;42319:3;42342:24;42360:5;42342:24;:::i;:::-;42333:33;;42388:66;42381:5;42378:77;42375:103;;42458:18;;:::i;:::-;42375:103;42505:1;42498:5;42494:13;42487:20;;42280:233;;;:::o;42519:180::-;42567:77;42564:1;42557:88;42664:4;42661:1;42654:15;42688:4;42685:1;42678:15;42705:185;42745:1;42762:20;42780:1;42762:20;:::i;:::-;42757:25;;42796:20;42814:1;42796:20;:::i;:::-;42791:25;;42835:1;42825:35;;42840:18;;:::i;:::-;42825:35;42882:1;42879;42875:9;42870:14;;42705:185;;;;:::o;42896:176::-;42928:1;42945:20;42963:1;42945:20;:::i;:::-;42940:25;;42979:20;42997:1;42979:20;:::i;:::-;42974:25;;43018:1;43008:35;;43023:18;;:::i;:::-;43008:35;43064:1;43061;43057:9;43052:14;;42896:176;;;;:::o;43078:180::-;43126:77;43123:1;43116:88;43223:4;43220:1;43213:15;43247:4;43244:1;43237:15;43264:98;43315:6;43349:5;43343:12;43333:22;;43264:98;;;:::o;43368:168::-;43451:11;43485:6;43480:3;43473:19;43525:4;43520:3;43516:14;43501:29;;43368:168;;;;:::o;43542:373::-;43628:3;43656:38;43688:5;43656:38;:::i;:::-;43710:70;43773:6;43768:3;43710:70;:::i;:::-;43703:77;;43789:65;43847:6;43842:3;43835:4;43828:5;43824:16;43789:65;:::i;:::-;43879:29;43901:6;43879:29;:::i;:::-;43874:3;43870:39;43863:46;;43632:283;43542:373;;;;:::o;43921:640::-;44116:4;44154:3;44143:9;44139:19;44131:27;;44168:71;44236:1;44225:9;44221:17;44212:6;44168:71;:::i;:::-;44249:72;44317:2;44306:9;44302:18;44293:6;44249:72;:::i;:::-;44331;44399:2;44388:9;44384:18;44375:6;44331:72;:::i;:::-;44450:9;44444:4;44440:20;44435:2;44424:9;44420:18;44413:48;44478:76;44549:4;44540:6;44478:76;:::i;:::-;44470:84;;43921:640;;;;;;;:::o;44567:141::-;44623:5;44654:6;44648:13;44639:22;;44670:32;44696:5;44670:32;:::i;:::-;44567:141;;;;:::o;44714:349::-;44783:6;44832:2;44820:9;44811:7;44807:23;44803:32;44800:119;;;44838:79;;:::i;:::-;44800:119;44958:1;44983:63;45038:7;45029:6;45018:9;45014:22;44983:63;:::i;:::-;44973:73;;44929:127;44714:349;;;;:::o
Swarm Source
ipfs://add2e9a9a9ecc75fccfddbb931297fe37b95c09a75f5e424258811881bc14a47
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.