Feature Tip: Add private address tag to any address under My Name Tag !
ERC-721
Overview
Max Total Supply
5,500 MAYG_221203
Holders
842
Market
Volume (24H)
N/A
Min Price (24H)
N/A
Max Price (24H)
N/A
Other Info
Token Contract
Balance
1 MAYG_221203Loading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
MAYG_721a
Compiler Version
v0.8.17+commit.8df45f5f
Contract Source Code (Solidity Multiple files format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.6; import "./Context.sol"; import "./Ownable.sol"; import "./Strings.sol"; import './ReentrancyGuard.sol'; import "./ERC721A.sol"; // the rarible dependency files are needed to setup sales royalties on Rarible import "./RoyaltiesV2Impl.sol"; import "./LibPart.sol"; import "./LibRoyaltiesV2.sol"; import './DefaultOperatorFilterer.sol'; /* This contract allows for royalties and generational mints. The Contract also supports pausable as well as the standard ERC721a functionality (based on ERC721) The royalty interfaces supported are: Rarible ERC2981 royalty protocol (mintable, etc) Images are organized by batches of 500. Thus the uri will change for every 500 images. */ contract MAYG_721a is ERC721A, Ownable, ReentrancyGuard, RoyaltiesV2Impl, DefaultOperatorFilterer { bytes4 private constant _INTERFACE_ID_ERC2981 = 0x2a55205a; bool public paused = false; string public constant _baseExtension = ".json"; // maximum number of tokens that can mint in one batch uint256 private _maxFistGenMintBatchSize = 250; uint256 private _maxFirstGenTokens = 10000; string[20] private _imageRange; uint256 private constant _imageRangeBatchSize = 500; uint256 private constant _imageRangeBatches = 20; event Received(address operator, address from, uint256 tokenId, bytes data, uint256 gas); constructor( string memory _cid ) ERC721A( "MAYG SYGNE", "MAYG_221203" ) { setCIDforRange(_cid, 0); } function transferFrom(address from, address to, uint256 tokenId) public override onlyAllowedOperator(from) { super.transferFrom(from, to, tokenId); } function safeTransferFrom(address from, address to, uint256 tokenId) public override onlyAllowedOperator(from) { super.safeTransferFrom(from, to, tokenId); } function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public override onlyAllowedOperator(from) { super.safeTransferFrom(from, to, tokenId, data); } function mint(address _to, uint256 _quantity) public onlyOwner { require(!paused); require(_quantity > 0, "MAYG_721a: invalid quantity, 0"); require(_quantity <= _maxFistGenMintBatchSize, "MAYG_721a: invalid quantity, too large"); uint256 supply = totalSupply(); require(supply + _quantity <= _maxFirstGenTokens, "MAYG_721a: invalid quantity, too many first gen tokens"); _safeMint(_to, _quantity); } /* */ function tokenURI(uint256 _tokenId) public view override returns (string memory) { string memory cid = getCIDForTokenInternal(_tokenId); string memory tokenIdStr = Strings.toString(_tokenId); bytes memory b = abi.encodePacked(cid, tokenIdStr, _baseExtension); return string(b); } function onERC721Received( address operator, address from, uint256 tokenId, bytes memory data ) public override returns (bytes4) { /* // for testing reverts with a message from the receiver contract if (bytes1(data) == 0x01) { revert('reverted in the receiver contract!'); } // for testing with the returned wrong value from the receiver contract if (bytes1(data) == 0x02) { return 0x0; } // for testing the reentrancy protection if (bytes1(data) == 0x03) { IERC721AMock(_erc721aMock).safeMint(address(this), 1); } */ emit Received(operator, from, tokenId, data, 20000); return this.onERC721Received.selector; } function withdraw() public onlyOwner nonReentrant { (bool success, ) = payable(msg.sender).call{value: address(this).balance}(""); require(success); } // configure royalties for Rariable // note: Royalty percentages are in basis points so a 10% sales royalty should be entered as 1000. function setRoyalties(uint _tokenId, address payable _royaltiesRecipientAddress, uint96 _percentageBasisPoints) public onlyOwner { LibPart.Part[] memory _royalties = new LibPart.Part[](1); _royalties[0].value = _percentageBasisPoints; _royalties[0].account = _royaltiesRecipientAddress; _saveRoyalties(_tokenId, _royalties); } // configure royalties for Mintable using the ERC2981 standard function royaltyInfo(uint256 _tokenId, uint256 _salePrice) external view returns (address receiver, uint256 royaltyAmount) { //use the same royalties that were saved for Rariable LibPart.Part[] memory _royalties = royalties[_tokenId]; if(_royalties.length > 0) { return (_royalties[0].account, (_salePrice * _royalties[0].value) / 10000); } _royalties = royalties[0]; if(_royalties.length > 0) { return (_royalties[0].account, (_salePrice * _royalties[0].value) / 10000); } return (address(0), 0); } function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721A) returns (bool) { if(interfaceId == LibRoyaltiesV2._INTERFACE_ID_ROYALTIES) { return true; } if(interfaceId == _INTERFACE_ID_ERC2981) { return true; } return super.supportsInterface(interfaceId); } //pause the contract and do not allow any more minting function pause(bool _state) public onlyOwner { paused = _state; } function burn(uint256 tokenId, bool approvalCheck) public onlyOwner { _burn( tokenId, approvalCheck); } // start on 1 function _startTokenId() internal pure override returns (uint256) { return 1; } /* // token minting constraints _maxFistGenMintBatchSize : max number of tokens one can mint in a batch in a first gen mint. _maxFirstGenTokens : total number of first generation tokens */ function setMintConstraints(uint256 maxFistGenMintBatchSize, uint256 maxFirstGenTokens ) public onlyOwner { _maxFistGenMintBatchSize = maxFistGenMintBatchSize; _maxFirstGenTokens = maxFirstGenTokens; } // strings are 128 bytes long // CIDs are 48 bytes // _imageRangeBatchSize = 500; // 20 ranges, from 0 to 19 // not ideal, but we are only storing 20 ranges. // uint256 => string ) private _imageRange; // const uint256 _imageRangeBatchSize = 500; function setCIDforRange(string memory _cid, uint256 _rangeNo ) public onlyOwner { _imageRange[_rangeNo] = _cid; } function getCIDForToken( uint256 tokenId ) public onlyOwner view returns (string memory) { return getCIDForTokenInternal(tokenId); } function getCIDForTokenInternal( uint256 tokenId ) internal view returns (string memory) { require(tokenId > 0 , "tokenId of zero is out of range" ); uint256 cidIndex = (tokenId-1) / _imageRangeBatchSize; require (cidIndex < _imageRangeBatches, "missing CID value for token"); return _imageRange[cidIndex]; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./LibPart.sol"; abstract contract AbstractRoyalties { mapping (uint256 => LibPart.Part[]) internal royalties; function _saveRoyalties(uint256 id, LibPart.Part[] memory _royalties) internal { uint256 totalValue; for (uint i = 0; i < _royalties.length; i++) { require(_royalties[i].account != address(0x0), "Recipient should be present"); require(_royalties[i].value != 0, "Royalty value should be positive"); totalValue += _royalties[i].value; royalties[id].push(_royalties[i]); } require(totalValue < 10000, "Royalty total value should be < 10000"); _onRoyaltiesSet(id, _royalties); } function _updateAccount(uint256 _id, address _from, address _to) internal { uint length = royalties[_id].length; for(uint i = 0; i < length; i++) { if (royalties[_id][i].account == _from) { royalties[_id][i].account = payable(address(uint160(_to))); } } } function _onRoyaltiesSet(uint256 id, LibPart.Part[] memory _royalties) virtual internal; }
// 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"; abstract 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. * * ``` * 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 // ERC721A Contracts v4.0.0 // Creator: Chiru Labs pragma solidity ^0.8.4; import './IERC721A.sol'; import "./IERC721Receiver.sol"; //import "hardhat/console.sol"; /** * @dev ERC721 token receiver interface. */ /* interface ERC721A__IERC721Receiver { function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); } */ /** * @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). */ abstract contract ERC721A is IERC721A, IERC721Receiver { // Mask of an entry in packed address data. uint256 private constant BITMASK_ADDRESS_DATA_ENTRY = (1 << 64) - 1; // The bit position of `numberMinted` in packed address data. uint256 private constant BITPOS_NUMBER_MINTED = 64; // The bit position of `numberBurned` in packed address data. uint256 private constant BITPOS_NUMBER_BURNED = 128; // The bit position of `aux` in packed address data. uint256 private constant BITPOS_AUX = 192; // Mask of all 256 bits in packed address data except the 64 bits for `aux`. uint256 private constant BITMASK_AUX_COMPLEMENT = (1 << 192) - 1; // The bit position of `startTimestamp` in packed ownership. uint256 private constant BITPOS_START_TIMESTAMP = 160; // The bit mask of the `burned` bit in packed ownership. uint256 private constant BITMASK_BURNED = 1 << 224; // The bit position of the `nextInitialized` bit in packed ownership. uint256 private constant BITPOS_NEXT_INITIALIZED = 225; // The bit mask of the `nextInitialized` bit in packed ownership. uint256 private constant BITMASK_NEXT_INITIALIZED = 1 << 225; // The tokenId of the next token to be minted. uint256 private _currentIndex; // The number of tokens burned. uint256 private _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 `_packedOwnershipOf` implementation for details. // // Bits Layout: // - [0..159] `addr` // - [160..223] `startTimestamp` // - [224] `burned` // - [225] `nextInitialized` mapping(uint256 => uint256) private _packedOwnerships; // Mapping owner address to address data. // // Bits Layout: // - [0..63] `balance` // - [64..127] `numberMinted` // - [128..191] `numberBurned` // - [192..255] `aux` mapping(address => uint256) private _packedAddressData; // 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(); } /** * @dev Returns the starting token ID. * To change the starting token ID, please override this function. */ function _startTokenId() internal view virtual returns (uint256) { return 0; } /** * @dev Returns the next token ID to be minted. */ function _nextTokenId() internal view returns (uint256) { return _currentIndex; } /** * @dev Returns the total number of tokens in existence. * Burned tokens will reduce the count. * To get the total number of tokens minted, please see `_totalMinted`. */ 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(); } } /** * @dev 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 Returns the total number of tokens burned. */ function _totalBurned() internal view returns (uint256) { return _burnCounter; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { // The interface IDs are constants representing the first 4 bytes of the XOR of // all function selectors in the interface. See: https://eips.ethereum.org/EIPS/eip-165 // e.g. `bytes4(i.functionA.selector ^ i.functionB.selector ^ ...)` return interfaceId == 0x01ffc9a7 || // ERC165 interface ID for ERC165. interfaceId == 0x80ac58cd || // ERC165 interface ID for ERC721. interfaceId == 0x5b5e139f; // ERC165 interface ID for ERC721Metadata. } /** * @dev See {IERC721-balanceOf}. */ function balanceOf(address owner) public view override returns (uint256) { if (_addressToUint256(owner) == 0) revert BalanceQueryForZeroAddress(); return _packedAddressData[owner] & BITMASK_ADDRESS_DATA_ENTRY; } /** * Returns the number of tokens minted by `owner`. */ function _numberMinted(address owner) internal view returns (uint256) { return (_packedAddressData[owner] >> BITPOS_NUMBER_MINTED) & BITMASK_ADDRESS_DATA_ENTRY; } /** * Returns the number of tokens burned by or on behalf of `owner`. */ function _numberBurned(address owner) internal view returns (uint256) { return (_packedAddressData[owner] >> BITPOS_NUMBER_BURNED) & BITMASK_ADDRESS_DATA_ENTRY; } /** * Returns the auxiliary data for `owner`. (e.g. number of whitelist mint slots used). */ function _getAux(address owner) internal view returns (uint64) { return uint64(_packedAddressData[owner] >> BITPOS_AUX); } /** * Sets the auxiliary 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 { uint256 packed = _packedAddressData[owner]; uint256 auxCasted; assembly { // Cast aux without masking. auxCasted := aux } packed = (packed & BITMASK_AUX_COMPLEMENT) | (auxCasted << BITPOS_AUX); _packedAddressData[owner] = packed; } /** * Returns the packed ownership data of `tokenId`. */ function _packedOwnershipOf(uint256 tokenId) private view returns (uint256) { uint256 curr = tokenId; unchecked { if (_startTokenId() <= curr) if (curr < _currentIndex) { uint256 packed = _packedOwnerships[curr]; // If not burned. if (packed & BITMASK_BURNED == 0) { // 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. // // We can directly compare the packed value. // If the address is zero, packed is zero. while (packed == 0) { packed = _packedOwnerships[--curr]; } return packed; } } } revert OwnerQueryForNonexistentToken(); } /** * Returns the unpacked `TokenOwnership` struct from `packed`. */ function _unpackedOwnership(uint256 packed) private pure returns (TokenOwnership memory ownership) { ownership.addr = address(uint160(packed)); ownership.startTimestamp = uint64(packed >> BITPOS_START_TIMESTAMP); ownership.burned = packed & BITMASK_BURNED != 0; } /** * Returns the unpacked `TokenOwnership` struct at `index`. */ function _ownershipAt(uint256 index) internal view returns (TokenOwnership memory) { return _unpackedOwnership(_packedOwnerships[index]); } /** * @dev Initializes the ownership slot minted at `index` for efficiency purposes. */ function _initializeOwnershipAt(uint256 index) internal { if (_packedOwnerships[index] == 0) { _packedOwnerships[index] = _packedOwnershipOf(index); } } /** * 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) { return _unpackedOwnership(_packedOwnershipOf(tokenId)); } /** * @dev See {IERC721-ownerOf}. */ function ownerOf(uint256 tokenId) public view override returns (address) { return address(uint160(_packedOwnershipOf(tokenId))); } /** * @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, _toString(tokenId))) : ''; } /** * @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, it can be overridden in child contracts. */ function _baseURI() internal view virtual returns (string memory) { return ''; } /** * @dev Casts the address to uint256 without masking. */ function _addressToUint256(address value) private pure returns (uint256 result) { assembly { result := value } } /** * @dev Casts the boolean to uint256 without branching. */ function _boolToUint256(bool value) private pure returns (uint256 result) { assembly { result := value } } /** * @dev See {IERC721-approve}. */ function approve(address to, uint256 tokenId) public override { address owner = address(uint160(_packedOwnershipOf(tokenId))); if (_msgSenderERC721A() != owner) if (!isApprovedForAll(owner, _msgSenderERC721A())) { revert ApprovalCallerNotOwnerNorApproved(); } _tokenApprovals[tokenId] = to; emit Approval(owner, to, tokenId); } /** * @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 == _msgSenderERC721A()) revert ApproveToCaller(); _operatorApprovals[_msgSenderERC721A()][operator] = approved; emit ApprovalForAll(_msgSenderERC721A(), 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.code.length != 0) 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 && // If within bounds, _packedOwnerships[tokenId] & BITMASK_BURNED == 0; // and not 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 for each mint. */ function _safeMint( address to, uint256 quantity, bytes memory _data ) internal { _mint(to, quantity); unchecked { if (to.code.length != 0) { uint256 end = _currentIndex; uint256 index = end - quantity; do { if (!_checkContractOnERC721Received(address(0), to, index++, _data)) { revert TransferToNonERC721ReceiverImplementer(); } } while (index < end); // Reentrancy protection. if (_currentIndex != end) revert(); } } } /** * @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 for each mint. */ function _mint(address to, uint256 quantity) internal { uint256 startTokenId = _currentIndex; if (_addressToUint256(to) == 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 { // Updates: // - `balance += quantity`. // - `numberMinted += quantity`. // // We can directly add to the balance and number minted. _packedAddressData[to] += quantity * ((1 << BITPOS_NUMBER_MINTED) | 1); // Updates: // - `address` to the owner. // - `startTimestamp` to the timestamp of minting. // - `burned` to `false`. // - `nextInitialized` to `quantity == 1`. _packedOwnerships[startTokenId] = _addressToUint256(to) | (block.timestamp << BITPOS_START_TIMESTAMP) | (_boolToUint256(quantity == 1) << BITPOS_NEXT_INITIALIZED); uint256 offset; do { emit Transfer(address(0), to, startTokenId + offset++); } while (offset < quantity); _currentIndex = startTokenId + quantity; } _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 { uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId); if (address(uint160(prevOwnershipPacked)) != from) revert TransferFromIncorrectOwner(); address approvedAddress = _tokenApprovals[tokenId]; bool isApprovedOrOwner = (_msgSenderERC721A() == from || isApprovedForAll(from, _msgSenderERC721A()) || approvedAddress == _msgSenderERC721A()); if (!isApprovedOrOwner) revert TransferCallerNotOwnerNorApproved(); if (_addressToUint256(to) == 0) revert TransferToZeroAddress(); _beforeTokenTransfers(from, to, tokenId, 1); // Clear approvals from the previous owner. if (_addressToUint256(approvedAddress) != 0) { delete _tokenApprovals[tokenId]; } // 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 { // We can directly increment and decrement the balances. --_packedAddressData[from]; // Updates: `balance -= 1`. ++_packedAddressData[to]; // Updates: `balance += 1`. // Updates: // - `address` to the next owner. // - `startTimestamp` to the timestamp of transfering. // - `burned` to `false`. // - `nextInitialized` to `true`. _packedOwnerships[tokenId] = _addressToUint256(to) | (block.timestamp << BITPOS_START_TIMESTAMP) | BITMASK_NEXT_INITIALIZED; // If the next slot may not have been initialized (i.e. `nextInitialized == false`) . if (prevOwnershipPacked & BITMASK_NEXT_INITIALIZED == 0) { uint256 nextTokenId = tokenId + 1; // If the next slot's address is zero and not burned (i.e. packed value is zero). if (_packedOwnerships[nextTokenId] == 0) { // If the next slot is within bounds. if (nextTokenId != _currentIndex) { // Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`. _packedOwnerships[nextTokenId] = prevOwnershipPacked; } } } } 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 { uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId); address from = address(uint160(prevOwnershipPacked)); address approvedAddress = _tokenApprovals[tokenId]; if (approvalCheck) { bool isApprovedOrOwner = (_msgSenderERC721A() == from || isApprovedForAll(from, _msgSenderERC721A()) || approvedAddress == _msgSenderERC721A()); if (!isApprovedOrOwner) revert TransferCallerNotOwnerNorApproved(); } _beforeTokenTransfers(from, address(0), tokenId, 1); // Clear approvals from the previous owner. if (_addressToUint256(approvedAddress) != 0) { delete _tokenApprovals[tokenId]; } // 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 { // Updates: // - `balance -= 1`. // - `numberBurned += 1`. // // We can directly decrement the balance, and increment the number burned. // This is equivalent to `packed -= 1; packed += 1 << BITPOS_NUMBER_BURNED;`. _packedAddressData[from] += (1 << BITPOS_NUMBER_BURNED) - 1; // Updates: // - `address` to the last owner. // - `startTimestamp` to the timestamp of burning. // - `burned` to `true`. // - `nextInitialized` to `true`. _packedOwnerships[tokenId] = _addressToUint256(from) | (block.timestamp << BITPOS_START_TIMESTAMP) | BITMASK_BURNED | BITMASK_NEXT_INITIALIZED; // If the next slot may not have been initialized (i.e. `nextInitialized == false`) . if (prevOwnershipPacked & BITMASK_NEXT_INITIALIZED == 0) { uint256 nextTokenId = tokenId + 1; // If the next slot's address is zero and not burned (i.e. packed value is zero). if (_packedOwnerships[nextTokenId] == 0) { // If the next slot is within bounds. if (nextTokenId != _currentIndex) { // Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`. _packedOwnerships[nextTokenId] = prevOwnershipPacked; } } } } 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 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(_msgSenderERC721A(), 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 {} /** * @dev Returns the message sender (defaults to `msg.sender`). * * If you are writing GSN compatible contracts, you need to override this function. */ function _msgSenderERC721A() internal view virtual returns (address) { return msg.sender; } /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function _toString(uint256 value) internal pure returns (string memory ptr) { assembly { // The maximum value of a uint256 contains 78 digits (1 byte per digit), // but we allocate 128 bytes to keep the free memory pointer 32-byte word aliged. // We will need 1 32-byte word to store the length, // and 3 32-byte words to store a maximum of 78 digits. Total: 32 + 3 * 32 = 128. ptr := add(mload(0x40), 128) // Update the free memory pointer to allocate. mstore(0x40, ptr) // Cache the end of the memory to calculate the length later. let end := ptr // We write the string from the rightmost digit to the leftmost digit. // The following is essentially a do-while loop that also handles the zero case. // Costs a bit more than early returning for the zero case, // but cheaper in terms of deployment and overall runtime costs. for { // Initialize and perform the first pass without check. let temp := value // Move the pointer 1 byte leftwards to point to an empty character slot. ptr := sub(ptr, 1) // Write the character to the pointer. 48 is the ASCII index of '0'. mstore8(ptr, add(48, mod(temp, 10))) temp := div(temp, 10) } temp { // Keep dividing `temp` until zero. temp := div(temp, 10) } { // Body of the for loop. ptr := sub(ptr, 1) mstore8(ptr, add(48, mod(temp, 10))) } let length := sub(end, ptr) // Move the pointer 32 bytes leftwards to make room for the length. ptr := sub(ptr, 32) // Store the length. mstore(ptr, length) } } }
// SPDX-License-Identifier: MIT // ERC721A Contracts v4.0.0 // Creator: Chiru Labs pragma solidity ^0.8.4; /** * @dev Interface of an ERC721A compliant contract. */ interface IERC721A { /** * 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(); /** * 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(); struct TokenOwnership { // The address of the owner. address addr; // Keeps track of the start time of ownership with minimal overhead for tokenomics. uint64 startTimestamp; uint8 mintable; // Whether the token has been burned. bool burned; } /** * @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); // ============================== // 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); // ============================== // IERC721 // ============================== /** * @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`. * * 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; /** * @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 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 the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @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); // ============================== // IERC721Metadata // ============================== /** * @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 (last updated v4.6.0) (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 `IERC721Receiver.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; interface IOperatorFilterRegistry { function isOperatorAllowed(address registrant, address operator) external view returns (bool); function register(address registrant) external; function registerAndSubscribe(address registrant, address subscription) external; function registerAndCopyEntries(address registrant, address registrantToCopy) external; function unregister(address addr) 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 // secondary sales royalties on rarible // pragma solidity ^0.8.0; library LibPart { bytes32 public constant TYPE_HASH = keccak256("Part(address account,uint96 value)"); struct Part { address payable account; uint96 value; } function hash(Part memory part) internal pure returns (bytes32) { return keccak256(abi.encode(TYPE_HASH, part.account, part.value)); } }
// SPDX-License-Identifier: MIT // secondary sales royalties on rarible pragma solidity ^0.8.0; library LibRoyaltiesV2 { /* * bytes4(keccak256('getRaribleV2Royalties(uint256)')) == 0xcad96cca */ bytes4 constant _INTERFACE_ID_ROYALTIES = 0xcad96cca; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10**64) { value /= 10**64; result += 64; } if (value >= 10**32) { value /= 10**32; result += 32; } if (value >= 10**16) { value /= 10**16; result += 16; } if (value >= 10**8) { value /= 10**8; result += 8; } if (value >= 10**4) { value /= 10**4; result += 4; } if (value >= 10**2) { value /= 10**2; result += 2; } if (value >= 10**1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import {IOperatorFilterRegistry} from "./IOperatorFilterRegistry.sol"; abstract 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(address from) virtual { // Check registry code length to facilitate testing in environments without a deployed registry. if (address(operatorFilterRegistry).code.length > 0) { // Allow spending tokens from addresses with balance // Note that this still allows listings and marketplaces with escrow to transfer tokens if transferred // from an EOA. if (from == msg.sender) { _; return; } if ( !( operatorFilterRegistry.isOperatorAllowed(address(this), msg.sender) && operatorFilterRegistry.isOperatorAllowed(address(this), from) ) ) { 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 (last updated v4.7.0) (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 Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { 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() external { 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"; /** * @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 (last updated v4.8.0) (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() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: MIT // secondary sales royalties on rarible pragma solidity ^0.8.0; import "./LibPart.sol"; interface RoyaltiesV2 { event RoyaltiesSet(uint256 tokenId, LibPart.Part[] royalties); function getRaribleV2Royalties(uint256 id) external view returns (LibPart.Part[] memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./AbstractRoyalties.sol"; import "./RoyaltiesV2.sol"; contract RoyaltiesV2Impl is AbstractRoyalties, RoyaltiesV2 { function getRaribleV2Royalties(uint256 id) override external view returns (LibPart.Part[] memory) { LibPart.Part[] memory _royalties = royalties[id]; if(_royalties.length > 0) { return royalties[id]; } _royalties = royalties[0]; return _royalties; } function _onRoyaltiesSet(uint256 id, LibPart.Part[] memory _royalties) override internal { emit RoyaltiesSet(id, _royalties); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./Math.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @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] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"string","name":"_cid","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ApprovalCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"ApprovalQueryForNonexistentToken","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":false,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"gas","type":"uint256"}],"name":"Received","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"components":[{"internalType":"address payable","name":"account","type":"address"},{"internalType":"uint96","name":"value","type":"uint96"}],"indexed":false,"internalType":"struct LibPart.Part[]","name":"royalties","type":"tuple[]"}],"name":"RoyaltiesSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"_baseExtension","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","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":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bool","name":"approvalCheck","type":"bool"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getCIDForToken","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getRaribleV2Royalties","outputs":[{"components":[{"internalType":"address payable","name":"account","type":"address"},{"internalType":"uint96","name":"value","type":"uint96"}],"internalType":"struct LibPart.Part[]","name":"","type":"tuple[]"}],"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":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_quantity","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","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":"bool","name":"_state","type":"bool"}],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"royaltyAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_cid","type":"string"},{"internalType":"uint256","name":"_rangeNo","type":"uint256"}],"name":"setCIDforRange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"maxFistGenMintBatchSize","type":"uint256"},{"internalType":"uint256","name":"maxFirstGenTokens","type":"uint256"}],"name":"setMintConstraints","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"address payable","name":"_royaltiesRecipientAddress","type":"address"},{"internalType":"uint96","name":"_percentageBasisPoints","type":"uint96"}],"name":"setRoyalties","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":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60806040526000600b60006101000a81548160ff02191690831515021790555060fa600c55612710600d553480156200003757600080fd5b506040516200544e3803806200544e83398181016040528101906200005d9190620006b6565b733cc6cdda760b79bafa08df41ecfa224f810dceb660016040518060400160405280600a81526020017f4d415947205359474e45000000000000000000000000000000000000000000008152506040518060400160405280600b81526020017f4d4159475f3232313230330000000000000000000000000000000000000000008152508160029081620000f1919062000952565b50806003908162000103919062000952565b50620001146200035560201b60201c565b60008190555050506200013c620001306200035e60201b60201c565b6200036660201b60201c565b600160098190555060006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b111562000339578015620001ff576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff16637d3e3dbe30846040518363ffffffff1660e01b8152600401620001c592919062000a7e565b600060405180830381600087803b158015620001e057600080fd5b505af1158015620001f5573d6000803e3d6000fd5b5050505062000338565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614620002b9576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663a0af290330846040518363ffffffff1660e01b81526004016200027f92919062000a7e565b600060405180830381600087803b1580156200029a57600080fd5b505af1158015620002af573d6000803e3d6000fd5b5050505062000337565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff16634420e486306040518263ffffffff1660e01b815260040162000302919062000aab565b600060405180830381600087803b1580156200031d57600080fd5b505af115801562000332573d6000803e3d6000fd5b505050505b5b5b50506200034e8160006200042c60201b60201c565b5062000b7a565b60006001905090565b600033905090565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6200043c6200046860201b60201c565b81600e826014811062000454576200045362000ac8565b5b01908162000463919062000952565b505050565b620004786200035e60201b60201c565b73ffffffffffffffffffffffffffffffffffffffff166200049e620004f960201b60201c565b73ffffffffffffffffffffffffffffffffffffffff1614620004f7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620004ee9062000b58565b60405180910390fd5b565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6200058c8262000541565b810181811067ffffffffffffffff82111715620005ae57620005ad62000552565b5b80604052505050565b6000620005c362000523565b9050620005d1828262000581565b919050565b600067ffffffffffffffff821115620005f457620005f362000552565b5b620005ff8262000541565b9050602081019050919050565b60005b838110156200062c5780820151818401526020810190506200060f565b60008484015250505050565b60006200064f6200064984620005d6565b620005b7565b9050828152602081018484840111156200066e576200066d6200053c565b5b6200067b8482856200060c565b509392505050565b600082601f8301126200069b576200069a62000537565b5b8151620006ad84826020860162000638565b91505092915050565b600060208284031215620006cf57620006ce6200052d565b5b600082015167ffffffffffffffff811115620006f057620006ef62000532565b5b620006fe8482850162000683565b91505092915050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806200075a57607f821691505b60208210810362000770576200076f62000712565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302620007da7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826200079b565b620007e686836200079b565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b6000620008336200082d6200082784620007fe565b62000808565b620007fe565b9050919050565b6000819050919050565b6200084f8362000812565b620008676200085e826200083a565b848454620007a8565b825550505050565b600090565b6200087e6200086f565b6200088b81848462000844565b505050565b5b81811015620008b357620008a760008262000874565b60018101905062000891565b5050565b601f8211156200090257620008cc8162000776565b620008d7846200078b565b81016020851015620008e7578190505b620008ff620008f6856200078b565b83018262000890565b50505b505050565b600082821c905092915050565b6000620009276000198460080262000907565b1980831691505092915050565b600062000942838362000914565b9150826002028217905092915050565b6200095d8262000707565b67ffffffffffffffff81111562000979576200097862000552565b5b62000985825462000741565b62000992828285620008b7565b600060209050601f831160018114620009ca5760008415620009b5578287015190505b620009c1858262000934565b86555062000a31565b601f198416620009da8662000776565b60005b8281101562000a0457848901518255600182019150602085019450602081019050620009dd565b8683101562000a24578489015162000a20601f89168262000914565b8355505b6001600288020188555050505b505050505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600062000a668262000a39565b9050919050565b62000a788162000a59565b82525050565b600060408201905062000a95600083018562000a6d565b62000aa4602083018462000a6d565b9392505050565b600060208201905062000ac2600083018462000a6d565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082825260208201905092915050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b600062000b4060208362000af7565b915062000b4d8262000b08565b602082019050919050565b6000602082019050818103600083015262000b738162000b31565b9050919050565b6148c48062000b8a6000396000f3fe608060405234801561001057600080fd5b50600436106101da5760003560e01c80635c975abb116101045780639fac68cb116100a2578063cad96cca11610071578063cad96cca14610540578063e985e9c514610570578063ed6bd3ed146105a0578063f2fde38b146105bc576101da565b80639fac68cb146104bc578063a22cb465146104d8578063b88d4fde146104f4578063c87b56dd14610510576101da565b8063715018a6116100de578063715018a6146104465780638da5cb5b146104505780638ece17871461046e57806395d89b411461049e576101da565b80635c975abb146103c85780636352211e146103e657806370a0823114610416576101da565b806318160ddd1161017c578063340403131161014b578063340403131461036a5780633ccfd60b1461038657806340c10f191461039057806342842e0e146103ac576101da565b806318160ddd146102e157806323b872dd146102ff5780632672c9021461031b5780632a55205a14610339576101da565b8063081812fc116101b8578063081812fc14610249578063095ea7b314610279578063143094db14610295578063150b7a02146102b1576101da565b806301ffc9a7146101df57806302329a291461020f57806306fdde031461022b575b600080fd5b6101f960048036038101906101f491906132c0565b6105d8565b6040516102069190613308565b60405180910390f35b6102296004803603810190610224919061334f565b610695565b005b6102336106ba565b604051610240919061340c565b60405180910390f35b610263600480360381019061025e9190613464565b61074c565b60405161027091906134d2565b60405180910390f35b610293600480360381019061028e9190613519565b6107c8565b005b6102af60048036038101906102aa91906135db565b610909565b005b6102cb60048036038101906102c69190613763565b610a10565b6040516102d891906137f5565b60405180910390f35b6102e9610a65565b6040516102f6919061381f565b60405180910390f35b6103196004803603810190610314919061383a565b610a7c565b005b610323610c5e565b604051610330919061340c565b60405180910390f35b610353600480360381019061034e919061388d565b610c97565b6040516103619291906138cd565b60405180910390f35b610384600480360381019061037f919061388d565b610f96565b005b61038e610fb0565b005b6103aa60048036038101906103a59190613519565b611041565b005b6103c660048036038101906103c1919061383a565b611156565b005b6103d0611338565b6040516103dd9190613308565b60405180910390f35b61040060048036038101906103fb9190613464565b61134b565b60405161040d91906134d2565b60405180910390f35b610430600480360381019061042b91906138f6565b61135d565b60405161043d919061381f565b60405180910390f35b61044e6113f1565b005b610458611405565b60405161046591906134d2565b60405180910390f35b61048860048036038101906104839190613464565b61142f565b604051610495919061340c565b60405180910390f35b6104a6611449565b6040516104b3919061340c565b60405180910390f35b6104d660048036038101906104d19190613923565b6114db565b005b6104f260048036038101906104ed9190613963565b6114f1565b005b61050e60048036038101906105099190613763565b611668565b005b61052a60048036038101906105259190613464565b61184d565b604051610537919061340c565b60405180910390f35b61055a60048036038101906105559190613464565b6118d1565b6040516105679190613a9f565b60405180910390f35b61058a60048036038101906105859190613ac1565b611be0565b6040516105979190613308565b60405180910390f35b6105ba60048036038101906105b59190613ba2565b611c74565b005b6105d660048036038101906105d191906138f6565b611ca3565b005b600063cad96cca60e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19160361062f5760019050610690565b632a55205a60e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916036106845760019050610690565b61068d82611d26565b90505b919050565b61069d611db8565b80600b60006101000a81548160ff02191690831515021790555050565b6060600280546106c990613c2d565b80601f01602080910402602001604051908101604052809291908181526020018280546106f590613c2d565b80156107425780601f1061071757610100808354040283529160200191610742565b820191906000526020600020905b81548152906001019060200180831161072557829003601f168201915b5050505050905090565b600061075782611e36565b61078d576040517fcf4700e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6006600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b60006107d382611e95565b90508073ffffffffffffffffffffffffffffffffffffffff166107f4611f61565b73ffffffffffffffffffffffffffffffffffffffff1614610857576108208161081b611f61565b611be0565b610856576040517fcfb3b94200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b826006600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b610911611db8565b6000600167ffffffffffffffff81111561092e5761092d613638565b5b60405190808252806020026020018201604052801561096757816020015b610954613216565b81526020019060019003908161094c5790505b509050818160008151811061097f5761097e613c5e565b5b6020026020010151602001906bffffffffffffffffffffffff1690816bffffffffffffffffffffffff168152505082816000815181106109c2576109c1613c5e565b5b60200260200101516000019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050610a0a8482611f69565b50505050565b60007f28fa6e16458f9c24aa59ddd4085264573006dbe30304837873c7deafc702b03885858585614e20604051610a4b959493929190613d27565b60405180910390a163150b7a0260e01b9050949350505050565b6000610a6f6121ea565b6001546000540303905090565b8260006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b1115610c4c573373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610aee57610ae98484846121f3565b610c58565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430336040518363ffffffff1660e01b8152600401610b37929190613d81565b602060405180830381865afa158015610b54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b789190613dbf565b8015610c0a57506daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b8152600401610bc8929190613d81565b602060405180830381865afa158015610be5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c099190613dbf565b5b610c4b57336040517fede71dcc000000000000000000000000000000000000000000000000000000008152600401610c4291906134d2565b60405180910390fd5b5b610c578484846121f3565b5b50505050565b6040518060400160405280600581526020017f2e6a736f6e00000000000000000000000000000000000000000000000000000081525081565b6000806000600a6000868152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b82821015610d91578382906000526020600020016040518060400160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff166bffffffffffffffffffffffff168152505081526020019060010190610ccf565b505050509050600081511115610e115780600081518110610db557610db4613c5e565b5b60200260200101516000015161271082600081518110610dd857610dd7613c5e565b5b6020026020010151602001516bffffffffffffffffffffffff1686610dfd9190613e1b565b610e079190613e8c565b9250925050610f8f565b600a6000808152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b82821015610f06578382906000526020600020016040518060400160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff166bffffffffffffffffffffffff168152505081526020019060010190610e44565b505050509050600081511115610f865780600081518110610f2a57610f29613c5e565b5b60200260200101516000015161271082600081518110610f4d57610f4c613c5e565b5b6020026020010151602001516bffffffffffffffffffffffff1686610f729190613e1b565b610f7c9190613e8c565b9250925050610f8f565b60008092509250505b9250929050565b610f9e611db8565b81600c8190555080600d819055505050565b610fb8611db8565b610fc0612203565b60003373ffffffffffffffffffffffffffffffffffffffff1647604051610fe690613eee565b60006040518083038185875af1925050503d8060008114611023576040519150601f19603f3d011682016040523d82523d6000602084013e611028565b606091505b505090508061103657600080fd5b5061103f612252565b565b611049611db8565b600b60009054906101000a900460ff161561106357600080fd5b600081116110a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161109d90613f4f565b60405180910390fd5b600c548111156110eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110e290613fe1565b60405180910390fd5b60006110f5610a65565b9050600d5482826111069190614001565b1115611147576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161113e906140a7565b60405180910390fd5b611151838361225c565b505050565b8260006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b1115611326573373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036111c8576111c384848461227a565b611332565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430336040518363ffffffff1660e01b8152600401611211929190613d81565b602060405180830381865afa15801561122e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112529190613dbf565b80156112e457506daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b81526004016112a2929190613d81565b602060405180830381865afa1580156112bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e39190613dbf565b5b61132557336040517fede71dcc00000000000000000000000000000000000000000000000000000000815260040161131c91906134d2565b60405180910390fd5b5b61133184848461227a565b5b50505050565b600b60009054906101000a900460ff1681565b600061135682611e95565b9050919050565b6000806113698361229a565b036113a0576040517f8f4eb60400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054169050919050565b6113f9611db8565b61140360006122a4565b565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6060611439611db8565b6114428261236a565b9050919050565b60606003805461145890613c2d565b80601f016020809104026020016040519081016040528092919081815260200182805461148490613c2d565b80156114d15780601f106114a6576101008083540402835291602001916114d1565b820191906000526020600020905b8154815290600101906020018083116114b457829003601f168201915b5050505050905090565b6114e3611db8565b6114ed82826124b6565b5050565b6114f9611f61565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361155d576040517fb06307db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806007600061156a611f61565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff16611617611f61565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405161165c9190613308565b60405180910390a35050565b8360006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b1115611839573373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036116db576116d6858585856127ce565b611846565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430336040518363ffffffff1660e01b8152600401611724929190613d81565b602060405180830381865afa158015611741573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117659190613dbf565b80156117f757506daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b81526004016117b5929190613d81565b602060405180830381865afa1580156117d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117f69190613dbf565b5b61183857336040517fede71dcc00000000000000000000000000000000000000000000000000000000815260040161182f91906134d2565b60405180910390fd5b5b611845858585856127ce565b5b5050505050565b6060600061185a8361236a565b9050600061186784612841565b9050600082826040518060400160405280600581526020017f2e6a736f6e0000000000000000000000000000000000000000000000000000008152506040516020016118b593929190614103565b6040516020818303038152906040529050809350505050919050565b60606000600a6000848152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b828210156119ca578382906000526020600020016040518060400160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff166bffffffffffffffffffffffff168152505081526020019060010190611908565b505050509050600081511115611adb57600a6000848152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b82821015611acf578382906000526020600020016040518060400160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff166bffffffffffffffffffffffff168152505081526020019060010190611a0d565b50505050915050611bdb565b600a6000808152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b82821015611bd0578382906000526020600020016040518060400160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff166bffffffffffffffffffffffff168152505081526020019060010190611b0e565b505050509050809150505b919050565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b611c7c611db8565b81600e8260148110611c9157611c90613c5e565b5b019081611c9e91906142d6565b505050565b611cab611db8565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611d1a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d119061441a565b60405180910390fd5b611d23816122a4565b50565b60006301ffc9a760e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480611d8157506380ac58cd60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80611db15750635b5e139f60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b611dc061290f565b73ffffffffffffffffffffffffffffffffffffffff16611dde611405565b73ffffffffffffffffffffffffffffffffffffffff1614611e34576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e2b90614486565b60405180910390fd5b565b600081611e416121ea565b11158015611e50575060005482105b8015611e8e575060007c0100000000000000000000000000000000000000000000000000000000600460008581526020019081526020016000205416145b9050919050565b60008082905080611ea46121ea565b11611f2a57600054811015611f295760006004600083815260200190815260200160002054905060007c0100000000000000000000000000000000000000000000000000000000821603611f27575b60008103611f1d576004600083600190039350838152602001908152602001600020549050611ef3565b8092505050611f5c565b505b5b6040517fdf2d9b4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b600033905090565b600080600090505b825181101561219657600073ffffffffffffffffffffffffffffffffffffffff16838281518110611fa557611fa4613c5e565b5b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1603612007576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ffe906144f2565b60405180910390fd5b600083828151811061201c5761201b613c5e565b5b6020026020010151602001516bffffffffffffffffffffffff1603612076576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161206d9061455e565b60405180910390fd5b82818151811061208957612088613c5e565b5b6020026020010151602001516bffffffffffffffffffffffff16826120ae9190614001565b9150600a60008581526020019081526020016000208382815181106120d6576120d5613c5e565b5b60200260200101519080600181540180825580915050600190039060005260206000200160009091909190915060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055505050808061218e9061457e565b915050611f71565b5061271081106121db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121d290614638565b60405180910390fd5b6121e58383612917565b505050565b60006001905090565b6121fe838383612954565b505050565b600260095403612248576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161223f906146a4565b60405180910390fd5b6002600981905550565b6001600981905550565b612276828260405180602001604052806000815250612d19565b5050565b61229583838360405180602001604052806000815250611668565b505050565b6000819050919050565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6060600082116123af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123a690614710565b60405180910390fd5b60006101f46001846123c19190614730565b6123cb9190613e8c565b905060148110612410576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612407906147b0565b60405180910390fd5b600e816014811061242457612423613c5e565b5b01805461243090613c2d565b80601f016020809104026020016040519081016040528092919081815260200182805461245c90613c2d565b80156124a95780601f1061247e576101008083540402835291602001916124a9565b820191906000526020600020905b81548152906001019060200180831161248c57829003601f168201915b5050505050915050919050565b60006124c183611e95565b9050600081905060006006600086815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905083156125ce5760008273ffffffffffffffffffffffffffffffffffffffff16612527611f61565b73ffffffffffffffffffffffffffffffffffffffff161480612556575061255583612550611f61565b611be0565b5b806125935750612564611f61565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050806125cc576040517f59c896be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b6125dc826000876001612db6565b60006125e78261229a565b14612623576006600086815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690555b600160806001901b03600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055507c02000000000000000000000000000000000000000000000000000000007c010000000000000000000000000000000000000000000000000000000060a042901b6126c28561229a565b171717600460008781526020019081526020016000208190555060007c020000000000000000000000000000000000000000000000000000000084160361274b5760006001860190506000600460008381526020019081526020016000205403612749576000548114612748578360046000838152602001908152602001600020819055505b5b505b84600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46127b5826000876001612dbc565b6001600081548092919060010191905055505050505050565b6127d9848484612954565b60008373ffffffffffffffffffffffffffffffffffffffff163b1461283b5761280484848484612dc2565b61283a576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b50505050565b60606000600161285084612f12565b01905060008167ffffffffffffffff81111561286f5761286e613638565b5b6040519080825280601f01601f1916602001820160405280156128a15781602001600182028036833780820191505090505b509050600082602001820190505b600115612904578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a85816128f8576128f7613e5d565b5b049450600085036128af575b819350505050919050565b600033905090565b7f3fa96d7b6bcbfe71ef171666d84db3cf52fa2d1c8afdb1cc8e486177f208b7df82826040516129489291906147d0565b60405180910390a15050565b600061295f82611e95565b90508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146129c6576040517fa114810000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006006600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008573ffffffffffffffffffffffffffffffffffffffff16612a1f611f61565b73ffffffffffffffffffffffffffffffffffffffff161480612a4e5750612a4d86612a48611f61565b611be0565b5b80612a8b5750612a5c611f61565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b905080612ac4576040517f59c896be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612acf8661229a565b03612b06576040517fea553b3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612b138686866001612db6565b6000612b1e8361229a565b14612b5a576006600085815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690555b600560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600081546001900391905081905550600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008154600101919050819055507c020000000000000000000000000000000000000000000000000000000060a042901b612c218761229a565b1717600460008681526020019081526020016000208190555060007c0200000000000000000000000000000000000000000000000000000000841603612ca95760006001850190506000600460008381526020019081526020016000205403612ca7576000548114612ca6578360046000838152602001908152602001600020819055505b5b505b838573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4612d118686866001612dbc565b505050505050565b612d238383613065565b60008373ffffffffffffffffffffffffffffffffffffffff163b14612db157600080549050600083820390505b612d636000868380600101945086612dc2565b612d99576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b818110612d50578160005414612dae57600080fd5b50505b505050565b50505050565b50505050565b60008373ffffffffffffffffffffffffffffffffffffffff1663150b7a02612de8611f61565b8786866040518563ffffffff1660e01b8152600401612e0a9493929190614800565b6020604051808303816000875af1925050508015612e4657506040513d601f19601f82011682018060405250810190612e439190614861565b60015b612ebf573d8060008114612e76576040519150601f19603f3d011682016040523d82523d6000602084013e612e7b565b606091505b506000815103612eb7576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050949350505050565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310612f70577a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008381612f6657612f65613e5d565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310612fad576d04ee2d6d415b85acef81000000008381612fa357612fa2613e5d565b5b0492506020810190505b662386f26fc100008310612fdc57662386f26fc100008381612fd257612fd1613e5d565b5b0492506010810190505b6305f5e1008310613005576305f5e1008381612ffb57612ffa613e5d565b5b0492506008810190505b612710831061302a5761271083816130205761301f613e5d565b5b0492506004810190505b6064831061304d576064838161304357613042613e5d565b5b0492506002810190505b600a831061305c576001810190505b80915050919050565b60008054905060006130768461229a565b036130ad576040517f2e07630000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082036130e7576040517fb562e8dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6130f46000848385612db6565b600160406001901b178202600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555060e16131596001841461320c565b901b60a042901b6131698561229a565b1717600460008381526020019081526020016000208190555060005b8080600101915082018473ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a482811061318557828201600081905550506132076000848385612dbc565b505050565b6000819050919050565b6040518060400160405280600073ffffffffffffffffffffffffffffffffffffffff16815260200160006bffffffffffffffffffffffff1681525090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61329d81613268565b81146132a857600080fd5b50565b6000813590506132ba81613294565b92915050565b6000602082840312156132d6576132d561325e565b5b60006132e4848285016132ab565b91505092915050565b60008115159050919050565b613302816132ed565b82525050565b600060208201905061331d60008301846132f9565b92915050565b61332c816132ed565b811461333757600080fd5b50565b60008135905061334981613323565b92915050565b6000602082840312156133655761336461325e565b5b60006133738482850161333a565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156133b657808201518184015260208101905061339b565b60008484015250505050565b6000601f19601f8301169050919050565b60006133de8261337c565b6133e88185613387565b93506133f8818560208601613398565b613401816133c2565b840191505092915050565b6000602082019050818103600083015261342681846133d3565b905092915050565b6000819050919050565b6134418161342e565b811461344c57600080fd5b50565b60008135905061345e81613438565b92915050565b60006020828403121561347a5761347961325e565b5b60006134888482850161344f565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006134bc82613491565b9050919050565b6134cc816134b1565b82525050565b60006020820190506134e760008301846134c3565b92915050565b6134f6816134b1565b811461350157600080fd5b50565b600081359050613513816134ed565b92915050565b600080604083850312156135305761352f61325e565b5b600061353e85828601613504565b925050602061354f8582860161344f565b9150509250929050565b600061356482613491565b9050919050565b61357481613559565b811461357f57600080fd5b50565b6000813590506135918161356b565b92915050565b60006bffffffffffffffffffffffff82169050919050565b6135b881613597565b81146135c357600080fd5b50565b6000813590506135d5816135af565b92915050565b6000806000606084860312156135f4576135f361325e565b5b60006136028682870161344f565b935050602061361386828701613582565b9250506040613624868287016135c6565b9150509250925092565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b613670826133c2565b810181811067ffffffffffffffff8211171561368f5761368e613638565b5b80604052505050565b60006136a2613254565b90506136ae8282613667565b919050565b600067ffffffffffffffff8211156136ce576136cd613638565b5b6136d7826133c2565b9050602081019050919050565b82818337600083830152505050565b6000613706613701846136b3565b613698565b90508281526020810184848401111561372257613721613633565b5b61372d8482856136e4565b509392505050565b600082601f83011261374a5761374961362e565b5b813561375a8482602086016136f3565b91505092915050565b6000806000806080858703121561377d5761377c61325e565b5b600061378b87828801613504565b945050602061379c87828801613504565b93505060406137ad8782880161344f565b925050606085013567ffffffffffffffff8111156137ce576137cd613263565b5b6137da87828801613735565b91505092959194509250565b6137ef81613268565b82525050565b600060208201905061380a60008301846137e6565b92915050565b6138198161342e565b82525050565b60006020820190506138346000830184613810565b92915050565b6000806000606084860312156138535761385261325e565b5b600061386186828701613504565b935050602061387286828701613504565b92505060406138838682870161344f565b9150509250925092565b600080604083850312156138a4576138a361325e565b5b60006138b28582860161344f565b92505060206138c38582860161344f565b9150509250929050565b60006040820190506138e260008301856134c3565b6138ef6020830184613810565b9392505050565b60006020828403121561390c5761390b61325e565b5b600061391a84828501613504565b91505092915050565b6000806040838503121561393a5761393961325e565b5b60006139488582860161344f565b92505060206139598582860161333a565b9150509250929050565b6000806040838503121561397a5761397961325e565b5b600061398885828601613504565b92505060206139998582860161333a565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6139d881613559565b82525050565b6139e781613597565b82525050565b604082016000820151613a0360008501826139cf565b506020820151613a1660208501826139de565b50505050565b6000613a2883836139ed565b60408301905092915050565b6000602082019050919050565b6000613a4c826139a3565b613a5681856139ae565b9350613a61836139bf565b8060005b83811015613a92578151613a798882613a1c565b9750613a8483613a34565b925050600181019050613a65565b5085935050505092915050565b60006020820190508181036000830152613ab98184613a41565b905092915050565b60008060408385031215613ad857613ad761325e565b5b6000613ae685828601613504565b9250506020613af785828601613504565b9150509250929050565b600067ffffffffffffffff821115613b1c57613b1b613638565b5b613b25826133c2565b9050602081019050919050565b6000613b45613b4084613b01565b613698565b905082815260208101848484011115613b6157613b60613633565b5b613b6c8482856136e4565b509392505050565b600082601f830112613b8957613b8861362e565b5b8135613b99848260208601613b32565b91505092915050565b60008060408385031215613bb957613bb861325e565b5b600083013567ffffffffffffffff811115613bd757613bd6613263565b5b613be385828601613b74565b9250506020613bf48582860161344f565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680613c4557607f821691505b602082108103613c5857613c57613bfe565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600081519050919050565b600082825260208201905092915050565b6000613cb482613c8d565b613cbe8185613c98565b9350613cce818560208601613398565b613cd7816133c2565b840191505092915050565b6000819050919050565b6000819050919050565b6000613d11613d0c613d0784613ce2565b613cec565b61342e565b9050919050565b613d2181613cf6565b82525050565b600060a082019050613d3c60008301886134c3565b613d4960208301876134c3565b613d566040830186613810565b8181036060830152613d688185613ca9565b9050613d776080830184613d18565b9695505050505050565b6000604082019050613d9660008301856134c3565b613da360208301846134c3565b9392505050565b600081519050613db981613323565b92915050565b600060208284031215613dd557613dd461325e565b5b6000613de384828501613daa565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000613e268261342e565b9150613e318361342e565b9250828202613e3f8161342e565b91508282048414831517613e5657613e55613dec565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000613e978261342e565b9150613ea28361342e565b925082613eb257613eb1613e5d565b5b828204905092915050565b600081905092915050565b50565b6000613ed8600083613ebd565b9150613ee382613ec8565b600082019050919050565b6000613ef982613ecb565b9150819050919050565b7f4d4159475f373231613a20696e76616c6964207175616e746974792c20300000600082015250565b6000613f39601e83613387565b9150613f4482613f03565b602082019050919050565b60006020820190508181036000830152613f6881613f2c565b9050919050565b7f4d4159475f373231613a20696e76616c6964207175616e746974792c20746f6f60008201527f206c617267650000000000000000000000000000000000000000000000000000602082015250565b6000613fcb602683613387565b9150613fd682613f6f565b604082019050919050565b60006020820190508181036000830152613ffa81613fbe565b9050919050565b600061400c8261342e565b91506140178361342e565b925082820190508082111561402f5761402e613dec565b5b92915050565b7f4d4159475f373231613a20696e76616c6964207175616e746974792c20746f6f60008201527f206d616e792066697273742067656e20746f6b656e7300000000000000000000602082015250565b6000614091603683613387565b915061409c82614035565b604082019050919050565b600060208201905081810360008301526140c081614084565b9050919050565b600081905092915050565b60006140dd8261337c565b6140e781856140c7565b93506140f7818560208601613398565b80840191505092915050565b600061410f82866140d2565b915061411b82856140d2565b915061412782846140d2565b9150819050949350505050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026141967fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82614159565b6141a08683614159565b95508019841693508086168417925050509392505050565b60006141d36141ce6141c98461342e565b613cec565b61342e565b9050919050565b6000819050919050565b6141ed836141b8565b6142016141f9826141da565b848454614166565b825550505050565b600090565b614216614209565b6142218184846141e4565b505050565b5b818110156142455761423a60008261420e565b600181019050614227565b5050565b601f82111561428a5761425b81614134565b61426484614149565b81016020851015614273578190505b61428761427f85614149565b830182614226565b50505b505050565b600082821c905092915050565b60006142ad6000198460080261428f565b1980831691505092915050565b60006142c6838361429c565b9150826002028217905092915050565b6142df8261337c565b67ffffffffffffffff8111156142f8576142f7613638565b5b6143028254613c2d565b61430d828285614249565b600060209050601f831160018114614340576000841561432e578287015190505b61433885826142ba565b8655506143a0565b601f19841661434e86614134565b60005b8281101561437657848901518255600182019150602085019450602081019050614351565b86831015614393578489015161438f601f89168261429c565b8355505b6001600288020188555050505b505050505050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000614404602683613387565b915061440f826143a8565b604082019050919050565b60006020820190508181036000830152614433816143f7565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000614470602083613387565b915061447b8261443a565b602082019050919050565b6000602082019050818103600083015261449f81614463565b9050919050565b7f526563697069656e742073686f756c642062652070726573656e740000000000600082015250565b60006144dc601b83613387565b91506144e7826144a6565b602082019050919050565b6000602082019050818103600083015261450b816144cf565b9050919050565b7f526f79616c74792076616c75652073686f756c6420626520706f736974697665600082015250565b6000614548602083613387565b915061455382614512565b602082019050919050565b600060208201905081810360008301526145778161453b565b9050919050565b60006145898261342e565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036145bb576145ba613dec565b5b600182019050919050565b7f526f79616c747920746f74616c2076616c75652073686f756c64206265203c2060008201527f3130303030000000000000000000000000000000000000000000000000000000602082015250565b6000614622602583613387565b915061462d826145c6565b604082019050919050565b6000602082019050818103600083015261465181614615565b9050919050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b600061468e601f83613387565b915061469982614658565b602082019050919050565b600060208201905081810360008301526146bd81614681565b9050919050565b7f746f6b656e4964206f66207a65726f206973206f7574206f662072616e676500600082015250565b60006146fa601f83613387565b9150614705826146c4565b602082019050919050565b60006020820190508181036000830152614729816146ed565b9050919050565b600061473b8261342e565b91506147468361342e565b925082820390508181111561475e5761475d613dec565b5b92915050565b7f6d697373696e67204349442076616c756520666f7220746f6b656e0000000000600082015250565b600061479a601b83613387565b91506147a582614764565b602082019050919050565b600060208201905081810360008301526147c98161478d565b9050919050565b60006040820190506147e56000830185613810565b81810360208301526147f78184613a41565b90509392505050565b600060808201905061481560008301876134c3565b61482260208301866134c3565b61482f6040830185613810565b81810360608301526148418184613ca9565b905095945050505050565b60008151905061485b81613294565b92915050565b6000602082840312156148775761487661325e565b5b60006148858482850161484c565b9150509291505056fea2646970667358221220a54fa0ae72a15494fc22efc8ddb9b17fa57cb1554149af36c8c090c40fb012cc64736f6c634300081100330000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000005068747470733a2f2f6d6179672e6d7970696e6174612e636c6f75642f697066732f516d646945314876506e6b4b655370633359334d673856544e545458447133365032364c687667545953644255352f00000000000000000000000000000000
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101da5760003560e01c80635c975abb116101045780639fac68cb116100a2578063cad96cca11610071578063cad96cca14610540578063e985e9c514610570578063ed6bd3ed146105a0578063f2fde38b146105bc576101da565b80639fac68cb146104bc578063a22cb465146104d8578063b88d4fde146104f4578063c87b56dd14610510576101da565b8063715018a6116100de578063715018a6146104465780638da5cb5b146104505780638ece17871461046e57806395d89b411461049e576101da565b80635c975abb146103c85780636352211e146103e657806370a0823114610416576101da565b806318160ddd1161017c578063340403131161014b578063340403131461036a5780633ccfd60b1461038657806340c10f191461039057806342842e0e146103ac576101da565b806318160ddd146102e157806323b872dd146102ff5780632672c9021461031b5780632a55205a14610339576101da565b8063081812fc116101b8578063081812fc14610249578063095ea7b314610279578063143094db14610295578063150b7a02146102b1576101da565b806301ffc9a7146101df57806302329a291461020f57806306fdde031461022b575b600080fd5b6101f960048036038101906101f491906132c0565b6105d8565b6040516102069190613308565b60405180910390f35b6102296004803603810190610224919061334f565b610695565b005b6102336106ba565b604051610240919061340c565b60405180910390f35b610263600480360381019061025e9190613464565b61074c565b60405161027091906134d2565b60405180910390f35b610293600480360381019061028e9190613519565b6107c8565b005b6102af60048036038101906102aa91906135db565b610909565b005b6102cb60048036038101906102c69190613763565b610a10565b6040516102d891906137f5565b60405180910390f35b6102e9610a65565b6040516102f6919061381f565b60405180910390f35b6103196004803603810190610314919061383a565b610a7c565b005b610323610c5e565b604051610330919061340c565b60405180910390f35b610353600480360381019061034e919061388d565b610c97565b6040516103619291906138cd565b60405180910390f35b610384600480360381019061037f919061388d565b610f96565b005b61038e610fb0565b005b6103aa60048036038101906103a59190613519565b611041565b005b6103c660048036038101906103c1919061383a565b611156565b005b6103d0611338565b6040516103dd9190613308565b60405180910390f35b61040060048036038101906103fb9190613464565b61134b565b60405161040d91906134d2565b60405180910390f35b610430600480360381019061042b91906138f6565b61135d565b60405161043d919061381f565b60405180910390f35b61044e6113f1565b005b610458611405565b60405161046591906134d2565b60405180910390f35b61048860048036038101906104839190613464565b61142f565b604051610495919061340c565b60405180910390f35b6104a6611449565b6040516104b3919061340c565b60405180910390f35b6104d660048036038101906104d19190613923565b6114db565b005b6104f260048036038101906104ed9190613963565b6114f1565b005b61050e60048036038101906105099190613763565b611668565b005b61052a60048036038101906105259190613464565b61184d565b604051610537919061340c565b60405180910390f35b61055a60048036038101906105559190613464565b6118d1565b6040516105679190613a9f565b60405180910390f35b61058a60048036038101906105859190613ac1565b611be0565b6040516105979190613308565b60405180910390f35b6105ba60048036038101906105b59190613ba2565b611c74565b005b6105d660048036038101906105d191906138f6565b611ca3565b005b600063cad96cca60e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19160361062f5760019050610690565b632a55205a60e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916036106845760019050610690565b61068d82611d26565b90505b919050565b61069d611db8565b80600b60006101000a81548160ff02191690831515021790555050565b6060600280546106c990613c2d565b80601f01602080910402602001604051908101604052809291908181526020018280546106f590613c2d565b80156107425780601f1061071757610100808354040283529160200191610742565b820191906000526020600020905b81548152906001019060200180831161072557829003601f168201915b5050505050905090565b600061075782611e36565b61078d576040517fcf4700e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6006600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b60006107d382611e95565b90508073ffffffffffffffffffffffffffffffffffffffff166107f4611f61565b73ffffffffffffffffffffffffffffffffffffffff1614610857576108208161081b611f61565b611be0565b610856576040517fcfb3b94200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b826006600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b610911611db8565b6000600167ffffffffffffffff81111561092e5761092d613638565b5b60405190808252806020026020018201604052801561096757816020015b610954613216565b81526020019060019003908161094c5790505b509050818160008151811061097f5761097e613c5e565b5b6020026020010151602001906bffffffffffffffffffffffff1690816bffffffffffffffffffffffff168152505082816000815181106109c2576109c1613c5e565b5b60200260200101516000019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050610a0a8482611f69565b50505050565b60007f28fa6e16458f9c24aa59ddd4085264573006dbe30304837873c7deafc702b03885858585614e20604051610a4b959493929190613d27565b60405180910390a163150b7a0260e01b9050949350505050565b6000610a6f6121ea565b6001546000540303905090565b8260006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b1115610c4c573373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610aee57610ae98484846121f3565b610c58565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430336040518363ffffffff1660e01b8152600401610b37929190613d81565b602060405180830381865afa158015610b54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b789190613dbf565b8015610c0a57506daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b8152600401610bc8929190613d81565b602060405180830381865afa158015610be5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c099190613dbf565b5b610c4b57336040517fede71dcc000000000000000000000000000000000000000000000000000000008152600401610c4291906134d2565b60405180910390fd5b5b610c578484846121f3565b5b50505050565b6040518060400160405280600581526020017f2e6a736f6e00000000000000000000000000000000000000000000000000000081525081565b6000806000600a6000868152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b82821015610d91578382906000526020600020016040518060400160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff166bffffffffffffffffffffffff168152505081526020019060010190610ccf565b505050509050600081511115610e115780600081518110610db557610db4613c5e565b5b60200260200101516000015161271082600081518110610dd857610dd7613c5e565b5b6020026020010151602001516bffffffffffffffffffffffff1686610dfd9190613e1b565b610e079190613e8c565b9250925050610f8f565b600a6000808152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b82821015610f06578382906000526020600020016040518060400160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff166bffffffffffffffffffffffff168152505081526020019060010190610e44565b505050509050600081511115610f865780600081518110610f2a57610f29613c5e565b5b60200260200101516000015161271082600081518110610f4d57610f4c613c5e565b5b6020026020010151602001516bffffffffffffffffffffffff1686610f729190613e1b565b610f7c9190613e8c565b9250925050610f8f565b60008092509250505b9250929050565b610f9e611db8565b81600c8190555080600d819055505050565b610fb8611db8565b610fc0612203565b60003373ffffffffffffffffffffffffffffffffffffffff1647604051610fe690613eee565b60006040518083038185875af1925050503d8060008114611023576040519150601f19603f3d011682016040523d82523d6000602084013e611028565b606091505b505090508061103657600080fd5b5061103f612252565b565b611049611db8565b600b60009054906101000a900460ff161561106357600080fd5b600081116110a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161109d90613f4f565b60405180910390fd5b600c548111156110eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110e290613fe1565b60405180910390fd5b60006110f5610a65565b9050600d5482826111069190614001565b1115611147576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161113e906140a7565b60405180910390fd5b611151838361225c565b505050565b8260006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b1115611326573373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036111c8576111c384848461227a565b611332565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430336040518363ffffffff1660e01b8152600401611211929190613d81565b602060405180830381865afa15801561122e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112529190613dbf565b80156112e457506daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b81526004016112a2929190613d81565b602060405180830381865afa1580156112bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e39190613dbf565b5b61132557336040517fede71dcc00000000000000000000000000000000000000000000000000000000815260040161131c91906134d2565b60405180910390fd5b5b61133184848461227a565b5b50505050565b600b60009054906101000a900460ff1681565b600061135682611e95565b9050919050565b6000806113698361229a565b036113a0576040517f8f4eb60400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054169050919050565b6113f9611db8565b61140360006122a4565b565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6060611439611db8565b6114428261236a565b9050919050565b60606003805461145890613c2d565b80601f016020809104026020016040519081016040528092919081815260200182805461148490613c2d565b80156114d15780601f106114a6576101008083540402835291602001916114d1565b820191906000526020600020905b8154815290600101906020018083116114b457829003601f168201915b5050505050905090565b6114e3611db8565b6114ed82826124b6565b5050565b6114f9611f61565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361155d576040517fb06307db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806007600061156a611f61565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff16611617611f61565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405161165c9190613308565b60405180910390a35050565b8360006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b1115611839573373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036116db576116d6858585856127ce565b611846565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430336040518363ffffffff1660e01b8152600401611724929190613d81565b602060405180830381865afa158015611741573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117659190613dbf565b80156117f757506daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b81526004016117b5929190613d81565b602060405180830381865afa1580156117d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117f69190613dbf565b5b61183857336040517fede71dcc00000000000000000000000000000000000000000000000000000000815260040161182f91906134d2565b60405180910390fd5b5b611845858585856127ce565b5b5050505050565b6060600061185a8361236a565b9050600061186784612841565b9050600082826040518060400160405280600581526020017f2e6a736f6e0000000000000000000000000000000000000000000000000000008152506040516020016118b593929190614103565b6040516020818303038152906040529050809350505050919050565b60606000600a6000848152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b828210156119ca578382906000526020600020016040518060400160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff166bffffffffffffffffffffffff168152505081526020019060010190611908565b505050509050600081511115611adb57600a6000848152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b82821015611acf578382906000526020600020016040518060400160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff166bffffffffffffffffffffffff168152505081526020019060010190611a0d565b50505050915050611bdb565b600a6000808152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b82821015611bd0578382906000526020600020016040518060400160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff166bffffffffffffffffffffffff168152505081526020019060010190611b0e565b505050509050809150505b919050565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b611c7c611db8565b81600e8260148110611c9157611c90613c5e565b5b019081611c9e91906142d6565b505050565b611cab611db8565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611d1a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d119061441a565b60405180910390fd5b611d23816122a4565b50565b60006301ffc9a760e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480611d8157506380ac58cd60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80611db15750635b5e139f60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b611dc061290f565b73ffffffffffffffffffffffffffffffffffffffff16611dde611405565b73ffffffffffffffffffffffffffffffffffffffff1614611e34576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e2b90614486565b60405180910390fd5b565b600081611e416121ea565b11158015611e50575060005482105b8015611e8e575060007c0100000000000000000000000000000000000000000000000000000000600460008581526020019081526020016000205416145b9050919050565b60008082905080611ea46121ea565b11611f2a57600054811015611f295760006004600083815260200190815260200160002054905060007c0100000000000000000000000000000000000000000000000000000000821603611f27575b60008103611f1d576004600083600190039350838152602001908152602001600020549050611ef3565b8092505050611f5c565b505b5b6040517fdf2d9b4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b600033905090565b600080600090505b825181101561219657600073ffffffffffffffffffffffffffffffffffffffff16838281518110611fa557611fa4613c5e565b5b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1603612007576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ffe906144f2565b60405180910390fd5b600083828151811061201c5761201b613c5e565b5b6020026020010151602001516bffffffffffffffffffffffff1603612076576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161206d9061455e565b60405180910390fd5b82818151811061208957612088613c5e565b5b6020026020010151602001516bffffffffffffffffffffffff16826120ae9190614001565b9150600a60008581526020019081526020016000208382815181106120d6576120d5613c5e565b5b60200260200101519080600181540180825580915050600190039060005260206000200160009091909190915060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055505050808061218e9061457e565b915050611f71565b5061271081106121db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121d290614638565b60405180910390fd5b6121e58383612917565b505050565b60006001905090565b6121fe838383612954565b505050565b600260095403612248576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161223f906146a4565b60405180910390fd5b6002600981905550565b6001600981905550565b612276828260405180602001604052806000815250612d19565b5050565b61229583838360405180602001604052806000815250611668565b505050565b6000819050919050565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6060600082116123af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123a690614710565b60405180910390fd5b60006101f46001846123c19190614730565b6123cb9190613e8c565b905060148110612410576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612407906147b0565b60405180910390fd5b600e816014811061242457612423613c5e565b5b01805461243090613c2d565b80601f016020809104026020016040519081016040528092919081815260200182805461245c90613c2d565b80156124a95780601f1061247e576101008083540402835291602001916124a9565b820191906000526020600020905b81548152906001019060200180831161248c57829003601f168201915b5050505050915050919050565b60006124c183611e95565b9050600081905060006006600086815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905083156125ce5760008273ffffffffffffffffffffffffffffffffffffffff16612527611f61565b73ffffffffffffffffffffffffffffffffffffffff161480612556575061255583612550611f61565b611be0565b5b806125935750612564611f61565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050806125cc576040517f59c896be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b6125dc826000876001612db6565b60006125e78261229a565b14612623576006600086815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690555b600160806001901b03600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055507c02000000000000000000000000000000000000000000000000000000007c010000000000000000000000000000000000000000000000000000000060a042901b6126c28561229a565b171717600460008781526020019081526020016000208190555060007c020000000000000000000000000000000000000000000000000000000084160361274b5760006001860190506000600460008381526020019081526020016000205403612749576000548114612748578360046000838152602001908152602001600020819055505b5b505b84600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46127b5826000876001612dbc565b6001600081548092919060010191905055505050505050565b6127d9848484612954565b60008373ffffffffffffffffffffffffffffffffffffffff163b1461283b5761280484848484612dc2565b61283a576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b50505050565b60606000600161285084612f12565b01905060008167ffffffffffffffff81111561286f5761286e613638565b5b6040519080825280601f01601f1916602001820160405280156128a15781602001600182028036833780820191505090505b509050600082602001820190505b600115612904578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a85816128f8576128f7613e5d565b5b049450600085036128af575b819350505050919050565b600033905090565b7f3fa96d7b6bcbfe71ef171666d84db3cf52fa2d1c8afdb1cc8e486177f208b7df82826040516129489291906147d0565b60405180910390a15050565b600061295f82611e95565b90508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146129c6576040517fa114810000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006006600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008573ffffffffffffffffffffffffffffffffffffffff16612a1f611f61565b73ffffffffffffffffffffffffffffffffffffffff161480612a4e5750612a4d86612a48611f61565b611be0565b5b80612a8b5750612a5c611f61565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b905080612ac4576040517f59c896be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612acf8661229a565b03612b06576040517fea553b3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612b138686866001612db6565b6000612b1e8361229a565b14612b5a576006600085815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690555b600560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600081546001900391905081905550600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008154600101919050819055507c020000000000000000000000000000000000000000000000000000000060a042901b612c218761229a565b1717600460008681526020019081526020016000208190555060007c0200000000000000000000000000000000000000000000000000000000841603612ca95760006001850190506000600460008381526020019081526020016000205403612ca7576000548114612ca6578360046000838152602001908152602001600020819055505b5b505b838573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4612d118686866001612dbc565b505050505050565b612d238383613065565b60008373ffffffffffffffffffffffffffffffffffffffff163b14612db157600080549050600083820390505b612d636000868380600101945086612dc2565b612d99576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b818110612d50578160005414612dae57600080fd5b50505b505050565b50505050565b50505050565b60008373ffffffffffffffffffffffffffffffffffffffff1663150b7a02612de8611f61565b8786866040518563ffffffff1660e01b8152600401612e0a9493929190614800565b6020604051808303816000875af1925050508015612e4657506040513d601f19601f82011682018060405250810190612e439190614861565b60015b612ebf573d8060008114612e76576040519150601f19603f3d011682016040523d82523d6000602084013e612e7b565b606091505b506000815103612eb7576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050949350505050565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310612f70577a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008381612f6657612f65613e5d565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310612fad576d04ee2d6d415b85acef81000000008381612fa357612fa2613e5d565b5b0492506020810190505b662386f26fc100008310612fdc57662386f26fc100008381612fd257612fd1613e5d565b5b0492506010810190505b6305f5e1008310613005576305f5e1008381612ffb57612ffa613e5d565b5b0492506008810190505b612710831061302a5761271083816130205761301f613e5d565b5b0492506004810190505b6064831061304d576064838161304357613042613e5d565b5b0492506002810190505b600a831061305c576001810190505b80915050919050565b60008054905060006130768461229a565b036130ad576040517f2e07630000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082036130e7576040517fb562e8dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6130f46000848385612db6565b600160406001901b178202600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555060e16131596001841461320c565b901b60a042901b6131698561229a565b1717600460008381526020019081526020016000208190555060005b8080600101915082018473ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a482811061318557828201600081905550506132076000848385612dbc565b505050565b6000819050919050565b6040518060400160405280600073ffffffffffffffffffffffffffffffffffffffff16815260200160006bffffffffffffffffffffffff1681525090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61329d81613268565b81146132a857600080fd5b50565b6000813590506132ba81613294565b92915050565b6000602082840312156132d6576132d561325e565b5b60006132e4848285016132ab565b91505092915050565b60008115159050919050565b613302816132ed565b82525050565b600060208201905061331d60008301846132f9565b92915050565b61332c816132ed565b811461333757600080fd5b50565b60008135905061334981613323565b92915050565b6000602082840312156133655761336461325e565b5b60006133738482850161333a565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156133b657808201518184015260208101905061339b565b60008484015250505050565b6000601f19601f8301169050919050565b60006133de8261337c565b6133e88185613387565b93506133f8818560208601613398565b613401816133c2565b840191505092915050565b6000602082019050818103600083015261342681846133d3565b905092915050565b6000819050919050565b6134418161342e565b811461344c57600080fd5b50565b60008135905061345e81613438565b92915050565b60006020828403121561347a5761347961325e565b5b60006134888482850161344f565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006134bc82613491565b9050919050565b6134cc816134b1565b82525050565b60006020820190506134e760008301846134c3565b92915050565b6134f6816134b1565b811461350157600080fd5b50565b600081359050613513816134ed565b92915050565b600080604083850312156135305761352f61325e565b5b600061353e85828601613504565b925050602061354f8582860161344f565b9150509250929050565b600061356482613491565b9050919050565b61357481613559565b811461357f57600080fd5b50565b6000813590506135918161356b565b92915050565b60006bffffffffffffffffffffffff82169050919050565b6135b881613597565b81146135c357600080fd5b50565b6000813590506135d5816135af565b92915050565b6000806000606084860312156135f4576135f361325e565b5b60006136028682870161344f565b935050602061361386828701613582565b9250506040613624868287016135c6565b9150509250925092565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b613670826133c2565b810181811067ffffffffffffffff8211171561368f5761368e613638565b5b80604052505050565b60006136a2613254565b90506136ae8282613667565b919050565b600067ffffffffffffffff8211156136ce576136cd613638565b5b6136d7826133c2565b9050602081019050919050565b82818337600083830152505050565b6000613706613701846136b3565b613698565b90508281526020810184848401111561372257613721613633565b5b61372d8482856136e4565b509392505050565b600082601f83011261374a5761374961362e565b5b813561375a8482602086016136f3565b91505092915050565b6000806000806080858703121561377d5761377c61325e565b5b600061378b87828801613504565b945050602061379c87828801613504565b93505060406137ad8782880161344f565b925050606085013567ffffffffffffffff8111156137ce576137cd613263565b5b6137da87828801613735565b91505092959194509250565b6137ef81613268565b82525050565b600060208201905061380a60008301846137e6565b92915050565b6138198161342e565b82525050565b60006020820190506138346000830184613810565b92915050565b6000806000606084860312156138535761385261325e565b5b600061386186828701613504565b935050602061387286828701613504565b92505060406138838682870161344f565b9150509250925092565b600080604083850312156138a4576138a361325e565b5b60006138b28582860161344f565b92505060206138c38582860161344f565b9150509250929050565b60006040820190506138e260008301856134c3565b6138ef6020830184613810565b9392505050565b60006020828403121561390c5761390b61325e565b5b600061391a84828501613504565b91505092915050565b6000806040838503121561393a5761393961325e565b5b60006139488582860161344f565b92505060206139598582860161333a565b9150509250929050565b6000806040838503121561397a5761397961325e565b5b600061398885828601613504565b92505060206139998582860161333a565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6139d881613559565b82525050565b6139e781613597565b82525050565b604082016000820151613a0360008501826139cf565b506020820151613a1660208501826139de565b50505050565b6000613a2883836139ed565b60408301905092915050565b6000602082019050919050565b6000613a4c826139a3565b613a5681856139ae565b9350613a61836139bf565b8060005b83811015613a92578151613a798882613a1c565b9750613a8483613a34565b925050600181019050613a65565b5085935050505092915050565b60006020820190508181036000830152613ab98184613a41565b905092915050565b60008060408385031215613ad857613ad761325e565b5b6000613ae685828601613504565b9250506020613af785828601613504565b9150509250929050565b600067ffffffffffffffff821115613b1c57613b1b613638565b5b613b25826133c2565b9050602081019050919050565b6000613b45613b4084613b01565b613698565b905082815260208101848484011115613b6157613b60613633565b5b613b6c8482856136e4565b509392505050565b600082601f830112613b8957613b8861362e565b5b8135613b99848260208601613b32565b91505092915050565b60008060408385031215613bb957613bb861325e565b5b600083013567ffffffffffffffff811115613bd757613bd6613263565b5b613be385828601613b74565b9250506020613bf48582860161344f565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680613c4557607f821691505b602082108103613c5857613c57613bfe565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600081519050919050565b600082825260208201905092915050565b6000613cb482613c8d565b613cbe8185613c98565b9350613cce818560208601613398565b613cd7816133c2565b840191505092915050565b6000819050919050565b6000819050919050565b6000613d11613d0c613d0784613ce2565b613cec565b61342e565b9050919050565b613d2181613cf6565b82525050565b600060a082019050613d3c60008301886134c3565b613d4960208301876134c3565b613d566040830186613810565b8181036060830152613d688185613ca9565b9050613d776080830184613d18565b9695505050505050565b6000604082019050613d9660008301856134c3565b613da360208301846134c3565b9392505050565b600081519050613db981613323565b92915050565b600060208284031215613dd557613dd461325e565b5b6000613de384828501613daa565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000613e268261342e565b9150613e318361342e565b9250828202613e3f8161342e565b91508282048414831517613e5657613e55613dec565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000613e978261342e565b9150613ea28361342e565b925082613eb257613eb1613e5d565b5b828204905092915050565b600081905092915050565b50565b6000613ed8600083613ebd565b9150613ee382613ec8565b600082019050919050565b6000613ef982613ecb565b9150819050919050565b7f4d4159475f373231613a20696e76616c6964207175616e746974792c20300000600082015250565b6000613f39601e83613387565b9150613f4482613f03565b602082019050919050565b60006020820190508181036000830152613f6881613f2c565b9050919050565b7f4d4159475f373231613a20696e76616c6964207175616e746974792c20746f6f60008201527f206c617267650000000000000000000000000000000000000000000000000000602082015250565b6000613fcb602683613387565b9150613fd682613f6f565b604082019050919050565b60006020820190508181036000830152613ffa81613fbe565b9050919050565b600061400c8261342e565b91506140178361342e565b925082820190508082111561402f5761402e613dec565b5b92915050565b7f4d4159475f373231613a20696e76616c6964207175616e746974792c20746f6f60008201527f206d616e792066697273742067656e20746f6b656e7300000000000000000000602082015250565b6000614091603683613387565b915061409c82614035565b604082019050919050565b600060208201905081810360008301526140c081614084565b9050919050565b600081905092915050565b60006140dd8261337c565b6140e781856140c7565b93506140f7818560208601613398565b80840191505092915050565b600061410f82866140d2565b915061411b82856140d2565b915061412782846140d2565b9150819050949350505050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026141967fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82614159565b6141a08683614159565b95508019841693508086168417925050509392505050565b60006141d36141ce6141c98461342e565b613cec565b61342e565b9050919050565b6000819050919050565b6141ed836141b8565b6142016141f9826141da565b848454614166565b825550505050565b600090565b614216614209565b6142218184846141e4565b505050565b5b818110156142455761423a60008261420e565b600181019050614227565b5050565b601f82111561428a5761425b81614134565b61426484614149565b81016020851015614273578190505b61428761427f85614149565b830182614226565b50505b505050565b600082821c905092915050565b60006142ad6000198460080261428f565b1980831691505092915050565b60006142c6838361429c565b9150826002028217905092915050565b6142df8261337c565b67ffffffffffffffff8111156142f8576142f7613638565b5b6143028254613c2d565b61430d828285614249565b600060209050601f831160018114614340576000841561432e578287015190505b61433885826142ba565b8655506143a0565b601f19841661434e86614134565b60005b8281101561437657848901518255600182019150602085019450602081019050614351565b86831015614393578489015161438f601f89168261429c565b8355505b6001600288020188555050505b505050505050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000614404602683613387565b915061440f826143a8565b604082019050919050565b60006020820190508181036000830152614433816143f7565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000614470602083613387565b915061447b8261443a565b602082019050919050565b6000602082019050818103600083015261449f81614463565b9050919050565b7f526563697069656e742073686f756c642062652070726573656e740000000000600082015250565b60006144dc601b83613387565b91506144e7826144a6565b602082019050919050565b6000602082019050818103600083015261450b816144cf565b9050919050565b7f526f79616c74792076616c75652073686f756c6420626520706f736974697665600082015250565b6000614548602083613387565b915061455382614512565b602082019050919050565b600060208201905081810360008301526145778161453b565b9050919050565b60006145898261342e565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036145bb576145ba613dec565b5b600182019050919050565b7f526f79616c747920746f74616c2076616c75652073686f756c64206265203c2060008201527f3130303030000000000000000000000000000000000000000000000000000000602082015250565b6000614622602583613387565b915061462d826145c6565b604082019050919050565b6000602082019050818103600083015261465181614615565b9050919050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b600061468e601f83613387565b915061469982614658565b602082019050919050565b600060208201905081810360008301526146bd81614681565b9050919050565b7f746f6b656e4964206f66207a65726f206973206f7574206f662072616e676500600082015250565b60006146fa601f83613387565b9150614705826146c4565b602082019050919050565b60006020820190508181036000830152614729816146ed565b9050919050565b600061473b8261342e565b91506147468361342e565b925082820390508181111561475e5761475d613dec565b5b92915050565b7f6d697373696e67204349442076616c756520666f7220746f6b656e0000000000600082015250565b600061479a601b83613387565b91506147a582614764565b602082019050919050565b600060208201905081810360008301526147c98161478d565b9050919050565b60006040820190506147e56000830185613810565b81810360208301526147f78184613a41565b90509392505050565b600060808201905061481560008301876134c3565b61482260208301866134c3565b61482f6040830185613810565b81810360608301526148418184613ca9565b905095945050505050565b60008151905061485b81613294565b92915050565b6000602082840312156148775761487661325e565b5b60006148858482850161484c565b9150509291505056fea2646970667358221220a54fa0ae72a15494fc22efc8ddb9b17fa57cb1554149af36c8c090c40fb012cc64736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000005068747470733a2f2f6d6179672e6d7970696e6174612e636c6f75642f697066732f516d646945314876506e6b4b655370633359334d673856544e545458447133365032364c687667545953644255352f00000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _cid (string): https://mayg.mypinata.cloud/ipfs/QmdiE1HvPnkKeSpc3Y3Mg8VTNTTXDq36P26LhvgTYSdBU5/
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000020
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000050
Arg [2] : 68747470733a2f2f6d6179672e6d7970696e6174612e636c6f75642f69706673
Arg [3] : 2f516d646945314876506e6b4b655370633359334d673856544e545458447133
Arg [4] : 365032364c687667545953644255352f00000000000000000000000000000000
Deployed Bytecode Sourcemap
748:6176:10:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4863:333;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;5260:71;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;9883:98:3;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;11830:200;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;11364:405;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;3897:344:10;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;2838:746;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;4056:309:3;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1517:157:10;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;945:48;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;4312:547;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;5774:271;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;3588:161;;;:::i;:::-;;2061:443;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;1678:165;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;914:26;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;9679:142:3;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;5639:231;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1824:101:15;;;:::i;:::-;;1194:85;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;6450:138:10;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;10045:102:3;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;5335:109:10;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;12097:303:3;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;1847:210:10;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;2518:316;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;187:291:20;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;12466:162:3;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;6327:119:10;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;2074:198:15;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;4863:333:10;4957:4;258:10:9;4989:38:10;;4974:53;;;:11;:53;;;;4971:90;;5048:4;5041:11;;;;4971:90;899:10;5087:21;;5072:36;;;:11;:36;;;;5069:71;;5127:4;5120:11;;;;5069:71;5155:36;5179:11;5155:23;:36::i;:::-;5148:43;;4863:333;;;;:::o;5260:71::-;1087:13:15;:11;:13::i;:::-;5320:6:10::1;5311;;:15;;;;;;;;;;;;;;;;;;5260:71:::0;:::o;9883:98:3:-;9937:13;9969:5;9962:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9883:98;:::o;11830:200::-;11898:7;11922:16;11930:7;11922;:16::i;:::-;11917:64;;11947:34;;;;;;;;;;;;;;11917:64;11999:15;:24;12015:7;11999:24;;;;;;;;;;;;;;;;;;;;;11992:31;;11830:200;;;:::o;11364:405::-;11436:13;11468:27;11487:7;11468:18;:27::i;:::-;11436:61;;11535:5;11512:28;;:19;:17;:19::i;:::-;:28;;;11508:172;;11559:44;11576:5;11583:19;:17;:19::i;:::-;11559:16;:44::i;:::-;11554:126;;11630:35;;;;;;;;;;;;;;11554:126;11508:172;11717:2;11690:15;:24;11706:7;11690:24;;;;;;;;;;;;:29;;;;;;;;;;;;;;;;;;11754:7;11750:2;11734:28;;11743:5;11734:28;;;;;;;;;;;;11426:343;11364:405;;:::o;3897:344:10:-;1087:13:15;:11;:13::i;:::-;4032:32:10::1;4086:1;4067:21;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;4032:56;;4116:22;4094:10;4105:1;4094:13;;;;;;;;:::i;:::-;;;;;;;;:19;;:44;;;;;;;;;::::0;::::1;4168:26;4144:10;4155:1;4144:13;;;;;;;;:::i;:::-;;;;;;;;:21;;:50;;;;;;;;;::::0;::::1;4200:36;4215:8;4225:10;4200:14;:36::i;:::-;4026:215;3897:344:::0;;;:::o;2838:746::-;2985:6;3488:46;3497:8;3507:4;3513:7;3522:4;3528:5;3488:46;;;;;;;;;;:::i;:::-;;;;;;;;3549:30;;;3542:37;;2838:746;;;;;;:::o;4056:309:3:-;4109:7;4333:15;:13;:15::i;:::-;4318:12;;4302:13;;:28;:46;4295:53;;4056:309;:::o;1517:157:10:-;1618:4;1475:1:14;310:42;1429:43;;;:47;1425:683;;;1712:10;1704:18;;:4;:18;;;1700:82;;1632:37:10::1;1651:4;1657:2;1661:7;1632:18;:37::i;:::-;1761:7:14::0;;1700:82;310:42;1839:40;;;1888:4;1895:10;1839:67;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:156;;;;;310:42;1934:40;;;1983:4;1990;1934:61;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1839:156;1795:303;;2072:10;2053:30;;;;;;;;;;;:::i;:::-;;;;;;;;1795:303;1425:683;1632:37:10::1;1651:4;1657:2;1661:7;1632:18;:37::i;:::-;1517:157:::0;;;;;:::o;945:48::-;;;;;;;;;;;;;;;;;;;:::o;4312:547::-;4394:16;4412:21;4501:32;4536:9;:19;4546:8;4536:19;;;;;;;;;;;4501:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4584:1;4564:10;:17;:21;4561:115;;;4603:10;4614:1;4603:13;;;;;;;;:::i;:::-;;;;;;;;:21;;;4663:5;4640:10;4651:1;4640:13;;;;;;;;:::i;:::-;;;;;;;;:19;;;4627:32;;:10;:32;;;;:::i;:::-;4626:42;;;;:::i;:::-;4595:74;;;;;;;4561:115;4694:9;:12;4704:1;4694:12;;;;;;;;;;;4681:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4735:1;4715:10;:17;:21;4712:115;;;4754:10;4765:1;4754:13;;;;;;;;:::i;:::-;;;;;;;;:21;;;4814:5;4791:10;4802:1;4791:13;;;;;;;;:::i;:::-;;;;;;;;:19;;;4778:32;;:10;:32;;;;:::i;:::-;4777:42;;;;:::i;:::-;4746:74;;;;;;;4712:115;4848:1;4852;4832:22;;;;;4312:547;;;;;;:::o;5774:271::-;1087:13:15;:11;:13::i;:::-;5973:23:10::1;5946:24;:50;;;;6023:17;6002:18;:38;;;;5774:271:::0;;:::o;3588:161::-;1087:13:15;:11;:13::i;:::-;2261:21:18::1;:19;:21::i;:::-;3646:12:10::2;3672:10;3664:24;;3696:21;3664:58;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3645:77;;;3736:7;3728:16;;;::::0;::::2;;3638:111;2303:20:18::1;:18;:20::i;:::-;3588:161:10:o:0;2061:443::-;1087:13:15;:11;:13::i;:::-;2141:6:10::1;;;;;;;;;;;2140:7;2132:16;;;::::0;::::1;;2177:1;2165:9;:13;2157:56;;;;;;;;;;;;:::i;:::-;;;;;;;;;2242:24;;2229:9;:37;;2221:88;;;;;;;;;;;;:::i;:::-;;;;;;;;;2318:14;2335:13;:11;:13::i;:::-;2318:30;;2386:18;;2373:9;2364:6;:18;;;;:::i;:::-;:40;;2356:107;;;;;;;;;;;;:::i;:::-;;;;;;;;;2472:25;2482:3;2487:9;2472;:25::i;:::-;2124:380;2061:443:::0;;:::o;1678:165::-;1783:4;1475:1:14;310:42;1429:43;;;:47;1425:683;;;1712:10;1704:18;;:4;:18;;;1700:82;;1797:41:10::1;1820:4;1826:2;1830:7;1797:22;:41::i;:::-;1761:7:14::0;;1700:82;310:42;1839:40;;;1888:4;1895:10;1839:67;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:156;;;;;310:42;1934:40;;;1983:4;1990;1934:61;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1839:156;1795:303;;2072:10;2053:30;;;;;;;;;;;:::i;:::-;;;;;;;;1795:303;1425:683;1797:41:10::1;1820:4;1826:2;1830:7;1797:22;:41::i;:::-;1678:165:::0;;;;;:::o;914:26::-;;;;;;;;;;;;;:::o;9679:142:3:-;9743:7;9785:27;9804:7;9785:18;:27::i;:::-;9762:52;;9679:142;;;:::o;5639:231::-;5703:7;5754:1;5726:24;5744:5;5726:17;:24::i;:::-;:29;5722:70;;5764:28;;;;;;;;;;;;;;5722:70;1116:13;5809:18;:25;5828:5;5809:25;;;;;;;;;;;;;;;;:54;5802:61;;5639:231;;;:::o;1824:101:15:-;1087:13;:11;:13::i;:::-;1888:30:::1;1915:1;1888:18;:30::i;:::-;1824:101::o:0;1194:85::-;1240:7;1266:6;;;;;;;;;;;1259:13;;1194:85;:::o;6450:138:10:-;6524:13;1087::15;:11;:13::i;:::-;6552:31:10::1;6575:7;6552:22;:31::i;:::-;6545:38;;6450:138:::0;;;:::o;10045:102:3:-;10101:13;10133:7;10126:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10045:102;:::o;5335:109:10:-;1087:13:15;:11;:13::i;:::-;5409:30:10::1;5416:7;5425:13;5409:5;:30::i;:::-;5335:109:::0;;:::o;12097:303:3:-;12207:19;:17;:19::i;:::-;12195:31;;:8;:31;;;12191:61;;12235:17;;;;;;;;;;;;;;12191:61;12315:8;12263:18;:39;12282:19;:17;:19::i;:::-;12263:39;;;;;;;;;;;;;;;:49;12303:8;12263:49;;;;;;;;;;;;;;;;:60;;;;;;;;;;;;;;;;;;12374:8;12338:55;;12353:19;:17;:19::i;:::-;12338:55;;;12384:8;12338:55;;;;;;:::i;:::-;;;;;;;;12097:303;;:::o;1847:210:10:-;1989:4;1475:1:14;310:42;1429:43;;;:47;1425:683;;;1712:10;1704:18;;:4;:18;;;1700:82;;2005:47:10::1;2028:4;2034:2;2038:7;2047:4;2005:22;:47::i;:::-;1761:7:14::0;;1700:82;310:42;1839:40;;;1888:4;1895:10;1839:67;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:156;;;;;310:42;1934:40;;;1983:4;1990;1934:61;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1839:156;1795:303;;2072:10;2053:30;;;;;;;;;;;:::i;:::-;;;;;;;;1795:303;1425:683;2005:47:10::1;2028:4;2034:2;2038:7;2047:4;2005:22;:47::i;:::-;1847:210:::0;;;;;;:::o;2518:316::-;2600:13;2623:17;2643:32;2666:8;2643:22;:32::i;:::-;2623:52;;2681:24;2708:26;2725:8;2708:16;:26::i;:::-;2681:53;;2741:14;2775:3;2780:10;2792:14;;;;;;;;;;;;;;;;;2758:49;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;2741:66;;2827:1;2813:16;;;;;2518:316;;;:::o;187:291:20:-;262:21;293:32;328:9;:13;338:2;328:13;;;;;;;;;;;293:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;372:1;352:10;:17;:21;349:65;;;392:9;:13;402:2;392:13;;;;;;;;;;;385:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;349:65;434:9;:12;444:1;434:12;;;;;;;;;;;421:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;461:10;454:17;;;187:291;;;;:::o;12466:162:3:-;12563:4;12586:18;:25;12605:5;12586:25;;;;;;;;;;;;;;;:35;12612:8;12586:35;;;;;;;;;;;;;;;;;;;;;;;;;12579:42;;12466:162;;;;:::o;6327:119:10:-;1087:13:15;:11;:13::i;:::-;6437:4:10::1;6413:11;6425:8;6413:21;;;;;;;:::i;:::-;;;:28;;;;;;:::i;:::-;;6327:119:::0;;:::o;2074:198:15:-;1087:13;:11;:13::i;:::-;2182:1:::1;2162:22;;:8;:22;;::::0;2154:73:::1;;;;;;;;;;;;:::i;:::-;;;;;;;;;2237:28;2256:8;2237:18;:28::i;:::-;2074:198:::0;:::o;4973:607:3:-;5058:4;5368:10;5353:25;;:11;:25;;;;:101;;;;5444:10;5429:25;;:11;:25;;;;5353:101;:177;;;;5520:10;5505:25;;:11;:25;;;;5353:177;5334:196;;4973:607;;;:::o;1352:130:15:-;1426:12;:10;:12::i;:::-;1415:23;;:7;:5;:7::i;:::-;:23;;;1407:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;1352:130::o;13796:268:3:-;13853:4;13907:7;13888:15;:13;:15::i;:::-;:26;;:65;;;;;13940:13;;13930:7;:23;13888:65;:150;;;;;14037:1;1868:8;13990:17;:26;14008:7;13990:26;;;;;;;;;;;;:43;:48;13888:150;13869:169;;13796:268;;;:::o;7256:1105::-;7323:7;7342:12;7357:7;7342:22;;7422:4;7403:15;:13;:15::i;:::-;:23;7399:898;;7455:13;;7448:4;:20;7444:853;;;7492:14;7509:17;:23;7527:4;7509:23;;;;;;;;;;;;7492:40;;7623:1;1868:8;7596:6;:23;:28;7592:687;;8107:111;8124:1;8114:6;:11;8107:111;;8166:17;:25;8184:6;;;;;;;8166:25;;;;;;;;;;;;8157:34;;8107:111;;;8250:6;8243:13;;;;;;7592:687;7470:827;7444:853;7399:898;8323:31;;;;;;;;;;;;;;7256:1105;;;;:::o;26122:103::-;26182:7;26208:10;26201:17;;26122:103;:::o;186:566:0:-;275:18;308:6;317:1;308:10;;303:324;324:10;:17;320:1;:21;303:324;;;403:3;370:37;;:10;381:1;370:13;;;;;;;;:::i;:::-;;;;;;;;:21;;;:37;;;362:77;;;;;;;;;;;;:::i;:::-;;;;;;;;;484:1;461:10;472:1;461:13;;;;;;;;:::i;:::-;;;;;;;;:19;;;:24;;;453:69;;;;;;;;;;;;:::i;:::-;;;;;;;;;550:10;561:1;550:13;;;;;;;;:::i;:::-;;;;;;;;:19;;;536:33;;;;;;;:::i;:::-;;;583:9;:13;593:2;583:13;;;;;;;;;;;602:10;613:1;602:13;;;;;;;;:::i;:::-;;;;;;;;583:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;343:3;;;;;:::i;:::-;;;;303:324;;;;657:5;644:10;:18;636:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;714:31;730:2;734:10;714:15;:31::i;:::-;265:487;186:566;;:::o;5466:87:10:-;5523:7;5547:1;5540:8;;5466:87;:::o;12690:164:3:-;12819:28;12829:4;12835:2;12839:7;12819:9;:28::i;:::-;12690:164;;;:::o;2336:287:18:-;1759:1;2468:7;;:19;2460:63;;;;;;;;;;;;:::i;:::-;;;;;;;;;1759:1;2598:7;:18;;;;2336:287::o;2629:209::-;1716:1;2809:7;:22;;;;2629:209::o;14143:102:3:-;14211:27;14221:2;14225:8;14211:27;;;;;;;;;;;;:9;:27::i;:::-;14143:102;;:::o;12920:179::-;13053:39;13070:4;13076:2;13080:7;13053:39;;;;;;;;;;;;:16;:39::i;:::-;12920:179;;;:::o;10943:144::-;11007:14;11066:5;11056:15;;10943:144;;;:::o;2426:187:15:-;2499:16;2518:6;;;;;;;;;;;2499:25;;2543:8;2534:6;;:17;;;;;;;;;;;;;;;;;;2597:8;2566:40;;2587:8;2566:40;;;;;;;;;;;;2489:124;2426:187;:::o;6592:330:10:-;6666:13;6706:1;6696:7;:11;6688:57;;;;;;;;;;;;:::i;:::-;;;;;;;;;6752:16;1237:3;6780:1;6772:7;:9;;;;:::i;:::-;6771:34;;;;:::i;:::-;6752:53;;1290:2;6821:8;:29;6812:70;;;;;;;;;;;;:::i;:::-;;;;;;;;;6896:11;6908:8;6896:21;;;;;;;:::i;:::-;;;6889:28;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6592:330;;;:::o;20329:2870:3:-;20408:27;20438;20457:7;20438:18;:27::i;:::-;20408:57;;20476:12;20507:19;20476:52;;20538:23;20564:15;:24;20580:7;20564:24;;;;;;;;;;;;;;;;;;;;;20538:50;;20603:13;20599:300;;;20632:22;20681:4;20658:27;;:19;:17;:19::i;:::-;:27;;;:90;;;;20705:43;20722:4;20728:19;:17;:19::i;:::-;20705:16;:43::i;:::-;20658:90;:148;;;;20787:19;:17;:19::i;:::-;20768:38;;:15;:38;;;20658:148;20632:175;;20827:17;20822:66;;20853:35;;;;;;;;;;;;;;20822:66;20618:281;20599:300;20909:51;20931:4;20945:1;20949:7;20958:1;20909:21;:51::i;:::-;21065:1;21027:34;21045:15;21027:17;:34::i;:::-;:39;21023:101;;21089:15;:24;21105:7;21089:24;;;;;;;;;;;;21082:31;;;;;;;;;;;21023:101;21758:1;1373:3;21729:1;:25;;21728:31;21700:18;:24;21719:4;21700:24;;;;;;;;;;;;;;;;:59;;;;;;;;;;;2140:8;1868;1755:3;22078:15;:41;;22035:23;22053:4;22035:17;:23::i;:::-;:85;:118;:161;21990:17;:26;22008:7;21990:26;;;;;;;;;;;:206;;;;22363:1;2140:8;22313:19;:46;:51;22309:616;;22384:19;22416:1;22406:7;:11;22384:33;;22571:1;22537:17;:30;22555:11;22537:30;;;;;;;;;;;;:35;22533:378;;22673:13;;22658:11;:28;22654:239;;22851:19;22818:17;:30;22836:11;22818:30;;;;;;;;;;;:52;;;;22654:239;22533:378;22366:559;22309:616;22977:7;22973:1;22950:35;;22959:4;22950:35;;;;;;;;;;;;22995:50;23016:4;23030:1;23034:7;23043:1;22995:20;:50::i;:::-;23168:12;;:14;;;;;;;;;;;;;20398:2801;;;20329:2870;;:::o;13165:385::-;13326:28;13336:4;13342:2;13346:7;13326:9;:28::i;:::-;13386:1;13368:2;:14;;;:19;13364:180;;13406:56;13437:4;13443:2;13447:7;13456:5;13406:30;:56::i;:::-;13401:143;;13489:40;;;;;;;;;;;;;;13401:143;13364:180;13165:385;;;;:::o;410:696:21:-;466:13;515:14;552:1;532:17;543:5;532:10;:17::i;:::-;:21;515:38;;567:20;601:6;590:18;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;567:41;;622:11;748:6;744:2;740:15;732:6;728:28;721:35;;783:280;790:4;783:280;;;814:5;;;;;;;;953:8;948:2;941:5;937:14;932:30;927:3;919:44;1007:2;998:11;;;;;;:::i;:::-;;;;;1040:1;1031:5;:10;783:280;1027:21;783:280;1083:6;1076:13;;;;;410:696;;;:::o;640:96:1:-;693:7;719:10;712:17;;640:96;:::o;484:139:20:-;588:28;601:2;605:10;588:28;;;;;;;:::i;:::-;;;;;;;;484:139;;:::o;17357:2595:3:-;17467:27;17497;17516:7;17497:18;:27::i;:::-;17467:57;;17580:4;17539:45;;17555:19;17539:45;;;17535:86;;17593:28;;;;;;;;;;;;;;17535:86;17632:23;17658:15;:24;17674:7;17658:24;;;;;;;;;;;;;;;;;;;;;17632:50;;17693:22;17742:4;17719:27;;:19;:17;:19::i;:::-;:27;;;:86;;;;17762:43;17779:4;17785:19;:17;:19::i;:::-;17762:16;:43::i;:::-;17719:86;:140;;;;17840:19;:17;:19::i;:::-;17821:38;;:15;:38;;;17719:140;17693:167;;17876:17;17871:66;;17902:35;;;;;;;;;;;;;;17871:66;17976:1;17951:21;17969:2;17951:17;:21::i;:::-;:26;17947:62;;17986:23;;;;;;;;;;;;;;17947:62;18020:43;18042:4;18048:2;18052:7;18061:1;18020:21;:43::i;:::-;18168:1;18130:34;18148:15;18130:17;:34::i;:::-;:39;18126:101;;18192:15;:24;18208:7;18192:24;;;;;;;;;;;;18185:31;;;;;;;;;;;18126:101;18587:18;:24;18606:4;18587:24;;;;;;;;;;;;;;;;18585:26;;;;;;;;;;;;18655:18;:22;18674:2;18655:22;;;;;;;;;;;;;;;;18653:24;;;;;;;;;;;2140:8;1755:3;19027:15;:41;;18986:21;19004:2;18986:17;:21::i;:::-;:83;:126;18941:17;:26;18959:7;18941:26;;;;;;;;;;;:171;;;;19279:1;2140:8;19229:19;:46;:51;19225:616;;19300:19;19332:1;19322:7;:11;19300:33;;19487:1;19453:17;:30;19471:11;19453:30;;;;;;;;;;;;:35;19449:378;;19589:13;;19574:11;:28;19570:239;;19767:19;19734:17;:30;19752:11;19734:30;;;;;;;;;;;:52;;;;19570:239;19449:378;19282:559;19225:616;19885:7;19881:2;19866:27;;19875:4;19866:27;;;;;;;;;;;;19903:42;19924:4;19930:2;19934:7;19943:1;19903:20;:42::i;:::-;17457:2495;;;17357:2595;;;:::o;14619:661::-;14737:19;14743:2;14747:8;14737:5;:19::i;:::-;14813:1;14795:2;:14;;;:19;14791:473;;14834:11;14848:13;;14834:27;;14879:13;14901:8;14895:3;:14;14879:30;;14927:229;14957:62;14996:1;15000:2;15004:7;;;;;;15013:5;14957:30;:62::i;:::-;14952:165;;15054:40;;;;;;;;;;;;;;14952:165;15151:3;15143:5;:11;14927:229;;15236:3;15219:13;;:20;15215:34;;15241:8;;;15215:34;14816:448;;14791:473;14619:661;;;:::o;24990:154::-;;;;;:::o;25785:153::-;;;;;:::o;23680:679::-;23838:4;23874:2;23858:36;;;23895:19;:17;:19::i;:::-;23916:4;23922:7;23931:5;23858:79;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;23854:499;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24135:1;24118:6;:13;:18;24114:229;;24163:40;;;;;;;;;;;;;;24114:229;24303:6;24297:13;24288:6;24284:2;24280:15;24273:38;23854:499;24015:45;;;24005:55;;;:6;:55;;;;23998:62;;;23680:679;;;;;;:::o;9889:890:11:-;9942:7;9961:14;9978:1;9961:18;;10026:6;10017:5;:15;10013:99;;10061:6;10052:15;;;;;;:::i;:::-;;;;;10095:2;10085:12;;;;10013:99;10138:6;10129:5;:15;10125:99;;10173:6;10164:15;;;;;;:::i;:::-;;;;;10207:2;10197:12;;;;10125:99;10250:6;10241:5;:15;10237:99;;10285:6;10276:15;;;;;;:::i;:::-;;;;;10319:2;10309:12;;;;10237:99;10362:5;10353;:14;10349:96;;10396:5;10387:14;;;;;;:::i;:::-;;;;;10429:1;10419:11;;;;10349:96;10471:5;10462;:14;10458:96;;10505:5;10496:14;;;;;;:::i;:::-;;;;;10538:1;10528:11;;;;10458:96;10580:5;10571;:14;10567:96;;10614:5;10605:14;;;;;;:::i;:::-;;;;;10647:1;10637:11;;;;10567:96;10689:5;10680;:14;10676:64;;10724:1;10714:11;;;;10676:64;10766:6;10759:13;;;9889:890;;;:::o;15541:1574:3:-;15605:20;15628:13;;15605:36;;15680:1;15655:21;15673:2;15655:17;:21::i;:::-;:26;15651:58;;15690:19;;;;;;;;;;;;;;15651:58;15735:1;15723:8;:13;15719:44;;15745:18;;;;;;;;;;;;;;15719:44;15774:61;15804:1;15808:2;15812:12;15826:8;15774:21;:61::i;:::-;16367:1;1250:2;16338:1;:25;;16337:31;16325:8;:44;16299:18;:22;16318:2;16299:22;;;;;;;;;;;;;;;;:70;;;;;;;;;;;2008:3;16758:29;16785:1;16773:8;:13;16758:14;:29::i;:::-;:56;;1755:3;16696:15;:41;;16655:21;16673:2;16655:17;:21::i;:::-;:83;:160;16605:17;:31;16623:12;16605:31;;;;;;;;;;;:210;;;;16830:14;16858:117;16924:8;;;;;;16909:12;:23;16905:2;16884:49;;16901:1;16884:49;;;;;;;;;;;;16965:8;16956:6;:17;16858:117;;17020:8;17005:12;:23;16989:13;:39;;;;16082:957;17048:60;17077:1;17081:2;17085:12;17099:8;17048:20;:60::i;:::-;15595:1520;15541:1574;;:::o;11169:138::-;11227:14;11286:5;11276:15;;11169:138;;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;:::o;7:75:22:-;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:149;370:7;410:66;403:5;399:78;388:89;;334:149;;;:::o;489:120::-;561:23;578:5;561:23;:::i;:::-;554:5;551:34;541:62;;599:1;596;589:12;541:62;489:120;:::o;615:137::-;660:5;698:6;685:20;676:29;;714:32;740:5;714:32;:::i;:::-;615:137;;;;:::o;758:327::-;816:6;865:2;853:9;844:7;840:23;836:32;833:119;;;871:79;;:::i;:::-;833:119;991:1;1016:52;1060:7;1051:6;1040:9;1036:22;1016:52;:::i;:::-;1006:62;;962:116;758:327;;;;:::o;1091:90::-;1125:7;1168:5;1161:13;1154:21;1143:32;;1091:90;;;:::o;1187:109::-;1268:21;1283:5;1268:21;:::i;:::-;1263:3;1256:34;1187:109;;:::o;1302:210::-;1389:4;1427:2;1416:9;1412:18;1404:26;;1440:65;1502:1;1491:9;1487:17;1478:6;1440:65;:::i;:::-;1302:210;;;;:::o;1518:116::-;1588:21;1603:5;1588:21;:::i;:::-;1581:5;1578:32;1568:60;;1624:1;1621;1614:12;1568:60;1518:116;:::o;1640:133::-;1683:5;1721:6;1708:20;1699:29;;1737:30;1761:5;1737:30;:::i;:::-;1640:133;;;;:::o;1779:323::-;1835:6;1884:2;1872:9;1863:7;1859:23;1855:32;1852:119;;;1890:79;;:::i;:::-;1852:119;2010:1;2035:50;2077:7;2068:6;2057:9;2053:22;2035:50;:::i;:::-;2025:60;;1981:114;1779:323;;;;:::o;2108:99::-;2160:6;2194:5;2188:12;2178:22;;2108:99;;;:::o;2213:169::-;2297:11;2331:6;2326:3;2319:19;2371:4;2366:3;2362:14;2347:29;;2213:169;;;;:::o;2388:246::-;2469:1;2479:113;2493:6;2490:1;2487:13;2479:113;;;2578:1;2573:3;2569:11;2563:18;2559:1;2554:3;2550:11;2543:39;2515:2;2512:1;2508:10;2503:15;;2479:113;;;2626:1;2617:6;2612:3;2608:16;2601:27;2450:184;2388:246;;;:::o;2640:102::-;2681:6;2732:2;2728:7;2723:2;2716:5;2712:14;2708:28;2698:38;;2640:102;;;:::o;2748:377::-;2836:3;2864:39;2897:5;2864:39;:::i;:::-;2919:71;2983:6;2978:3;2919:71;:::i;:::-;2912:78;;2999:65;3057:6;3052:3;3045:4;3038:5;3034:16;2999:65;:::i;:::-;3089:29;3111:6;3089:29;:::i;:::-;3084:3;3080:39;3073:46;;2840:285;2748:377;;;;:::o;3131:313::-;3244:4;3282:2;3271:9;3267:18;3259:26;;3331:9;3325:4;3321:20;3317:1;3306:9;3302:17;3295:47;3359:78;3432:4;3423:6;3359:78;:::i;:::-;3351:86;;3131:313;;;;:::o;3450:77::-;3487:7;3516:5;3505:16;;3450:77;;;:::o;3533:122::-;3606:24;3624:5;3606:24;:::i;:::-;3599:5;3596:35;3586:63;;3645:1;3642;3635:12;3586:63;3533:122;:::o;3661:139::-;3707:5;3745:6;3732:20;3723:29;;3761:33;3788:5;3761:33;:::i;:::-;3661:139;;;;:::o;3806:329::-;3865:6;3914:2;3902:9;3893:7;3889:23;3885:32;3882:119;;;3920:79;;:::i;:::-;3882:119;4040:1;4065:53;4110:7;4101:6;4090:9;4086:22;4065:53;:::i;:::-;4055:63;;4011:117;3806:329;;;;:::o;4141:126::-;4178:7;4218:42;4211:5;4207:54;4196:65;;4141:126;;;:::o;4273:96::-;4310:7;4339:24;4357:5;4339:24;:::i;:::-;4328:35;;4273:96;;;:::o;4375:118::-;4462:24;4480:5;4462:24;:::i;:::-;4457:3;4450:37;4375:118;;:::o;4499:222::-;4592:4;4630:2;4619:9;4615:18;4607:26;;4643:71;4711:1;4700:9;4696:17;4687:6;4643:71;:::i;:::-;4499:222;;;;:::o;4727:122::-;4800:24;4818:5;4800:24;:::i;:::-;4793:5;4790:35;4780:63;;4839:1;4836;4829:12;4780:63;4727:122;:::o;4855:139::-;4901:5;4939:6;4926:20;4917:29;;4955:33;4982:5;4955:33;:::i;:::-;4855:139;;;;:::o;5000:474::-;5068:6;5076;5125:2;5113:9;5104:7;5100:23;5096:32;5093:119;;;5131:79;;:::i;:::-;5093:119;5251:1;5276:53;5321:7;5312:6;5301:9;5297:22;5276:53;:::i;:::-;5266:63;;5222:117;5378:2;5404:53;5449:7;5440:6;5429:9;5425:22;5404:53;:::i;:::-;5394:63;;5349:118;5000:474;;;;;:::o;5480:104::-;5525:7;5554:24;5572:5;5554:24;:::i;:::-;5543:35;;5480:104;;;:::o;5590:138::-;5671:32;5697:5;5671:32;:::i;:::-;5664:5;5661:43;5651:71;;5718:1;5715;5708:12;5651:71;5590:138;:::o;5734:155::-;5788:5;5826:6;5813:20;5804:29;;5842:41;5877:5;5842:41;:::i;:::-;5734:155;;;;:::o;5895:109::-;5931:7;5971:26;5964:5;5960:38;5949:49;;5895:109;;;:::o;6010:120::-;6082:23;6099:5;6082:23;:::i;:::-;6075:5;6072:34;6062:62;;6120:1;6117;6110:12;6062:62;6010:120;:::o;6136:137::-;6181:5;6219:6;6206:20;6197:29;;6235:32;6261:5;6235:32;:::i;:::-;6136:137;;;;:::o;6279:633::-;6363:6;6371;6379;6428:2;6416:9;6407:7;6403:23;6399:32;6396:119;;;6434:79;;:::i;:::-;6396:119;6554:1;6579:53;6624:7;6615:6;6604:9;6600:22;6579:53;:::i;:::-;6569:63;;6525:117;6681:2;6707:61;6760:7;6751:6;6740:9;6736:22;6707:61;:::i;:::-;6697:71;;6652:126;6817:2;6843:52;6887:7;6878:6;6867:9;6863:22;6843:52;:::i;:::-;6833:62;;6788:117;6279:633;;;;;:::o;6918:117::-;7027:1;7024;7017:12;7041:117;7150:1;7147;7140:12;7164:180;7212:77;7209:1;7202:88;7309:4;7306:1;7299:15;7333:4;7330:1;7323:15;7350:281;7433:27;7455:4;7433:27;:::i;:::-;7425:6;7421:40;7563:6;7551:10;7548:22;7527:18;7515:10;7512:34;7509:62;7506:88;;;7574:18;;:::i;:::-;7506:88;7614:10;7610:2;7603:22;7393:238;7350:281;;:::o;7637:129::-;7671:6;7698:20;;:::i;:::-;7688:30;;7727:33;7755:4;7747:6;7727:33;:::i;:::-;7637:129;;;:::o;7772:307::-;7833:4;7923:18;7915:6;7912:30;7909:56;;;7945:18;;:::i;:::-;7909:56;7983:29;8005:6;7983:29;:::i;:::-;7975:37;;8067:4;8061;8057:15;8049:23;;7772:307;;;:::o;8085:146::-;8182:6;8177:3;8172;8159:30;8223:1;8214:6;8209:3;8205:16;8198:27;8085:146;;;:::o;8237:423::-;8314:5;8339:65;8355:48;8396:6;8355:48;:::i;:::-;8339:65;:::i;:::-;8330:74;;8427:6;8420:5;8413:21;8465:4;8458:5;8454:16;8503:3;8494:6;8489:3;8485:16;8482:25;8479:112;;;8510:79;;:::i;:::-;8479:112;8600:54;8647:6;8642:3;8637;8600:54;:::i;:::-;8320:340;8237:423;;;;;:::o;8679:338::-;8734:5;8783:3;8776:4;8768:6;8764:17;8760:27;8750:122;;8791:79;;:::i;:::-;8750:122;8908:6;8895:20;8933:78;9007:3;8999:6;8992:4;8984:6;8980:17;8933:78;:::i;:::-;8924:87;;8740:277;8679:338;;;;:::o;9023:943::-;9118:6;9126;9134;9142;9191:3;9179:9;9170:7;9166:23;9162:33;9159:120;;;9198:79;;:::i;:::-;9159:120;9318:1;9343:53;9388:7;9379:6;9368:9;9364:22;9343:53;:::i;:::-;9333:63;;9289:117;9445:2;9471:53;9516:7;9507:6;9496:9;9492:22;9471:53;:::i;:::-;9461:63;;9416:118;9573:2;9599:53;9644:7;9635:6;9624:9;9620:22;9599:53;:::i;:::-;9589:63;;9544:118;9729:2;9718:9;9714:18;9701:32;9760:18;9752:6;9749:30;9746:117;;;9782:79;;:::i;:::-;9746:117;9887:62;9941:7;9932:6;9921:9;9917:22;9887:62;:::i;:::-;9877:72;;9672:287;9023:943;;;;;;;:::o;9972:115::-;10057:23;10074:5;10057:23;:::i;:::-;10052:3;10045:36;9972:115;;:::o;10093:218::-;10184:4;10222:2;10211:9;10207:18;10199:26;;10235:69;10301:1;10290:9;10286:17;10277:6;10235:69;:::i;:::-;10093:218;;;;:::o;10317:118::-;10404:24;10422:5;10404:24;:::i;:::-;10399:3;10392:37;10317:118;;:::o;10441:222::-;10534:4;10572:2;10561:9;10557:18;10549:26;;10585:71;10653:1;10642:9;10638:17;10629:6;10585:71;:::i;:::-;10441:222;;;;:::o;10669:619::-;10746:6;10754;10762;10811:2;10799:9;10790:7;10786:23;10782:32;10779:119;;;10817:79;;:::i;:::-;10779:119;10937:1;10962:53;11007:7;10998:6;10987:9;10983:22;10962:53;:::i;:::-;10952:63;;10908:117;11064:2;11090:53;11135:7;11126:6;11115:9;11111:22;11090:53;:::i;:::-;11080:63;;11035:118;11192:2;11218:53;11263:7;11254:6;11243:9;11239:22;11218:53;:::i;:::-;11208:63;;11163:118;10669:619;;;;;:::o;11294:474::-;11362:6;11370;11419:2;11407:9;11398:7;11394:23;11390:32;11387:119;;;11425:79;;:::i;:::-;11387:119;11545:1;11570:53;11615:7;11606:6;11595:9;11591:22;11570:53;:::i;:::-;11560:63;;11516:117;11672:2;11698:53;11743:7;11734:6;11723:9;11719:22;11698:53;:::i;:::-;11688:63;;11643:118;11294:474;;;;;:::o;11774:332::-;11895:4;11933:2;11922:9;11918:18;11910:26;;11946:71;12014:1;12003:9;11999:17;11990:6;11946:71;:::i;:::-;12027:72;12095:2;12084:9;12080:18;12071:6;12027:72;:::i;:::-;11774:332;;;;;:::o;12112:329::-;12171:6;12220:2;12208:9;12199:7;12195:23;12191:32;12188:119;;;12226:79;;:::i;:::-;12188:119;12346:1;12371:53;12416:7;12407:6;12396:9;12392:22;12371:53;:::i;:::-;12361:63;;12317:117;12112:329;;;;:::o;12447:468::-;12512:6;12520;12569:2;12557:9;12548:7;12544:23;12540:32;12537:119;;;12575:79;;:::i;:::-;12537:119;12695:1;12720:53;12765:7;12756:6;12745:9;12741:22;12720:53;:::i;:::-;12710:63;;12666:117;12822:2;12848:50;12890:7;12881:6;12870:9;12866:22;12848:50;:::i;:::-;12838:60;;12793:115;12447:468;;;;;:::o;12921:::-;12986:6;12994;13043:2;13031:9;13022:7;13018:23;13014:32;13011:119;;;13049:79;;:::i;:::-;13011:119;13169:1;13194:53;13239:7;13230:6;13219:9;13215:22;13194:53;:::i;:::-;13184:63;;13140:117;13296:2;13322:50;13364:7;13355:6;13344:9;13340:22;13322:50;:::i;:::-;13312:60;;13267:115;12921:468;;;;;:::o;13395:136::-;13484:6;13518:5;13512:12;13502:22;;13395:136;;;:::o;13537:206::-;13658:11;13692:6;13687:3;13680:19;13732:4;13727:3;13723:14;13708:29;;13537:206;;;;:::o;13749:154::-;13838:4;13861:3;13853:11;;13891:4;13886:3;13882:14;13874:22;;13749:154;;;:::o;13909:132::-;14002:32;14028:5;14002:32;:::i;:::-;13997:3;13990:45;13909:132;;:::o;14047:105::-;14122:23;14139:5;14122:23;:::i;:::-;14117:3;14110:36;14047:105;;:::o;14208:509::-;14339:4;14334:3;14330:14;14429:4;14422:5;14418:16;14412:23;14448:79;14521:4;14516:3;14512:14;14498:12;14448:79;:::i;:::-;14354:183;14620:4;14613:5;14609:16;14603:23;14639:61;14694:4;14689:3;14685:14;14671:12;14639:61;:::i;:::-;14547:163;14308:409;14208:509;;:::o;14723:267::-;14836:10;14857:90;14943:3;14935:6;14857:90;:::i;:::-;14979:4;14974:3;14970:14;14956:28;;14723:267;;;;:::o;14996:135::-;15088:4;15120;15115:3;15111:14;15103:22;;14996:135;;;:::o;15191:908::-;15354:3;15383:76;15453:5;15383:76;:::i;:::-;15475:108;15576:6;15571:3;15475:108;:::i;:::-;15468:115;;15607:78;15679:5;15607:78;:::i;:::-;15708:7;15739:1;15724:350;15749:6;15746:1;15743:13;15724:350;;;15825:6;15819:13;15852:107;15955:3;15940:13;15852:107;:::i;:::-;15845:114;;15982:82;16057:6;15982:82;:::i;:::-;15972:92;;15784:290;15771:1;15768;15764:9;15759:14;;15724:350;;;15728:14;16090:3;16083:10;;15359:740;;;15191:908;;;;:::o;16105:461::-;16292:4;16330:2;16319:9;16315:18;16307:26;;16379:9;16373:4;16369:20;16365:1;16354:9;16350:17;16343:47;16407:152;16554:4;16545:6;16407:152;:::i;:::-;16399:160;;16105:461;;;;:::o;16572:474::-;16640:6;16648;16697:2;16685:9;16676:7;16672:23;16668:32;16665:119;;;16703:79;;:::i;:::-;16665:119;16823:1;16848:53;16893:7;16884:6;16873:9;16869:22;16848:53;:::i;:::-;16838:63;;16794:117;16950:2;16976:53;17021:7;17012:6;17001:9;16997:22;16976:53;:::i;:::-;16966:63;;16921:118;16572:474;;;;;:::o;17052:308::-;17114:4;17204:18;17196:6;17193:30;17190:56;;;17226:18;;:::i;:::-;17190:56;17264:29;17286:6;17264:29;:::i;:::-;17256:37;;17348:4;17342;17338:15;17330:23;;17052:308;;;:::o;17366:425::-;17444:5;17469:66;17485:49;17527:6;17485:49;:::i;:::-;17469:66;:::i;:::-;17460:75;;17558:6;17551:5;17544:21;17596:4;17589:5;17585:16;17634:3;17625:6;17620:3;17616:16;17613:25;17610:112;;;17641:79;;:::i;:::-;17610:112;17731:54;17778:6;17773:3;17768;17731:54;:::i;:::-;17450:341;17366:425;;;;;:::o;17811:340::-;17867:5;17916:3;17909:4;17901:6;17897:17;17893:27;17883:122;;17924:79;;:::i;:::-;17883:122;18041:6;18028:20;18066:79;18141:3;18133:6;18126:4;18118:6;18114:17;18066:79;:::i;:::-;18057:88;;17873:278;17811:340;;;;:::o;18157:654::-;18235:6;18243;18292:2;18280:9;18271:7;18267:23;18263:32;18260:119;;;18298:79;;:::i;:::-;18260:119;18446:1;18435:9;18431:17;18418:31;18476:18;18468:6;18465:30;18462:117;;;18498:79;;:::i;:::-;18462:117;18603:63;18658:7;18649:6;18638:9;18634:22;18603:63;:::i;:::-;18593:73;;18389:287;18715:2;18741:53;18786:7;18777:6;18766:9;18762:22;18741:53;:::i;:::-;18731:63;;18686:118;18157:654;;;;;:::o;18817:180::-;18865:77;18862:1;18855:88;18962:4;18959:1;18952:15;18986:4;18983:1;18976:15;19003:320;19047:6;19084:1;19078:4;19074:12;19064:22;;19131:1;19125:4;19121:12;19152:18;19142:81;;19208:4;19200:6;19196:17;19186:27;;19142:81;19270:2;19262:6;19259:14;19239:18;19236:38;19233:84;;19289:18;;:::i;:::-;19233:84;19054:269;19003:320;;;:::o;19329:180::-;19377:77;19374:1;19367:88;19474:4;19471:1;19464:15;19498:4;19495:1;19488:15;19515:98;19566:6;19600:5;19594:12;19584:22;;19515:98;;;:::o;19619:168::-;19702:11;19736:6;19731:3;19724:19;19776:4;19771:3;19767:14;19752:29;;19619:168;;;;:::o;19793:373::-;19879:3;19907:38;19939:5;19907:38;:::i;:::-;19961:70;20024:6;20019:3;19961:70;:::i;:::-;19954:77;;20040:65;20098:6;20093:3;20086:4;20079:5;20075:16;20040:65;:::i;:::-;20130:29;20152:6;20130:29;:::i;:::-;20125:3;20121:39;20114:46;;19883:283;19793:373;;;;:::o;20172:89::-;20221:7;20250:5;20239:16;;20172:89;;;:::o;20267:60::-;20295:3;20316:5;20309:12;;20267:60;;;:::o;20333:166::-;20395:9;20428:65;20446:46;20455:36;20485:5;20455:36;:::i;:::-;20446:46;:::i;:::-;20428:65;:::i;:::-;20415:78;;20333:166;;;:::o;20505:155::-;20604:49;20647:5;20604:49;:::i;:::-;20599:3;20592:62;20505:155;;:::o;20666:775::-;20901:4;20939:3;20928:9;20924:19;20916:27;;20953:71;21021:1;21010:9;21006:17;20997:6;20953:71;:::i;:::-;21034:72;21102:2;21091:9;21087:18;21078:6;21034:72;:::i;:::-;21116;21184:2;21173:9;21169:18;21160:6;21116:72;:::i;:::-;21235:9;21229:4;21225:20;21220:2;21209:9;21205:18;21198:48;21263:76;21334:4;21325:6;21263:76;:::i;:::-;21255:84;;21349:85;21429:3;21418:9;21414:19;21405:6;21349:85;:::i;:::-;20666:775;;;;;;;;:::o;21447:332::-;21568:4;21606:2;21595:9;21591:18;21583:26;;21619:71;21687:1;21676:9;21672:17;21663:6;21619:71;:::i;:::-;21700:72;21768:2;21757:9;21753:18;21744:6;21700:72;:::i;:::-;21447:332;;;;;:::o;21785:137::-;21839:5;21870:6;21864:13;21855:22;;21886:30;21910:5;21886:30;:::i;:::-;21785:137;;;;:::o;21928:345::-;21995:6;22044:2;22032:9;22023:7;22019:23;22015:32;22012:119;;;22050:79;;:::i;:::-;22012:119;22170:1;22195:61;22248:7;22239:6;22228:9;22224:22;22195:61;:::i;:::-;22185:71;;22141:125;21928:345;;;;:::o;22279:180::-;22327:77;22324:1;22317:88;22424:4;22421:1;22414:15;22448:4;22445:1;22438:15;22465:410;22505:7;22528:20;22546:1;22528:20;:::i;:::-;22523:25;;22562:20;22580:1;22562:20;:::i;:::-;22557:25;;22617:1;22614;22610:9;22639:30;22657:11;22639:30;:::i;:::-;22628:41;;22818:1;22809:7;22805:15;22802:1;22799:22;22779:1;22772:9;22752:83;22729:139;;22848:18;;:::i;:::-;22729:139;22513:362;22465:410;;;;:::o;22881:180::-;22929:77;22926:1;22919:88;23026:4;23023:1;23016:15;23050:4;23047:1;23040:15;23067:185;23107:1;23124:20;23142:1;23124:20;:::i;:::-;23119:25;;23158:20;23176:1;23158:20;:::i;:::-;23153:25;;23197:1;23187:35;;23202:18;;:::i;:::-;23187:35;23244:1;23241;23237:9;23232:14;;23067:185;;;;:::o;23258:147::-;23359:11;23396:3;23381:18;;23258:147;;;;:::o;23411:114::-;;:::o;23531:398::-;23690:3;23711:83;23792:1;23787:3;23711:83;:::i;:::-;23704:90;;23803:93;23892:3;23803:93;:::i;:::-;23921:1;23916:3;23912:11;23905:18;;23531:398;;;:::o;23935:379::-;24119:3;24141:147;24284:3;24141:147;:::i;:::-;24134:154;;24305:3;24298:10;;23935:379;;;:::o;24320:180::-;24460:32;24456:1;24448:6;24444:14;24437:56;24320:180;:::o;24506:366::-;24648:3;24669:67;24733:2;24728:3;24669:67;:::i;:::-;24662:74;;24745:93;24834:3;24745:93;:::i;:::-;24863:2;24858:3;24854:12;24847:19;;24506:366;;;:::o;24878:419::-;25044:4;25082:2;25071:9;25067:18;25059:26;;25131:9;25125:4;25121:20;25117:1;25106:9;25102:17;25095:47;25159:131;25285:4;25159:131;:::i;:::-;25151:139;;24878:419;;;:::o;25303:225::-;25443:34;25439:1;25431:6;25427:14;25420:58;25512:8;25507:2;25499:6;25495:15;25488:33;25303:225;:::o;25534:366::-;25676:3;25697:67;25761:2;25756:3;25697:67;:::i;:::-;25690:74;;25773:93;25862:3;25773:93;:::i;:::-;25891:2;25886:3;25882:12;25875:19;;25534:366;;;:::o;25906:419::-;26072:4;26110:2;26099:9;26095:18;26087:26;;26159:9;26153:4;26149:20;26145:1;26134:9;26130:17;26123:47;26187:131;26313:4;26187:131;:::i;:::-;26179:139;;25906:419;;;:::o;26331:191::-;26371:3;26390:20;26408:1;26390:20;:::i;:::-;26385:25;;26424:20;26442:1;26424:20;:::i;:::-;26419:25;;26467:1;26464;26460:9;26453:16;;26488:3;26485:1;26482:10;26479:36;;;26495:18;;:::i;:::-;26479:36;26331:191;;;;:::o;26528:241::-;26668:34;26664:1;26656:6;26652:14;26645:58;26737:24;26732:2;26724:6;26720:15;26713:49;26528:241;:::o;26775:366::-;26917:3;26938:67;27002:2;26997:3;26938:67;:::i;:::-;26931:74;;27014:93;27103:3;27014:93;:::i;:::-;27132:2;27127:3;27123:12;27116:19;;26775:366;;;:::o;27147:419::-;27313:4;27351:2;27340:9;27336:18;27328:26;;27400:9;27394:4;27390:20;27386:1;27375:9;27371:17;27364:47;27428:131;27554:4;27428:131;:::i;:::-;27420:139;;27147:419;;;:::o;27572:148::-;27674:11;27711:3;27696:18;;27572:148;;;;:::o;27726:390::-;27832:3;27860:39;27893:5;27860:39;:::i;:::-;27915:89;27997:6;27992:3;27915:89;:::i;:::-;27908:96;;28013:65;28071:6;28066:3;28059:4;28052:5;28048:16;28013:65;:::i;:::-;28103:6;28098:3;28094:16;28087:23;;27836:280;27726:390;;;;:::o;28122:595::-;28350:3;28372:95;28463:3;28454:6;28372:95;:::i;:::-;28365:102;;28484:95;28575:3;28566:6;28484:95;:::i;:::-;28477:102;;28596:95;28687:3;28678:6;28596:95;:::i;:::-;28589:102;;28708:3;28701:10;;28122:595;;;;;;:::o;28723:141::-;28772:4;28795:3;28787:11;;28818:3;28815:1;28808:14;28852:4;28849:1;28839:18;28831:26;;28723:141;;;:::o;28870:93::-;28907:6;28954:2;28949;28942:5;28938:14;28934:23;28924:33;;28870:93;;;:::o;28969:107::-;29013:8;29063:5;29057:4;29053:16;29032:37;;28969:107;;;;:::o;29082:393::-;29151:6;29201:1;29189:10;29185:18;29224:97;29254:66;29243:9;29224:97;:::i;:::-;29342:39;29372:8;29361:9;29342:39;:::i;:::-;29330:51;;29414:4;29410:9;29403:5;29399:21;29390:30;;29463:4;29453:8;29449:19;29442:5;29439:30;29429:40;;29158:317;;29082:393;;;;;:::o;29481:142::-;29531:9;29564:53;29582:34;29591:24;29609:5;29591:24;:::i;:::-;29582:34;:::i;:::-;29564:53;:::i;:::-;29551:66;;29481:142;;;:::o;29629:75::-;29672:3;29693:5;29686:12;;29629:75;;;:::o;29710:269::-;29820:39;29851:7;29820:39;:::i;:::-;29881:91;29930:41;29954:16;29930:41;:::i;:::-;29922:6;29915:4;29909:11;29881:91;:::i;:::-;29875:4;29868:105;29786:193;29710:269;;;:::o;29985:73::-;30030:3;29985:73;:::o;30064:189::-;30141:32;;:::i;:::-;30182:65;30240:6;30232;30226:4;30182:65;:::i;:::-;30117:136;30064:189;;:::o;30259:186::-;30319:120;30336:3;30329:5;30326:14;30319:120;;;30390:39;30427:1;30420:5;30390:39;:::i;:::-;30363:1;30356:5;30352:13;30343:22;;30319:120;;;30259:186;;:::o;30451:543::-;30552:2;30547:3;30544:11;30541:446;;;30586:38;30618:5;30586:38;:::i;:::-;30670:29;30688:10;30670:29;:::i;:::-;30660:8;30656:44;30853:2;30841:10;30838:18;30835:49;;;30874:8;30859:23;;30835:49;30897:80;30953:22;30971:3;30953:22;:::i;:::-;30943:8;30939:37;30926:11;30897:80;:::i;:::-;30556:431;;30541:446;30451:543;;;:::o;31000:117::-;31054:8;31104:5;31098:4;31094:16;31073:37;;31000:117;;;;:::o;31123:169::-;31167:6;31200:51;31248:1;31244:6;31236:5;31233:1;31229:13;31200:51;:::i;:::-;31196:56;31281:4;31275;31271:15;31261:25;;31174:118;31123:169;;;;:::o;31297:295::-;31373:4;31519:29;31544:3;31538:4;31519:29;:::i;:::-;31511:37;;31581:3;31578:1;31574:11;31568:4;31565:21;31557:29;;31297:295;;;;:::o;31597:1395::-;31714:37;31747:3;31714:37;:::i;:::-;31816:18;31808:6;31805:30;31802:56;;;31838:18;;:::i;:::-;31802:56;31882:38;31914:4;31908:11;31882:38;:::i;:::-;31967:67;32027:6;32019;32013:4;31967:67;:::i;:::-;32061:1;32085:4;32072:17;;32117:2;32109:6;32106:14;32134:1;32129:618;;;;32791:1;32808:6;32805:77;;;32857:9;32852:3;32848:19;32842:26;32833:35;;32805:77;32908:67;32968:6;32961:5;32908:67;:::i;:::-;32902:4;32895:81;32764:222;32099:887;;32129:618;32181:4;32177:9;32169:6;32165:22;32215:37;32247:4;32215:37;:::i;:::-;32274:1;32288:208;32302:7;32299:1;32296:14;32288:208;;;32381:9;32376:3;32372:19;32366:26;32358:6;32351:42;32432:1;32424:6;32420:14;32410:24;;32479:2;32468:9;32464:18;32451:31;;32325:4;32322:1;32318:12;32313:17;;32288:208;;;32524:6;32515:7;32512:19;32509:179;;;32582:9;32577:3;32573:19;32567:26;32625:48;32667:4;32659:6;32655:17;32644:9;32625:48;:::i;:::-;32617:6;32610:64;32532:156;32509:179;32734:1;32730;32722:6;32718:14;32714:22;32708:4;32701:36;32136:611;;;32099:887;;31689:1303;;;31597:1395;;:::o;32998:225::-;33138:34;33134:1;33126:6;33122:14;33115:58;33207:8;33202:2;33194:6;33190:15;33183:33;32998:225;:::o;33229:366::-;33371:3;33392:67;33456:2;33451:3;33392:67;:::i;:::-;33385:74;;33468:93;33557:3;33468:93;:::i;:::-;33586:2;33581:3;33577:12;33570:19;;33229:366;;;:::o;33601:419::-;33767:4;33805:2;33794:9;33790:18;33782:26;;33854:9;33848:4;33844:20;33840:1;33829:9;33825:17;33818:47;33882:131;34008:4;33882:131;:::i;:::-;33874:139;;33601:419;;;:::o;34026:182::-;34166:34;34162:1;34154:6;34150:14;34143:58;34026:182;:::o;34214:366::-;34356:3;34377:67;34441:2;34436:3;34377:67;:::i;:::-;34370:74;;34453:93;34542:3;34453:93;:::i;:::-;34571:2;34566:3;34562:12;34555:19;;34214:366;;;:::o;34586:419::-;34752:4;34790:2;34779:9;34775:18;34767:26;;34839:9;34833:4;34829:20;34825:1;34814:9;34810:17;34803:47;34867:131;34993:4;34867:131;:::i;:::-;34859:139;;34586:419;;;:::o;35011:177::-;35151:29;35147:1;35139:6;35135:14;35128:53;35011:177;:::o;35194:366::-;35336:3;35357:67;35421:2;35416:3;35357:67;:::i;:::-;35350:74;;35433:93;35522:3;35433:93;:::i;:::-;35551:2;35546:3;35542:12;35535:19;;35194:366;;;:::o;35566:419::-;35732:4;35770:2;35759:9;35755:18;35747:26;;35819:9;35813:4;35809:20;35805:1;35794:9;35790:17;35783:47;35847:131;35973:4;35847:131;:::i;:::-;35839:139;;35566:419;;;:::o;35991:182::-;36131:34;36127:1;36119:6;36115:14;36108:58;35991:182;:::o;36179:366::-;36321:3;36342:67;36406:2;36401:3;36342:67;:::i;:::-;36335:74;;36418:93;36507:3;36418:93;:::i;:::-;36536:2;36531:3;36527:12;36520:19;;36179:366;;;:::o;36551:419::-;36717:4;36755:2;36744:9;36740:18;36732:26;;36804:9;36798:4;36794:20;36790:1;36779:9;36775:17;36768:47;36832:131;36958:4;36832:131;:::i;:::-;36824:139;;36551:419;;;:::o;36976:233::-;37015:3;37038:24;37056:5;37038:24;:::i;:::-;37029:33;;37084:66;37077:5;37074:77;37071:103;;37154:18;;:::i;:::-;37071:103;37201:1;37194:5;37190:13;37183:20;;36976:233;;;:::o;37215:224::-;37355:34;37351:1;37343:6;37339:14;37332:58;37424:7;37419:2;37411:6;37407:15;37400:32;37215:224;:::o;37445:366::-;37587:3;37608:67;37672:2;37667:3;37608:67;:::i;:::-;37601:74;;37684:93;37773:3;37684:93;:::i;:::-;37802:2;37797:3;37793:12;37786:19;;37445:366;;;:::o;37817:419::-;37983:4;38021:2;38010:9;38006:18;37998:26;;38070:9;38064:4;38060:20;38056:1;38045:9;38041:17;38034:47;38098:131;38224:4;38098:131;:::i;:::-;38090:139;;37817:419;;;:::o;38242:181::-;38382:33;38378:1;38370:6;38366:14;38359:57;38242:181;:::o;38429:366::-;38571:3;38592:67;38656:2;38651:3;38592:67;:::i;:::-;38585:74;;38668:93;38757:3;38668:93;:::i;:::-;38786:2;38781:3;38777:12;38770:19;;38429:366;;;:::o;38801:419::-;38967:4;39005:2;38994:9;38990:18;38982:26;;39054:9;39048:4;39044:20;39040:1;39029:9;39025:17;39018:47;39082:131;39208:4;39082:131;:::i;:::-;39074:139;;38801:419;;;:::o;39226:181::-;39366:33;39362:1;39354:6;39350:14;39343:57;39226:181;:::o;39413:366::-;39555:3;39576:67;39640:2;39635:3;39576:67;:::i;:::-;39569:74;;39652:93;39741:3;39652:93;:::i;:::-;39770:2;39765:3;39761:12;39754:19;;39413:366;;;:::o;39785:419::-;39951:4;39989:2;39978:9;39974:18;39966:26;;40038:9;40032:4;40028:20;40024:1;40013:9;40009:17;40002:47;40066:131;40192:4;40066:131;:::i;:::-;40058:139;;39785:419;;;:::o;40210:194::-;40250:4;40270:20;40288:1;40270:20;:::i;:::-;40265:25;;40304:20;40322:1;40304:20;:::i;:::-;40299:25;;40348:1;40345;40341:9;40333:17;;40372:1;40366:4;40363:11;40360:37;;;40377:18;;:::i;:::-;40360:37;40210:194;;;;:::o;40410:177::-;40550:29;40546:1;40538:6;40534:14;40527:53;40410:177;:::o;40593:366::-;40735:3;40756:67;40820:2;40815:3;40756:67;:::i;:::-;40749:74;;40832:93;40921:3;40832:93;:::i;:::-;40950:2;40945:3;40941:12;40934:19;;40593:366;;;:::o;40965:419::-;41131:4;41169:2;41158:9;41154:18;41146:26;;41218:9;41212:4;41208:20;41204:1;41193:9;41189:17;41182:47;41246:131;41372:4;41246:131;:::i;:::-;41238:139;;40965:419;;;:::o;41390:571::-;41605:4;41643:2;41632:9;41628:18;41620:26;;41656:71;41724:1;41713:9;41709:17;41700:6;41656:71;:::i;:::-;41774:9;41768:4;41764:20;41759:2;41748:9;41744:18;41737:48;41802:152;41949:4;41940:6;41802:152;:::i;:::-;41794:160;;41390:571;;;;;:::o;41967:640::-;42162:4;42200:3;42189:9;42185:19;42177:27;;42214:71;42282:1;42271:9;42267:17;42258:6;42214:71;:::i;:::-;42295:72;42363:2;42352:9;42348:18;42339:6;42295:72;:::i;:::-;42377;42445:2;42434:9;42430:18;42421:6;42377:72;:::i;:::-;42496:9;42490:4;42486:20;42481:2;42470:9;42466:18;42459:48;42524:76;42595:4;42586:6;42524:76;:::i;:::-;42516:84;;41967:640;;;;;;;:::o;42613:141::-;42669:5;42700:6;42694:13;42685:22;;42716:32;42742:5;42716:32;:::i;:::-;42613:141;;;;:::o;42760:349::-;42829:6;42878:2;42866:9;42857:7;42853:23;42849:32;42846:119;;;42884:79;;:::i;:::-;42846:119;43004:1;43029:63;43084:7;43075:6;43064:9;43060:22;43029:63;:::i;:::-;43019:73;;42975:127;42760:349;;;;:::o
Swarm Source
ipfs://a54fa0ae72a15494fc22efc8ddb9b17fa57cb1554149af36c8c090c40fb012cc
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.