Feature Tip: Add private address tag to any address under My Name Tag !
ERC-721
NFT
Overview
Max Total Supply
15,000 COMIC3
Holders
3,475
Market
Volume (24H)
N/A
Min Price (24H)
N/A
Max Price (24H)
N/A
Other Info
Token Contract
Balance
1 COMIC3Loading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
PunksThreeVRF
Compiler Version
v0.8.15+commit.e14f2714
Optimization Enabled:
Yes with 50000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.15; import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol"; import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol"; import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; import "./ERC721Enumerable.sol"; contract PunksThreeVRF is VRFConsumerBaseV2, ERC721Enumerable { using ECDSA for bytes32; struct Window { uint128 startWindow; uint128 endWindow; } struct Prize { bool tokenType; //1155 is 0, 721 is 1 bool mint; address tokenAddress; } address constant FOUNDERS_DAO = 0x580A96BC816C2324Bdff5eb2a7E159AE7ee63022; address signer; address immutable tokenHolder; uint256 public immutable PRICE; VRFCoordinatorV2Interface immutable COORDINATOR; bytes32 keyHash; uint32 callbackGasLimit = 2500000; uint16 requestConfirmations = 3; uint64 subscriptionId; uint256 public maxSale; uint8[] public remainingTokens; uint256 public amountSold; uint256 prizeCounter; uint256 stageCounter; mapping(uint256 => address) public requestToAddress; mapping(address => uint256) public amountMinted; mapping(uint256 => Window) public stages; mapping(uint256 => Prize) public prizes; Window publicWindow; error windowClosed(); error signatureInvalid(); error amountInvalid(); error allPrizesDistributed(); error insufficientPayment(); error soldOut(); error withdrawFailed(); error addStagesFailed(); error callerNotOwnerNorApproved(); error notSameLength(); error maxSupplyExceeded(); constructor( address _vrfCoordinator, bytes32 _keyHash, uint64 _subscriptionId, address _signer, address _tokenHolder, string memory _name, string memory _symbol, string memory _uri, uint256 _price ) PVERC721(_name, _symbol, _uri, 15000) VRFConsumerBaseV2(_vrfCoordinator) { COORDINATOR = VRFCoordinatorV2Interface(_vrfCoordinator); subscriptionId = _subscriptionId; keyHash = _keyHash; signer = _signer; tokenHolder = _tokenHolder; PRICE = _price; _internalMint(FOUNDERS_DAO); } function fillRemainingTokens(uint8 _prizeId, uint256 _amount) public onlyOwner { for(uint256 i; i < _amount;) { remainingTokens.push(_prizeId); unchecked { ++i; } } maxSale += _amount; } function clearRemainingTokens(uint256 _newMaxSale) external onlyOwner { remainingTokens = new uint8[](0); maxSale = _newMaxSale; } function setPublicWindow(Window calldata window) external onlyOwner { publicWindow.startWindow = window.startWindow; publicWindow.endWindow = window.endWindow; } function setSigner(address _signer) external onlyOwner { signer = _signer; } function addStages(Window[] memory windows) external onlyOwner { for (uint256 i; i < windows.length; i++) { if(windows[i].startWindow >= windows[i].endWindow) { revert addStagesFailed(); } Window storage p = stages[stageCounter]; p.startWindow = windows[i].startWindow; p.endWindow = windows[i].endWindow; ++stageCounter; } } function editStage(uint256 _id, uint128 _startWindow, uint128 _endWindow) external onlyOwner { stages[_id].startWindow = _startWindow; stages[_id].endWindow = _endWindow; } function addTieredPrizes(address _tokenAddress, bool _tokenType, bool _mint, uint256 _amount) external onlyOwner { Prize storage p = prizes[prizeCounter]; p.tokenType = _tokenType; p.tokenAddress = _tokenAddress; p.mint = _mint; fillRemainingTokens(uint8(prizeCounter), _amount); ++prizeCounter; } function editTieredPrize(uint256 _id, address _tokenAddress, bool _tokenType, bool _mint) external onlyOwner { prizes[_id].tokenType = _tokenType; prizes[_id].tokenAddress = _tokenAddress; prizes[_id].mint = _mint; } function burn(uint256 tokenId) external { if(!isApprovedForAll[ownerOf(tokenId)][msg.sender] && getApproved[tokenId] != msg.sender && ownerOf(tokenId) != msg.sender ) { revert callerNotOwnerNorApproved(); } _burn(tokenId); } function ownerMint ( address[] calldata _to, uint256[] calldata _amount ) external onlyOwner { if(_to.length != _amount.length) { revert notSameLength(); } for(uint256 i; i < _to.length; i++) { if(tokenCounter + _amount[i] > MAX_SUPPLY) { revert maxSupplyExceeded(); } _mintMany(_to[i], _amount[i]); } } function setKeyHash(bytes32 _keyHash) external onlyOwner { keyHash = _keyHash; } function setCallbackGasLimit(uint32 _callbackGasLimit) external onlyOwner { callbackGasLimit = _callbackGasLimit; } function setRequestConfirmations(uint16 _requestConfirmations) external onlyOwner { requestConfirmations = _requestConfirmations; } function setSubscriptionId(uint64 _subscriptionId) external onlyOwner { subscriptionId = _subscriptionId; } function withdraw(address payable _to, uint256 _amount) external onlyOwner { (bool sent, bytes memory data) = _to.call{value: _amount}(""); if(!sent) { revert withdrawFailed(); } } function mint( bytes calldata _signature, uint256 _stage, uint256 _maxAtCurrentStage, uint32 _amount ) external payable { if(_amount + amountSold > maxSale) { revert soldOut(); } if(_amount * PRICE != msg.value) { revert insufficientPayment(); } if(block.timestamp < stages[_stage].startWindow || block.timestamp > stages[_stage].endWindow) { revert windowClosed(); } bytes32 hash = keccak256(abi.encodePacked(msg.sender, _stage, _maxAtCurrentStage)); if (hash.toEthSignedMessageHash().recover(_signature) != signer) { revert signatureInvalid(); } if(_amount + amountMinted[msg.sender] > _maxAtCurrentStage){ revert amountInvalid(); } amountMinted[msg.sender] += _amount; amountSold += _amount; sendVRFRequests(_amount); } function publicMint( uint32 _amount ) external payable { if(_amount + amountSold > maxSale) { revert soldOut(); } if(_amount * PRICE != msg.value) { revert insufficientPayment(); } if(block.timestamp < publicWindow.startWindow || block.timestamp > publicWindow.endWindow) { revert windowClosed(); } if(_amount > 20){ revert amountInvalid(); } amountSold += _amount; sendVRFRequests(_amount); } function sendPrize( uint256 prizeId, address receiver ) external onlyOwner { Prize memory prize = prizes[prizeId]; address tokenAddress = prize.tokenAddress; if (tokenAddress == address(this)) { _internalMint(receiver); } else { if(prize.mint) { IComicThreeSE(tokenAddress).mint(receiver); } else if (prize.tokenType) { IERC721Enumerable token = IERC721Enumerable(tokenAddress); token.transferFrom(tokenHolder, receiver, token.tokenOfOwnerByIndex(tokenHolder,0)); } else { IERC1155(prize.tokenAddress).safeTransferFrom(tokenHolder, receiver, 0, 1, ""); } } } function sendVRFRequests ( uint32 _tokenAmount ) internal { while (_tokenAmount > 0) { uint32 _amountTemp = _tokenAmount > 10 ? 10 : _tokenAmount; _tokenAmount -= _amountTemp; uint256 s_requestId = COORDINATOR.requestRandomWords( keyHash, subscriptionId, requestConfirmations, callbackGasLimit, _amountTemp ); requestToAddress[s_requestId] = msg.sender; } } function fulfillRandomWords( uint256 requestId, uint256[] memory randomWords ) internal override { for(uint256 i; i < randomWords.length;) { uint256 amountRemaining = remainingTokens.length; uint256 pickedIndex = randomWords[i] % amountRemaining; Prize memory prize = prizes[remainingTokens[pickedIndex]]; remainingTokens[pickedIndex] = remainingTokens[amountRemaining - 1]; remainingTokens.pop(); address receiver = requestToAddress[requestId]; address tokenAddress = prize.tokenAddress; if (tokenAddress == address(this)) { _internalMint(receiver); } else { if(prize.mint) { IComicThreeSE(tokenAddress).mint(receiver); } else if (prize.tokenType) { IERC721Enumerable token = IERC721Enumerable(tokenAddress); token.transferFrom(tokenHolder, receiver, token.tokenOfOwnerByIndex(tokenHolder,0)); } else { IERC1155(prize.tokenAddress).safeTransferFrom(tokenHolder, receiver, 0, 1, ""); } } unchecked { ++i; } } } } interface IComicThreeSE { function mint(address to) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /** **************************************************************************** * @notice Interface for contracts using VRF randomness * ***************************************************************************** * @dev PURPOSE * * @dev Reggie the Random Oracle (not his real job) wants to provide randomness * @dev to Vera the verifier in such a way that Vera can be sure he's not * @dev making his output up to suit himself. Reggie provides Vera a public key * @dev to which he knows the secret key. Each time Vera provides a seed to * @dev Reggie, he gives back a value which is computed completely * @dev deterministically from the seed and the secret key. * * @dev Reggie provides a proof by which Vera can verify that the output was * @dev correctly computed once Reggie tells it to her, but without that proof, * @dev the output is indistinguishable to her from a uniform random sample * @dev from the output space. * * @dev The purpose of this contract is to make it easy for unrelated contracts * @dev to talk to Vera the verifier about the work Reggie is doing, to provide * @dev simple access to a verifiable source of randomness. It ensures 2 things: * @dev 1. The fulfillment came from the VRFCoordinator * @dev 2. The consumer contract implements fulfillRandomWords. * ***************************************************************************** * @dev USAGE * * @dev Calling contracts must inherit from VRFConsumerBase, and can * @dev initialize VRFConsumerBase's attributes in their constructor as * @dev shown: * * @dev contract VRFConsumer { * @dev constructor(<other arguments>, address _vrfCoordinator, address _link) * @dev VRFConsumerBase(_vrfCoordinator) public { * @dev <initialization with other arguments goes here> * @dev } * @dev } * * @dev The oracle will have given you an ID for the VRF keypair they have * @dev committed to (let's call it keyHash). Create subscription, fund it * @dev and your consumer contract as a consumer of it (see VRFCoordinatorInterface * @dev subscription management functions). * @dev Call requestRandomWords(keyHash, subId, minimumRequestConfirmations, * @dev callbackGasLimit, numWords), * @dev see (VRFCoordinatorInterface for a description of the arguments). * * @dev Once the VRFCoordinator has received and validated the oracle's response * @dev to your request, it will call your contract's fulfillRandomWords method. * * @dev The randomness argument to fulfillRandomWords is a set of random words * @dev generated from your requestId and the blockHash of the request. * * @dev If your contract could have concurrent requests open, you can use the * @dev requestId returned from requestRandomWords to track which response is associated * @dev with which randomness request. * @dev See "SECURITY CONSIDERATIONS" for principles to keep in mind, * @dev if your contract could have multiple requests in flight simultaneously. * * @dev Colliding `requestId`s are cryptographically impossible as long as seeds * @dev differ. * * ***************************************************************************** * @dev SECURITY CONSIDERATIONS * * @dev A method with the ability to call your fulfillRandomness method directly * @dev could spoof a VRF response with any random value, so it's critical that * @dev it cannot be directly called by anything other than this base contract * @dev (specifically, by the VRFConsumerBase.rawFulfillRandomness method). * * @dev For your users to trust that your contract's random behavior is free * @dev from malicious interference, it's best if you can write it so that all * @dev behaviors implied by a VRF response are executed *during* your * @dev fulfillRandomness method. If your contract must store the response (or * @dev anything derived from it) and use it later, you must ensure that any * @dev user-significant behavior which depends on that stored value cannot be * @dev manipulated by a subsequent VRF request. * * @dev Similarly, both miners and the VRF oracle itself have some influence * @dev over the order in which VRF responses appear on the blockchain, so if * @dev your contract could have multiple VRF requests in flight simultaneously, * @dev you must ensure that the order in which the VRF responses arrive cannot * @dev be used to manipulate your contract's user-significant behavior. * * @dev Since the block hash of the block which contains the requestRandomness * @dev call is mixed into the input to the VRF *last*, a sufficiently powerful * @dev miner could, in principle, fork the blockchain to evict the block * @dev containing the request, forcing the request to be included in a * @dev different block with a different hash, and therefore a different input * @dev to the VRF. However, such an attack would incur a substantial economic * @dev cost. This cost scales with the number of blocks the VRF oracle waits * @dev until it calls responds to a request. It is for this reason that * @dev that you can signal to an oracle you'd like them to wait longer before * @dev responding to the request (however this is not enforced in the contract * @dev and so remains effective only in the case of unmodified oracle software). */ abstract contract VRFConsumerBaseV2 { error OnlyCoordinatorCanFulfill(address have, address want); address private immutable vrfCoordinator; /** * @param _vrfCoordinator address of VRFCoordinator contract */ constructor(address _vrfCoordinator) { vrfCoordinator = _vrfCoordinator; } /** * @notice fulfillRandomness handles the VRF response. Your contract must * @notice implement it. See "SECURITY CONSIDERATIONS" above for important * @notice principles to keep in mind when implementing your fulfillRandomness * @notice method. * * @dev VRFConsumerBaseV2 expects its subcontracts to have a method with this * @dev signature, and will call it once it has verified the proof * @dev associated with the randomness. (It is triggered via a call to * @dev rawFulfillRandomness, below.) * * @param requestId The Id initially returned by requestRandomness * @param randomWords the VRF output expanded to the requested number of words */ function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal virtual; // rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF // proof. rawFulfillRandomness then calls fulfillRandomness, after validating // the origin of the call function rawFulfillRandomWords(uint256 requestId, uint256[] memory randomWords) external { if (msg.sender != vrfCoordinator) { revert OnlyCoordinatorCanFulfill(msg.sender, vrfCoordinator); } fulfillRandomWords(requestId, randomWords); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface VRFCoordinatorV2Interface { /** * @notice Get configuration relevant for making requests * @return minimumRequestConfirmations global min for request confirmations * @return maxGasLimit global max for request gas limit * @return s_provingKeyHashes list of registered key hashes */ function getRequestConfig() external view returns ( uint16, uint32, bytes32[] memory ); /** * @notice Request a set of random words. * @param keyHash - Corresponds to a particular oracle job which uses * that key for generating the VRF proof. Different keyHash's have different gas price * ceilings, so you can select a specific one to bound your maximum per request cost. * @param subId - The ID of the VRF subscription. Must be funded * with the minimum subscription balance required for the selected keyHash. * @param minimumRequestConfirmations - How many blocks you'd like the * oracle to wait before responding to the request. See SECURITY CONSIDERATIONS * for why you may want to request more. The acceptable range is * [minimumRequestBlockConfirmations, 200]. * @param callbackGasLimit - How much gas you'd like to receive in your * fulfillRandomWords callback. Note that gasleft() inside fulfillRandomWords * may be slightly less than this amount because of gas used calling the function * (argument decoding etc.), so you may need to request slightly more than you expect * to have inside fulfillRandomWords. The acceptable range is * [0, maxGasLimit] * @param numWords - The number of uint256 random values you'd like to receive * in your fulfillRandomWords callback. Note these numbers are expanded in a * secure way by the VRFCoordinator from a single random value supplied by the oracle. * @return requestId - A unique identifier of the request. Can be used to match * a request to a response in fulfillRandomWords. */ function requestRandomWords( bytes32 keyHash, uint64 subId, uint16 minimumRequestConfirmations, uint32 callbackGasLimit, uint32 numWords ) external returns (uint256 requestId); /** * @notice Create a VRF subscription. * @return subId - A unique subscription id. * @dev You can manage the consumer set dynamically with addConsumer/removeConsumer. * @dev Note to fund the subscription, use transferAndCall. For example * @dev LINKTOKEN.transferAndCall( * @dev address(COORDINATOR), * @dev amount, * @dev abi.encode(subId)); */ function createSubscription() external returns (uint64 subId); /** * @notice Get a VRF subscription. * @param subId - ID of the subscription * @return balance - LINK balance of the subscription in juels. * @return reqCount - number of requests for this subscription, determines fee tier. * @return owner - owner of the subscription. * @return consumers - list of consumer address which are able to use this subscription. */ function getSubscription(uint64 subId) external view returns ( uint96 balance, uint64 reqCount, address owner, address[] memory consumers ); /** * @notice Request subscription owner transfer. * @param subId - ID of the subscription * @param newOwner - proposed new owner of the subscription */ function requestSubscriptionOwnerTransfer(uint64 subId, address newOwner) external; /** * @notice Request subscription owner transfer. * @param subId - ID of the subscription * @dev will revert if original owner of subId has * not requested that msg.sender become the new owner. */ function acceptSubscriptionOwnerTransfer(uint64 subId) external; /** * @notice Add a consumer to a VRF subscription. * @param subId - ID of the subscription * @param consumer - New consumer which can use the subscription */ function addConsumer(uint64 subId, address consumer) external; /** * @notice Remove a consumer from a VRF subscription. * @param subId - ID of the subscription * @param consumer - Consumer to remove from the subscription */ function removeConsumer(uint64 subId, address consumer) external; /** * @notice Cancel a subscription * @param subId - ID of the subscription * @param to - Where to send the remaining LINK to */ function cancelSubscription(uint64 subId, address to) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../Strings.sol"; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } else if (error == RecoverError.InvalidSignatureV) { revert("ECDSA: invalid signature 'v' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { // Check the signature length // - case 65: r,s,v signature (standard) // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._ if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else if (signature.length == 64) { bytes32 r; bytes32 vs; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. assembly { r := mload(add(signature, 0x20)) vs := mload(add(signature, 0x40)) } return tryRecover(hash, r, vs); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address, RecoverError) { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } if (v != 27 && v != 28) { return (address(0), RecoverError.InvalidSignatureV); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { // 32 is the length in bytes of hash, // enforced by the type signature above return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC1155/IERC1155.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC1155 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-1155[EIP]. * * _Available since v3.1._ */ interface IERC1155 is IERC165 { /** * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`. */ event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); /** * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all * transfers. */ event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values ); /** * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to * `approved`. */ event ApprovalForAll(address indexed account, address indexed operator, bool approved); /** * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. * * If an {URI} event was emitted for `id`, the standard * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value * returned by {IERC1155MetadataURI-uri}. */ event URI(string value, uint256 indexed id); /** * @dev Returns the amount of tokens of token type `id` owned by `account`. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) external view returns (uint256); /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory); /** * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`, * * Emits an {ApprovalForAll} event. * * Requirements: * * - `operator` cannot be the caller. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns true if `operator` is approved to transfer ``account``'s tokens. * * See {setApprovalForAll}. */ function isApprovedForAll(address account, address operator) external view returns (bool); /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) external; /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721Enumerable.sol) pragma solidity ^0.8.0; import "./PVERC721.sol"; import "@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol"; /** * @dev This implements an optional extension of {ERC721} defined in the EIP that adds * enumerability of all the token ids in the contract as well as all token ids owned by each * account. */ abstract contract ERC721Enumerable is PVERC721 { // Mapping from owner to list of owned token IDs mapping(address => mapping(uint256 => uint256)) private _ownedTokens; // Mapping from token ID to index of the owner tokens list mapping(uint256 => uint256) private _ownedTokensIndex; // Array with all token ids, used for enumeration uint256[] private _allTokens; // Mapping from token id to position in the allTokens array mapping(uint256 => uint256) private _allTokensIndex; /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721) returns (bool) { return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}. */ function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual returns (uint256) { require(index < ERC721.balanceOf(owner), "ERC721Enumerable: owner index out of bounds"); return _ownedTokens[owner][index]; } /** * @dev See {IERC721Enumerable-totalSupply}. */ function totalSupply() public view virtual returns (uint256) { return _allTokens.length; } /** * @dev See {IERC721Enumerable-tokenByIndex}. */ function tokenByIndex(uint256 index) public view virtual returns (uint256) { require(index < ERC721Enumerable.totalSupply(), "ERC721Enumerable: global index out of bounds"); return _allTokens[index]; } /** * @dev Hook that is called before any token transfer. This includes minting * and burning. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, ``from``'s `tokenId` will be burned. * - `from` cannot be the zero address. * - `to` cannot be the zero address. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function transferFrom(address from, address to, uint256 id) public override { _beforeTokenTransfer(from, to, id); super.transferFrom(from, to, id); } function _mint(address to, uint256 id) internal override { _beforeTokenTransfer(address(0), to, id); super._mint(to, id); } function _burn(uint256 id) internal override { _beforeTokenTransfer(_ownerOf[id], address(0), id); super._burn(id); } function _beforeTokenTransfer( address from, address to, uint256 tokenId ) internal virtual { if (from == address(0)) { _addTokenToAllTokensEnumeration(tokenId); } else if (from != to) { _removeTokenFromOwnerEnumeration(from, tokenId); } if (to == address(0)) { _removeTokenFromAllTokensEnumeration(tokenId); } else if (to != from) { _addTokenToOwnerEnumeration(to, tokenId); } } /** * @dev Private function to add a token to this extension's ownership-tracking data structures. * @param to address representing the new owner of the given token ID * @param tokenId uint256 ID of the token to be added to the tokens list of the given address */ function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private { uint256 length = ERC721.balanceOf(to); _ownedTokens[to][length] = tokenId; _ownedTokensIndex[tokenId] = length; } /** * @dev Private function to add a token to this extension's token tracking data structures. * @param tokenId uint256 ID of the token to be added to the tokens list */ function _addTokenToAllTokensEnumeration(uint256 tokenId) private { _allTokensIndex[tokenId] = _allTokens.length; _allTokens.push(tokenId); } /** * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for * gas optimizations e.g. when performing a transfer operation (avoiding double writes). * This has O(1) time complexity, but alters the order of the _ownedTokens array. * @param from address representing the previous owner of the given token ID * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address */ function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private { // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and // then delete the last slot (swap and pop). uint256 lastTokenIndex = ERC721.balanceOf(from) - 1; uint256 tokenIndex = _ownedTokensIndex[tokenId]; // When the token to delete is the last token, the swap operation is unnecessary if (tokenIndex != lastTokenIndex) { uint256 lastTokenId = _ownedTokens[from][lastTokenIndex]; _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index } // This also deletes the contents at the last position of the array delete _ownedTokensIndex[tokenId]; delete _ownedTokens[from][lastTokenIndex]; } /** * @dev Private function to remove a token from this extension's token tracking data structures. * This has O(1) time complexity, but alters the order of the _allTokens array. * @param tokenId uint256 ID of the token to be removed from the tokens list */ function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private { // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and // then delete the last slot (swap and pop). uint256 lastTokenIndex = _allTokens.length - 1; uint256 tokenIndex = _allTokensIndex[tokenId]; // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding // an 'if' statement (like in _removeTokenFromOwnerEnumeration) uint256 lastTokenId = _allTokens[lastTokenIndex]; _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index // This also deletes the contents at the last position of the array delete _allTokensIndex[tokenId]; _allTokens.pop(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.15; import "@rari-capital/solmate/src/auth/Owned.sol"; import "@rari-capital/solmate/src/tokens/ERC721.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; contract PVERC721 is ERC721, Owned { using Strings for uint256; uint256 tokenCounter; string uri; uint256 immutable MAX_SUPPLY; error notExists(); constructor( string memory _name, string memory _symbol, string memory _uri, uint256 _maxSupply ) ERC721(_name, _symbol) Owned(msg.sender) { uri = _uri; MAX_SUPPLY = _maxSupply; } function _mintMany(address _account, uint256 _amount) internal { for (uint256 i; i < _amount; ) { _internalMint(_account); unchecked { i++; } } } function _internalMint(address _account) internal { require(tokenCounter < MAX_SUPPLY, "Max supply reached"); ++tokenCounter; _mint(_account, tokenCounter); } function setURI(string memory _uri) external onlyOwner { uri = _uri; } function tokenURI(uint256 tokenId) public view override returns (string memory) { if (tokenCounter < tokenId) { revert notExists(); } return uri; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol) pragma solidity ^0.8.0; import "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Enumerable is IERC721 { /** * @dev Returns the total amount of tokens stored by the contract. */ function totalSupply() external view returns (uint256); /** * @dev Returns a token ID owned by `owner` at a given `index` of its token list. * Use along with {balanceOf} to enumerate all of ``owner``'s tokens. */ function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256); /** * @dev Returns a token ID at a given `index` of all the tokens stored by the contract. * Use along with {totalSupply} to enumerate all tokens. */ function tokenByIndex(uint256 index) external view returns (uint256); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Simple single owner authorization mixin. /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/auth/Owned.sol) abstract contract Owned { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event OwnerUpdated(address indexed user, address indexed newOwner); /*////////////////////////////////////////////////////////////// OWNERSHIP STORAGE //////////////////////////////////////////////////////////////*/ address public owner; modifier onlyOwner() virtual { require(msg.sender == owner, "UNAUTHORIZED"); _; } /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor(address _owner) { owner = _owner; emit OwnerUpdated(address(0), _owner); } /*////////////////////////////////////////////////////////////// OWNERSHIP LOGIC //////////////////////////////////////////////////////////////*/ function setOwner(address newOwner) public virtual onlyOwner { owner = newOwner; emit OwnerUpdated(msg.sender, newOwner); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Modern, minimalist, and gas efficient ERC-721 implementation. /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol) abstract contract ERC721 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Transfer(address indexed from, address indexed to, uint256 indexed id); event Approval(address indexed owner, address indexed spender, uint256 indexed id); event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /*////////////////////////////////////////////////////////////// METADATA STORAGE/LOGIC //////////////////////////////////////////////////////////////*/ string public name; string public symbol; function tokenURI(uint256 id) public view virtual returns (string memory); /*////////////////////////////////////////////////////////////// ERC721 BALANCE/OWNER STORAGE //////////////////////////////////////////////////////////////*/ mapping(uint256 => address) internal _ownerOf; mapping(address => uint256) internal _balanceOf; function ownerOf(uint256 id) public view virtual returns (address owner) { require((owner = _ownerOf[id]) != address(0), "NOT_MINTED"); } function balanceOf(address owner) public view virtual returns (uint256) { require(owner != address(0), "ZERO_ADDRESS"); return _balanceOf[owner]; } /*////////////////////////////////////////////////////////////// ERC721 APPROVAL STORAGE //////////////////////////////////////////////////////////////*/ mapping(uint256 => address) public getApproved; mapping(address => mapping(address => bool)) public isApprovedForAll; /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor(string memory _name, string memory _symbol) { name = _name; symbol = _symbol; } /*////////////////////////////////////////////////////////////// ERC721 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 id) public virtual { address owner = _ownerOf[id]; require(msg.sender == owner || isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED"); getApproved[id] = spender; emit Approval(owner, spender, id); } function setApprovalForAll(address operator, bool approved) public virtual { isApprovedForAll[msg.sender][operator] = approved; emit ApprovalForAll(msg.sender, operator, approved); } function transferFrom( address from, address to, uint256 id ) public virtual { require(from == _ownerOf[id], "WRONG_FROM"); require(to != address(0), "INVALID_RECIPIENT"); require( msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id], "NOT_AUTHORIZED" ); // Underflow of the sender's balance is impossible because we check for // ownership above and the recipient's balance can't realistically overflow. unchecked { _balanceOf[from]--; _balanceOf[to]++; } _ownerOf[id] = to; delete getApproved[id]; emit Transfer(from, to, id); } function safeTransferFrom( address from, address to, uint256 id ) public virtual { transferFrom(from, to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } function safeTransferFrom( address from, address to, uint256 id, bytes calldata data ) public virtual { transferFrom(from, to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } /*////////////////////////////////////////////////////////////// ERC165 LOGIC //////////////////////////////////////////////////////////////*/ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165 interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721 interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address to, uint256 id) internal virtual { require(to != address(0), "INVALID_RECIPIENT"); require(_ownerOf[id] == address(0), "ALREADY_MINTED"); // Counter overflow is incredibly unrealistic. unchecked { _balanceOf[to]++; } _ownerOf[id] = to; emit Transfer(address(0), to, id); } function _burn(uint256 id) internal virtual { address owner = _ownerOf[id]; require(owner != address(0), "NOT_MINTED"); // Ownership check above ensures no underflow. unchecked { _balanceOf[owner]--; } delete _ownerOf[id]; delete getApproved[id]; emit Transfer(owner, address(0), id); } /*////////////////////////////////////////////////////////////// INTERNAL SAFE MINT LOGIC //////////////////////////////////////////////////////////////*/ function _safeMint(address to, uint256 id) internal virtual { _mint(to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } function _safeMint( address to, uint256 id, bytes memory data ) internal virtual { _mint(to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } } /// @notice A generic interface for a contract which properly accepts ERC721 tokens. /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol) abstract contract ERC721TokenReceiver { function onERC721Received( address, address, uint256, bytes calldata ) external virtual returns (bytes4) { return ERC721TokenReceiver.onERC721Received.selector; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * 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); }
{ "optimizer": { "enabled": true, "runs": 50000 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_vrfCoordinator","type":"address"},{"internalType":"bytes32","name":"_keyHash","type":"bytes32"},{"internalType":"uint64","name":"_subscriptionId","type":"uint64"},{"internalType":"address","name":"_signer","type":"address"},{"internalType":"address","name":"_tokenHolder","type":"address"},{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"string","name":"_uri","type":"string"},{"internalType":"uint256","name":"_price","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"have","type":"address"},{"internalType":"address","name":"want","type":"address"}],"name":"OnlyCoordinatorCanFulfill","type":"error"},{"inputs":[],"name":"addStagesFailed","type":"error"},{"inputs":[],"name":"allPrizesDistributed","type":"error"},{"inputs":[],"name":"amountInvalid","type":"error"},{"inputs":[],"name":"callerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"insufficientPayment","type":"error"},{"inputs":[],"name":"maxSupplyExceeded","type":"error"},{"inputs":[],"name":"notExists","type":"error"},{"inputs":[],"name":"notSameLength","type":"error"},{"inputs":[],"name":"signatureInvalid","type":"error"},{"inputs":[],"name":"soldOut","type":"error"},{"inputs":[],"name":"windowClosed","type":"error"},{"inputs":[],"name":"withdrawFailed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","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":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerUpdated","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":"id","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"PRICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint128","name":"startWindow","type":"uint128"},{"internalType":"uint128","name":"endWindow","type":"uint128"}],"internalType":"struct PunksThreeVRF.Window[]","name":"windows","type":"tuple[]"}],"name":"addStages","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"bool","name":"_tokenType","type":"bool"},{"internalType":"bool","name":"_mint","type":"bool"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"addTieredPrizes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"amountMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"amountSold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"id","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"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newMaxSale","type":"uint256"}],"name":"clearRemainingTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"},{"internalType":"uint128","name":"_startWindow","type":"uint128"},{"internalType":"uint128","name":"_endWindow","type":"uint128"}],"name":"editStage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"},{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"bool","name":"_tokenType","type":"bool"},{"internalType":"bool","name":"_mint","type":"bool"}],"name":"editTieredPrize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"_prizeId","type":"uint8"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"fillRemainingTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSale","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_signature","type":"bytes"},{"internalType":"uint256","name":"_stage","type":"uint256"},{"internalType":"uint256","name":"_maxAtCurrentStage","type":"uint256"},{"internalType":"uint32","name":"_amount","type":"uint32"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_to","type":"address[]"},{"internalType":"uint256[]","name":"_amount","type":"uint256[]"}],"name":"ownerMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"prizes","outputs":[{"internalType":"bool","name":"tokenType","type":"bool"},{"internalType":"bool","name":"mint","type":"bool"},{"internalType":"address","name":"tokenAddress","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_amount","type":"uint32"}],"name":"publicMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"requestId","type":"uint256"},{"internalType":"uint256[]","name":"randomWords","type":"uint256[]"}],"name":"rawFulfillRandomWords","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"remainingTokens","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"requestToAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","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":"id","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"prizeId","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"sendPrize","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":"uint32","name":"_callbackGasLimit","type":"uint32"}],"name":"setCallbackGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_keyHash","type":"bytes32"}],"name":"setKeyHash","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint128","name":"startWindow","type":"uint128"},{"internalType":"uint128","name":"endWindow","type":"uint128"}],"internalType":"struct PunksThreeVRF.Window","name":"window","type":"tuple"}],"name":"setPublicWindow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_requestConfirmations","type":"uint16"}],"name":"setRequestConfirmations","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_signer","type":"address"}],"name":"setSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_subscriptionId","type":"uint64"}],"name":"setSubscriptionId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_uri","type":"string"}],"name":"setURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"stages","outputs":[{"internalType":"uint128","name":"startWindow","type":"uint128"},{"internalType":"uint128","name":"endWindow","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
610120604052600f805465ffffffffffff19166403002625a01790553480156200002857600080fd5b5060405162005aa038038062005aa08339810160408190526200004b91620006ff565b6001600160a01b038916608052838383613a9833848460006200006f83826200087e565b5060016200007e82826200087e565b5050600680546001600160a01b0319166001600160a01b0384169081179091556040519091506000907f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d76908290a3506008620000db83826200087e565b5060a0525050506001600160a01b0389811661010052600f8054600160301b600160701b03191666010000000000006001600160401b038b1602179055600e899055600d80546001600160a01b031916888316179055851660c05260e08190526200015a73580a96bc816c2324bdff5eb2a7e159ae7ee6302262000169565b505050505050505050620009c2565b60a05160075410620001b75760405162461bcd60e51b815260206004820152601260248201527113585e081cdd5c1c1b1e481c995858da195960721b60448201526064015b60405180910390fd5b600760008154620001c89062000960565b90915550600754620001dc908290620001df565b50565b620001ed6000838362000208565b620002048282620002d160201b62002d911760201c565b5050565b6001600160a01b03831662000266576200026081600b80546000838152600c60205260408120829055600182018355919091527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90155565b6200028c565b816001600160a01b0316836001600160a01b0316146200028c576200028c8382620003e0565b6001600160a01b038216620002ab57620002a6816200048d565b505050565b826001600160a01b0316826001600160a01b031614620002a657620002a6828262000547565b6001600160a01b0382166200031d5760405162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b6044820152606401620001ae565b6000818152600260205260409020546001600160a01b031615620003755760405162461bcd60e51b815260206004820152600e60248201526d1053149150511657d3525395115160921b6044820152606401620001ae565b6001600160a01b038216600081815260036020908152604080832080546001019055848352600290915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b60006001620003fa846200059860201b620017d51760201c565b6200040691906200097c565b6000838152600a60205260409020549091508082146200045a576001600160a01b03841660009081526009602090815260408083208584528252808320548484528184208190558352600a90915290208190555b506000918252600a602090815260408084208490556001600160a01b039094168352600981528383209183525290812055565b600b54600090620004a1906001906200097c565b6000838152600c6020526040812054600b8054939450909284908110620004cc57620004cc62000996565b9060005260206000200154905080600b8381548110620004f057620004f062000996565b6000918252602080832090910192909255828152600c9091526040808220849055858252812055600b8054806200052b576200052b620009ac565b6001900381819060005260206000200160009055905550505050565b60006200055f836200059860201b620017d51760201c565b6001600160a01b0390931660009081526009602090815260408083208684528252808320859055938252600a9052919091209190915550565b60006001600160a01b038216620005e15760405162461bcd60e51b815260206004820152600c60248201526b5a45524f5f4144445245535360a01b6044820152606401620001ae565b506001600160a01b031660009081526003602052604090205490565b80516001600160a01b03811681146200061557600080fd5b919050565b80516001600160401b03811681146200061557600080fd5b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200065a57600080fd5b81516001600160401b038082111562000677576200067762000632565b604051601f8301601f19908116603f01168101908282118183101715620006a257620006a262000632565b81604052838152602092508683858801011115620006bf57600080fd5b600091505b83821015620006e35785820183015181830184015290820190620006c4565b83821115620006f55760008385830101525b9695505050505050565b60008060008060008060008060006101208a8c0312156200071f57600080fd5b6200072a8a620005fd565b985060208a015197506200074160408b016200061a565b96506200075160608b01620005fd565b95506200076160808b01620005fd565b60a08b01519095506001600160401b03808211156200077f57600080fd5b6200078d8d838e0162000648565b955060c08c0151915080821115620007a457600080fd5b620007b28d838e0162000648565b945060e08c0151915080821115620007c957600080fd5b50620007d88c828d0162000648565b9250506101008a015190509295985092959850929598565b600181811c908216806200080557607f821691505b6020821081036200082657634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620002a657600081815260208120601f850160051c81016020861015620008555750805b601f850160051c820191505b81811015620008765782815560010162000861565b505050505050565b81516001600160401b038111156200089a576200089a62000632565b620008b281620008ab8454620007f0565b846200082c565b602080601f831160018114620008ea5760008415620008d15750858301515b600019600386901b1c1916600185901b17855562000876565b600085815260208120601f198616915b828110156200091b57888601518255948401946001909101908401620008fa565b50858210156200093a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052601160045260246000fd5b6000600182016200097557620009756200094a565b5060010190565b6000828210156200099157620009916200094a565b500390565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c05160e0516101005161506862000a386000396000613aa70152600081816106ff01528181611e670152612a86015260008181611b7b01528181611cec015281816132aa015261341b01526000818161162f01526138db015260008181610f860152610fee01526150686000f3fe6080604052600436106102fd5760003560e01c8063845ddcb21161018f578063b88d4fde116100e1578063e985e9c51161008a578063f151d79111610064578063f151d791146109df578063f3fef3a3146109f2578063ff69b94b14610a1257600080fd5b8063e985e9c5146108f9578063ea7b4f7714610934578063eccb3a4f1461095457600080fd5b8063c87b56dd116100bb578063c87b56dd14610876578063d1a4647714610896578063d84058f3146108b657600080fd5b8063b88d4fde14610816578063bfecafe514610836578063c6ca404f1461085657600080fd5b80639854471011610143578063a4be83431161011d578063a4be8343146107c3578063a4eb718c146107d6578063af676625146107f657600080fd5b80639854471014610763578063a0e59e2e14610783578063a22cb465146107a357600080fd5b80638d859f3e116101745780638d859f3e146106ed5780638da5cb5b1461072157806395d89b411461074e57600080fd5b8063845ddcb21461064d5780638824f5a7146106cd57600080fd5b80632f745c59116102535780634f6ccce7116101fc57806369f7d2f2116101d657806369f7d2f2146105ed5780636c19e7831461060d57806370a082311461062d57600080fd5b80634f6ccce71461059757806352a16bb0146105b75780636352211e146105cd57600080fd5b806342842e0e1161022d57806342842e0e1461052a57806342966c681461054a578063438a67e71461056a57600080fd5b80632f745c59146104d457806335d305ad146104f45780633e30046a1461051457600080fd5b8063095ea7b3116102b557806318160ddd1161028f57806318160ddd146104755780631fe543e31461049457806323b872dd146104b457600080fd5b8063095ea7b31461040357806313af403514610423578063171ee95a1461044357600080fd5b806304c624d0116102e657806304c624d01461035957806306fdde0314610379578063081812fc1461039b57600080fd5b806301ffc9a71461030257806302fe530514610337575b600080fd5b34801561030e57600080fd5b5061032261031d366004614393565b610a32565b60405190151581526020015b60405180910390f35b34801561034357600080fd5b5061035761035236600461445e565b610a8e565b005b34801561036557600080fd5b50610357610374366004614543565b610b24565b34801561038557600080fd5b5061038e610c70565b60405161032e9190614590565b3480156103a757600080fd5b506103de6103b6366004614603565b60046020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161032e565b34801561040f57600080fd5b5061035761041e36600461461c565b610cfe565b34801561042f57600080fd5b5061035761043e366004614648565b610e48565b34801561044f57600080fd5b5061046361045e366004614603565b610f3a565b60405160ff909116815260200161032e565b34801561048157600080fd5b50600b545b60405190815260200161032e565b3480156104a057600080fd5b506103576104af366004614689565b610f6e565b3480156104c057600080fd5b506103576104cf36600461472b565b611025565b3480156104e057600080fd5b506104866104ef36600461461c565b611040565b34801561050057600080fd5b5061035761050f36600461478c565b61110f565b34801561052057600080fd5b5061048660105481565b34801561053657600080fd5b5061035761054536600461472b565b6111d2565b34801561055657600080fd5b50610357610565366004614603565b611337565b34801561057657600080fd5b50610486610585366004614648565b60166020526000908152604090205481565b3480156105a357600080fd5b506104866105b2366004614603565b611419565b3480156105c357600080fd5b5061048660125481565b3480156105d957600080fd5b506103de6105e8366004614603565b6114d7565b3480156105f957600080fd5b5061035761060836600461480d565b611568565b34801561061957600080fd5b50610357610628366004614648565b61170d565b34801561063957600080fd5b50610486610648366004614648565b6117d5565b34801561065957600080fd5b506106a4610668366004614603565b6017602052600090815260409020546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041682565b604080516fffffffffffffffffffffffffffffffff93841681529290911660208301520161032e565b3480156106d957600080fd5b506103576106e8366004614879565b61187d565b3480156106f957600080fd5b506104867f000000000000000000000000000000000000000000000000000000000000000081565b34801561072d57600080fd5b506006546103de9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561075a57600080fd5b5061038e61193b565b34801561076f57600080fd5b5061035761077e366004614603565b611948565b34801561078f57600080fd5b5061035761079e36600461489d565b6119ce565b3480156107af57600080fd5b506103576107be3660046148cd565b611d7c565b6103576107d1366004614958565b611e13565b3480156107e257600080fd5b506103576107f13660046149bf565b61213c565b34801561080257600080fd5b506103576108113660046149da565b6121f4565b34801561082257600080fd5b50610357610831366004614a29565b61232a565b34801561084257600080fd5b50610357610851366004614a9c565b61247d565b34801561086257600080fd5b50610357610871366004614b61565b612685565b34801561088257600080fd5b5061038e610891366004614603565b612787565b3480156108a257600080fd5b506103576108b1366004614b85565b612857565b3480156108c257600080fd5b506103de6108d1366004614603565b60156020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b34801561090557600080fd5b50610322610914366004614b9d565b600560209081526000928352604080842090915290825290205460ff1681565b34801561094057600080fd5b5061035761094f366004614bcb565b61296c565b34801561096057600080fd5b506109ac61096f366004614603565b60186020526000908152604090205460ff8082169161010081049091169062010000900473ffffffffffffffffffffffffffffffffffffffff1683565b604080519315158452911515602084015273ffffffffffffffffffffffffffffffffffffffff169082015260600161032e565b6103576109ed3660046149bf565b612a32565b3480156109fe57600080fd5b50610357610a0d36600461461c565b612bd0565b348015610a1e57600080fd5b50610357610a2d366004614603565b612ced565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f780e9d63000000000000000000000000000000000000000000000000000000001480610a885750610a8882612f2a565b92915050565b60065473ffffffffffffffffffffffffffffffffffffffff163314610b14576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b6008610b208282614c88565b5050565b60065473ffffffffffffffffffffffffffffffffffffffff163314610ba5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610b0b565b60138054600090815260186020526040902080547fffffffffffffffffffff0000000000000000000000000000000000000000ff00168515157fffffffffffffffffffff0000000000000000000000000000000000000000ffff16176201000073ffffffffffffffffffffffffffffffffffffffff881602177fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16610100851515021781559054610c569083612685565b601360008154610c6590614dd1565b909155505050505050565b60008054610c7d90614bf5565b80601f0160208091040260200160405190810160405280929190818152602001828054610ca990614bf5565b8015610cf65780601f10610ccb57610100808354040283529160200191610cf6565b820191906000526020600020905b815481529060010190602001808311610cd957829003601f168201915b505050505081565b60008181526002602052604090205473ffffffffffffffffffffffffffffffffffffffff1633811480610d61575073ffffffffffffffffffffffffffffffffffffffff8116600090815260056020908152604080832033845290915290205460ff165b610dc7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f4e4f545f415554484f52495a45440000000000000000000000000000000000006044820152606401610b0b565b60008281526004602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff87811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b60065473ffffffffffffffffffffffffffffffffffffffff163314610ec9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610b0b565b600680547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff831690811790915560405133907f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d7690600090a350565b60118181548110610f4a57600080fd5b9060005260206000209060209182820401919006915054906101000a900460ff1681565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461101b576040517f1cf993f400000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166024820152604401610b0b565b610b20828261300b565b6110308383836134b5565b61103b8383836135bb565b505050565b600061104b836117d5565b82106110d9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201527f74206f6620626f756e64730000000000000000000000000000000000000000006064820152608401610b0b565b5073ffffffffffffffffffffffffffffffffffffffff919091166000908152600960209081526040808320938352929052205490565b60065473ffffffffffffffffffffffffffffffffffffffff163314611190576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610b0b565b6000928352601760205260409092206fffffffffffffffffffffffffffffffff9283167001000000000000000000000000000000000292909116919091179055565b6111dd838383611025565b73ffffffffffffffffffffffffffffffffffffffff82163b15806112d157506040517f150b7a020000000000000000000000000000000000000000000000000000000080825233600483015273ffffffffffffffffffffffffffffffffffffffff858116602484015260448301849052608060648401526000608484015290919084169063150b7a029060a4016020604051808303816000875af1158015611289573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112ad9190614e09565b7fffffffff0000000000000000000000000000000000000000000000000000000016145b61103b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f554e534146455f524543495049454e54000000000000000000000000000000006044820152606401610b0b565b60056000611344836114d7565b73ffffffffffffffffffffffffffffffffffffffff1681526020808201929092526040908101600090812033825290925290205460ff161580156113ac575060008181526004602052604090205473ffffffffffffffffffffffffffffffffffffffff163314155b80156113d65750336113bd826114d7565b73ffffffffffffffffffffffffffffffffffffffff1614155b1561140d576040517f770f9e9600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61141681613882565b50565b6000611424600b5490565b82106114b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201527f7574206f6620626f756e647300000000000000000000000000000000000000006064820152608401610b0b565b600b82815481106114c5576114c5614e26565b90600052602060002001549050919050565b60008181526002602052604090205473ffffffffffffffffffffffffffffffffffffffff1680611563576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f4e4f545f4d494e544544000000000000000000000000000000000000000000006044820152606401610b0b565b919050565b60065473ffffffffffffffffffffffffffffffffffffffff1633146115e9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610b0b565b828114611622576040517fcebbe75800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b83811015611706577f000000000000000000000000000000000000000000000000000000000000000083838381811061166057611660614e26565b905060200201356007546116749190614e55565b11156116ac576040517f73132c2800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6116f48585838181106116c1576116c1614e26565b90506020020160208101906116d69190614648565b8484848181106116e8576116e8614e26565b905060200201356138bd565b806116fe81614dd1565b915050611625565b5050505050565b60065473ffffffffffffffffffffffffffffffffffffffff16331461178e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610b0b565b600d80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b600073ffffffffffffffffffffffffffffffffffffffff8216611854576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f5a45524f5f4144445245535300000000000000000000000000000000000000006044820152606401610b0b565b5073ffffffffffffffffffffffffffffffffffffffff1660009081526003602052604090205490565b60065473ffffffffffffffffffffffffffffffffffffffff1633146118fe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610b0b565b600f805461ffff909216640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffffffff909216919091179055565b60018054610c7d90614bf5565b60065473ffffffffffffffffffffffffffffffffffffffff1633146119c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610b0b565b600e55565b60065473ffffffffffffffffffffffffffffffffffffffff163314611a4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610b0b565b6000828152601860209081526040918290208251606081018452905460ff808216151583526101008204161515928201929092526201000090910473ffffffffffffffffffffffffffffffffffffffff1691810182905290308103611abc57611ab7836138d9565b611d76565b816020015115611b4c576040517f6a62784200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152821690636a62784290602401600060405180830381600087803b158015611b2f57600080fd5b505af1158015611b43573d6000803e3d6000fd5b50505050611d76565b815115611caa576040517f2f745c590000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff8181166004840152600060248401528392908316916323b872dd9187908490632f745c5990604401602060405180830381865afa158015611bf4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c189190614e6d565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815273ffffffffffffffffffffffffffffffffffffffff93841660048201529290911660248301526044820152606401600060405180830381600087803b158015611c8c57600080fd5b505af1158015611ca0573d6000803e3d6000fd5b5050505050611d76565b60408281015190517ff242432a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116600483015285811660248301526000604483018190526001606484015260a0608484015260a48301529091169063f242432a9060c401600060405180830381600087803b158015611d5d57600080fd5b505af1158015611d71573d6000803e3d6000fd5b505050505b50505050565b33600081815260056020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168085529083529281902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b601054601254611e299063ffffffff8416614e55565b1115611e61576040517f893da6c900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b34611e927f000000000000000000000000000000000000000000000000000000000000000063ffffffff8416614e86565b14611ec9576040517f3716a68d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000838152601760205260409020546fffffffffffffffffffffffffffffffff16421080611f2a575060008381526017602052604090205470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1642115b15611f61576040517f4db894d600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003360601b1660208201526034810184905260548101839052600090607401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600d54601f8a01839004830285018301909352888452935073ffffffffffffffffffffffffffffffffffffffff9091169161203a91899089908190840183828082843760009201919091525061203492508691506139859050565b906139d8565b73ffffffffffffffffffffffffffffffffffffffff1614612087576040517f0db90c6100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526016602052604090205483906120a99063ffffffff8516614e55565b11156120e1576040517f60a7a10800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152601660205260408120805463ffffffff85169290612106908490614e55565b925050819055508163ffffffff16601260008282546121259190614e55565b909155506121349050826139fc565b505050505050565b60065473ffffffffffffffffffffffffffffffffffffffff1633146121bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610b0b565b600f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff92909216919091179055565b60065473ffffffffffffffffffffffffffffffffffffffff163314612275576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610b0b565b60009384526018602052604090932080547fffffffffffffffffffff0000000000000000000000000000000000000000ff00169115157fffffffffffffffffffff0000000000000000000000000000000000000000ffff16919091176201000073ffffffffffffffffffffffffffffffffffffffff9390931692909202919091177fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010092151592909202919091179055565b612335858585611025565b73ffffffffffffffffffffffffffffffffffffffff84163b158061241757506040517f150b7a02000000000000000000000000000000000000000000000000000000008082529073ffffffffffffffffffffffffffffffffffffffff86169063150b7a02906123b09033908a90899089908990600401614ec3565b6020604051808303816000875af11580156123cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123f39190614e09565b7fffffffff0000000000000000000000000000000000000000000000000000000016145b611706576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f554e534146455f524543495049454e54000000000000000000000000000000006044820152606401610b0b565b60065473ffffffffffffffffffffffffffffffffffffffff1633146124fe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610b0b565b60005b8151811015610b205781818151811061251c5761251c614e26565b6020026020010151602001516fffffffffffffffffffffffffffffffff1682828151811061254c5761254c614e26565b6020026020010151600001516fffffffffffffffffffffffffffffffff16106125a1576040517fd965c05e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601454600090815260176020526040902082518390839081106125c6576125c6614e26565b60209081029190910101515181547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff909116178155825183908390811061262157612621614e26565b602090810291909101810151015181546fffffffffffffffffffffffffffffffff9182167001000000000000000000000000000000000291161781556014805460009061266d90614dd1565b9091555081905061267d81614dd1565b915050612501565b60065473ffffffffffffffffffffffffffffffffffffffff163314612706576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610b0b565b60005b8181101561276b576011805460018181018355600092909252602081047f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c6801805460ff808816601f9094166101000a9384029302191691909117905501612709565b50806010600082825461277e9190614e55565b90915550505050565b60608160075410156127c5576040517f0b39e1bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600880546127d290614bf5565b80601f01602080910402602001604051908101604052809291908181526020018280546127fe90614bf5565b801561284b5780601f106128205761010080835404028352916020019161284b565b820191906000526020600020905b81548152906001019060200180831161282e57829003601f168201915b50505050509050919050565b60065473ffffffffffffffffffffffffffffffffffffffff1633146128d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610b0b565b6128e56020820182614f42565b601980547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff929092169190911790556129366040820160208301614f42565b601980546fffffffffffffffffffffffffffffffff92831670010000000000000000000000000000000002921691909117905550565b60065473ffffffffffffffffffffffffffffffffffffffff1633146129ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610b0b565b600f805467ffffffffffffffff9092166601000000000000027fffffffffffffffffffffffffffffffffffff0000000000000000ffffffffffff909216919091179055565b601054601254612a489063ffffffff8416614e55565b1115612a80576040517f893da6c900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b34612ab17f000000000000000000000000000000000000000000000000000000000000000063ffffffff8416614e86565b14612ae8576040517f3716a68d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6019546fffffffffffffffffffffffffffffffff16421080612b31575060195470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1642115b15612b68576040517f4db894d600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60148163ffffffff161115612ba9576040517f60a7a10800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8063ffffffff1660126000828254612bc19190614e55565b909155506114169050816139fc565b60065473ffffffffffffffffffffffffffffffffffffffff163314612c51576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610b0b565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d8060008114612cac576040519150601f19603f3d011682016040523d82523d6000602084013e612cb1565b606091505b509150915081611d76576040517f67b2cd0500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60065473ffffffffffffffffffffffffffffffffffffffff163314612d6e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610b0b565b6040805160008152602081019182905251612d8b916011916142aa565b50601055565b73ffffffffffffffffffffffffffffffffffffffff8216612e0e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f494e56414c49445f524543495049454e540000000000000000000000000000006044820152606401610b0b565b60008181526002602052604090205473ffffffffffffffffffffffffffffffffffffffff1615612e9a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f414c52454144595f4d494e5445440000000000000000000000000000000000006044820152606401610b0b565b73ffffffffffffffffffffffffffffffffffffffff8216600081815260036020908152604080832080546001019055848352600290915280822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083161480612fbd57507f80ac58cd000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b80610a885750507fffffffff00000000000000000000000000000000000000000000000000000000167f5b5e139f000000000000000000000000000000000000000000000000000000001490565b60005b815181101561103b576011548251600090829085908590811061303357613033614e26565b60200260200101516130459190614f5d565b90506000601860006011848154811061306057613060614e26565b600091825260208083208183040154601f90921661010090810a90920460ff9081168552848201959095526040938401909220835160608101855290548086161515825291820490941615159184019190915262010000900473ffffffffffffffffffffffffffffffffffffffff1690820152905060116130e2600185614f98565b815481106130f2576130f2614e26565b90600052602060002090602091828204019190069054906101000a900460ff166011838154811061312557613125614e26565b90600052602060002090602091828204019190066101000a81548160ff021916908360ff160217905550601180548061316057613160614faf565b600082815260208082207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909301818104909301805460ff601f86166101000a02191690559190925587825260159052604090819020549082015173ffffffffffffffffffffffffffffffffffffffff9182169130908216036131eb576131e6826138d9565b6134a5565b82602001511561327b576040517f6a62784200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152821690636a62784290602401600060405180830381600087803b15801561325e57600080fd5b505af1158015613272573d6000803e3d6000fd5b505050506134a5565b8251156133d9576040517f2f745c590000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff8181166004840152600060248401528392908316916323b872dd9186908490632f745c5990604401602060405180830381865afa158015613323573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133479190614e6d565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815273ffffffffffffffffffffffffffffffffffffffff93841660048201529290911660248301526044820152606401600060405180830381600087803b1580156133bb57600080fd5b505af11580156133cf573d6000803e3d6000fd5b50505050506134a5565b60408381015190517ff242432a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116600483015284811660248301526000604483018190526001606484015260a0608484015260a48301529091169063f242432a9060c401600060405180830381600087803b15801561348c57600080fd5b505af11580156134a0573d6000803e3d6000fd5b505050505b856001019550505050505061300e565b73ffffffffffffffffffffffffffffffffffffffff831661351d5761351881600b80546000838152600c60205260408120829055600182018355919091527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90155565b61355a565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161461355a5761355a8382613b67565b73ffffffffffffffffffffffffffffffffffffffff821661357e5761103b81613c1e565b8273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161461103b5761103b8282613ccd565b60008181526002602052604090205473ffffffffffffffffffffffffffffffffffffffff84811691161461364b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f57524f4e475f46524f4d000000000000000000000000000000000000000000006044820152606401610b0b565b73ffffffffffffffffffffffffffffffffffffffff82166136c8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f494e56414c49445f524543495049454e540000000000000000000000000000006044820152606401610b0b565b3373ffffffffffffffffffffffffffffffffffffffff8416148061371c575073ffffffffffffffffffffffffffffffffffffffff8316600090815260056020908152604080832033845290915290205460ff165b8061374a575060008181526004602052604090205473ffffffffffffffffffffffffffffffffffffffff1633145b6137b0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f4e4f545f415554484f52495a45440000000000000000000000000000000000006044820152606401610b0b565b73ffffffffffffffffffffffffffffffffffffffff808416600081815260036020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019055938616808352848320805460010190558583526002825284832080547fffffffffffffffffffffffff00000000000000000000000000000000000000009081168317909155600490925284832080549092169091559251849392917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6000818152600260205260408120546138b49173ffffffffffffffffffffffffffffffffffffffff90911690836134b5565b61141681613d1e565b60005b8181101561103b576138d1836138d9565b6001016138c0565b7f000000000000000000000000000000000000000000000000000000000000000060075410613964576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4d617820737570706c79207265616368656400000000000000000000000000006044820152606401610b0b565b60076000815461397390614dd1565b90915550600754611416908290613e68565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b60008060006139e78585613e7e565b915091506139f481613eec565b509392505050565b63ffffffff811615611416576000600a8263ffffffff1611613a1e5781613a21565b600a5b9050613a2d8183614fde565b600e54600f546040517f5d3b1d3000000000000000000000000000000000000000000000000000000000815260048101929092526601000000000000810467ffffffffffffffff166024830152640100000000810461ffff16604483015263ffffffff9081166064830152831660848201529092506000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690635d3b1d309060a4016020604051808303816000875af1158015613b05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b299190614e6d565b600090815260156020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001633179055506139fc9050565b60006001613b74846117d5565b613b7e9190614f98565b6000838152600a6020526040902054909150808214613bde5773ffffffffffffffffffffffffffffffffffffffff841660009081526009602090815260408083208584528252808320548484528184208190558352600a90915290208190555b506000918252600a6020908152604080842084905573ffffffffffffffffffffffffffffffffffffffff9094168352600981528383209183525290812055565b600b54600090613c3090600190614f98565b6000838152600c6020526040812054600b8054939450909284908110613c5857613c58614e26565b9060005260206000200154905080600b8381548110613c7957613c79614e26565b6000918252602080832090910192909255828152600c9091526040808220849055858252812055600b805480613cb157613cb1614faf565b6001900381819060005260206000200160009055905550505050565b6000613cd8836117d5565b73ffffffffffffffffffffffffffffffffffffffff90931660009081526009602090815260408083208684528252808320859055938252600a9052919091209190915550565b60008181526002602052604090205473ffffffffffffffffffffffffffffffffffffffff1680613daa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f4e4f545f4d494e544544000000000000000000000000000000000000000000006044820152606401610b0b565b73ffffffffffffffffffffffffffffffffffffffff8116600081815260036020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190558583526002825280832080547fffffffffffffffffffffffff000000000000000000000000000000000000000090811690915560049092528083208054909216909155518492907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b613e74600083836134b5565b610b208282612d91565b6000808251604103613eb45760208301516040840151606085015160001a613ea887828585614140565b94509450505050613ee5565b8251604003613edd5760208301516040840151613ed2868383614258565b935093505050613ee5565b506000905060025b9250929050565b6000816004811115613f0057613f00615003565b03613f085750565b6001816004811115613f1c57613f1c615003565b03613f83576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610b0b565b6002816004811115613f9757613f97615003565b03613ffe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610b0b565b600381600481111561401257614012615003565b0361409f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152608401610b0b565b60048160048111156140b3576140b3615003565b03611416576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152608401610b0b565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115614177575060009050600361424f565b8460ff16601b1415801561418f57508460ff16601c14155b156141a0575060009050600461424f565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156141f4573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff81166142485760006001925092505061424f565b9150600090505b94509492505050565b6000807f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83168161428e60ff86901c601b614e55565b905061429c87828885614140565b935093505050935093915050565b82805482825590600052602060002090601f016020900481019282156143405791602002820160005b8382111561431157835183826101000a81548160ff021916908360ff16021790555092602001926001016020816000010492830192600103026142d3565b801561433e5782816101000a81549060ff0219169055600101602081600001049283019260010302614311565b505b5061434c929150614350565b5090565b5b8082111561434c5760008155600101614351565b7fffffffff000000000000000000000000000000000000000000000000000000008116811461141657600080fd5b6000602082840312156143a557600080fd5b81356143b081614365565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715614409576144096143b7565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614456576144566143b7565b604052919050565b6000602080838503121561447157600080fd5b823567ffffffffffffffff8082111561448957600080fd5b818501915085601f83011261449d57600080fd5b8135818111156144af576144af6143b7565b6144df847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161440f565b915080825286848285010111156144f557600080fd5b8084840185840137600090820190930192909252509392505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461141657600080fd5b8035801515811461156357600080fd5b6000806000806080858703121561455957600080fd5b843561456481614511565b935061457260208601614533565b925061458060408601614533565b9396929550929360600135925050565b600060208083528351808285015260005b818110156145bd578581018301518582016040015282016145a1565b818111156145cf576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60006020828403121561461557600080fd5b5035919050565b6000806040838503121561462f57600080fd5b823561463a81614511565b946020939093013593505050565b60006020828403121561465a57600080fd5b81356143b081614511565b600067ffffffffffffffff82111561467f5761467f6143b7565b5060051b60200190565b6000806040838503121561469c57600080fd5b8235915060208084013567ffffffffffffffff8111156146bb57600080fd5b8401601f810186136146cc57600080fd5b80356146df6146da82614665565b61440f565b81815260059190911b820183019083810190888311156146fe57600080fd5b928401925b8284101561471c57833582529284019290840190614703565b80955050505050509250929050565b60008060006060848603121561474057600080fd5b833561474b81614511565b9250602084013561475b81614511565b929592945050506040919091013590565b80356fffffffffffffffffffffffffffffffff8116811461156357600080fd5b6000806000606084860312156147a157600080fd5b833592506147b16020850161476c565b91506147bf6040850161476c565b90509250925092565b60008083601f8401126147da57600080fd5b50813567ffffffffffffffff8111156147f257600080fd5b6020830191508360208260051b8501011115613ee557600080fd5b6000806000806040858703121561482357600080fd5b843567ffffffffffffffff8082111561483b57600080fd5b614847888389016147c8565b9096509450602087013591508082111561486057600080fd5b5061486d878288016147c8565b95989497509550505050565b60006020828403121561488b57600080fd5b813561ffff811681146143b057600080fd5b600080604083850312156148b057600080fd5b8235915060208301356148c281614511565b809150509250929050565b600080604083850312156148e057600080fd5b82356148eb81614511565b91506148f960208401614533565b90509250929050565b60008083601f84011261491457600080fd5b50813567ffffffffffffffff81111561492c57600080fd5b602083019150836020828501011115613ee557600080fd5b803563ffffffff8116811461156357600080fd5b60008060008060006080868803121561497057600080fd5b853567ffffffffffffffff81111561498757600080fd5b61499388828901614902565b90965094505060208601359250604086013591506149b360608701614944565b90509295509295909350565b6000602082840312156149d157600080fd5b6143b082614944565b600080600080608085870312156149f057600080fd5b843593506020850135614a0281614511565b9250614a1060408601614533565b9150614a1e60608601614533565b905092959194509250565b600080600080600060808688031215614a4157600080fd5b8535614a4c81614511565b94506020860135614a5c81614511565b935060408601359250606086013567ffffffffffffffff811115614a7f57600080fd5b614a8b88828901614902565b969995985093965092949392505050565b60006020808385031215614aaf57600080fd5b823567ffffffffffffffff811115614ac657600080fd5b8301601f81018513614ad757600080fd5b8035614ae56146da82614665565b81815260069190911b82018301908381019087831115614b0457600080fd5b928401925b82841015614b565760408489031215614b225760008081fd5b614b2a6143e6565b614b338561476c565b8152614b4086860161476c565b8187015282526040939093019290840190614b09565b979650505050505050565b60008060408385031215614b7457600080fd5b823560ff8116811461463a57600080fd5b600060408284031215614b9757600080fd5b50919050565b60008060408385031215614bb057600080fd5b8235614bbb81614511565b915060208301356148c281614511565b600060208284031215614bdd57600080fd5b813567ffffffffffffffff811681146143b057600080fd5b600181811c90821680614c0957607f821691505b602082108103614b97577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b601f82111561103b57600081815260208120601f850160051c81016020861015614c695750805b601f850160051c820191505b8181101561213457828155600101614c75565b815167ffffffffffffffff811115614ca257614ca26143b7565b614cb681614cb08454614bf5565b84614c42565b602080601f831160018114614d095760008415614cd35750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555612134565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015614d5657888601518255948401946001909101908401614d37565b5085821015614d9257878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614e0257614e02614da2565b5060010190565b600060208284031215614e1b57600080fd5b81516143b081614365565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008219821115614e6857614e68614da2565b500190565b600060208284031215614e7f57600080fd5b5051919050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615614ebe57614ebe614da2565b500290565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525084604083015260806060830152826080830152828460a0840137600060a0848401015260a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85011683010190509695505050505050565b600060208284031215614f5457600080fd5b6143b08261476c565b600082614f93577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500690565b600082821015614faa57614faa614da2565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600063ffffffff83811690831681811015614ffb57614ffb614da2565b039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea2646970667358221220b3787f1c0442129146dc2167c9ec1391f227ef854fc8d4c6d91045ccab1f8fee64736f6c634300080f0033000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e699098af398995b04c28e9951adb9721ef74c74f93e6a478f39e7e0777be13527e7ef00000000000000000000000000000000000000000000000000000000000000a9000000000000000000000000f27276ef311886b6433865db600fa7e3d4d86b13000000000000000000000000cf3bc13c0f19b9549364cc5f4b7ea807b737c0620000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000002c68af0bb140000000000000000000000000000000000000000000000000000000000000000000d50554e4b5320436f6d69632033000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006434f4d49433300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000036697066733a2f2f516d5a66693833795a396b45347154683366417a72725532526f4547516444514d774a6673324e6e39466f4b65432f00000000000000000000
Deployed Bytecode
0x6080604052600436106102fd5760003560e01c8063845ddcb21161018f578063b88d4fde116100e1578063e985e9c51161008a578063f151d79111610064578063f151d791146109df578063f3fef3a3146109f2578063ff69b94b14610a1257600080fd5b8063e985e9c5146108f9578063ea7b4f7714610934578063eccb3a4f1461095457600080fd5b8063c87b56dd116100bb578063c87b56dd14610876578063d1a4647714610896578063d84058f3146108b657600080fd5b8063b88d4fde14610816578063bfecafe514610836578063c6ca404f1461085657600080fd5b80639854471011610143578063a4be83431161011d578063a4be8343146107c3578063a4eb718c146107d6578063af676625146107f657600080fd5b80639854471014610763578063a0e59e2e14610783578063a22cb465146107a357600080fd5b80638d859f3e116101745780638d859f3e146106ed5780638da5cb5b1461072157806395d89b411461074e57600080fd5b8063845ddcb21461064d5780638824f5a7146106cd57600080fd5b80632f745c59116102535780634f6ccce7116101fc57806369f7d2f2116101d657806369f7d2f2146105ed5780636c19e7831461060d57806370a082311461062d57600080fd5b80634f6ccce71461059757806352a16bb0146105b75780636352211e146105cd57600080fd5b806342842e0e1161022d57806342842e0e1461052a57806342966c681461054a578063438a67e71461056a57600080fd5b80632f745c59146104d457806335d305ad146104f45780633e30046a1461051457600080fd5b8063095ea7b3116102b557806318160ddd1161028f57806318160ddd146104755780631fe543e31461049457806323b872dd146104b457600080fd5b8063095ea7b31461040357806313af403514610423578063171ee95a1461044357600080fd5b806304c624d0116102e657806304c624d01461035957806306fdde0314610379578063081812fc1461039b57600080fd5b806301ffc9a71461030257806302fe530514610337575b600080fd5b34801561030e57600080fd5b5061032261031d366004614393565b610a32565b60405190151581526020015b60405180910390f35b34801561034357600080fd5b5061035761035236600461445e565b610a8e565b005b34801561036557600080fd5b50610357610374366004614543565b610b24565b34801561038557600080fd5b5061038e610c70565b60405161032e9190614590565b3480156103a757600080fd5b506103de6103b6366004614603565b60046020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161032e565b34801561040f57600080fd5b5061035761041e36600461461c565b610cfe565b34801561042f57600080fd5b5061035761043e366004614648565b610e48565b34801561044f57600080fd5b5061046361045e366004614603565b610f3a565b60405160ff909116815260200161032e565b34801561048157600080fd5b50600b545b60405190815260200161032e565b3480156104a057600080fd5b506103576104af366004614689565b610f6e565b3480156104c057600080fd5b506103576104cf36600461472b565b611025565b3480156104e057600080fd5b506104866104ef36600461461c565b611040565b34801561050057600080fd5b5061035761050f36600461478c565b61110f565b34801561052057600080fd5b5061048660105481565b34801561053657600080fd5b5061035761054536600461472b565b6111d2565b34801561055657600080fd5b50610357610565366004614603565b611337565b34801561057657600080fd5b50610486610585366004614648565b60166020526000908152604090205481565b3480156105a357600080fd5b506104866105b2366004614603565b611419565b3480156105c357600080fd5b5061048660125481565b3480156105d957600080fd5b506103de6105e8366004614603565b6114d7565b3480156105f957600080fd5b5061035761060836600461480d565b611568565b34801561061957600080fd5b50610357610628366004614648565b61170d565b34801561063957600080fd5b50610486610648366004614648565b6117d5565b34801561065957600080fd5b506106a4610668366004614603565b6017602052600090815260409020546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041682565b604080516fffffffffffffffffffffffffffffffff93841681529290911660208301520161032e565b3480156106d957600080fd5b506103576106e8366004614879565b61187d565b3480156106f957600080fd5b506104867f00000000000000000000000000000000000000000000000002c68af0bb14000081565b34801561072d57600080fd5b506006546103de9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561075a57600080fd5b5061038e61193b565b34801561076f57600080fd5b5061035761077e366004614603565b611948565b34801561078f57600080fd5b5061035761079e36600461489d565b6119ce565b3480156107af57600080fd5b506103576107be3660046148cd565b611d7c565b6103576107d1366004614958565b611e13565b3480156107e257600080fd5b506103576107f13660046149bf565b61213c565b34801561080257600080fd5b506103576108113660046149da565b6121f4565b34801561082257600080fd5b50610357610831366004614a29565b61232a565b34801561084257600080fd5b50610357610851366004614a9c565b61247d565b34801561086257600080fd5b50610357610871366004614b61565b612685565b34801561088257600080fd5b5061038e610891366004614603565b612787565b3480156108a257600080fd5b506103576108b1366004614b85565b612857565b3480156108c257600080fd5b506103de6108d1366004614603565b60156020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b34801561090557600080fd5b50610322610914366004614b9d565b600560209081526000928352604080842090915290825290205460ff1681565b34801561094057600080fd5b5061035761094f366004614bcb565b61296c565b34801561096057600080fd5b506109ac61096f366004614603565b60186020526000908152604090205460ff8082169161010081049091169062010000900473ffffffffffffffffffffffffffffffffffffffff1683565b604080519315158452911515602084015273ffffffffffffffffffffffffffffffffffffffff169082015260600161032e565b6103576109ed3660046149bf565b612a32565b3480156109fe57600080fd5b50610357610a0d36600461461c565b612bd0565b348015610a1e57600080fd5b50610357610a2d366004614603565b612ced565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f780e9d63000000000000000000000000000000000000000000000000000000001480610a885750610a8882612f2a565b92915050565b60065473ffffffffffffffffffffffffffffffffffffffff163314610b14576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b6008610b208282614c88565b5050565b60065473ffffffffffffffffffffffffffffffffffffffff163314610ba5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610b0b565b60138054600090815260186020526040902080547fffffffffffffffffffff0000000000000000000000000000000000000000ff00168515157fffffffffffffffffffff0000000000000000000000000000000000000000ffff16176201000073ffffffffffffffffffffffffffffffffffffffff881602177fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16610100851515021781559054610c569083612685565b601360008154610c6590614dd1565b909155505050505050565b60008054610c7d90614bf5565b80601f0160208091040260200160405190810160405280929190818152602001828054610ca990614bf5565b8015610cf65780601f10610ccb57610100808354040283529160200191610cf6565b820191906000526020600020905b815481529060010190602001808311610cd957829003601f168201915b505050505081565b60008181526002602052604090205473ffffffffffffffffffffffffffffffffffffffff1633811480610d61575073ffffffffffffffffffffffffffffffffffffffff8116600090815260056020908152604080832033845290915290205460ff165b610dc7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f4e4f545f415554484f52495a45440000000000000000000000000000000000006044820152606401610b0b565b60008281526004602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff87811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b60065473ffffffffffffffffffffffffffffffffffffffff163314610ec9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610b0b565b600680547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff831690811790915560405133907f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d7690600090a350565b60118181548110610f4a57600080fd5b9060005260206000209060209182820401919006915054906101000a900460ff1681565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e69909161461101b576040517f1cf993f400000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e69909166024820152604401610b0b565b610b20828261300b565b6110308383836134b5565b61103b8383836135bb565b505050565b600061104b836117d5565b82106110d9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201527f74206f6620626f756e64730000000000000000000000000000000000000000006064820152608401610b0b565b5073ffffffffffffffffffffffffffffffffffffffff919091166000908152600960209081526040808320938352929052205490565b60065473ffffffffffffffffffffffffffffffffffffffff163314611190576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610b0b565b6000928352601760205260409092206fffffffffffffffffffffffffffffffff9283167001000000000000000000000000000000000292909116919091179055565b6111dd838383611025565b73ffffffffffffffffffffffffffffffffffffffff82163b15806112d157506040517f150b7a020000000000000000000000000000000000000000000000000000000080825233600483015273ffffffffffffffffffffffffffffffffffffffff858116602484015260448301849052608060648401526000608484015290919084169063150b7a029060a4016020604051808303816000875af1158015611289573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112ad9190614e09565b7fffffffff0000000000000000000000000000000000000000000000000000000016145b61103b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f554e534146455f524543495049454e54000000000000000000000000000000006044820152606401610b0b565b60056000611344836114d7565b73ffffffffffffffffffffffffffffffffffffffff1681526020808201929092526040908101600090812033825290925290205460ff161580156113ac575060008181526004602052604090205473ffffffffffffffffffffffffffffffffffffffff163314155b80156113d65750336113bd826114d7565b73ffffffffffffffffffffffffffffffffffffffff1614155b1561140d576040517f770f9e9600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61141681613882565b50565b6000611424600b5490565b82106114b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201527f7574206f6620626f756e647300000000000000000000000000000000000000006064820152608401610b0b565b600b82815481106114c5576114c5614e26565b90600052602060002001549050919050565b60008181526002602052604090205473ffffffffffffffffffffffffffffffffffffffff1680611563576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f4e4f545f4d494e544544000000000000000000000000000000000000000000006044820152606401610b0b565b919050565b60065473ffffffffffffffffffffffffffffffffffffffff1633146115e9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610b0b565b828114611622576040517fcebbe75800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b83811015611706577f0000000000000000000000000000000000000000000000000000000000003a9883838381811061166057611660614e26565b905060200201356007546116749190614e55565b11156116ac576040517f73132c2800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6116f48585838181106116c1576116c1614e26565b90506020020160208101906116d69190614648565b8484848181106116e8576116e8614e26565b905060200201356138bd565b806116fe81614dd1565b915050611625565b5050505050565b60065473ffffffffffffffffffffffffffffffffffffffff16331461178e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610b0b565b600d80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b600073ffffffffffffffffffffffffffffffffffffffff8216611854576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f5a45524f5f4144445245535300000000000000000000000000000000000000006044820152606401610b0b565b5073ffffffffffffffffffffffffffffffffffffffff1660009081526003602052604090205490565b60065473ffffffffffffffffffffffffffffffffffffffff1633146118fe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610b0b565b600f805461ffff909216640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffffffff909216919091179055565b60018054610c7d90614bf5565b60065473ffffffffffffffffffffffffffffffffffffffff1633146119c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610b0b565b600e55565b60065473ffffffffffffffffffffffffffffffffffffffff163314611a4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610b0b565b6000828152601860209081526040918290208251606081018452905460ff808216151583526101008204161515928201929092526201000090910473ffffffffffffffffffffffffffffffffffffffff1691810182905290308103611abc57611ab7836138d9565b611d76565b816020015115611b4c576040517f6a62784200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152821690636a62784290602401600060405180830381600087803b158015611b2f57600080fd5b505af1158015611b43573d6000803e3d6000fd5b50505050611d76565b815115611caa576040517f2f745c590000000000000000000000000000000000000000000000000000000081527f000000000000000000000000cf3bc13c0f19b9549364cc5f4b7ea807b737c06273ffffffffffffffffffffffffffffffffffffffff8181166004840152600060248401528392908316916323b872dd9187908490632f745c5990604401602060405180830381865afa158015611bf4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c189190614e6d565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815273ffffffffffffffffffffffffffffffffffffffff93841660048201529290911660248301526044820152606401600060405180830381600087803b158015611c8c57600080fd5b505af1158015611ca0573d6000803e3d6000fd5b5050505050611d76565b60408281015190517ff242432a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000cf3bc13c0f19b9549364cc5f4b7ea807b737c0628116600483015285811660248301526000604483018190526001606484015260a0608484015260a48301529091169063f242432a9060c401600060405180830381600087803b158015611d5d57600080fd5b505af1158015611d71573d6000803e3d6000fd5b505050505b50505050565b33600081815260056020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168085529083529281902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b601054601254611e299063ffffffff8416614e55565b1115611e61576040517f893da6c900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b34611e927f00000000000000000000000000000000000000000000000002c68af0bb14000063ffffffff8416614e86565b14611ec9576040517f3716a68d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000838152601760205260409020546fffffffffffffffffffffffffffffffff16421080611f2a575060008381526017602052604090205470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1642115b15611f61576040517f4db894d600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003360601b1660208201526034810184905260548101839052600090607401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600d54601f8a01839004830285018301909352888452935073ffffffffffffffffffffffffffffffffffffffff9091169161203a91899089908190840183828082843760009201919091525061203492508691506139859050565b906139d8565b73ffffffffffffffffffffffffffffffffffffffff1614612087576040517f0db90c6100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526016602052604090205483906120a99063ffffffff8516614e55565b11156120e1576040517f60a7a10800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152601660205260408120805463ffffffff85169290612106908490614e55565b925050819055508163ffffffff16601260008282546121259190614e55565b909155506121349050826139fc565b505050505050565b60065473ffffffffffffffffffffffffffffffffffffffff1633146121bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610b0b565b600f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff92909216919091179055565b60065473ffffffffffffffffffffffffffffffffffffffff163314612275576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610b0b565b60009384526018602052604090932080547fffffffffffffffffffff0000000000000000000000000000000000000000ff00169115157fffffffffffffffffffff0000000000000000000000000000000000000000ffff16919091176201000073ffffffffffffffffffffffffffffffffffffffff9390931692909202919091177fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010092151592909202919091179055565b612335858585611025565b73ffffffffffffffffffffffffffffffffffffffff84163b158061241757506040517f150b7a02000000000000000000000000000000000000000000000000000000008082529073ffffffffffffffffffffffffffffffffffffffff86169063150b7a02906123b09033908a90899089908990600401614ec3565b6020604051808303816000875af11580156123cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123f39190614e09565b7fffffffff0000000000000000000000000000000000000000000000000000000016145b611706576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f554e534146455f524543495049454e54000000000000000000000000000000006044820152606401610b0b565b60065473ffffffffffffffffffffffffffffffffffffffff1633146124fe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610b0b565b60005b8151811015610b205781818151811061251c5761251c614e26565b6020026020010151602001516fffffffffffffffffffffffffffffffff1682828151811061254c5761254c614e26565b6020026020010151600001516fffffffffffffffffffffffffffffffff16106125a1576040517fd965c05e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601454600090815260176020526040902082518390839081106125c6576125c6614e26565b60209081029190910101515181547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff909116178155825183908390811061262157612621614e26565b602090810291909101810151015181546fffffffffffffffffffffffffffffffff9182167001000000000000000000000000000000000291161781556014805460009061266d90614dd1565b9091555081905061267d81614dd1565b915050612501565b60065473ffffffffffffffffffffffffffffffffffffffff163314612706576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610b0b565b60005b8181101561276b576011805460018181018355600092909252602081047f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c6801805460ff808816601f9094166101000a9384029302191691909117905501612709565b50806010600082825461277e9190614e55565b90915550505050565b60608160075410156127c5576040517f0b39e1bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600880546127d290614bf5565b80601f01602080910402602001604051908101604052809291908181526020018280546127fe90614bf5565b801561284b5780601f106128205761010080835404028352916020019161284b565b820191906000526020600020905b81548152906001019060200180831161282e57829003601f168201915b50505050509050919050565b60065473ffffffffffffffffffffffffffffffffffffffff1633146128d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610b0b565b6128e56020820182614f42565b601980547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff929092169190911790556129366040820160208301614f42565b601980546fffffffffffffffffffffffffffffffff92831670010000000000000000000000000000000002921691909117905550565b60065473ffffffffffffffffffffffffffffffffffffffff1633146129ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610b0b565b600f805467ffffffffffffffff9092166601000000000000027fffffffffffffffffffffffffffffffffffff0000000000000000ffffffffffff909216919091179055565b601054601254612a489063ffffffff8416614e55565b1115612a80576040517f893da6c900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b34612ab17f00000000000000000000000000000000000000000000000002c68af0bb14000063ffffffff8416614e86565b14612ae8576040517f3716a68d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6019546fffffffffffffffffffffffffffffffff16421080612b31575060195470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1642115b15612b68576040517f4db894d600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60148163ffffffff161115612ba9576040517f60a7a10800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8063ffffffff1660126000828254612bc19190614e55565b909155506114169050816139fc565b60065473ffffffffffffffffffffffffffffffffffffffff163314612c51576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610b0b565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d8060008114612cac576040519150601f19603f3d011682016040523d82523d6000602084013e612cb1565b606091505b509150915081611d76576040517f67b2cd0500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60065473ffffffffffffffffffffffffffffffffffffffff163314612d6e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610b0b565b6040805160008152602081019182905251612d8b916011916142aa565b50601055565b73ffffffffffffffffffffffffffffffffffffffff8216612e0e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f494e56414c49445f524543495049454e540000000000000000000000000000006044820152606401610b0b565b60008181526002602052604090205473ffffffffffffffffffffffffffffffffffffffff1615612e9a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f414c52454144595f4d494e5445440000000000000000000000000000000000006044820152606401610b0b565b73ffffffffffffffffffffffffffffffffffffffff8216600081815260036020908152604080832080546001019055848352600290915280822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083161480612fbd57507f80ac58cd000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b80610a885750507fffffffff00000000000000000000000000000000000000000000000000000000167f5b5e139f000000000000000000000000000000000000000000000000000000001490565b60005b815181101561103b576011548251600090829085908590811061303357613033614e26565b60200260200101516130459190614f5d565b90506000601860006011848154811061306057613060614e26565b600091825260208083208183040154601f90921661010090810a90920460ff9081168552848201959095526040938401909220835160608101855290548086161515825291820490941615159184019190915262010000900473ffffffffffffffffffffffffffffffffffffffff1690820152905060116130e2600185614f98565b815481106130f2576130f2614e26565b90600052602060002090602091828204019190069054906101000a900460ff166011838154811061312557613125614e26565b90600052602060002090602091828204019190066101000a81548160ff021916908360ff160217905550601180548061316057613160614faf565b600082815260208082207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909301818104909301805460ff601f86166101000a02191690559190925587825260159052604090819020549082015173ffffffffffffffffffffffffffffffffffffffff9182169130908216036131eb576131e6826138d9565b6134a5565b82602001511561327b576040517f6a62784200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152821690636a62784290602401600060405180830381600087803b15801561325e57600080fd5b505af1158015613272573d6000803e3d6000fd5b505050506134a5565b8251156133d9576040517f2f745c590000000000000000000000000000000000000000000000000000000081527f000000000000000000000000cf3bc13c0f19b9549364cc5f4b7ea807b737c06273ffffffffffffffffffffffffffffffffffffffff8181166004840152600060248401528392908316916323b872dd9186908490632f745c5990604401602060405180830381865afa158015613323573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133479190614e6d565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815273ffffffffffffffffffffffffffffffffffffffff93841660048201529290911660248301526044820152606401600060405180830381600087803b1580156133bb57600080fd5b505af11580156133cf573d6000803e3d6000fd5b50505050506134a5565b60408381015190517ff242432a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000cf3bc13c0f19b9549364cc5f4b7ea807b737c0628116600483015284811660248301526000604483018190526001606484015260a0608484015260a48301529091169063f242432a9060c401600060405180830381600087803b15801561348c57600080fd5b505af11580156134a0573d6000803e3d6000fd5b505050505b856001019550505050505061300e565b73ffffffffffffffffffffffffffffffffffffffff831661351d5761351881600b80546000838152600c60205260408120829055600182018355919091527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90155565b61355a565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161461355a5761355a8382613b67565b73ffffffffffffffffffffffffffffffffffffffff821661357e5761103b81613c1e565b8273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161461103b5761103b8282613ccd565b60008181526002602052604090205473ffffffffffffffffffffffffffffffffffffffff84811691161461364b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f57524f4e475f46524f4d000000000000000000000000000000000000000000006044820152606401610b0b565b73ffffffffffffffffffffffffffffffffffffffff82166136c8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f494e56414c49445f524543495049454e540000000000000000000000000000006044820152606401610b0b565b3373ffffffffffffffffffffffffffffffffffffffff8416148061371c575073ffffffffffffffffffffffffffffffffffffffff8316600090815260056020908152604080832033845290915290205460ff165b8061374a575060008181526004602052604090205473ffffffffffffffffffffffffffffffffffffffff1633145b6137b0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f4e4f545f415554484f52495a45440000000000000000000000000000000000006044820152606401610b0b565b73ffffffffffffffffffffffffffffffffffffffff808416600081815260036020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019055938616808352848320805460010190558583526002825284832080547fffffffffffffffffffffffff00000000000000000000000000000000000000009081168317909155600490925284832080549092169091559251849392917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6000818152600260205260408120546138b49173ffffffffffffffffffffffffffffffffffffffff90911690836134b5565b61141681613d1e565b60005b8181101561103b576138d1836138d9565b6001016138c0565b7f0000000000000000000000000000000000000000000000000000000000003a9860075410613964576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4d617820737570706c79207265616368656400000000000000000000000000006044820152606401610b0b565b60076000815461397390614dd1565b90915550600754611416908290613e68565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b60008060006139e78585613e7e565b915091506139f481613eec565b509392505050565b63ffffffff811615611416576000600a8263ffffffff1611613a1e5781613a21565b600a5b9050613a2d8183614fde565b600e54600f546040517f5d3b1d3000000000000000000000000000000000000000000000000000000000815260048101929092526601000000000000810467ffffffffffffffff166024830152640100000000810461ffff16604483015263ffffffff9081166064830152831660848201529092506000907f000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e6990973ffffffffffffffffffffffffffffffffffffffff1690635d3b1d309060a4016020604051808303816000875af1158015613b05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b299190614e6d565b600090815260156020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001633179055506139fc9050565b60006001613b74846117d5565b613b7e9190614f98565b6000838152600a6020526040902054909150808214613bde5773ffffffffffffffffffffffffffffffffffffffff841660009081526009602090815260408083208584528252808320548484528184208190558352600a90915290208190555b506000918252600a6020908152604080842084905573ffffffffffffffffffffffffffffffffffffffff9094168352600981528383209183525290812055565b600b54600090613c3090600190614f98565b6000838152600c6020526040812054600b8054939450909284908110613c5857613c58614e26565b9060005260206000200154905080600b8381548110613c7957613c79614e26565b6000918252602080832090910192909255828152600c9091526040808220849055858252812055600b805480613cb157613cb1614faf565b6001900381819060005260206000200160009055905550505050565b6000613cd8836117d5565b73ffffffffffffffffffffffffffffffffffffffff90931660009081526009602090815260408083208684528252808320859055938252600a9052919091209190915550565b60008181526002602052604090205473ffffffffffffffffffffffffffffffffffffffff1680613daa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f4e4f545f4d494e544544000000000000000000000000000000000000000000006044820152606401610b0b565b73ffffffffffffffffffffffffffffffffffffffff8116600081815260036020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190558583526002825280832080547fffffffffffffffffffffffff000000000000000000000000000000000000000090811690915560049092528083208054909216909155518492907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b613e74600083836134b5565b610b208282612d91565b6000808251604103613eb45760208301516040840151606085015160001a613ea887828585614140565b94509450505050613ee5565b8251604003613edd5760208301516040840151613ed2868383614258565b935093505050613ee5565b506000905060025b9250929050565b6000816004811115613f0057613f00615003565b03613f085750565b6001816004811115613f1c57613f1c615003565b03613f83576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610b0b565b6002816004811115613f9757613f97615003565b03613ffe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610b0b565b600381600481111561401257614012615003565b0361409f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152608401610b0b565b60048160048111156140b3576140b3615003565b03611416576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152608401610b0b565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115614177575060009050600361424f565b8460ff16601b1415801561418f57508460ff16601c14155b156141a0575060009050600461424f565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156141f4573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff81166142485760006001925092505061424f565b9150600090505b94509492505050565b6000807f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83168161428e60ff86901c601b614e55565b905061429c87828885614140565b935093505050935093915050565b82805482825590600052602060002090601f016020900481019282156143405791602002820160005b8382111561431157835183826101000a81548160ff021916908360ff16021790555092602001926001016020816000010492830192600103026142d3565b801561433e5782816101000a81549060ff0219169055600101602081600001049283019260010302614311565b505b5061434c929150614350565b5090565b5b8082111561434c5760008155600101614351565b7fffffffff000000000000000000000000000000000000000000000000000000008116811461141657600080fd5b6000602082840312156143a557600080fd5b81356143b081614365565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715614409576144096143b7565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614456576144566143b7565b604052919050565b6000602080838503121561447157600080fd5b823567ffffffffffffffff8082111561448957600080fd5b818501915085601f83011261449d57600080fd5b8135818111156144af576144af6143b7565b6144df847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161440f565b915080825286848285010111156144f557600080fd5b8084840185840137600090820190930192909252509392505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461141657600080fd5b8035801515811461156357600080fd5b6000806000806080858703121561455957600080fd5b843561456481614511565b935061457260208601614533565b925061458060408601614533565b9396929550929360600135925050565b600060208083528351808285015260005b818110156145bd578581018301518582016040015282016145a1565b818111156145cf576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60006020828403121561461557600080fd5b5035919050565b6000806040838503121561462f57600080fd5b823561463a81614511565b946020939093013593505050565b60006020828403121561465a57600080fd5b81356143b081614511565b600067ffffffffffffffff82111561467f5761467f6143b7565b5060051b60200190565b6000806040838503121561469c57600080fd5b8235915060208084013567ffffffffffffffff8111156146bb57600080fd5b8401601f810186136146cc57600080fd5b80356146df6146da82614665565b61440f565b81815260059190911b820183019083810190888311156146fe57600080fd5b928401925b8284101561471c57833582529284019290840190614703565b80955050505050509250929050565b60008060006060848603121561474057600080fd5b833561474b81614511565b9250602084013561475b81614511565b929592945050506040919091013590565b80356fffffffffffffffffffffffffffffffff8116811461156357600080fd5b6000806000606084860312156147a157600080fd5b833592506147b16020850161476c565b91506147bf6040850161476c565b90509250925092565b60008083601f8401126147da57600080fd5b50813567ffffffffffffffff8111156147f257600080fd5b6020830191508360208260051b8501011115613ee557600080fd5b6000806000806040858703121561482357600080fd5b843567ffffffffffffffff8082111561483b57600080fd5b614847888389016147c8565b9096509450602087013591508082111561486057600080fd5b5061486d878288016147c8565b95989497509550505050565b60006020828403121561488b57600080fd5b813561ffff811681146143b057600080fd5b600080604083850312156148b057600080fd5b8235915060208301356148c281614511565b809150509250929050565b600080604083850312156148e057600080fd5b82356148eb81614511565b91506148f960208401614533565b90509250929050565b60008083601f84011261491457600080fd5b50813567ffffffffffffffff81111561492c57600080fd5b602083019150836020828501011115613ee557600080fd5b803563ffffffff8116811461156357600080fd5b60008060008060006080868803121561497057600080fd5b853567ffffffffffffffff81111561498757600080fd5b61499388828901614902565b90965094505060208601359250604086013591506149b360608701614944565b90509295509295909350565b6000602082840312156149d157600080fd5b6143b082614944565b600080600080608085870312156149f057600080fd5b843593506020850135614a0281614511565b9250614a1060408601614533565b9150614a1e60608601614533565b905092959194509250565b600080600080600060808688031215614a4157600080fd5b8535614a4c81614511565b94506020860135614a5c81614511565b935060408601359250606086013567ffffffffffffffff811115614a7f57600080fd5b614a8b88828901614902565b969995985093965092949392505050565b60006020808385031215614aaf57600080fd5b823567ffffffffffffffff811115614ac657600080fd5b8301601f81018513614ad757600080fd5b8035614ae56146da82614665565b81815260069190911b82018301908381019087831115614b0457600080fd5b928401925b82841015614b565760408489031215614b225760008081fd5b614b2a6143e6565b614b338561476c565b8152614b4086860161476c565b8187015282526040939093019290840190614b09565b979650505050505050565b60008060408385031215614b7457600080fd5b823560ff8116811461463a57600080fd5b600060408284031215614b9757600080fd5b50919050565b60008060408385031215614bb057600080fd5b8235614bbb81614511565b915060208301356148c281614511565b600060208284031215614bdd57600080fd5b813567ffffffffffffffff811681146143b057600080fd5b600181811c90821680614c0957607f821691505b602082108103614b97577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b601f82111561103b57600081815260208120601f850160051c81016020861015614c695750805b601f850160051c820191505b8181101561213457828155600101614c75565b815167ffffffffffffffff811115614ca257614ca26143b7565b614cb681614cb08454614bf5565b84614c42565b602080601f831160018114614d095760008415614cd35750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555612134565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015614d5657888601518255948401946001909101908401614d37565b5085821015614d9257878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614e0257614e02614da2565b5060010190565b600060208284031215614e1b57600080fd5b81516143b081614365565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008219821115614e6857614e68614da2565b500190565b600060208284031215614e7f57600080fd5b5051919050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615614ebe57614ebe614da2565b500290565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525084604083015260806060830152826080830152828460a0840137600060a0848401015260a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85011683010190509695505050505050565b600060208284031215614f5457600080fd5b6143b08261476c565b600082614f93577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500690565b600082821015614faa57614faa614da2565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600063ffffffff83811690831681811015614ffb57614ffb614da2565b039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea2646970667358221220b3787f1c0442129146dc2167c9ec1391f227ef854fc8d4c6d91045ccab1f8fee64736f6c634300080f0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e699098af398995b04c28e9951adb9721ef74c74f93e6a478f39e7e0777be13527e7ef00000000000000000000000000000000000000000000000000000000000000a9000000000000000000000000f27276ef311886b6433865db600fa7e3d4d86b13000000000000000000000000cf3bc13c0f19b9549364cc5f4b7ea807b737c0620000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000002c68af0bb140000000000000000000000000000000000000000000000000000000000000000000d50554e4b5320436f6d69632033000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006434f4d49433300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000036697066733a2f2f516d5a66693833795a396b45347154683366417a72725532526f4547516444514d774a6673324e6e39466f4b65432f00000000000000000000
-----Decoded View---------------
Arg [0] : _vrfCoordinator (address): 0x271682DEB8C4E0901D1a1550aD2e64D568E69909
Arg [1] : _keyHash (bytes32): 0x8af398995b04c28e9951adb9721ef74c74f93e6a478f39e7e0777be13527e7ef
Arg [2] : _subscriptionId (uint64): 169
Arg [3] : _signer (address): 0xF27276eF311886b6433865Db600fa7E3D4D86b13
Arg [4] : _tokenHolder (address): 0xcf3bC13C0F19B9549364CC5F4b7EA807b737C062
Arg [5] : _name (string): PUNKS Comic 3
Arg [6] : _symbol (string): COMIC3
Arg [7] : _uri (string): ipfs://QmZfi83yZ9kE4qTh3fAzrrU2RoEGQdDQMwJfs2Nn9FoKeC/
Arg [8] : _price (uint256): 200000000000000000
-----Encoded View---------------
16 Constructor Arguments found :
Arg [0] : 000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e69909
Arg [1] : 8af398995b04c28e9951adb9721ef74c74f93e6a478f39e7e0777be13527e7ef
Arg [2] : 00000000000000000000000000000000000000000000000000000000000000a9
Arg [3] : 000000000000000000000000f27276ef311886b6433865db600fa7e3d4d86b13
Arg [4] : 000000000000000000000000cf3bc13c0f19b9549364cc5f4b7ea807b737c062
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000120
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000160
Arg [7] : 00000000000000000000000000000000000000000000000000000000000001a0
Arg [8] : 00000000000000000000000000000000000000000000000002c68af0bb140000
Arg [9] : 000000000000000000000000000000000000000000000000000000000000000d
Arg [10] : 50554e4b5320436f6d6963203300000000000000000000000000000000000000
Arg [11] : 0000000000000000000000000000000000000000000000000000000000000006
Arg [12] : 434f4d4943330000000000000000000000000000000000000000000000000000
Arg [13] : 0000000000000000000000000000000000000000000000000000000000000036
Arg [14] : 697066733a2f2f516d5a66693833795a396b45347154683366417a7272553252
Arg [15] : 6f4547516444514d774a6673324e6e39466f4b65432f00000000000000000000
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.