ERC-721
NFT
Overview
Max Total Supply
3,825 TAMAGOGI
Holders
1,683
Market
Volume (24H)
N/A
Min Price (24H)
N/A
Max Price (24H)
N/A
Other Info
Token Contract
Balance
3 TAMAGOGILoading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
Tamagogi
Compiler Version
v0.8.7+commit.e28d00a7
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT // ___ __ __ __ // | /\ |\/| /\ / _ / \/ _ | // | /--\| |/--\\__)\__/\__)| // // Tamagogi is a fully onchain tamagotchi dapp. // https://tamagogi.xyz pragma solidity ^0.8.7; import "https://github.com/RollaProject/solidity-datetime/blob/master/contracts/DateTimeContract.sol"; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; import "erc721a/contracts/ERC721A.sol"; import "base64-sol/base64.sol"; import "./tamagogi_drawer.sol"; contract Tamagogi is Ownable, ERC721A, ReentrancyGuard, TamagogiDrawer { struct TMGG { string name; uint lastFeed; uint lastPlay; uint lastHit; uint birthhash; } struct PetMdata { uint tokenId; uint seed; uint hunger; uint bored; uint unhappiness; bool isMaster; bool rerollable; } struct Config { uint price; uint propMaxSupply; uint petMaxSupply; uint[3] hungerRate; uint[3] boredRate; uint[3] hitRate; uint[3] hitRasing; uint[5] reactionRate; bool revealProp; bool revealPet; MintStage mintStage; } //@@@ enum enum MintStage { PAUSED, PROPS, PETS_MERKLE, PETS } //@@@ event event EPlay( uint tokenId, address sender ); event EHit( uint tokenId, address sender ); event EFeed( uint tokenId, address sender ); constructor() ERC721A("Tamagogi Pets", "TAMAGOGI") { config.price = 0; config.propMaxSupply = 2000; config.petMaxSupply = 1825; config.mintStage = MintStage.PAUSED; config.hungerRate = [8,40,120]; config.boredRate = [6,30,90]; config.hitRate = [4,20,60]; config.hitRasing = [9,3,1]; config.reactionRate = [0,10,20,30,40]; config.revealProp = false; config.revealPet = false; } DateTimeContract private dateTimeContract = new DateTimeContract(); bytes32 public rootHash = 0x0; Config public config; mapping(uint => uint) public seeds; mapping(uint => TMGG) public TMGGs; mapping(uint => bool) public rerollTable; mapping(string => bool) public nameTable; mapping(address => bool) public propMinted; mapping(address => bool) public petMinted; uint private bornTimestamp = 1640995201; uint private bornIdx = 0; uint private airdropId = 1; uint public airdropProgress = 0; uint public airdropReceivers = 947; //@@@ modifier modifier validToken(uint tokenId) { require(tokenId >= _startTokenId() && tokenId <= _totalMinted(), "Not valid id"); _; } modifier validOwner(uint tokenId) { require(ownerOf(tokenId) == msg.sender, "You are not token's owner"); _; } modifier revealPetOnly() { require(config.revealPet, "Not reveal"); _; } modifier petOnly(uint tokenId) { require(tokenId > config.propMaxSupply && tokenId <= config.petMaxSupply + config.propMaxSupply, "Not valid pet id"); _; } //@@@ mint function _getProp(address _address, uint quantity) private { for (uint i = 0; i < quantity; i ++) { uint seed = _getRandom(airdropId); seeds[airdropId] = seed; airdropId++; } _safeMint(_address, quantity); } function airdrop(address[] calldata addresses, uint256[] calldata quantity) external onlyOwner { require(airdropProgress + addresses.length <= airdropReceivers, "Exceed the limit"); for (uint i = 0; i < addresses.length; i ++) { _getProp(addresses[i], quantity[i]); } airdropProgress += addresses.length; } function hatchEgg() external payable { require(config.mintStage == MintStage.PETS, "Not in stage to mint TMGG"); require(_totalMinted() < config.petMaxSupply + config.propMaxSupply, "No pet left"); require(!petMinted[msg.sender], "Max to 1"); require(1 * config.price <= msg.value,"No enough eth."); _hatchEgg(); } function allowlistHatchEgg(bytes32[] calldata _proof) external payable { require(config.mintStage == MintStage.PETS_MERKLE, "Not in stage to mint merkle TMGG"); require(_totalMinted() < config.petMaxSupply + config.propMaxSupply, "No pet left"); require(!petMinted[msg.sender], "Max to 1"); require(1 * config.price <= msg.value,"No enough eth."); bytes32 leaf = keccak256(abi.encodePacked(msg.sender)); require(MerkleProof.verify(_proof, rootHash, leaf), "invalid proof"); _hatchEgg(); } function _hatchEgg() private { uint mintId = _startTokenId() + _totalMinted(); if (bornIdx == 5) { bornIdx = 0; bornTimestamp = dateTimeContract.addDays(bornTimestamp, 1); } TMGG memory preBornTMGG = TMGG('', block.timestamp, block.timestamp, 0, bornTimestamp); TMGGs[mintId] = preBornTMGG; bornIdx++; uint seed = _getRandom(mintId); seeds[mintId] = seed; _safeMint(msg.sender, 1); petMinted[msg.sender] = true; } //@@@ pet function function setName(uint tokenId, string calldata name) external validOwner(tokenId) revealPetOnly() petOnly(tokenId) { require(nameTable[name] == false, "Name exist"); uint nameLength = utfStringLength(name); require(nameLength > 1 && nameLength < 18, "Not valid name"); TMGGs[tokenId].name = name; nameTable[name] = true; } // everyone can call these function to feed, hit or play with any pet function play(uint tokenId) external revealPetOnly() petOnly(tokenId) { TMGGs[tokenId].lastPlay = block.timestamp; emit EPlay(tokenId, msg.sender); } function feed(uint tokenId) external revealPetOnly() petOnly(tokenId) { TMGGs[tokenId].lastFeed = block.timestamp; emit EFeed(tokenId, msg.sender); } function hit(uint tokenId) external revealPetOnly() petOnly(tokenId) { TMGGs[tokenId].lastHit = block.timestamp; emit EHit(tokenId, msg.sender); } function reroll(uint tokenId) external validOwner(tokenId) revealPetOnly() petOnly(tokenId) { require(!rerollTable[tokenId], "Not available"); seeds[tokenId] = _getRandom(tokenId); rerollTable[tokenId] = true; } function isBirthdate(uint tokenId) public view petOnly(tokenId) returns (bool) { TMGG memory tmgg = TMGGs[tokenId]; uint _now = block.timestamp; uint seed = seeds[tokenId]; uint offset = seed % 31536000; return dateTimeContract.getDay(_now) == dateTimeContract.getDay(tmgg.birthhash + offset) && dateTimeContract.getMonth(_now) == dateTimeContract.getMonth(tmgg.birthhash + offset); } function getBirthdate(uint tokenId) public view petOnly(tokenId) returns (uint month, uint day) { TMGG memory tmgg = TMGGs[tokenId]; uint seed = seeds[tokenId]; uint offset = seed % 31536000; uint _month = dateTimeContract.getMonth(tmgg.birthhash + offset); uint _day = dateTimeContract.getDay(tmgg.birthhash + offset); return (_month, _day); } function getPetUnhappinessAndProp(uint tokenId) public view revealPetOnly() petOnly(tokenId) returns(uint, bool, bool ,bool) { uint _now = block.timestamp; TMGG memory tmgg = TMGGs[tokenId]; uint hunger = dateTimeContract.diffHours(tmgg.lastFeed, _now); uint bored = dateTimeContract.diffHours(tmgg.lastPlay, _now); uint _baseHit = tmgg.lastHit == 0 ? 0 : (_now - tmgg.lastHit) / 60; uint hitVal = 0; if (_baseHit <= config.hitRate[0]) { hitVal = _baseHit * config.hitRasing[0]; } else if (_baseHit < config.hitRate[1]) { hitVal = _baseHit * config.hitRasing[1]; } else if (_baseHit < config.hitRate[2]) { hitVal = _baseHit * config.hitRasing[2]; } else { hitVal = _baseHit * 0; } uint[] memory ownerTokens = tokensOfOwner(ownerOf(tokenId)); bool ownFood = false; bool ownToy = false; bool ownShield = false; for(uint i = 0; i < ownerTokens.length; i++) { uint id = ownerTokens[i]; if (id <= config.propMaxSupply) { uint seed = seeds[id]; uint propNumber = propOdds[seed % propOdds.length]; if (propNumber == 0) { // own food hunger = 0; ownFood = true; } else if (propNumber == 1) { // own toy bored = 0; ownToy = true; } else if (propNumber == 2) { // own shiled hitVal = 0; ownShield = true; } } } uint _unhappiness = hunger + bored + hitVal; return (_unhappiness, ownFood, ownToy, ownShield); } function getPetHungerAndBored(uint tokenId) public view revealPetOnly() petOnly(tokenId) returns(uint, uint) { uint _now = block.timestamp; TMGG memory tmgg = TMGGs[tokenId]; uint hunger = dateTimeContract.diffHours(tmgg.lastFeed, _now); uint bored = dateTimeContract.diffHours(tmgg.lastPlay, _now); uint[] memory ownerTokens = tokensOfOwner(ownerOf(tokenId)); for(uint i = 0; i < ownerTokens.length; i++) { uint id = ownerTokens[i]; if (id <= config.propMaxSupply) { uint seed = seeds[id]; uint propNumber = propOdds[seed % propOdds.length]; if (propNumber == 0) { // own food hunger = 0; } else if (propNumber == 1) { // own toy bored = 0; } } } return (hunger, bored); } function _getReactionTraitIndex(uint _unhappiness) private view returns (uint) { if (_unhappiness <= config.reactionRate[0]) { return reaction[3]; } else if (_unhappiness < config.reactionRate[1]) { return reaction[0]; } else if (_unhappiness < config.reactionRate[2]) { return reaction[1]; } else if (_unhappiness < config.reactionRate[3]) { return reaction[2]; } else { return reaction[4]; } } function _getPetTraits(PetMdata memory petMeta) private pure returns (string memory) { string memory attr = string(abi.encodePacked( '{ "trait_type": "hunger", "display_type": "number", "value": ',Strings.toString(petMeta.hunger),'},', '{ "trait_type": "bored", "display_type": "number", "value": ',Strings.toString(petMeta.bored),'},' )); return attr; } function _getPetStyleTraits(PetMdata memory petMeta) private view returns (string memory) { string memory masterLabel = petMeta.isMaster ? "yes" : "no"; string memory rerolled = petMeta.rerollable ? "yes" : "no"; string memory attr = string(abi.encodePacked( '{ "trait_type": "type", "value": "pets"},', '{ "trait_type": "master", "value": "',masterLabel,'"},', '{ "trait_type": "rerolled", "value": "',rerolled,'"},', '{ "trait_type": "unhappiness", "display_type": "number", "value": ',Strings.toString(petMeta.unhappiness),'},', _getPetReactionTraits(petMeta), _getPetEarTraits(petMeta), _getPetHeadTraits(petMeta), _getPetBodyTraits(petMeta) )); return attr; } function _getPetReactionTraits(PetMdata memory petMeta) private view returns (string memory) { string memory attr = string(abi.encodePacked( '{ "trait_type": "reaction", "value": "',reactionTraits[_getReactionTraitIndex(petMeta.unhappiness)],'"},' )); return attr; } function _getPetEarTraits(PetMdata memory petMeta) private view returns (string memory) { string memory attr = string(abi.encodePacked( '{ "trait_type": "ear", "value": "',earTraits[ear[(petMeta.seed / 2) % ear.length]],'"},' )); return attr; } function _getPetHeadTraits(PetMdata memory petMeta) private view returns (string memory) { string memory attr = string(abi.encodePacked( '{ "trait_type": "head", "value": "',headTraits[head[(petMeta.seed / 3) % head.length]],'"},' )); return attr; } function _getPetBodyTraits(PetMdata memory petMeta) private view returns (string memory) { string memory attr = string(abi.encodePacked( '{ "trait_type": "body", "value": "',bodyTraits[body[(petMeta.seed / 4) % body.length]],'"},' )); return attr; } function _getPetsName(PetMdata memory petMeta) private view returns (string memory) { (uint month, uint day) = getBirthdate(petMeta.tokenId); TMGG memory tmgg = TMGGs[petMeta.tokenId]; string memory name = utfStringLength(tmgg.name) > 1 ? string(abi.encodePacked(tmgg.name, " / ")) : ""; return string(abi.encodePacked( '{"name": "',name,'#',Strings.toString(petMeta.tokenId),' Tamagogi (',Strings.toString(month),'/',Strings.toString(day),')','",' )); } function _getPetsBirthTrait(PetMdata memory petMeta) private view returns (string memory) { (uint month, uint day) = getBirthdate(petMeta.tokenId); return string(abi.encodePacked( '{ "trait_type": "birthdate", "value": "',Strings.toString(month),'/',Strings.toString(day),'"}' )); } function _getPetsMetadata(uint tokenId) private view returns (string memory) { (uint unhappiness, bool ownFood, bool ownToy, bool ownShield) = getPetUnhappinessAndProp(tokenId); (uint hunger, uint bored) = getPetHungerAndBored(tokenId); bool hbd = isBirthdate(tokenId); bool isMaster = ownFood && ownToy && ownShield || hbd ? true : false; uint reactionId = _getReactionTraitIndex(unhappiness); PetMdata memory petMeta = PetMdata(tokenId, seeds[tokenId], hunger, bored, unhappiness, isMaster, rerollTable[tokenId]); string memory _svgString = drawReveal(seeds[tokenId], reactionId, isMaster); string memory json = string( abi.encodePacked( _getPetsName(petMeta), '"description": "Tamagogi is a Tamagotchi Dapp and fully generated on-chain. The contract interaction and time will affect the status and reaction of the pet. If you collect other items, the pet will show love!",', '"attributes": [', _getPetTraits(petMeta), _getPetStyleTraits(petMeta), _getPetsBirthTrait(petMeta), '],' '"image": "data:image/svg+xml;base64,', Base64.encode(bytes(drawSVG(_svgString))), '"}' ) ); return Base64.encode( bytes( string(json) ) ); } function _getPetsUnrevealMetadata(uint tokenId) private view returns (string memory) { (uint month, uint day) = getBirthdate(tokenId); uint _seed = seeds[tokenId]; string memory json = Base64.encode( bytes( string( abi.encodePacked( '{"name": "#',Strings.toString(tokenId),' Tamagogi Egg (',Strings.toString(month),'/',Strings.toString(day),')','", "description": "Unbroken Tamagogi eggs...",', '"attributes": [', '{ "trait_type": "type", "value": "pets"},', '{ "trait_type": "birthdate", "value": "',Strings.toString(month),'/',Strings.toString(day),'"}', '],', '"image": "ipfs://QmW1tccYqBmSLQFTfN8rWw8JHXxx7hZS4MiiwWWDN5tvG8/',Strings.toString(eggs[_seed % eggs.length]),'.gif"}' ) ) ) ); return json; } function _getPropsMetadata(uint tokenId) private view returns (string memory) { uint _seed = seeds[tokenId]; uint _propIndex = propOdds[_seed % propOdds.length]; string memory _desc = propDesc[_propIndex]; string memory _traitName = propTraits[_propIndex]; string memory json = Base64.encode( bytes( string( abi.encodePacked( '{"name": "#',Strings.toString(tokenId),' Tamagogi (',_traitName,')", "description": "',_desc,'",', '"attributes": [', '{ "trait_type": "type", "value": "props"},', '{ "trait_type": "usage", "value": "',_traitName,'"}' '],', '"image": "ipfs://QmVxCDfmwgY2psAh7wti8aLCykkj99snygGQ89p2zkfAtf/',_traitName,'.gif"}' ) ) ) ); return json; } function _getPropsUnrevealMetadata(uint tokenId) private pure returns (string memory) { string memory json = Base64.encode( bytes( string( abi.encodePacked( '{"name": "#',Strings.toString(tokenId),' Tamagogi (Unreveal Props)", "description": "Unreveal Props",', '"attributes": [', '{ "trait_type": "type", "value": "props"}', '],', '"image": "ipfs://QmTbB6DD2w8t36zLPvBEdoWo62RFMyJi9EXcj99ZixPrxC"}' ) ) ) ); return json; } //@@@ override function _tokenURI(uint256 tokenId) private view validToken(tokenId) returns (string memory) { string memory json = tokenId <= config.propMaxSupply ? config.revealProp ? _getPropsMetadata(tokenId) : _getPropsUnrevealMetadata(tokenId) : config.revealPet ? _getPetsMetadata(tokenId) : _getPetsUnrevealMetadata(tokenId); return string(abi.encodePacked('data:application/json;base64,', json)); } function tokenURI(uint256 tokenId) override (ERC721A) public view returns (string memory) { return _tokenURI(tokenId); } function _startTokenId() override internal pure virtual returns (uint256) { return 1; } //@@@ admin function setMintStage(uint _stage) external onlyOwner { config.mintStage = MintStage(_stage); } function setHungerRate(uint[3] calldata _rate) external onlyOwner { config.hungerRate = _rate; } function setBoredRate(uint[3] calldata _rate) external onlyOwner { config.boredRate = _rate; } function setHitRate(uint[3] calldata _rate) external onlyOwner { config.hitRate = _rate; } function setReactionRate(uint[5] calldata _rate) external onlyOwner { config.reactionRate = _rate; } function setHitRasing(uint[3] calldata _rate) external onlyOwner { config.hitRasing = _rate; } function setRevealPet() external onlyOwner { config.revealPet = true; } function setRevealProp() external onlyOwner { config.revealProp = true; } function setPrice(uint _price) external onlyOwner { config.price = _price; } function setMerkle(bytes32 _hash) external onlyOwner { rootHash = _hash; } //@@@ others // ERC721AQueryable.sol function tokensOfOwner(address owner) public view virtual returns (uint256[] memory) { unchecked { uint256 tokenIdsIdx; address currOwnershipAddr; uint256 tokenIdsLength = balanceOf(owner); uint256[] memory tokenIds = new uint256[](tokenIdsLength); TokenOwnership memory ownership; for (uint256 i = _startTokenId(); tokenIdsIdx != tokenIdsLength; ++i) { ownership = _ownershipAt(i); if (ownership.burned) { continue; } if (ownership.addr != address(0)) { currOwnershipAddr = ownership.addr; } if (currOwnershipAddr == owner) { tokenIds[tokenIdsIdx++] = i; } } return tokenIds; } } // https://ethereum.stackexchange.com/questions/13862/is-it-possible-to-check-string-variables-length-inside-the-contract function utfStringLength(string memory str) pure internal returns (uint length) { uint i=0; bytes memory string_rep = bytes(str); while (i<string_rep.length) { if (string_rep[i]>>7==0) i+=1; else if (string_rep[i]>>5==bytes1(uint8(0x6))) i+=2; else if (string_rep[i]>>4==bytes1(uint8(0xE))) i+=3; else if (string_rep[i]>>3==bytes1(uint8(0x1E))) i+=4; else //For safety i+=1; length++; } } function _getRandom(uint tokenId) private view returns (uint) { uint randomlize = uint(keccak256(abi.encodePacked(blockhash(block.number - 1), tokenId, msg.sender))); return randomlize; } }
pragma solidity ^0.8.7; import "base64-sol/base64.sol"; import "./tamagogi_data.sol"; // SPDX-License-Identifier: MIT contract TamagogiDrawer is TamagogiData { function drawImage(bytes memory trait) private pure returns (string memory) { return string(abi.encodePacked( '<image x="0" y="0" width="32" height="32" image-rendering="pixelated" preserveAspectRatio="xMidYMid" xlink:href="data:image/png;base64,',Base64.encode(bytes(trait)),'"/>' )); } function drawReveal(uint seed, uint reactionId, bool isMaster) internal view returns (string memory) { bytes memory bodyImageData = bodyBytes[(seed / 4) % body.length]; bytes memory headImageData = headBytes[(seed / 3) % head.length]; bytes memory earImageData = earBytes[(seed / 2) % ear.length]; bytes memory reactionImageData = reactionBytes[reactionId]; string memory imgString = string(abi.encodePacked( drawImage(bodyImageData), drawImage(headImageData), drawImage(reactionImageData), drawImage(earImageData) )); if (isMaster) { //master imgString = string(abi.encodePacked( imgString, drawImage(masterBytes[0]) )); } return imgString; } function drawSVG(string memory svgString) internal pure returns (string memory) { return string(abi.encodePacked( '<svg width="960" height="960" version="1.1" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">', '<rect width="100%" height="100%" fill="#aad999" />', svgString, "</svg>" )); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0; /// @title Base64 /// @author Brecht Devos - <[email protected]> /// @notice Provides functions for encoding/decoding base64 library Base64 { string internal constant TABLE_ENCODE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; bytes internal constant TABLE_DECODE = hex"0000000000000000000000000000000000000000000000000000000000000000" hex"00000000000000000000003e0000003f3435363738393a3b3c3d000000000000" hex"00000102030405060708090a0b0c0d0e0f101112131415161718190000000000" hex"001a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132330000000000"; function encode(bytes memory data) internal pure returns (string memory) { if (data.length == 0) return ''; // load the table into memory string memory table = TABLE_ENCODE; // multiply by 4/3 rounded up uint256 encodedLen = 4 * ((data.length + 2) / 3); // add some extra buffer at the end required for the writing string memory result = new string(encodedLen + 32); assembly { // set the actual output length mstore(result, encodedLen) // prepare the lookup table let tablePtr := add(table, 1) // input ptr let dataPtr := data let endPtr := add(dataPtr, mload(data)) // result ptr, jump over length let resultPtr := add(result, 32) // run over the input, 3 bytes at a time for {} lt(dataPtr, endPtr) {} { // read 3 bytes dataPtr := add(dataPtr, 3) let input := mload(dataPtr) // write 4 characters mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F)))) resultPtr := add(resultPtr, 1) mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F)))) resultPtr := add(resultPtr, 1) mstore8(resultPtr, mload(add(tablePtr, and(shr( 6, input), 0x3F)))) resultPtr := add(resultPtr, 1) mstore8(resultPtr, mload(add(tablePtr, and( input, 0x3F)))) resultPtr := add(resultPtr, 1) } // padding with '=' switch mod(mload(data), 3) case 1 { mstore(sub(resultPtr, 2), shl(240, 0x3d3d)) } case 2 { mstore(sub(resultPtr, 1), shl(248, 0x3d)) } } return result; } function decode(string memory _data) internal pure returns (bytes memory) { bytes memory data = bytes(_data); if (data.length == 0) return new bytes(0); require(data.length % 4 == 0, "invalid base64 decoder input"); // load the table into memory bytes memory table = TABLE_DECODE; // every 4 characters represent 3 bytes uint256 decodedLen = (data.length / 4) * 3; // add some extra buffer at the end required for the writing bytes memory result = new bytes(decodedLen + 32); assembly { // padding with '=' let lastBytes := mload(add(data, mload(data))) if eq(and(lastBytes, 0xFF), 0x3d) { decodedLen := sub(decodedLen, 1) if eq(and(lastBytes, 0xFFFF), 0x3d3d) { decodedLen := sub(decodedLen, 1) } } // set the actual output length mstore(result, decodedLen) // prepare the lookup table let tablePtr := add(table, 1) // input ptr let dataPtr := data let endPtr := add(dataPtr, mload(data)) // result ptr, jump over length let resultPtr := add(result, 32) // run over the input, 4 characters at a time for {} lt(dataPtr, endPtr) {} { // read 4 characters dataPtr := add(dataPtr, 4) let input := mload(dataPtr) // write 3 bytes let output := add( add( shl(18, and(mload(add(tablePtr, and(shr(24, input), 0xFF))), 0xFF)), shl(12, and(mload(add(tablePtr, and(shr(16, input), 0xFF))), 0xFF))), add( shl( 6, and(mload(add(tablePtr, and(shr( 8, input), 0xFF))), 0xFF)), and(mload(add(tablePtr, and( input , 0xFF))), 0xFF) ) ) mstore(resultPtr, shl(232, output)) resultPtr := add(resultPtr, 3) } } return result; } }
// SPDX-License-Identifier: MIT // ERC721A Contracts v4.2.2 // Creator: Chiru Labs pragma solidity ^0.8.4; import './IERC721A.sol'; /** * @dev Interface of ERC721 token receiver. */ interface ERC721A__IERC721Receiver { function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); } /** * @title ERC721A * * @dev Implementation of the [ERC721](https://eips.ethereum.org/EIPS/eip-721) * Non-Fungible Token Standard, including the Metadata extension. * Optimized for lower gas during batch mints. * * Token IDs are minted in sequential order (e.g. 0, 1, 2, 3, ...) * starting from `_startTokenId()`. * * Assumptions: * * - An owner cannot have more than 2**64 - 1 (max value of uint64) of supply. * - The maximum token ID cannot exceed 2**256 - 1 (max value of uint256). */ contract ERC721A is IERC721A { // Reference type for token approval. struct TokenApprovalRef { address value; } // ============================================================= // CONSTANTS // ============================================================= // Mask of an entry in packed address data. uint256 private constant _BITMASK_ADDRESS_DATA_ENTRY = (1 << 64) - 1; // The bit position of `numberMinted` in packed address data. uint256 private constant _BITPOS_NUMBER_MINTED = 64; // The bit position of `numberBurned` in packed address data. uint256 private constant _BITPOS_NUMBER_BURNED = 128; // The bit position of `aux` in packed address data. uint256 private constant _BITPOS_AUX = 192; // Mask of all 256 bits in packed address data except the 64 bits for `aux`. uint256 private constant _BITMASK_AUX_COMPLEMENT = (1 << 192) - 1; // The bit position of `startTimestamp` in packed ownership. uint256 private constant _BITPOS_START_TIMESTAMP = 160; // The bit mask of the `burned` bit in packed ownership. uint256 private constant _BITMASK_BURNED = 1 << 224; // The bit position of the `nextInitialized` bit in packed ownership. uint256 private constant _BITPOS_NEXT_INITIALIZED = 225; // The bit mask of the `nextInitialized` bit in packed ownership. uint256 private constant _BITMASK_NEXT_INITIALIZED = 1 << 225; // The bit position of `extraData` in packed ownership. uint256 private constant _BITPOS_EXTRA_DATA = 232; // Mask of all 256 bits in a packed ownership except the 24 bits for `extraData`. uint256 private constant _BITMASK_EXTRA_DATA_COMPLEMENT = (1 << 232) - 1; // The mask of the lower 160 bits for addresses. uint256 private constant _BITMASK_ADDRESS = (1 << 160) - 1; // The maximum `quantity` that can be minted with {_mintERC2309}. // This limit is to prevent overflows on the address data entries. // For a limit of 5000, a total of 3.689e15 calls to {_mintERC2309} // is required to cause an overflow, which is unrealistic. uint256 private constant _MAX_MINT_ERC2309_QUANTITY_LIMIT = 5000; // The `Transfer` event signature is given by: // `keccak256(bytes("Transfer(address,address,uint256)"))`. bytes32 private constant _TRANSFER_EVENT_SIGNATURE = 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef; // ============================================================= // STORAGE // ============================================================= // The next token ID to be minted. uint256 private _currentIndex; // The number of tokens burned. uint256 private _burnCounter; // Token name string private _name; // Token symbol string private _symbol; // Mapping from token ID to ownership details // An empty struct value does not necessarily mean the token is unowned. // See {_packedOwnershipOf} implementation for details. // // Bits Layout: // - [0..159] `addr` // - [160..223] `startTimestamp` // - [224] `burned` // - [225] `nextInitialized` // - [232..255] `extraData` mapping(uint256 => uint256) private _packedOwnerships; // Mapping owner address to address data. // // Bits Layout: // - [0..63] `balance` // - [64..127] `numberMinted` // - [128..191] `numberBurned` // - [192..255] `aux` mapping(address => uint256) private _packedAddressData; // Mapping from token ID to approved address. mapping(uint256 => TokenApprovalRef) private _tokenApprovals; // Mapping from owner to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; // ============================================================= // CONSTRUCTOR // ============================================================= constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; _currentIndex = _startTokenId(); } // ============================================================= // TOKEN COUNTING OPERATIONS // ============================================================= /** * @dev Returns the starting token ID. * To change the starting token ID, please override this function. */ function _startTokenId() internal view virtual returns (uint256) { return 0; } /** * @dev Returns the next token ID to be minted. */ function _nextTokenId() internal view virtual returns (uint256) { return _currentIndex; } /** * @dev Returns the total number of tokens in existence. * Burned tokens will reduce the count. * To get the total number of tokens minted, please see {_totalMinted}. */ function totalSupply() public view virtual override returns (uint256) { // Counter underflow is impossible as _burnCounter cannot be incremented // more than `_currentIndex - _startTokenId()` times. unchecked { return _currentIndex - _burnCounter - _startTokenId(); } } /** * @dev Returns the total amount of tokens minted in the contract. */ function _totalMinted() internal view virtual returns (uint256) { // Counter underflow is impossible as `_currentIndex` does not decrement, // and it is initialized to `_startTokenId()`. unchecked { return _currentIndex - _startTokenId(); } } /** * @dev Returns the total number of tokens burned. */ function _totalBurned() internal view virtual returns (uint256) { return _burnCounter; } // ============================================================= // ADDRESS DATA OPERATIONS // ============================================================= /** * @dev Returns the number of tokens in `owner`'s account. */ function balanceOf(address owner) public view virtual override returns (uint256) { if (owner == address(0)) revert BalanceQueryForZeroAddress(); return _packedAddressData[owner] & _BITMASK_ADDRESS_DATA_ENTRY; } /** * Returns the number of tokens minted by `owner`. */ function _numberMinted(address owner) internal view returns (uint256) { return (_packedAddressData[owner] >> _BITPOS_NUMBER_MINTED) & _BITMASK_ADDRESS_DATA_ENTRY; } /** * Returns the number of tokens burned by or on behalf of `owner`. */ function _numberBurned(address owner) internal view returns (uint256) { return (_packedAddressData[owner] >> _BITPOS_NUMBER_BURNED) & _BITMASK_ADDRESS_DATA_ENTRY; } /** * Returns the auxiliary data for `owner`. (e.g. number of whitelist mint slots used). */ function _getAux(address owner) internal view returns (uint64) { return uint64(_packedAddressData[owner] >> _BITPOS_AUX); } /** * Sets the auxiliary data for `owner`. (e.g. number of whitelist mint slots used). * If there are multiple variables, please pack them into a uint64. */ function _setAux(address owner, uint64 aux) internal virtual { uint256 packed = _packedAddressData[owner]; uint256 auxCasted; // Cast `aux` with assembly to avoid redundant masking. assembly { auxCasted := aux } packed = (packed & _BITMASK_AUX_COMPLEMENT) | (auxCasted << _BITPOS_AUX); _packedAddressData[owner] = packed; } // ============================================================= // IERC165 // ============================================================= /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified) * to learn more about how these ids are created. * * This function call must use less than 30000 gas. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { // The interface IDs are constants representing the first 4 bytes // of the XOR of all function selectors in the interface. // See: [ERC165](https://eips.ethereum.org/EIPS/eip-165) // (e.g. `bytes4(i.functionA.selector ^ i.functionB.selector ^ ...)`) return interfaceId == 0x01ffc9a7 || // ERC165 interface ID for ERC165. interfaceId == 0x80ac58cd || // ERC165 interface ID for ERC721. interfaceId == 0x5b5e139f; // ERC165 interface ID for ERC721Metadata. } // ============================================================= // IERC721Metadata // ============================================================= /** * @dev Returns the token collection name. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the token collection symbol. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { if (!_exists(tokenId)) revert URIQueryForNonexistentToken(); string memory baseURI = _baseURI(); return bytes(baseURI).length != 0 ? string(abi.encodePacked(baseURI, _toString(tokenId))) : ''; } /** * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each * token will be the concatenation of the `baseURI` and the `tokenId`. Empty * by default, it can be overridden in child contracts. */ function _baseURI() internal view virtual returns (string memory) { return ''; } // ============================================================= // OWNERSHIPS OPERATIONS // ============================================================= /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) public view virtual override returns (address) { return address(uint160(_packedOwnershipOf(tokenId))); } /** * @dev Gas spent here starts off proportional to the maximum mint batch size. * It gradually moves to O(1) as tokens get transferred around over time. */ function _ownershipOf(uint256 tokenId) internal view virtual returns (TokenOwnership memory) { return _unpackedOwnership(_packedOwnershipOf(tokenId)); } /** * @dev Returns the unpacked `TokenOwnership` struct at `index`. */ function _ownershipAt(uint256 index) internal view virtual returns (TokenOwnership memory) { return _unpackedOwnership(_packedOwnerships[index]); } /** * @dev Initializes the ownership slot minted at `index` for efficiency purposes. */ function _initializeOwnershipAt(uint256 index) internal virtual { if (_packedOwnerships[index] == 0) { _packedOwnerships[index] = _packedOwnershipOf(index); } } /** * Returns the packed ownership data of `tokenId`. */ function _packedOwnershipOf(uint256 tokenId) private view returns (uint256) { uint256 curr = tokenId; unchecked { if (_startTokenId() <= curr) if (curr < _currentIndex) { uint256 packed = _packedOwnerships[curr]; // If not burned. if (packed & _BITMASK_BURNED == 0) { // Invariant: // There will always be an initialized ownership slot // (i.e. `ownership.addr != address(0) && ownership.burned == false`) // before an unintialized ownership slot // (i.e. `ownership.addr == address(0) && ownership.burned == false`) // Hence, `curr` will not underflow. // // We can directly compare the packed value. // If the address is zero, packed will be zero. while (packed == 0) { packed = _packedOwnerships[--curr]; } return packed; } } } revert OwnerQueryForNonexistentToken(); } /** * @dev Returns the unpacked `TokenOwnership` struct from `packed`. */ function _unpackedOwnership(uint256 packed) private pure returns (TokenOwnership memory ownership) { ownership.addr = address(uint160(packed)); ownership.startTimestamp = uint64(packed >> _BITPOS_START_TIMESTAMP); ownership.burned = packed & _BITMASK_BURNED != 0; ownership.extraData = uint24(packed >> _BITPOS_EXTRA_DATA); } /** * @dev Packs ownership data into a single uint256. */ function _packOwnershipData(address owner, uint256 flags) private view returns (uint256 result) { assembly { // Mask `owner` to the lower 160 bits, in case the upper bits somehow aren't clean. owner := and(owner, _BITMASK_ADDRESS) // `owner | (block.timestamp << _BITPOS_START_TIMESTAMP) | flags`. result := or(owner, or(shl(_BITPOS_START_TIMESTAMP, timestamp()), flags)) } } /** * @dev Returns the `nextInitialized` flag set if `quantity` equals 1. */ function _nextInitializedFlag(uint256 quantity) private pure returns (uint256 result) { // For branchless setting of the `nextInitialized` flag. assembly { // `(quantity == 1) << _BITPOS_NEXT_INITIALIZED`. result := shl(_BITPOS_NEXT_INITIALIZED, eq(quantity, 1)) } } // ============================================================= // APPROVAL OPERATIONS // ============================================================= /** * @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) public virtual override { address owner = ownerOf(tokenId); if (_msgSenderERC721A() != owner) if (!isApprovedForAll(owner, _msgSenderERC721A())) { revert ApprovalCallerNotOwnerNorApproved(); } _tokenApprovals[tokenId].value = to; emit Approval(owner, to, tokenId); } /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) public view virtual override returns (address) { if (!_exists(tokenId)) revert ApprovalQueryForNonexistentToken(); return _tokenApprovals[tokenId].value; } /** * @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) public virtual override { if (operator == _msgSenderERC721A()) revert ApproveToCaller(); _operatorApprovals[_msgSenderERC721A()][operator] = approved; emit ApprovalForAll(_msgSenderERC721A(), operator, approved); } /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll}. */ function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev Returns whether `tokenId` exists. * * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. * * Tokens start existing when they are minted. See {_mint}. */ function _exists(uint256 tokenId) internal view virtual returns (bool) { return _startTokenId() <= tokenId && tokenId < _currentIndex && // If within bounds, _packedOwnerships[tokenId] & _BITMASK_BURNED == 0; // and not burned. } /** * @dev Returns whether `msgSender` is equal to `approvedAddress` or `owner`. */ function _isSenderApprovedOrOwner( address approvedAddress, address owner, address msgSender ) private pure returns (bool result) { assembly { // Mask `owner` to the lower 160 bits, in case the upper bits somehow aren't clean. owner := and(owner, _BITMASK_ADDRESS) // Mask `msgSender` to the lower 160 bits, in case the upper bits somehow aren't clean. msgSender := and(msgSender, _BITMASK_ADDRESS) // `msgSender == owner || msgSender == approvedAddress`. result := or(eq(msgSender, owner), eq(msgSender, approvedAddress)) } } /** * @dev Returns the storage slot and value for the approved address of `tokenId`. */ function _getApprovedSlotAndAddress(uint256 tokenId) private view returns (uint256 approvedAddressSlot, address approvedAddress) { TokenApprovalRef storage tokenApproval = _tokenApprovals[tokenId]; // The following is equivalent to `approvedAddress = _tokenApprovals[tokenId]`. assembly { approvedAddressSlot := tokenApproval.slot approvedAddress := sload(approvedAddressSlot) } } // ============================================================= // TRANSFER OPERATIONS // ============================================================= /** * @dev Transfers `tokenId` from `from` to `to`. * * 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 ) public virtual override { uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId); if (address(uint160(prevOwnershipPacked)) != from) revert TransferFromIncorrectOwner(); (uint256 approvedAddressSlot, address approvedAddress) = _getApprovedSlotAndAddress(tokenId); // The nested ifs save around 20+ gas over a compound boolean condition. if (!_isSenderApprovedOrOwner(approvedAddress, from, _msgSenderERC721A())) if (!isApprovedForAll(from, _msgSenderERC721A())) revert TransferCallerNotOwnerNorApproved(); if (to == address(0)) revert TransferToZeroAddress(); _beforeTokenTransfers(from, to, tokenId, 1); // Clear approvals from the previous owner. assembly { if approvedAddress { // This is equivalent to `delete _tokenApprovals[tokenId]`. sstore(approvedAddressSlot, 0) } } // Underflow of the sender's balance is impossible because we check for // ownership above and the recipient's balance can't realistically overflow. // Counter overflow is incredibly unrealistic as `tokenId` would have to be 2**256. unchecked { // We can directly increment and decrement the balances. --_packedAddressData[from]; // Updates: `balance -= 1`. ++_packedAddressData[to]; // Updates: `balance += 1`. // Updates: // - `address` to the next owner. // - `startTimestamp` to the timestamp of transfering. // - `burned` to `false`. // - `nextInitialized` to `true`. _packedOwnerships[tokenId] = _packOwnershipData( to, _BITMASK_NEXT_INITIALIZED | _nextExtraData(from, to, prevOwnershipPacked) ); // If the next slot may not have been initialized (i.e. `nextInitialized == false`) . if (prevOwnershipPacked & _BITMASK_NEXT_INITIALIZED == 0) { uint256 nextTokenId = tokenId + 1; // If the next slot's address is zero and not burned (i.e. packed value is zero). if (_packedOwnerships[nextTokenId] == 0) { // If the next slot is within bounds. if (nextTokenId != _currentIndex) { // Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`. _packedOwnerships[nextTokenId] = prevOwnershipPacked; } } } } emit Transfer(from, to, tokenId); _afterTokenTransfers(from, to, tokenId, 1); } /** * @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`. */ function safeTransferFrom( address from, address to, uint256 tokenId ) public virtual override { safeTransferFrom(from, to, tokenId, ''); } /** * @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 memory _data ) public virtual override { transferFrom(from, to, tokenId); if (to.code.length != 0) if (!_checkContractOnERC721Received(from, to, tokenId, _data)) { revert TransferToNonERC721ReceiverImplementer(); } } /** * @dev Hook that is called before a set of serially-ordered token IDs * are about to be transferred. This includes minting. * And also called before burning one token. * * `startTokenId` - the first token ID to be transferred. * `quantity` - the amount to be transferred. * * Calling conditions: * * - When `from` and `to` are both non-zero, `from`'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, `tokenId` will be burned by `from`. * - `from` and `to` are never both zero. */ function _beforeTokenTransfers( address from, address to, uint256 startTokenId, uint256 quantity ) internal virtual {} /** * @dev Hook that is called after a set of serially-ordered token IDs * have been transferred. This includes minting. * And also called after one token has been burned. * * `startTokenId` - the first token ID to be transferred. * `quantity` - the amount to be transferred. * * Calling conditions: * * - When `from` and `to` are both non-zero, `from`'s `tokenId` has been * transferred to `to`. * - When `from` is zero, `tokenId` has been minted for `to`. * - When `to` is zero, `tokenId` has been burned by `from`. * - `from` and `to` are never both zero. */ function _afterTokenTransfers( address from, address to, uint256 startTokenId, uint256 quantity ) internal virtual {} /** * @dev Private function to invoke {IERC721Receiver-onERC721Received} on a target contract. * * `from` - Previous owner of the given token ID. * `to` - Target address that will receive the token. * `tokenId` - Token ID to be transferred. * `_data` - Optional data to send along with the call. * * Returns whether the call correctly returned the expected magic value. */ function _checkContractOnERC721Received( address from, address to, uint256 tokenId, bytes memory _data ) private returns (bool) { try ERC721A__IERC721Receiver(to).onERC721Received(_msgSenderERC721A(), from, tokenId, _data) returns ( bytes4 retval ) { return retval == ERC721A__IERC721Receiver(to).onERC721Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { revert TransferToNonERC721ReceiverImplementer(); } else { assembly { revert(add(32, reason), mload(reason)) } } } } // ============================================================= // MINT OPERATIONS // ============================================================= /** * @dev Mints `quantity` tokens and transfers them to `to`. * * Requirements: * * - `to` cannot be the zero address. * - `quantity` must be greater than 0. * * Emits a {Transfer} event for each mint. */ function _mint(address to, uint256 quantity) internal virtual { uint256 startTokenId = _currentIndex; if (quantity == 0) revert MintZeroQuantity(); _beforeTokenTransfers(address(0), to, startTokenId, quantity); // Overflows are incredibly unrealistic. // `balance` and `numberMinted` have a maximum limit of 2**64. // `tokenId` has a maximum limit of 2**256. unchecked { // Updates: // - `balance += quantity`. // - `numberMinted += quantity`. // // We can directly add to the `balance` and `numberMinted`. _packedAddressData[to] += quantity * ((1 << _BITPOS_NUMBER_MINTED) | 1); // Updates: // - `address` to the owner. // - `startTimestamp` to the timestamp of minting. // - `burned` to `false`. // - `nextInitialized` to `quantity == 1`. _packedOwnerships[startTokenId] = _packOwnershipData( to, _nextInitializedFlag(quantity) | _nextExtraData(address(0), to, 0) ); uint256 toMasked; uint256 end = startTokenId + quantity; // Use assembly to loop and emit the `Transfer` event for gas savings. assembly { // Mask `to` to the lower 160 bits, in case the upper bits somehow aren't clean. toMasked := and(to, _BITMASK_ADDRESS) // Emit the `Transfer` event. log4( 0, // Start of data (0, since no data). 0, // End of data (0, since no data). _TRANSFER_EVENT_SIGNATURE, // Signature. 0, // `address(0)`. toMasked, // `to`. startTokenId // `tokenId`. ) for { let tokenId := add(startTokenId, 1) } iszero(eq(tokenId, end)) { tokenId := add(tokenId, 1) } { // Emit the `Transfer` event. Similar to above. log4(0, 0, _TRANSFER_EVENT_SIGNATURE, 0, toMasked, tokenId) } } if (toMasked == 0) revert MintToZeroAddress(); _currentIndex = end; } _afterTokenTransfers(address(0), to, startTokenId, quantity); } /** * @dev Mints `quantity` tokens and transfers them to `to`. * * This function is intended for efficient minting only during contract creation. * * It emits only one {ConsecutiveTransfer} as defined in * [ERC2309](https://eips.ethereum.org/EIPS/eip-2309), * instead of a sequence of {Transfer} event(s). * * Calling this function outside of contract creation WILL make your contract * non-compliant with the ERC721 standard. * For full ERC721 compliance, substituting ERC721 {Transfer} event(s) with the ERC2309 * {ConsecutiveTransfer} event is only permissible during contract creation. * * Requirements: * * - `to` cannot be the zero address. * - `quantity` must be greater than 0. * * Emits a {ConsecutiveTransfer} event. */ function _mintERC2309(address to, uint256 quantity) internal virtual { uint256 startTokenId = _currentIndex; if (to == address(0)) revert MintToZeroAddress(); if (quantity == 0) revert MintZeroQuantity(); if (quantity > _MAX_MINT_ERC2309_QUANTITY_LIMIT) revert MintERC2309QuantityExceedsLimit(); _beforeTokenTransfers(address(0), to, startTokenId, quantity); // Overflows are unrealistic due to the above check for `quantity` to be below the limit. unchecked { // Updates: // - `balance += quantity`. // - `numberMinted += quantity`. // // We can directly add to the `balance` and `numberMinted`. _packedAddressData[to] += quantity * ((1 << _BITPOS_NUMBER_MINTED) | 1); // Updates: // - `address` to the owner. // - `startTimestamp` to the timestamp of minting. // - `burned` to `false`. // - `nextInitialized` to `quantity == 1`. _packedOwnerships[startTokenId] = _packOwnershipData( to, _nextInitializedFlag(quantity) | _nextExtraData(address(0), to, 0) ); emit ConsecutiveTransfer(startTokenId, startTokenId + quantity - 1, address(0), to); _currentIndex = startTokenId + quantity; } _afterTokenTransfers(address(0), to, startTokenId, quantity); } /** * @dev Safely mints `quantity` tokens and transfers them to `to`. * * Requirements: * * - If `to` refers to a smart contract, it must implement * {IERC721Receiver-onERC721Received}, which is called for each safe transfer. * - `quantity` must be greater than 0. * * See {_mint}. * * Emits a {Transfer} event for each mint. */ function _safeMint( address to, uint256 quantity, bytes memory _data ) internal virtual { _mint(to, quantity); unchecked { if (to.code.length != 0) { uint256 end = _currentIndex; uint256 index = end - quantity; do { if (!_checkContractOnERC721Received(address(0), to, index++, _data)) { revert TransferToNonERC721ReceiverImplementer(); } } while (index < end); // Reentrancy protection. if (_currentIndex != end) revert(); } } } /** * @dev Equivalent to `_safeMint(to, quantity, '')`. */ function _safeMint(address to, uint256 quantity) internal virtual { _safeMint(to, quantity, ''); } // ============================================================= // BURN OPERATIONS // ============================================================= /** * @dev Equivalent to `_burn(tokenId, false)`. */ function _burn(uint256 tokenId) internal virtual { _burn(tokenId, false); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId, bool approvalCheck) internal virtual { uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId); address from = address(uint160(prevOwnershipPacked)); (uint256 approvedAddressSlot, address approvedAddress) = _getApprovedSlotAndAddress(tokenId); if (approvalCheck) { // The nested ifs save around 20+ gas over a compound boolean condition. if (!_isSenderApprovedOrOwner(approvedAddress, from, _msgSenderERC721A())) if (!isApprovedForAll(from, _msgSenderERC721A())) revert TransferCallerNotOwnerNorApproved(); } _beforeTokenTransfers(from, address(0), tokenId, 1); // Clear approvals from the previous owner. assembly { if approvedAddress { // This is equivalent to `delete _tokenApprovals[tokenId]`. sstore(approvedAddressSlot, 0) } } // Underflow of the sender's balance is impossible because we check for // ownership above and the recipient's balance can't realistically overflow. // Counter overflow is incredibly unrealistic as `tokenId` would have to be 2**256. unchecked { // Updates: // - `balance -= 1`. // - `numberBurned += 1`. // // We can directly decrement the balance, and increment the number burned. // This is equivalent to `packed -= 1; packed += 1 << _BITPOS_NUMBER_BURNED;`. _packedAddressData[from] += (1 << _BITPOS_NUMBER_BURNED) - 1; // Updates: // - `address` to the last owner. // - `startTimestamp` to the timestamp of burning. // - `burned` to `true`. // - `nextInitialized` to `true`. _packedOwnerships[tokenId] = _packOwnershipData( from, (_BITMASK_BURNED | _BITMASK_NEXT_INITIALIZED) | _nextExtraData(from, address(0), prevOwnershipPacked) ); // If the next slot may not have been initialized (i.e. `nextInitialized == false`) . if (prevOwnershipPacked & _BITMASK_NEXT_INITIALIZED == 0) { uint256 nextTokenId = tokenId + 1; // If the next slot's address is zero and not burned (i.e. packed value is zero). if (_packedOwnerships[nextTokenId] == 0) { // If the next slot is within bounds. if (nextTokenId != _currentIndex) { // Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`. _packedOwnerships[nextTokenId] = prevOwnershipPacked; } } } } emit Transfer(from, address(0), tokenId); _afterTokenTransfers(from, address(0), tokenId, 1); // Overflow not possible, as _burnCounter cannot be exceed _currentIndex times. unchecked { _burnCounter++; } } // ============================================================= // EXTRA DATA OPERATIONS // ============================================================= /** * @dev Directly sets the extra data for the ownership data `index`. */ function _setExtraDataAt(uint256 index, uint24 extraData) internal virtual { uint256 packed = _packedOwnerships[index]; if (packed == 0) revert OwnershipNotInitializedForExtraData(); uint256 extraDataCasted; // Cast `extraData` with assembly to avoid redundant masking. assembly { extraDataCasted := extraData } packed = (packed & _BITMASK_EXTRA_DATA_COMPLEMENT) | (extraDataCasted << _BITPOS_EXTRA_DATA); _packedOwnerships[index] = packed; } /** * @dev Called during each token transfer to set the 24bit `extraData` field. * Intended to be overridden by the cosumer contract. * * `previousExtraData` - the value of `extraData` before transfer. * * Calling conditions: * * - When `from` and `to` are both non-zero, `from`'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, `tokenId` will be burned by `from`. * - `from` and `to` are never both zero. */ function _extraData( address from, address to, uint24 previousExtraData ) internal view virtual returns (uint24) {} /** * @dev Returns the next extra data for the packed ownership data. * The returned result is shifted into position. */ function _nextExtraData( address from, address to, uint256 prevOwnershipPacked ) private view returns (uint256) { uint24 extraData = uint24(prevOwnershipPacked >> _BITPOS_EXTRA_DATA); return uint256(_extraData(from, to, extraData)) << _BITPOS_EXTRA_DATA; } // ============================================================= // OTHER OPERATIONS // ============================================================= /** * @dev Returns the message sender (defaults to `msg.sender`). * * If you are writing GSN compatible contracts, you need to override this function. */ function _msgSenderERC721A() internal view virtual returns (address) { return msg.sender; } /** * @dev Converts a uint256 to its ASCII string decimal representation. */ function _toString(uint256 value) internal pure virtual returns (string memory str) { assembly { // The maximum value of a uint256 contains 78 digits (1 byte per digit), // but we allocate 0x80 bytes to keep the free memory pointer 32-byte word aliged. // We will need 1 32-byte word to store the length, // and 3 32-byte words to store a maximum of 78 digits. Total: 0x20 + 3 * 0x20 = 0x80. str := add(mload(0x40), 0x80) // Update the free memory pointer to allocate. mstore(0x40, str) // Cache the end of the memory to calculate the length later. let end := str // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. // prettier-ignore for { let temp := value } 1 {} { str := sub(str, 1) // Write the character to the pointer. // The ASCII index of the '0' character is 48. mstore8(str, add(48, mod(temp, 10))) // Keep dividing `temp` until zero. temp := div(temp, 10) // prettier-ignore if iszero(temp) { break } } let length := sub(end, str) // Move the pointer 32 bytes leftwards to make room for the length. str := sub(str, 0x20) // Store the length. mstore(str, length) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // 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); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/cryptography/MerkleProof.sol) pragma solidity ^0.8.0; /** * @dev These functions deal with verification of Merkle Tree proofs. * * The proofs can be generated using the JavaScript library * https://github.com/miguelmota/merkletreejs[merkletreejs]. * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled. * * See `test/utils/cryptography/MerkleProof.test.js` for some examples. * * WARNING: You should avoid using leaf values that are 64 bytes long prior to * hashing, or use a hash function other than keccak256 for hashing leaves. * This is because the concatenation of a sorted pair of internal nodes in * the merkle tree could be reinterpreted as a leaf value. */ library MerkleProof { /** * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree * defined by `root`. For this, a `proof` must be provided, containing * sibling hashes on the branch from the leaf to the root of the tree. Each * pair of leaves and each pair of pre-images are assumed to be sorted. */ function verify( bytes32[] memory proof, bytes32 root, bytes32 leaf ) internal pure returns (bool) { return processProof(proof, leaf) == root; } /** * @dev Calldata version of {verify} * * _Available since v4.7._ */ function verifyCalldata( bytes32[] calldata proof, bytes32 root, bytes32 leaf ) internal pure returns (bool) { return processProofCalldata(proof, leaf) == root; } /** * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt * hash matches the root of the tree. When processing the proof, the pairs * of leafs & pre-images are assumed to be sorted. * * _Available since v4.4._ */ function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { computedHash = _hashPair(computedHash, proof[i]); } return computedHash; } /** * @dev Calldata version of {processProof} * * _Available since v4.7._ */ function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { computedHash = _hashPair(computedHash, proof[i]); } return computedHash; } /** * @dev Returns true if the `leaves` can be proved to be a part of a Merkle tree defined by * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}. * * _Available since v4.7._ */ function multiProofVerify( bytes32[] memory proof, bool[] memory proofFlags, bytes32 root, bytes32[] memory leaves ) internal pure returns (bool) { return processMultiProof(proof, proofFlags, leaves) == root; } /** * @dev Calldata version of {multiProofVerify} * * _Available since v4.7._ */ function multiProofVerifyCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32 root, bytes32[] memory leaves ) internal pure returns (bool) { return processMultiProofCalldata(proof, proofFlags, leaves) == root; } /** * @dev Returns the root of a tree reconstructed from `leaves` and the sibling nodes in `proof`, * consuming from one or the other at each step according to the instructions given by * `proofFlags`. * * _Available since v4.7._ */ function processMultiProof( bytes32[] memory proof, bool[] memory proofFlags, bytes32[] memory leaves ) internal pure returns (bytes32 merkleRoot) { // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the merkle tree. uint256 leavesLen = leaves.length; uint256 totalHashes = proofFlags.length; // Check proof validity. require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof"); // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](totalHashes); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value for the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < totalHashes; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++]; hashes[i] = _hashPair(a, b); } if (totalHashes > 0) { return hashes[totalHashes - 1]; } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } /** * @dev Calldata version of {processMultiProof} * * _Available since v4.7._ */ function processMultiProofCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32[] memory leaves ) internal pure returns (bytes32 merkleRoot) { // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the merkle tree. uint256 leavesLen = leaves.length; uint256 totalHashes = proofFlags.length; // Check proof validity. require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof"); // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](totalHashes); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value for the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < totalHashes; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++]; hashes[i] = _hashPair(a, b); } if (totalHashes > 0) { return hashes[totalHashes - 1]; } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) { return a < b ? _efficientHash(a, b) : _efficientHash(b, a); } function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) { /// @solidity memory-safe-assembly assembly { mstore(0x00, a) mstore(0x20, b) value := keccak256(0x00, 0x40) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // ---------------------------------------------------------------------------- // DateTime Library v2.0 - Contract Instance // // A gas-efficient Solidity date and time library // // https://github.com/bokkypoobah/DateTime // // Tested date range 1970/01/01 to 2345/12/31 // // Conventions: // Unit | Range | Notes // :-------- |:-------------:|:----- // timestamp | >= 0 | Unix timestamp, number of seconds since 1970/01/01 00:00:00 UTC // year | 1970 ... 2345 | // month | 1 ... 12 | // day | 1 ... 31 | // hour | 0 ... 23 | // minute | 0 ... 59 | // second | 0 ... 59 | // dayOfWeek | 1 ... 7 | 1 = Monday, ..., 7 = Sunday // // // Enjoy. (c) BokkyPooBah / Bok Consulting Pty Ltd 2018. // // GNU Lesser General Public License 3.0 // https://www.gnu.org/licenses/lgpl-3.0.en.html // ---------------------------------------------------------------------------- import "./DateTime.sol"; contract DateTimeContract { uint256 public constant SECONDS_PER_DAY = 24 * 60 * 60; uint256 public constant SECONDS_PER_HOUR = 60 * 60; uint256 public constant SECONDS_PER_MINUTE = 60; int256 public constant OFFSET19700101 = 2440588; uint256 public constant DOW_MON = 1; uint256 public constant DOW_TUE = 2; uint256 public constant DOW_WED = 3; uint256 public constant DOW_THU = 4; uint256 public constant DOW_FRI = 5; uint256 public constant DOW_SAT = 6; uint256 public constant DOW_SUN = 7; function _now() public view returns (uint256 timestamp) { timestamp = block.timestamp; } function _nowDateTime() public view returns (uint256 year, uint256 month, uint256 day, uint256 hour, uint256 minute, uint256 second) { (year, month, day, hour, minute, second) = DateTime.timestampToDateTime(block.timestamp); } function _daysFromDate(uint256 year, uint256 month, uint256 day) public pure returns (uint256 _days) { return DateTime._daysFromDate(year, month, day); } function _daysToDate(uint256 _days) public pure returns (uint256 year, uint256 month, uint256 day) { return DateTime._daysToDate(_days); } function timestampFromDate(uint256 year, uint256 month, uint256 day) public pure returns (uint256 timestamp) { return DateTime.timestampFromDate(year, month, day); } function timestampFromDateTime( uint256 year, uint256 month, uint256 day, uint256 hour, uint256 minute, uint256 second ) public pure returns (uint256 timestamp) { return DateTime.timestampFromDateTime(year, month, day, hour, minute, second); } function timestampToDate(uint256 timestamp) public pure returns (uint256 year, uint256 month, uint256 day) { (year, month, day) = DateTime.timestampToDate(timestamp); } function timestampToDateTime(uint256 timestamp) public pure returns (uint256 year, uint256 month, uint256 day, uint256 hour, uint256 minute, uint256 second) { (year, month, day, hour, minute, second) = DateTime.timestampToDateTime(timestamp); } function isValidDate(uint256 year, uint256 month, uint256 day) public pure returns (bool valid) { valid = DateTime.isValidDate(year, month, day); } function isValidDateTime(uint256 year, uint256 month, uint256 day, uint256 hour, uint256 minute, uint256 second) public pure returns (bool valid) { valid = DateTime.isValidDateTime(year, month, day, hour, minute, second); } function isLeapYear(uint256 timestamp) public pure returns (bool leapYear) { leapYear = DateTime.isLeapYear(timestamp); } function _isLeapYear(uint256 year) public pure returns (bool leapYear) { leapYear = DateTime._isLeapYear(year); } function isWeekDay(uint256 timestamp) public pure returns (bool weekDay) { weekDay = DateTime.isWeekDay(timestamp); } function isWeekEnd(uint256 timestamp) public pure returns (bool weekEnd) { weekEnd = DateTime.isWeekEnd(timestamp); } function getDaysInMonth(uint256 timestamp) public pure returns (uint256 daysInMonth) { daysInMonth = DateTime.getDaysInMonth(timestamp); } function _getDaysInMonth(uint256 year, uint256 month) public pure returns (uint256 daysInMonth) { daysInMonth = DateTime._getDaysInMonth(year, month); } function getDayOfWeek(uint256 timestamp) public pure returns (uint256 dayOfWeek) { dayOfWeek = DateTime.getDayOfWeek(timestamp); } function getYear(uint256 timestamp) public pure returns (uint256 year) { year = DateTime.getYear(timestamp); } function getMonth(uint256 timestamp) public pure returns (uint256 month) { month = DateTime.getMonth(timestamp); } function getDay(uint256 timestamp) public pure returns (uint256 day) { day = DateTime.getDay(timestamp); } function getHour(uint256 timestamp) public pure returns (uint256 hour) { hour = DateTime.getHour(timestamp); } function getMinute(uint256 timestamp) public pure returns (uint256 minute) { minute = DateTime.getMinute(timestamp); } function getSecond(uint256 timestamp) public pure returns (uint256 second) { second = DateTime.getSecond(timestamp); } function addYears(uint256 timestamp, uint256 _years) public pure returns (uint256 newTimestamp) { newTimestamp = DateTime.addYears(timestamp, _years); } function addMonths(uint256 timestamp, uint256 _months) public pure returns (uint256 newTimestamp) { newTimestamp = DateTime.addMonths(timestamp, _months); } function addDays(uint256 timestamp, uint256 _days) public pure returns (uint256 newTimestamp) { newTimestamp = DateTime.addDays(timestamp, _days); } function addHours(uint256 timestamp, uint256 _hours) public pure returns (uint256 newTimestamp) { newTimestamp = DateTime.addHours(timestamp, _hours); } function addMinutes(uint256 timestamp, uint256 _minutes) public pure returns (uint256 newTimestamp) { newTimestamp = DateTime.addMinutes(timestamp, _minutes); } function addSeconds(uint256 timestamp, uint256 _seconds) public pure returns (uint256 newTimestamp) { newTimestamp = DateTime.addSeconds(timestamp, _seconds); } function subYears(uint256 timestamp, uint256 _years) public pure returns (uint256 newTimestamp) { newTimestamp = DateTime.subYears(timestamp, _years); } function subMonths(uint256 timestamp, uint256 _months) public pure returns (uint256 newTimestamp) { newTimestamp = DateTime.subMonths(timestamp, _months); } function subDays(uint256 timestamp, uint256 _days) public pure returns (uint256 newTimestamp) { newTimestamp = DateTime.subDays(timestamp, _days); } function subHours(uint256 timestamp, uint256 _hours) public pure returns (uint256 newTimestamp) { newTimestamp = DateTime.subHours(timestamp, _hours); } function subMinutes(uint256 timestamp, uint256 _minutes) public pure returns (uint256 newTimestamp) { newTimestamp = DateTime.subMinutes(timestamp, _minutes); } function subSeconds(uint256 timestamp, uint256 _seconds) public pure returns (uint256 newTimestamp) { newTimestamp = DateTime.subSeconds(timestamp, _seconds); } function diffYears(uint256 fromTimestamp, uint256 toTimestamp) public pure returns (uint256 _years) { _years = DateTime.diffYears(fromTimestamp, toTimestamp); } function diffMonths(uint256 fromTimestamp, uint256 toTimestamp) public pure returns (uint256 _months) { _months = DateTime.diffMonths(fromTimestamp, toTimestamp); } function diffDays(uint256 fromTimestamp, uint256 toTimestamp) public pure returns (uint256 _days) { _days = DateTime.diffDays(fromTimestamp, toTimestamp); } function diffHours(uint256 fromTimestamp, uint256 toTimestamp) public pure returns (uint256 _hours) { _hours = DateTime.diffHours(fromTimestamp, toTimestamp); } function diffMinutes(uint256 fromTimestamp, uint256 toTimestamp) public pure returns (uint256 _minutes) { _minutes = DateTime.diffMinutes(fromTimestamp, toTimestamp); } function diffSeconds(uint256 fromTimestamp, uint256 toTimestamp) public pure returns (uint256 _seconds) { _seconds = DateTime.diffSeconds(fromTimestamp, toTimestamp); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // ---------------------------------------------------------------------------- // DateTime Library v2.0 // // A gas-efficient Solidity date and time library // // https://github.com/bokkypoobah/BokkyPooBahsDateTimeLibrary // // Tested date range 1970/01/01 to 2345/12/31 // // Conventions: // Unit | Range | Notes // :-------- |:-------------:|:----- // timestamp | >= 0 | Unix timestamp, number of seconds since 1970/01/01 00:00:00 UTC // year | 1970 ... 2345 | // month | 1 ... 12 | // day | 1 ... 31 | // hour | 0 ... 23 | // minute | 0 ... 59 | // second | 0 ... 59 | // dayOfWeek | 1 ... 7 | 1 = Monday, ..., 7 = Sunday // // // Enjoy. (c) BokkyPooBah / Bok Consulting Pty Ltd 2018-2019. The MIT Licence. // ---------------------------------------------------------------------------- library DateTime { uint256 constant SECONDS_PER_DAY = 24 * 60 * 60; uint256 constant SECONDS_PER_HOUR = 60 * 60; uint256 constant SECONDS_PER_MINUTE = 60; int256 constant OFFSET19700101 = 2440588; uint256 constant DOW_MON = 1; uint256 constant DOW_TUE = 2; uint256 constant DOW_WED = 3; uint256 constant DOW_THU = 4; uint256 constant DOW_FRI = 5; uint256 constant DOW_SAT = 6; uint256 constant DOW_SUN = 7; // ------------------------------------------------------------------------ // Calculate the number of days from 1970/01/01 to year/month/day using // the date conversion algorithm from // http://aa.usno.navy.mil/faq/docs/JD_Formula.php // and subtracting the offset 2440588 so that 1970/01/01 is day 0 // // days = day // - 32075 // + 1461 * (year + 4800 + (month - 14) / 12) / 4 // + 367 * (month - 2 - (month - 14) / 12 * 12) / 12 // - 3 * ((year + 4900 + (month - 14) / 12) / 100) / 4 // - offset // ------------------------------------------------------------------------ function _daysFromDate(uint256 year, uint256 month, uint256 day) internal pure returns (uint256 _days) { require(year >= 1970); int256 _year = int256(year); int256 _month = int256(month); int256 _day = int256(day); int256 __days = _day - 32075 + (1461 * (_year + 4800 + (_month - 14) / 12)) / 4 + (367 * (_month - 2 - ((_month - 14) / 12) * 12)) / 12 - (3 * ((_year + 4900 + (_month - 14) / 12) / 100)) / 4 - OFFSET19700101; _days = uint256(__days); } // ------------------------------------------------------------------------ // Calculate year/month/day from the number of days since 1970/01/01 using // the date conversion algorithm from // http://aa.usno.navy.mil/faq/docs/JD_Formula.php // and adding the offset 2440588 so that 1970/01/01 is day 0 // // int L = days + 68569 + offset // int N = 4 * L / 146097 // L = L - (146097 * N + 3) / 4 // year = 4000 * (L + 1) / 1461001 // L = L - 1461 * year / 4 + 31 // month = 80 * L / 2447 // dd = L - 2447 * month / 80 // L = month / 11 // month = month + 2 - 12 * L // year = 100 * (N - 49) + year + L // ------------------------------------------------------------------------ function _daysToDate(uint256 _days) internal pure returns (uint256 year, uint256 month, uint256 day) { unchecked { int256 __days = int256(_days); int256 L = __days + 68569 + OFFSET19700101; int256 N = (4 * L) / 146097; L = L - (146097 * N + 3) / 4; int256 _year = (4000 * (L + 1)) / 1461001; L = L - (1461 * _year) / 4 + 31; int256 _month = (80 * L) / 2447; int256 _day = L - (2447 * _month) / 80; L = _month / 11; _month = _month + 2 - 12 * L; _year = 100 * (N - 49) + _year + L; year = uint256(_year); month = uint256(_month); day = uint256(_day); } } function timestampFromDate(uint256 year, uint256 month, uint256 day) internal pure returns (uint256 timestamp) { timestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY; } function timestampFromDateTime( uint256 year, uint256 month, uint256 day, uint256 hour, uint256 minute, uint256 second ) internal pure returns (uint256 timestamp) { timestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + hour * SECONDS_PER_HOUR + minute * SECONDS_PER_MINUTE + second; } function timestampToDate(uint256 timestamp) internal pure returns (uint256 year, uint256 month, uint256 day) { unchecked { (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY); } } function timestampToDateTime(uint256 timestamp) internal pure returns (uint256 year, uint256 month, uint256 day, uint256 hour, uint256 minute, uint256 second) { unchecked { (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY); uint256 secs = timestamp % SECONDS_PER_DAY; hour = secs / SECONDS_PER_HOUR; secs = secs % SECONDS_PER_HOUR; minute = secs / SECONDS_PER_MINUTE; second = secs % SECONDS_PER_MINUTE; } } function isValidDate(uint256 year, uint256 month, uint256 day) internal pure returns (bool valid) { if (year >= 1970 && month > 0 && month <= 12) { uint256 daysInMonth = _getDaysInMonth(year, month); if (day > 0 && day <= daysInMonth) { valid = true; } } } function isValidDateTime(uint256 year, uint256 month, uint256 day, uint256 hour, uint256 minute, uint256 second) internal pure returns (bool valid) { if (isValidDate(year, month, day)) { if (hour < 24 && minute < 60 && second < 60) { valid = true; } } } function isLeapYear(uint256 timestamp) internal pure returns (bool leapYear) { (uint256 year,,) = _daysToDate(timestamp / SECONDS_PER_DAY); leapYear = _isLeapYear(year); } function _isLeapYear(uint256 year) internal pure returns (bool leapYear) { leapYear = ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0); } function isWeekDay(uint256 timestamp) internal pure returns (bool weekDay) { weekDay = getDayOfWeek(timestamp) <= DOW_FRI; } function isWeekEnd(uint256 timestamp) internal pure returns (bool weekEnd) { weekEnd = getDayOfWeek(timestamp) >= DOW_SAT; } function getDaysInMonth(uint256 timestamp) internal pure returns (uint256 daysInMonth) { (uint256 year, uint256 month,) = _daysToDate(timestamp / SECONDS_PER_DAY); daysInMonth = _getDaysInMonth(year, month); } function _getDaysInMonth(uint256 year, uint256 month) internal pure returns (uint256 daysInMonth) { if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) { daysInMonth = 31; } else if (month != 2) { daysInMonth = 30; } else { daysInMonth = _isLeapYear(year) ? 29 : 28; } } // 1 = Monday, 7 = Sunday function getDayOfWeek(uint256 timestamp) internal pure returns (uint256 dayOfWeek) { uint256 _days = timestamp / SECONDS_PER_DAY; dayOfWeek = ((_days + 3) % 7) + 1; } function getYear(uint256 timestamp) internal pure returns (uint256 year) { (year,,) = _daysToDate(timestamp / SECONDS_PER_DAY); } function getMonth(uint256 timestamp) internal pure returns (uint256 month) { (, month,) = _daysToDate(timestamp / SECONDS_PER_DAY); } function getDay(uint256 timestamp) internal pure returns (uint256 day) { (,, day) = _daysToDate(timestamp / SECONDS_PER_DAY); } function getHour(uint256 timestamp) internal pure returns (uint256 hour) { uint256 secs = timestamp % SECONDS_PER_DAY; hour = secs / SECONDS_PER_HOUR; } function getMinute(uint256 timestamp) internal pure returns (uint256 minute) { uint256 secs = timestamp % SECONDS_PER_HOUR; minute = secs / SECONDS_PER_MINUTE; } function getSecond(uint256 timestamp) internal pure returns (uint256 second) { second = timestamp % SECONDS_PER_MINUTE; } function addYears(uint256 timestamp, uint256 _years) internal pure returns (uint256 newTimestamp) { (uint256 year, uint256 month, uint256 day) = _daysToDate(timestamp / SECONDS_PER_DAY); year += _years; uint256 daysInMonth = _getDaysInMonth(year, month); if (day > daysInMonth) { day = daysInMonth; } newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + (timestamp % SECONDS_PER_DAY); require(newTimestamp >= timestamp); } function addMonths(uint256 timestamp, uint256 _months) internal pure returns (uint256 newTimestamp) { (uint256 year, uint256 month, uint256 day) = _daysToDate(timestamp / SECONDS_PER_DAY); month += _months; year += (month - 1) / 12; month = ((month - 1) % 12) + 1; uint256 daysInMonth = _getDaysInMonth(year, month); if (day > daysInMonth) { day = daysInMonth; } newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + (timestamp % SECONDS_PER_DAY); require(newTimestamp >= timestamp); } function addDays(uint256 timestamp, uint256 _days) internal pure returns (uint256 newTimestamp) { newTimestamp = timestamp + _days * SECONDS_PER_DAY; require(newTimestamp >= timestamp); } function addHours(uint256 timestamp, uint256 _hours) internal pure returns (uint256 newTimestamp) { newTimestamp = timestamp + _hours * SECONDS_PER_HOUR; require(newTimestamp >= timestamp); } function addMinutes(uint256 timestamp, uint256 _minutes) internal pure returns (uint256 newTimestamp) { newTimestamp = timestamp + _minutes * SECONDS_PER_MINUTE; require(newTimestamp >= timestamp); } function addSeconds(uint256 timestamp, uint256 _seconds) internal pure returns (uint256 newTimestamp) { newTimestamp = timestamp + _seconds; require(newTimestamp >= timestamp); } function subYears(uint256 timestamp, uint256 _years) internal pure returns (uint256 newTimestamp) { (uint256 year, uint256 month, uint256 day) = _daysToDate(timestamp / SECONDS_PER_DAY); year -= _years; uint256 daysInMonth = _getDaysInMonth(year, month); if (day > daysInMonth) { day = daysInMonth; } newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + (timestamp % SECONDS_PER_DAY); require(newTimestamp <= timestamp); } function subMonths(uint256 timestamp, uint256 _months) internal pure returns (uint256 newTimestamp) { (uint256 year, uint256 month, uint256 day) = _daysToDate(timestamp / SECONDS_PER_DAY); uint256 yearMonth = year * 12 + (month - 1) - _months; year = yearMonth / 12; month = (yearMonth % 12) + 1; uint256 daysInMonth = _getDaysInMonth(year, month); if (day > daysInMonth) { day = daysInMonth; } newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + (timestamp % SECONDS_PER_DAY); require(newTimestamp <= timestamp); } function subDays(uint256 timestamp, uint256 _days) internal pure returns (uint256 newTimestamp) { newTimestamp = timestamp - _days * SECONDS_PER_DAY; require(newTimestamp <= timestamp); } function subHours(uint256 timestamp, uint256 _hours) internal pure returns (uint256 newTimestamp) { newTimestamp = timestamp - _hours * SECONDS_PER_HOUR; require(newTimestamp <= timestamp); } function subMinutes(uint256 timestamp, uint256 _minutes) internal pure returns (uint256 newTimestamp) { newTimestamp = timestamp - _minutes * SECONDS_PER_MINUTE; require(newTimestamp <= timestamp); } function subSeconds(uint256 timestamp, uint256 _seconds) internal pure returns (uint256 newTimestamp) { newTimestamp = timestamp - _seconds; require(newTimestamp <= timestamp); } function diffYears(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 _years) { require(fromTimestamp <= toTimestamp); (uint256 fromYear,,) = _daysToDate(fromTimestamp / SECONDS_PER_DAY); (uint256 toYear,,) = _daysToDate(toTimestamp / SECONDS_PER_DAY); _years = toYear - fromYear; } function diffMonths(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 _months) { require(fromTimestamp <= toTimestamp); (uint256 fromYear, uint256 fromMonth,) = _daysToDate(fromTimestamp / SECONDS_PER_DAY); (uint256 toYear, uint256 toMonth,) = _daysToDate(toTimestamp / SECONDS_PER_DAY); _months = toYear * 12 + toMonth - fromYear * 12 - fromMonth; } function diffDays(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 _days) { require(fromTimestamp <= toTimestamp); _days = (toTimestamp - fromTimestamp) / SECONDS_PER_DAY; } function diffHours(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 _hours) { require(fromTimestamp <= toTimestamp); _hours = (toTimestamp - fromTimestamp) / SECONDS_PER_HOUR; } function diffMinutes(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 _minutes) { require(fromTimestamp <= toTimestamp); _minutes = (toTimestamp - fromTimestamp) / SECONDS_PER_MINUTE; } function diffSeconds(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 _seconds) { require(fromTimestamp <= toTimestamp); _seconds = toTimestamp - fromTimestamp; } }
// SPDX-License-Identifier: MIT // ERC721A Contracts v4.2.2 // Creator: Chiru Labs pragma solidity ^0.8.4; /** * @dev Interface of ERC721A. */ interface IERC721A { /** * The caller must own the token or be an approved operator. */ error ApprovalCallerNotOwnerNorApproved(); /** * The token does not exist. */ error ApprovalQueryForNonexistentToken(); /** * The caller cannot approve to their own address. */ error ApproveToCaller(); /** * Cannot query the balance for the zero address. */ error BalanceQueryForZeroAddress(); /** * Cannot mint to the zero address. */ error MintToZeroAddress(); /** * The quantity of tokens minted must be more than zero. */ error MintZeroQuantity(); /** * The token does not exist. */ error OwnerQueryForNonexistentToken(); /** * The caller must own the token or be an approved operator. */ error TransferCallerNotOwnerNorApproved(); /** * The token must be owned by `from`. */ error TransferFromIncorrectOwner(); /** * Cannot safely transfer to a contract that does not implement the * ERC721Receiver interface. */ error TransferToNonERC721ReceiverImplementer(); /** * Cannot transfer to the zero address. */ error TransferToZeroAddress(); /** * The token does not exist. */ error URIQueryForNonexistentToken(); /** * The `quantity` minted with ERC2309 exceeds the safety limit. */ error MintERC2309QuantityExceedsLimit(); /** * The `extraData` cannot be set on an unintialized ownership slot. */ error OwnershipNotInitializedForExtraData(); // ============================================================= // STRUCTS // ============================================================= struct TokenOwnership { // The address of the owner. address addr; // Stores the start time of ownership with minimal overhead for tokenomics. uint64 startTimestamp; // Whether the token has been burned. bool burned; // Arbitrary data similar to `startTimestamp` that can be set via {_extraData}. uint24 extraData; } // ============================================================= // TOKEN COUNTERS // ============================================================= /** * @dev Returns the total number of tokens in existence. * Burned tokens will reduce the count. * To get the total number of tokens minted, please see {_totalMinted}. */ function totalSupply() external view returns (uint256); // ============================================================= // IERC165 // ============================================================= /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified) * to learn more about how these ids are created. * * This function call must use less than 30000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); // ============================================================= // IERC721 // ============================================================= /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables * (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in `owner`'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`, * 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, bytes calldata data ) external; /** * @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} * whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token * by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the * zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} * for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll}. */ function isApprovedForAll(address owner, address operator) external view returns (bool); // ============================================================= // IERC721Metadata // ============================================================= /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); // ============================================================= // IERC2309 // ============================================================= /** * @dev Emitted when tokens in `fromTokenId` to `toTokenId` * (inclusive) is transferred from `from` to `to`, as defined in the * [ERC2309](https://eips.ethereum.org/EIPS/eip-2309) standard. * * See {_mintERC2309} for more details. */ event ConsecutiveTransfer(uint256 indexed fromTokenId, uint256 toTokenId, address indexed from, address indexed to); }
pragma solidity ^0.8.7; // SPDX-License-Identifier: MIT contract TamagogiData { //@@@ props uint[10] internal propOdds = [0,0,0,0,1,1,1,1,2,2]; string[3] internal propTraits = ["food", "toy", "shield"]; string[3] internal propDesc = ["Food will be able to prevent your pet from starvation.","Toys can keep your pet from being bored.","Shield to protect your pet from being hit."]; //@@@ pets uint[3] internal eggs = [1,2,3]; uint[13] internal ear = [0,1,2,3,4,5,6,7,8,9,10,11,12]; uint[5] internal reaction = [0,1,2,3,4]; uint[11] internal head = [0,1,2,3,4,5,6,7,8,9,10]; uint[11] internal body = [0,1,2,3,4,5,6,7,8,9,10]; string[13] internal earTraits = ["Melody","Cinna","Racoon","Long ear","Dog","Teddy","Trapa","Shorthair","Rabbit","Mick","Mouse","Bear","Cat"]; string[5] internal reactionTraits = ["Normal","Angry","Sad","Smile","Upset"]; string[11] internal headTraits = ["Horn","Whiskers","Whiskers fat","Fluffy","Whiskers thin","Square","Hamster","Normal","Cricetinae","Naja","Plump"]; string[11] internal bodyTraits = ["Sit","Dress","Stand","Huddle up","Feeble","Star","Clothes","Strong","Squat","Hulk","Long legs"]; bytes[1] internal masterBytes = [bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af4000000017352474200aece1ce900000066494441545847edd5310e00100c85613d8efb1fc67108092961914a0dbfc540f25e3f0309ce4b9cf30305104000010410f84720c7982525e9fb8b5f7297d104eac11a58cb589638658c107dc13abc0fb2cb98a67cc9af4be8014d996f9e8c02082080000208145bcb2821effa51fe0000000049454e44ae426082')]; bytes[13] internal earBytes = [bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000080494441545847ed94410ac0200c04f5ff8f6ec921250475d7da22c87ad48d1927602d9b57dddcbf30005782ecd5e49c95c1fb51c02ecd196f14f75b3903e8ed3f6f1a01a0623f6773cd69af00f80b91ea21203382b70d284308c0b5cd6a8ef925032c401c4736f609c06fdf053b0201c8800cc8800cc8800cc8800cc8c0b9066edd51182171bab4cb0000000049454e44ae426082'),bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c0864880000008f494441545847ed93d10e80200845f5ff3fba461b8de80a526daeedf6a628f778b4de167f7d717efb05c0662c09b01d23817e4d78c8cc8084d9357e8c004a7b228052234732bd1701a8e2cc4ef5fdc2be5eaf34ad2acf40908d3347c3d0ddeadcccbd8f20a21e476d04f0263483d1fa054026fdef96a97d52bf657cfdd0ca5004a0011aa0011aa0011aa0011aa0811d3de21d21bb35e40a0000000049454e44ae426082'),bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c0864880000006c494441545847edd4d10a4011108461deffa14951d2b2e342a8ff5c9d8bc98e8fc470f98b97e7876f0aa42aa51696f3ca8265b196ebff67a7b795f70a5803572576f3ee1d980d6bc4a382b5a1a5daf3026587cab92bf7c1cc7802c79f090a2080000208208000020820804006486e132187d8c7c60000000049454e44ae426082'),bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000072494441545847ed94510a00210844ebfe876e290844dacd8996085e7fd1a8e353cae9f0c987eba7a881628cce62146dc8404d688bfabb85a8685bdcac9baa51922ada7b0d742aa3fdf544bfc6b544a02fd8dbe8fcfb1603b6e3c8ce48fa68c2dfbe0b0c40000210800004200001084000020fc5ac172190ff741b0000000049454e44ae426082'),bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000075494441545847ed92410ec0200804f5ff8f6ee381a4c12a0b1ebc8ce765990cf676f9f5cbfb5b04f038c0286f71796e57e84bac3c8248cdadca5625a7179bf6650046768029062ceb81cb00eaf2ef1ff88328016497ef206400af4e515f9a89ee79fae9c279003080010c60000318c0000630808117a9bd1321772d676e0000000049454e44ae426082'),bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c0864880000007e494441545847ed92510ac0300843dbfb1f7a459820d22e993f52c8be0a33f1edad73343fb379ff60009e1792998ddf43e550a995f84c3c237174ee0b2097a0a5bbf7109e017095b6001973889c39da438595e52788ad410460a13fff3e2f81d92b002a978fce3006e8b2caa00064400664400664400664400664a0ddc00276971321672fab0a0000000049454e44ae426082'),bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000074494441545847ed94310ec0200cc4e0ff8f2e4202d481e452a062317372674cd59c2e9f7cb93f298067027874c70b9b95771e6beff3ce4a9005e1959be03b0035b4ef47cadff3e365d57bd6c168b8f53dbb1d11801d08992f07dab5562dc87c39f0f77f02000c60000318c000063080010c60a000b8610b216fdcaceb0000000049454e44ae426082'),bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000070494441545847ed92410ac0200c04f5ff8f6e9b4341aa761772082de34590641d27f656bc7af1fded3300c7652a609ffb28d0a999843b0676c1713eae15e0ddbb9db4029001c61f7acd5000919f8190bd0a4006fcde80f1c05c891a412edde806000318c000063080010c600003e5064e048315215641d2fc0000000049454e44ae426082'),bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000068494441545847ed94610b00100c44f9ff3f9a28b5165792d6eaf9a6e1eede965a82570dd62fe90c3443cc9b57b523e81b0243c09eb77b55935d4e63c0271ca914015f7f6e41a8819df84ab406efd44a7577be7133035fbe0c0c40000210800004200001084000021df3d61521c08b49860000000049454e44ae426082'),bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000067494441545847ed93410a00200cc3f4ff8f56100411ba513d8810cfb5ed32ade5f1a98ff3cb1705da46292b6de95db3d945dddbc3337db80265a64c5dfdf08908b886aefebac03a40162e873d7d03eeef9539590137c8d6530002108000042000010840000210e80b6d0b213ce71b1e0000000049454e44ae426082'),bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000068494441545847ed94c10a00101404f9ff8f2607a5478c835cc64dedee5b4372fabcf2e7f9c902844019ae89e89b1c7b4e812d68d4c4fdea095d796e0bc4d3ad0ac4cc6de953813e90e8088d49438309fa188e3cb4c0b3efc20212908004242001094840021290400533b70d21044e4ab70000000049454e44ae426082'),bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000065494441545847edd4dd0a00100c8661bbff8ba61d90ffad24a9d7216bfb3c8984c74b1ecf0fdf04889dd42ab8b7aeb4f30868d3beee64afb98b1560362837a8cfbc75c393238025a06416afd6ec1ee5768627c0d5af82000820800002082080000208209000f7ce15214de4787a0000000049454e44ae426082'),bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c0864880000006d494441545847ed93410ac0200c04f5ff8f5602e6225476410896e979b39d0cb1b7e2af17ffbf3d0130962517569a534ab32838947ce4e419a530ca22276db4e572f6f3d41c807db3d3fd66ef7500f7d1fc03c0dddaca2b376015ba61003080010c60000318c0000630506e6002f73b0f211a4494500000000049454e44ae426082')]; bytes[5] internal reactionBytes = [bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c0864880000005f494441545847edd5bb0a00200846617dff87ae961a44f042e0721a237fe51b5265f8e8707f61000410400081aac03a5f77549379f3364014665745263cf3a63d80b7bb4a0d6d4055c013b977adac56d1cf15ce0008208000020820302eb00182580621fa639d260000000049454e44ae426082'),bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c0864880000005e494441545847ed95390e00200cc3e8ff1fcd3180104294b64317334362792052928f24f717003080010c60c06aa0f6af5b7bf373672d8016769b8a5781a97c847b004e2873e91e100598e56e88284078cd01c000063080010c6020dd4003cbd40721aa0beb880000000049454e44ae426082'),bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000061494441545847ed95410a00200804ebff8f2e3a142115ae045ea6abad4e73b05a924f4d9e5f00c00006308001d540db56b7cdbe6ad78daf028c4663d02df7aa1d215400cf00cf9d05a302d8574cede13ee1e0af6f1c000c60000318c00006d20d745ccf0721d52fc6040000000049454e44ae426082'),bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c0864880000005b494441545847edd5310e0020080441f9ffa3550a3b20014968d69620e714226bf8c8f0fc450004104000818ac0bedfb7d717d5cc5f3f1be00db006453577e56403b4efaedf00fa6a3de57bca8d5d1404400001041040008171810356ee0721ed9f05790000000049454e44ae426082'),bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000063494441545847ed954b0a00200844f3fe87eeb3898848cdc0cd6b6d33d3131a29c94792fd0b012000010840c04ba0f6af5bbb6399990da0899daae266e0321fe2de001603cb4c88c04a6598bd3ce45b80709b7b571036dc05080001084000021080400354df0721739252ba0000000049454e44ae426082')]; bytes[11] internal headBytes = [bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000074494441545847ed94410ec0200cc3e0ff8f66e3c01192954905c99c9bd432526b497e35797f01000318b8c6407befc557582be3945a45938326b30a4016189774d9b102f863f9e09b761d6d40d2efeaef7965a0cfec7c85cc3a005108b9dc3560988e8fb806e21b4412000c60000318c040ba81073af6102143c1dc740000000049454e44ae426082'),bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af4000000017352474200aece1ce900000072494441545847ed943112c0200804cf49feffe214190a6752c1450a2dd65a605d9021e9d2c63300c000063060187824dd8bbbaa8cad165199c0004b73380051a363208dcf0082bc537cca49f31c6d205eb0750666f10e4499a36ac1b78f7f07d10277018cdfb67605000c60000318c000065e01921281db558cba0000000049454e44ae426082'),bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c0864880000006a494441545847ed944b0a00200844ebfe87eeb310dae88404153c5741cc383cc55a2e57bddcbf10000210f882401bb7221b546a95b134d83864a14714e04473cbe77a7901a6c04a515210422f083c4b605d9ef9ceee81cddfd5678dd5e26dff130002108000042000810e4ece1021878663410000000049454e44ae426082'),bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c0864880000005b494441545847ed94db0900200cc474ffa17d2c604a058b10bfbdf408b4bd15bf5e3cbf5940031af8c2c058b7225b14b3044640e0901d195460f36f4a60960a2040031a7861203023ff85b6204f0e262da0010d6840031a283730013af6102192d097b20000000049454e44ae426082'),bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000060494441545847edd6cb0a0020084451fdff8feeb16813e4580411dcd669c31124b7c7c71fbf6f044000812f044adb15a741656da6b16c122c33594b804860f049c6c408963dd4087ae138eaee9c23558bc02eebf5ef030110400001041040a0028cd31421444923dc0000000049454e44ae426082'),bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000049494441545847edd6410a00200804c0fcffa3ab17a40421c17857973988319a2b9af70f010810f84260ee5b711b34edad0c4e871c8e59da2b0001021581a72f8300040810204080c0023af610215e442abd0000000049454e44ae426082'),bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000064494441545847ed94490e00200803f1ff8f763978841a354193e16a6ceb80144bae92ec6f04800004be2050fbaed80d2aef2a6129b0b0c8428da703dc78fd04e46a79046e9a872108100de168c32835a8ea23843aa7e2ca5c9e13000210800004200081063eee1021a0220e8e0000000049454e44ae426082'),bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000061494441545847ed94410e00100c04f5ff8f460f8eac20a926e3cc760cad95e065c1f50b0018c0400a03b5cf8a5350795605cb808d41b6ccf81ae0c5ed87a069d6ca403880d3bf80c8fb07e4fbdd76809f575db051e36e0b0018c000063080010c343af61021f9935c500000000049454e44ae426082'),bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000067494441545847ed954b0a00200805f3fe87eeb368994f2ab0605ae77318c3ac241f4bee5f00c00006be3050fbaed80595b5916019e22c33590b8032201506fe1237c303b8d17cf22db39e0618f4372c6c8f2030def32bea119e7710090060000318c00006d20d343af6102106b4da3d0000000049454e44ae426082'),bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000060494441545847ed96410a00200804f3ff8f2e844e511a68e461bab74ea348d23e1ff95cbf0180010c9436d0e78e88429a39a770bd142dbceeb86d2600650d68ff32e7e098e50d5a068499e101444db80fb80178fa6500000318c00006308081013eee10210f9b3be30000000049454e44ae426082'),bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000072494441545847ed94310e00210804f5ff8ff68ec2c4e2803d43a2c55859c0b219597b3b7cfae1f90d031080804260bc5155eabe129df666c2a980f08f841a91818ae1d39fabe519a81c1e9ac0c0b504ecdd2af7e0f712ae8b63f72cae5e1a6d70d8bf2b2cc45f2bc10004200001084000020fec3f1221ce89b1720000000049454e44ae426082')]; bytes[11] internal bodyBytes = [bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c086488000000b9494441545847ed96c10e80200c4321faff5fec4139cce0dc68410c979178215bf7a81b21a794b6eb5bb672008403e14038100e8403e140384038705c31fbe08b05e6b20f1228640052390c0025e4380473110014207e4d53a30530a3b8f0b95a1ec08ce2b5c6278051189d67ea300e588965afac7a3cbd3d89e90228e2226815d2a22dbb2db0bb77d1140888770a298c00dc8b8c01d010f5e4590008fa31b97f01c0f193001640f70471ffbc9ad4cce901608b76c52d073801df502d81d35c52b50000000049454e44ae426082'),bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c086488000000a4494441545847ed964b0ac0200c05957aff1377515d0444f2796ac1169e20144c759c1831a794aeda8fb54c001aa0011aa0011aa0011a000cdc35a62cbe58c27f9107493f49fb9636426963db00e304b3000dd685f00c788b2319e90d991016c0eee25a9a5488cf0248ee10d5688c5a494815ecc084e5fb2b006d375296d6d86b06ac7ab600c20b480e0e9a0289ef2f22eff0853b5f05404f3c1c376b009e180d3c0ef000b15d1d81d94175870000000049454e44ae426082'),bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c086488000000a6494441545847ed96c10a80201883957aff27ee501e0493e9e6df218405dedcfcfe39c29c523a9ef5db970de0049c801370024ec009ec90c0f5409ec10703d5aaef016a0400258d0220190d12a25a06400d84ab997acc007ae10a8cac1d01208332ac5ac6a2eff7c30114802a8c24d06a96000a7d3f450400f9bc6ac34ad86e8e024c7bfa05a026540f68fb21c34601d001f4be51145b01d04281e2d2ffd44a02d42cb2c10037c7f12981ef4fbe3c0000000049454e44ae426082'),bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c086488000000a0494441545847ed96c10a8020104495faff2fee907b30ac5667b6840e8d10c4e2eaf3b98a39a5b494efb396052003322003322003322003a481adf45b83af162a877990500375e0602e02f006b098b5ab9151bc6b2f0ad00231ff063ab41001e84d58edb340a7dd8a00046bf0e83ecdc03f016011012daf8fa157606dac9ddf3b96f0f24245e81988dc03530dd4d5a2555540efb2baed1863e069f5537902d801343f25816dd4601b0000000049454e44ae426082'),bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c086488000000a2494441545847ed964b0ac030084413dafb9fb88bc642200dea980f94c204bad2eae4f92139a57494efb3932980044880044880044880040204aee2734ebe58e0bfe84102030484b9313c013b92577d66acdf098850d17cb612f04458b6ad02a4ae43b734fc9ffe18e981362912d0dba7086837954072acbda0d9a7c7108ed0ea0e402568e36b48b5fc2d99c8c4b83dd027a8782325f07c5e71d12a0e505e73a1801b9c8b2581c49959130000000049454e44ae426082'),bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c0864880000009e494441545847ed96410ac0200c0495f6ff2feea17a08b4c1646314bcacd05b930c936db19652aef61c3b9500344003344003344003341030f0b477eee48d05d6a20b496fd0cf0a805bef01ac0e17696e1f0b60d77008e10164b55b7119e621020083e404f45b3b05d07bca1a7684d0ec81be0201b1d68120a1bd1500dd7c346c1b80566835d63b87eb8b18d079404dd15a7e998d0224ffc4b88c00c70dbcedba1d81b2a5703a0000000049454e44ae426082'),bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000092494441545847ed96410ac0200c0495f6ff2feea1061a0852bb9b40f1b282d0431227630af6d6da31f6b6d5052003322003322003322003a4816bc49dc9570b95c33e48ac586541680680ea644107731140b5f39967698201f0e42c4ccc2b0358277eb015612162ece71c2003b34a78a70f241c3e2f5c0160fe86df00e295d8f7db7cd0875b81ac01a6fb548c006460bb811b903311813716c23a0000000049454e44ae426082'),bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000089494441545847ed96b10ac0200c4423edff7f7187ea60493378977490c2096e313edf29d8ccece873db68029001199001199001199001c2c0d56bcee28f05ae653e24b0c9020eae4500b0016166d9230bc000c59a7f030cc3e3047ea00b99aa4711c4882b112cafc95780795a6f85817ca0b2003192b9b1d78e227a19a900102f8f2f11800c6c37700360131781b4054f830000000049454e44ae426082'),bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000091494441545847ed96b10e80200c444be4ffbfd8411848c060efda05872371f2da3e5ed050ccec6acfb1550420033220033220033220038481bb656af2c6026bd90b096cb401a46a1800aad1872158fb7b00b803e26cb83d9081a30068f8fc3e925da47906224d23d934c07b8867c0cbd2003dc80e8dc084003c88dd507ae783027d0523d71b6716fc85b30099e1548d001e930027810fe7f6160000000049454e44ae426082'),bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000098494441545847ed964b0ac0200c0523f5fe27eea26621049b98f82952784237d53c27038a8988aef21d1b090030000330000330000330e018b8cb7c5e7cad7433220f921508b7d60370030276a60decd8bcf2995996819d9b77217e033063a4ad5133a2062c00fecf433baa9f03c80d34c02500eeaa76573bec055a736dc6ebd47af7802c90619a766f5ebd3246000277cef812001c37f00086f72381b52e906c0000000049454e44ae426082'),bytes(hex'89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000092494441545847ed96d10ac02008458dedffbf780fab072142f3ea06637083bd44dae9e8a2262247ff3e1b8d0034400334400334400334001ab8faba33f96a816290070994c8810b63770023788cecc957966d1e0f20244f96632c377322004f60e6d87f01a832355ded03adbfdb4bc85fe0d56f4e6e6d0095ae0a60255fe708f0aa01b429c3a65bef0fb4070af70e1642801b8ad723816807111a0000000049454e44ae426082')]; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ApprovalCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"ApprovalQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"BalanceQueryForZeroAddress","type":"error"},{"inputs":[],"name":"MintERC2309QuantityExceedsLimit","type":"error"},{"inputs":[],"name":"MintToZeroAddress","type":"error"},{"inputs":[],"name":"MintZeroQuantity","type":"error"},{"inputs":[],"name":"OwnerQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"OwnershipNotInitializedForExtraData","type":"error"},{"inputs":[],"name":"TransferCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferToNonERC721ReceiverImplementer","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"inputs":[],"name":"URIQueryForNonexistentToken","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"fromTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toTokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"ConsecutiveTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"address","name":"sender","type":"address"}],"name":"EFeed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"address","name":"sender","type":"address"}],"name":"EHit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"address","name":"sender","type":"address"}],"name":"EPlay","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"TMGGs","outputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"lastFeed","type":"uint256"},{"internalType":"uint256","name":"lastPlay","type":"uint256"},{"internalType":"uint256","name":"lastHit","type":"uint256"},{"internalType":"uint256","name":"birthhash","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"addresses","type":"address[]"},{"internalType":"uint256[]","name":"quantity","type":"uint256[]"}],"name":"airdrop","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"airdropProgress","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"airdropReceivers","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"}],"name":"allowlistHatchEgg","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"config","outputs":[{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"propMaxSupply","type":"uint256"},{"internalType":"uint256","name":"petMaxSupply","type":"uint256"},{"internalType":"bool","name":"revealProp","type":"bool"},{"internalType":"bool","name":"revealPet","type":"bool"},{"internalType":"enum Tamagogi.MintStage","name":"mintStage","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"feed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getBirthdate","outputs":[{"internalType":"uint256","name":"month","type":"uint256"},{"internalType":"uint256","name":"day","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getPetHungerAndBored","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getPetUnhappinessAndProp","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bool","name":"","type":"bool"},{"internalType":"bool","name":"","type":"bool"},{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hatchEgg","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"hit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"isBirthdate","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"","type":"string"}],"name":"nameTable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"petMinted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"play","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"propMinted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"reroll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"rerollTable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rootHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"seeds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[3]","name":"_rate","type":"uint256[3]"}],"name":"setBoredRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[3]","name":"_rate","type":"uint256[3]"}],"name":"setHitRasing","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[3]","name":"_rate","type":"uint256[3]"}],"name":"setHitRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[3]","name":"_rate","type":"uint256[3]"}],"name":"setHungerRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_hash","type":"bytes32"}],"name":"setMerkle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stage","type":"uint256"}],"name":"setMintStage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"name","type":"string"}],"name":"setName","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_price","type":"uint256"}],"name":"setPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[5]","name":"_rate","type":"uint256[5]"}],"name":"setReactionRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setRevealPet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setRevealProp","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"tokensOfOwner","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6101c06040526000608081815260a082905260c082905260e09190915260016101008190526101208190526101408190526101605260026101808190526101a0526200004f90600a90816200107c565b506040805160a08101825260046060820190815263199bdbd960e21b6080830152815281518083018352600380825262746f7960e81b602083810191909152808401929092528351808501855260068152651cda1a595b1960d21b9281019290925292820152620000c49160149190620010c4565b506040805160c081019091526036606082018181528291620088716080840139815260200160405180606001604052806028815260200162008b756028913981526020016040518060600160405280602a81526020016200939d602a9139905262000134906017906003620010c4565b5060408051606081018252600181526002602082015260039181018290526200016191601a919062001117565b50604080516101a08101825260008152600160208201526002918101919091526003606082015260046080820152600560a0820152600660c0820152600760e082015260086101008201526009610120820152600a610140820152600b610160820152600c610180820152620001dc90601d90600d6200114c565b506040805160a081018252600081526001602082015260029181019190915260036060820152600460808201526200021990602a90600562001181565b50604080516101608101825260008152600160208201526002918101919091526003606082015260046080820152600560a0820152600660c0820152600760e082015260086101008201526009610120820152600a6101408201526200028490602f90600b620011b6565b50604080516101608101825260008152600160208201526002918101919091526003606082015260046080820152600560a0820152600660c0820152600760e082015260086101008201526009610120820152600a610140820152620002ef90603a90600b620011b6565b50604080516101e08101825260066101a08201818152654d656c6f647960d01b6101c084015282528251808401845260058082526443696e6e6160d81b6020838101919091528085019290925284518086018652838152652930b1b7b7b760d11b81840152848601528451808601865260088152672637b7339032b0b960c11b81840152606085015284518086018652600380825262446f6760e81b8285015260808601919091528551808701875282815264546564647960d81b8185015260a08601528551808701875282815264547261706160d81b8185015260c086015285518087018752600981526829b437b93a3430b4b960b91b8185015260e08601528551808701875293845265149858989a5d60d21b84840152610100850193909352845180860186526004808252634d69636b60e01b8285015261012086019190915285518087018752918252644d6f75736560d81b8284015261014085019190915284518086018652908152632132b0b960e11b8183015261016084015283518085019094529083526210d85d60ea1b908301526101808101919091526200049d90604590600d620011eb565b506040805160e081018252600660a0820190815265139bdc9b585b60d21b60c0830152815281518083018352600580825264416e67727960d81b6020838101919091528084019290925283518085018552600381526214d85960ea1b81840152838501528351808501855281815264536d696c6560d81b818401526060840152835180850190945280845264155c1cd95d60da1b9184019190915260808201929092526200054f916052919062001230565b50604080516101a08101825260046101608201818152632437b93760e11b6101808401528252825180840184526008815267576869736b65727360c01b6020828101919091528084019190915283518085018552600c81526b15da1a5cdad95c9cc819985d60a21b818301528385015283518085018552600680825265466c7566667960d01b82840152606085019190915284518086018652600d81526c2bb434b9b5b2b939903a3434b760991b818401526080850152845180860186528181526553717561726560d01b8184015260a08501528451808601865260078152662430b6b9ba32b960c91b8184015260c08501528451808601865290815265139bdc9b585b60d21b8183015260e084015283518085018552600a815269437269636574696e616560b01b8183015261010084015283518085018552918252634e616a6160e01b82820152610120830191909152825180840190935260058352640506c756d760dc1b90830152610140810191909152620006d390605790600b62001275565b506040518061016001604052806040518060400160405280600381526020016214da5d60ea1b815250815260200160405180604001604052806005815260200164447265737360d81b81525081526020016040518060400160405280600581526020016414dd185b9960da1b8152508152602001604051806040016040528060098152602001680487564646c652075760bc1b815250815260200160405180604001604052806006815260200165466565626c6560d01b81525081526020016040518060400160405280600481526020016329ba30b960e11b815250815260200160405180604001604052806007815260200166436c6f7468657360c81b8152508152602001604051806040016040528060068152602001655374726f6e6760d01b81525081526020016040518060400160405280600581526020016414dc5d585d60da1b81525081526020016040518060400160405280600481526020016348756c6b60e01b8152508152602001604051806040016040528060098152602001684c6f6e67206c65677360b81b815250815250606290600b6200087992919062001275565b5060405180602001604052806040518060e0016040528060ac8152602001620092f160ac91399052620008b190606d906001620012ba565b50604080516102a0810190915260c96101a082018181528291620086076101c0840139815260200160405180610100016040528060d8815260200162008e8c60d8913981526020016040518060e0016040528060b5815260200162009e6260b5913981526020016040518060e0016040528060bb815260200162008aba60bb913981526020016040518060e0016040528060be8152602001620099e260be9139815260200160405180610100016040528060c78152602001620086d060c7913981526020016040518060e0016040528060bd81526020016200969c60bd913981526020016040518060e0016040528060b98152602001620095e360b9913981526020016040518060e0016040528060b1815260200162009aa060b1913981526020016040518060e0016040528060b081526020016200915a60b0913981526020016040518060e0016040528060b1815260200162008a0960b1913981526020016040518060e0016040528060ae815260200162009cd960ae913981526020016040518060e0016040528060b6815260200162009fd460b69139905262000a5c90606e90600d6200130d565b5060408051610180810190915260a860a0820181815282916200900860c084013981526020016040518060e0016040528060a78152602001620088a760a7913981526020016040518060e0016040528060aa81526020016200a17560aa913981526020016040518060e0016040528060a4815260200162008cf960a4913981526020016040518060e0016040528060ac815260200162008c4d60ac9139905262000b0b90607b90600562001352565b5060408051610240810190915260bd6101608201818152829162009f1761018084013981526020016040518060e0016040528060b881526020016200a21f60b8913981526020016040518060e0016040528060b381526020016200984660b3913981526020016040518060e0016040528060a4815260200162008f6460a4913981526020016040518060e0016040528060a981526020016200953a60a9913981526020016040518060c0016040528060928152602001620093c76092913981526020016040518060e0016040528060ad815260200162009b5160ad913981526020016040518060e0016040528060aa8152602001620090b060aa913981526020016040518060e0016040528060b0815260200162008b9d60b0913981526020016040518060e0016040528060a981526020016200848c60a9913981526020016040518060e0016040528060bb81526020016200894e60bb9139905262000c7690608090600b62001397565b50604080516102a08101909152610102610160820181815282916200838a610180840139815260200160405180610120016040528060ed81526020016200975960ed9139815260200160405180610120016040528060ef815260200162008d9d60ef9139815260200160405180610120016040528060e98152602001620098f960e99139815260200160405180610120016040528060eb81526020016200a08a60eb9139815260200160405180610120016040528060e781526020016200920a60e79139815260200160405180610100016040528060db815260200162009bfe60db9139815260200160405180610100016040528060d281526020016200853560d29139815260200160405180610100016040528060da81526020016200879760da9139815260200160405180610120016040528060e181526020016200945960e19139815260200160405180610100016040528060db815260200162009d8760db9139905262000dec90608b90600b62001397565b5060405162000dfb90620013dc565b604051809103906000f08015801562000e18573d6000803e3d6000fd5b50609680546001600160a01b0319166001600160a01b0392909216919091179055600060978190556361cf998160b35560b4819055600160b55560b6556103b360b75534801562000e6857600080fd5b506040518060400160405280600d81526020016c54616d61676f6769205065747360981b8152506040518060400160405280600881526020016754414d41474f474960c01b81525062000eca62000ec46200102860201b60201c565b6200102c565b815162000edf906003906020850190620013ea565b50805162000ef5906004906020840190620013ea565b506001808155600955505060006098556107d0609955610721609a5560ac805462ff00001916905560408051606081018252600881526028602082015260789181019190915262000f4b90609b90600362001117565b506040805160608101825260068152601e6020820152605a9181019190915262000f7a90609e90600362001117565b50604080516060810182526004815260146020820152603c9181019190915262000fa99060a190600362001117565b50604080516060810182526009815260036020820181905260019282019290925262000fd99160a4919062001117565b506040805160a08101825260008152600a6020820152601491810191909152601e606082015260286080820152620010169060a790600562001181565b5060ac805461ffff191690556200153f565b3390565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b82600a8101928215620010b2579160200282015b82811115620010b2578251829060ff1690559160200191906001019062001090565b50620010c092915062001467565b5090565b826003810192821562001109579160200282015b82811115620011095782518051620010f8918491602090910190620013ea565b5091602001919060010190620010d8565b50620010c09291506200147e565b8260038101928215620010b25791602002820182811115620010b2578251829060ff1690559160200191906001019062001090565b82600d8101928215620010b25791602002820182811115620010b2578251829060ff1690559160200191906001019062001090565b8260058101928215620010b25791602002820182811115620010b2578251829060ff1690559160200191906001019062001090565b82600b8101928215620010b25791602002820182811115620010b2578251829060ff1690559160200191906001019062001090565b82600d810192821562001109579160200282015b828111156200110957825180516200121f918491602090910190620013ea565b5091602001919060010190620011ff565b826005810192821562001109579160200282015b8281111562001109578251805162001264918491602090910190620013ea565b509160200191906001019062001244565b82600b810192821562001109579160200282015b82811115620011095782518051620012a9918491602090910190620013ea565b509160200191906001019062001289565b8260018101928215620012ff579160200282015b82811115620012ff5782518051620012ee918491602090910190620013ea565b5091602001919060010190620012ce565b50620010c09291506200149f565b82600d8101928215620012ff579160200282015b82811115620012ff578251805162001341918491602090910190620013ea565b509160200191906001019062001321565b8260058101928215620012ff579160200282015b82811115620012ff578251805162001386918491602090910190620013ea565b509160200191906001019062001366565b82600b8101928215620012ff579160200282015b82811115620012ff5782518051620013cb918491602090910190620013ea565b5091602001919060010190620013ab565b61154e8062006e3c83390190565b828054620013f89062001502565b90600052602060002090601f0160209004810192826200141c5760008555620010b2565b82601f106200143757805160ff1916838001178555620010b2565b82800160010185558215620010b2579182015b82811115620010b25782518255916020019190600101906200144a565b5b80821115620010c0576000815560010162001468565b80821115620010c0576000620014958282620014c0565b506001016200147e565b80821115620010c0576000620014b68282620014c0565b506001016200149f565b508054620014ce9062001502565b6000825580601f10620014df575050565b601f016020900490600052602060002090810190620014ff919062001467565b50565b600181811c908216806200151757607f821691505b602082108114156200153957634e487b7160e01b600052602260045260246000fd5b50919050565b6158ed806200154f6000396000f3fe6080604052600436106102c95760003560e01c806370a0823111610175578063b88d4fde116100dc578063e985e9c511610095578063f0503e801161006f578063f0503e801461094f578063f2fde38b1461097c578063f59dfdfb1461099c578063fe55932a146109bc57600080fd5b8063e985e9c5146108c6578063ebd799cc1461090f578063ebf6e91d1461092f57600080fd5b8063b88d4fde14610800578063c23c863b14610820578063c87b56dd14610850578063ca9c4b3314610870578063d3a2da3814610878578063df33fa31146108b357600080fd5b806391b7f5ed1161012e57806391b7f5ed1461073b57806395d89b411461075b5780639b993a1a14610770578063a22cb465146107a0578063a22d5823146107c0578063b6d22551146107e057600080fd5b806370a082311461063f578063715018a61461065f5780637908213d1461067457806379502c55146106a55780638462151c146106f05780638da5cb5b1461071d57600080fd5b806332063f52116102345780635a353cd3116101ed57806366d38ba9116101c757806366d38ba9146105bf57806367243482146105df5780636840690b146105ff5780636898f82b1461061f57600080fd5b80635a353cd3146105555780635d186c9f1461058a5780636352211e1461059f57600080fd5b806332063f521461049a57806335b34ca2146104b05780633cd434aa146104e057806341b3ba3d146104f557806342842e0e14610515578063439bbfd21461053557600080fd5b80630ea61c47116102865780630ea61c47146103bf57806318160ddd146104075780631c19c2151461042e5780631d80009a1461044e57806323b872dd1461046457806325b1f5ef1461048457600080fd5b806301ffc9a7146102ce57806306fdde0314610303578063081812fc1461032557806308a337331461035d578063095ea7b31461037f57806309a3849a1461039f575b600080fd5b3480156102da57600080fd5b506102ee6102e93660046145ef565b6109dc565b60405190151581526020015b60405180910390f35b34801561030f57600080fd5b50610318610a2e565b6040516102fa9190615615565b34801561033157600080fd5b506103456103403660046145d6565b610ac0565b6040516001600160a01b0390911681526020016102fa565b34801561036957600080fd5b5061037d610378366004614592565b610b04565b005b34801561038b57600080fd5b5061037d61039a3660046144ba565b610b1d565b3480156103ab57600080fd5b5061037d6103ba3660046145b4565b610bbd565b3480156103cb57600080fd5b506103df6103da3660046145d6565b610bd2565b60408051948552921515602085015290151591830191909152151560608201526080016102fa565b34801561041357600080fd5b5060025460015403600019015b6040519081526020016102fa565b34801561043a57600080fd5b5061037d6104493660046145d6565b610fe2565b34801561045a57600080fd5b5061042060975481565b34801561047057600080fd5b5061037d61047f3660046143c6565b611127565b34801561049057600080fd5b5061042060b75481565b3480156104a657600080fd5b5061042060b65481565b3480156104bc57600080fd5b506102ee6104cb366004614378565b60b26020526000908152604090205460ff1681565b3480156104ec57600080fd5b5061037d6112b8565b34801561050157600080fd5b5061037d6105103660046145d6565b6112d1565b34801561052157600080fd5b5061037d6105303660046143c6565b6112de565b34801561054157600080fd5b5061037d610550366004614592565b6112fe565b34801561056157600080fd5b506105756105703660046145d6565b611313565b604080519283526020830191909152016102fa565b34801561059657600080fd5b5061037d611644565b3480156105ab57600080fd5b506103456105ba3660046145d6565b61165b565b3480156105cb57600080fd5b5061037d6105da3660046145d6565b611666565b3480156105eb57600080fd5b5061037d6105fa3660046144e4565b6116a8565b34801561060b57600080fd5b506102ee61061a3660046145d6565b611788565b34801561062b57600080fd5b5061037d61063a3660046145d6565b611b02565b34801561064b57600080fd5b5061042061065a366004614378565b611bbd565b34801561066b57600080fd5b5061037d611c0c565b34801561068057600080fd5b5061069461068f3660046145d6565b611c20565b6040516102fa959493929190615628565b3480156106b157600080fd5b50609854609954609a5460ac546106de9392919060ff808216916101008104821691620100009091041686565b6040516102fa969594939291906156ad565b3480156106fc57600080fd5b5061071061070b366004614378565b611cd6565b6040516102fa91906155dd565b34801561072957600080fd5b506000546001600160a01b0316610345565b34801561074757600080fd5b5061037d6107563660046145d6565b611de6565b34801561076757600080fd5b50610318611df3565b34801561077c57600080fd5b506102ee61078b3660046145d6565b60af6020526000908152604090205460ff1681565b3480156107ac57600080fd5b5061037d6107bb36600461447e565b611e02565b3480156107cc57600080fd5b5061037d6107db366004614592565b611e98565b3480156107ec57600080fd5b506105756107fb3660046145d6565b611ead565b34801561080c57600080fd5b5061037d61081b366004614402565b61212f565b34801561082c57600080fd5b506102ee61083b366004614378565b60b16020526000908152604090205460ff1681565b34801561085c57600080fd5b5061031861086b3660046145d6565b612179565b61037d612184565b34801561088457600080fd5b506102ee610893366004614629565b805160208183018101805160b08252928201919093012091525460ff1681565b61037d6108c1366004614550565b6122e4565b3480156108d257600080fd5b506102ee6108e1366004614393565b6001600160a01b03918216600090815260086020908152604080832093909416825291909152205460ff1690565b34801561091b57600080fd5b5061037d61092a366004614592565b6124fa565b34801561093b57600080fd5b5061037d61094a3660046145d6565b61250f565b34801561095b57600080fd5b5061042061096a3660046145d6565b60ad6020526000908152604090205481565b34801561098857600080fd5b5061037d610997366004614378565b6125c2565b3480156109a857600080fd5b5061037d6109b73660046145d6565b61263b565b3480156109c857600080fd5b5061037d6109d736600461468b565b6126ee565b60006301ffc9a760e01b6001600160e01b031983161480610a0d57506380ac58cd60e01b6001600160e01b03198316145b80610a285750635b5e139f60e01b6001600160e01b03198316145b92915050565b606060038054610a3d9061578f565b80601f0160208091040260200160405190810160405280929190818152602001828054610a699061578f565b8015610ab65780601f10610a8b57610100808354040283529160200191610ab6565b820191906000526020600020905b815481529060010190602001808311610a9957829003601f168201915b5050505050905090565b6000610acb826128f5565b610ae8576040516333d1c03960e21b815260040160405180910390fd5b506000908152600760205260409020546001600160a01b031690565b610b0c61292a565b610b1960a4826003614138565b5050565b6000610b288261165b565b9050336001600160a01b03821614610b6157610b4481336108e1565b610b61576040516367d9dca160e11b815260040160405180910390fd5b60008281526007602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b610bc561292a565b610b1960a7826005614176565b60ac54600090819081908190610100900460ff16610c0b5760405162461bcd60e51b8152600401610c0290615689565b60405180910390fd5b609954859081118015610c2d5750609954609a54610c299190615701565b8111155b610c495760405162461bcd60e51b8152600401610c029061565f565b600086815260ae6020526040808220815160a081019092528054429392919082908290610c759061578f565b80601f0160208091040260200160405190810160405280929190818152602001828054610ca19061578f565b8015610cee5780601f10610cc357610100808354040283529160200191610cee565b820191906000526020600020905b815481529060010190602001808311610cd157829003601f168201915b5050505050815260200160018201548152602001600282015481526020016003820154815260200160048201548152505090506000609660009054906101000a90046001600160a01b03166001600160a01b0316632af123b88360200151856040518363ffffffff1660e01b8152600401610d73929190918252602082015260400190565b60206040518083038186803b158015610d8b57600080fd5b505afa158015610d9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc39190614672565b609654604080850151905163055e247760e31b81529293506000926001600160a01b0390921691632af123b891610e07918890600401918252602082015260400190565b60206040518083038186803b158015610e1f57600080fd5b505afa158015610e33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e579190614672565b905060008360600151600014610e8857603c846060015186610e79919061574c565b610e839190615719565b610e8b565b60005b9050600060a18101548211610eb25760a460005b0154610eab908361572d565b9050610ee6565b60a254821015610ec55760a46001610e9f565b60a354821015610ed85760a46002610e9f565b610ee382600061572d565b90505b6000610ef461070b8e61165b565b90506000806000805b8451811015610fb0576000858281518110610f1a57610f1a615835565b602002602001015190506098600101548111610f9d57600081815260ad602052604081205490600a610f4c81846157df565b600a8110610f5c57610f5c615835565b0154905080610f725760009b5060019650610f9a565b8060011415610f885760009a5060019550610f9a565b8060021415610f9a5760009850600194505b50505b5080610fa8816157c4565b915050610efd565b50600085610fbe898b615701565b610fc89190615701565b9f50929d50909b5099505050505050505050509193509193565b8033610fed8261165b565b6001600160a01b03161461103f5760405162461bcd60e51b81526020600482015260196024820152782cb7ba9030b932903737ba103a37b5b2b713b99037bbb732b960391b6044820152606401610c02565b60ac54610100900460ff166110665760405162461bcd60e51b8152600401610c0290615689565b6099548290811180156110885750609954609a546110849190615701565b8111155b6110a45760405162461bcd60e51b8152600401610c029061565f565b600083815260af602052604090205460ff16156110f35760405162461bcd60e51b815260206004820152600d60248201526c4e6f7420617661696c61626c6560981b6044820152606401610c02565b6110fc83612984565b600093845260ad602090815260408086209290925560af9052909220805460ff191660011790555050565b6000611132826129dd565b9050836001600160a01b0316816001600160a01b0316146111655760405162a1148160e81b815260040160405180910390fd5b60008281526007602052604090208054338082146001600160a01b038816909114176111b25761119586336108e1565b6111b257604051632ce44b5f60e11b815260040160405180910390fd5b6001600160a01b0385166111d957604051633a954ecd60e21b815260040160405180910390fd5b80156111e457600082555b6001600160a01b038681166000908152600660205260408082208054600019019055918716808252919020805460010190554260a01b17600160e11b17600085815260056020526040902055600160e11b831661126f576001840160008181526005602052604090205461126d57600154811461126d5760008181526005602052604090208490555b505b83856001600160a01b0316876001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050505050565b6112c061292a565b60ac805461ff001916610100179055565b6112d961292a565b609755565b6112f98383836040518060200160405280600081525061212f565b505050565b61130661292a565b610b19609e826003614138565b60ac546000908190610100900460ff1661133f5760405162461bcd60e51b8152600401610c0290615689565b6099548390811180156113615750609954609a5461135d9190615701565b8111155b61137d5760405162461bcd60e51b8152600401610c029061565f565b600084815260ae6020526040808220815160a0810190925280544293929190829082906113a99061578f565b80601f01602080910402602001604051908101604052809291908181526020018280546113d59061578f565b80156114225780601f106113f757610100808354040283529160200191611422565b820191906000526020600020905b81548152906001019060200180831161140557829003601f168201915b5050505050815260200160018201548152602001600282015481526020016003820154815260200160048201548152505090506000609660009054906101000a90046001600160a01b03166001600160a01b0316632af123b88360200151856040518363ffffffff1660e01b81526004016114a7929190918252602082015260400190565b60206040518083038186803b1580156114bf57600080fd5b505afa1580156114d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114f79190614672565b609654604080850151905163055e247760e31b81529293506000926001600160a01b0390921691632af123b89161153b918890600401918252602082015260400190565b60206040518083038186803b15801561155357600080fd5b505afa158015611567573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061158b9190614672565b9050600061159b61070b8a61165b565b905060005b81518110156116355760008282815181106115bd576115bd615835565b60200260200101519050609860010154811161162257600081815260ad602052604081205490600a6115ef81846157df565b600a81106115ff576115ff615835565b0154905080611611576000965061161f565b806001141561161f57600095505b50505b508061162d816157c4565b9150506115a0565b50919650945050505050915091565b61164c61292a565b60ac805460ff19166001179055565b6000610a28826129dd565b61166e61292a565b8060038111156116805761168061581f565b60ac805462ff00001916620100008360038111156116a0576116a061581f565b021790555050565b6116b061292a565b60b75460b6546116c1908590615701565b11156117025760405162461bcd60e51b815260206004820152601060248201526f115e18d95959081d1a19481b1a5b5a5d60821b6044820152606401610c02565b60005b838110156117675761175585858381811061172257611722615835565b90506020020160208101906117379190614378565b84848481811061174957611749615835565b90506020020135612a4d565b8061175f816157c4565b915050611705565b508383905060b6600082825461177d9190615701565b909155505050505050565b600081609860010154811180156117ae5750609954609a546117aa9190615701565b8111155b6117ca5760405162461bcd60e51b8152600401610c029061565f565b600083815260ae6020526040808220815160a081019092528054829082906117f19061578f565b80601f016020809104026020016040519081016040528092919081815260200182805461181d9061578f565b801561186a5780601f1061183f5761010080835404028352916020019161186a565b820191906000526020600020905b81548152906001019060200180831161184d57829003601f168201915b5050505050815260200160018201548152602001600282015481526020016003820154815260200160048201548152505090506000429050600060ad600087815260200190815260200160002054905060006301e13380826118cc91906157df565b60965460808601519192506001600160a01b0316906365c72840906118f2908490615701565b6040518263ffffffff1660e01b815260040161191091815260200190565b60206040518083038186803b15801561192857600080fd5b505afa15801561193c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119609190614672565b6096546040516301971ca160e61b8152600481018690526001600160a01b03909116906365c728409060240160206040518083038186803b1580156119a457600080fd5b505afa1580156119b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119dc9190614672565b148015611af5575060965460808501516001600160a01b039091169063a324ad2490611a09908490615701565b6040518263ffffffff1660e01b8152600401611a2791815260200190565b60206040518083038186803b158015611a3f57600080fd5b505afa158015611a53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a779190614672565b6096546040516328c92b4960e21b8152600481018690526001600160a01b039091169063a324ad249060240160206040518083038186803b158015611abb57600080fd5b505afa158015611acf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611af39190614672565b145b9550505050505b50919050565b60ac54610100900460ff16611b295760405162461bcd60e51b8152600401610c0290615689565b609954819081118015611b4b5750609954609a54611b479190615701565b8111155b611b675760405162461bcd60e51b8152600401610c029061565f565b600082815260ae602090815260409182902042600290910155815184815233918101919091527fd0017656a8c92d10b2fa3a77fa3c1e8e4c28817e89311616b8eed8e68f68a95091015b60405180910390a15050565b60006001600160a01b038216611be6576040516323d3ad8160e21b815260040160405180910390fd5b506001600160a01b031660009081526006602052604090205467ffffffffffffffff1690565b611c1461292a565b611c1e6000612aac565b565b60ae60205260009081526040902080548190611c3b9061578f565b80601f0160208091040260200160405190810160405280929190818152602001828054611c679061578f565b8015611cb45780601f10611c8957610100808354040283529160200191611cb4565b820191906000526020600020905b815481529060010190602001808311611c9757829003601f168201915b5050505050908060010154908060020154908060030154908060040154905085565b60606000806000611ce685611bbd565b905060008167ffffffffffffffff811115611d0357611d0361584b565b604051908082528060200260200182016040528015611d2c578160200160208202803683370190505b509050611d5960408051608081018252600080825260208201819052918101829052606081019190915290565b60015b838614611dda57611d6c81612afc565b9150816040015115611d7d57611dd2565b81516001600160a01b031615611d9257815194505b876001600160a01b0316856001600160a01b03161415611dd25780838780600101985081518110611dc557611dc5615835565b6020026020010181815250505b600101611d5c565b50909695505050505050565b611dee61292a565b609855565b606060048054610a3d9061578f565b6001600160a01b038216331415611e2c5760405163b06307db60e01b815260040160405180910390fd5b3360008181526008602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b611ea061292a565b610b19609b826003614138565b6000808260986001015481118015611ed45750609954609a54611ed09190615701565b8111155b611ef05760405162461bcd60e51b8152600401610c029061565f565b600084815260ae6020526040808220815160a08101909252805482908290611f179061578f565b80601f0160208091040260200160405190810160405280929190818152602001828054611f439061578f565b8015611f905780601f10611f6557610100808354040283529160200191611f90565b820191906000526020600020905b815481529060010190602001808311611f7357829003601f168201915b505050505081526020016001820154815260200160028201548152602001600382015481526020016004820154815250509050600060ad600087815260200190815260200160002054905060006301e1338082611fed91906157df565b60965460808501519192506000916001600160a01b039091169063a324ad2490612018908590615701565b6040518263ffffffff1660e01b815260040161203691815260200190565b60206040518083038186803b15801561204e57600080fd5b505afa158015612062573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120869190614672565b60965460808601519192506000916001600160a01b03909116906365c72840906120b1908690615701565b6040518263ffffffff1660e01b81526004016120cf91815260200190565b60206040518083038186803b1580156120e757600080fd5b505afa1580156120fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061211f9190614672565b9197509095505050505050915091565b61213a848484611127565b6001600160a01b0383163b156121735761215684848484612b7b565b612173576040516368d2bf6b60e11b815260040160405180910390fd5b50505050565b6060610a2882612c73565b600360ac5462010000900460ff1660038111156121a3576121a361581f565b146121f05760405162461bcd60e51b815260206004820152601960248201527f4e6f7420696e20737461676520746f206d696e7420544d4747000000000000006044820152606401610c02565b609954609a546122009190615701565b60015460001901106122425760405162461bcd60e51b815260206004820152600b60248201526a139bc81c195d081b19599d60aa1b6044820152606401610c02565b33600090815260b2602052604090205460ff161561228d5760405162461bcd60e51b81526020600482015260086024820152674d617820746f203160c01b6044820152606401610c02565b609854349061229d90600161572d565b11156122dc5760405162461bcd60e51b815260206004820152600e60248201526d27379032b737bab3b41032ba341760911b6044820152606401610c02565b611c1e612d42565b600260ac5462010000900460ff1660038111156123035761230361581f565b146123505760405162461bcd60e51b815260206004820181905260248201527f4e6f7420696e20737461676520746f206d696e74206d65726b6c6520544d47476044820152606401610c02565b609954609a546123609190615701565b60015460001901106123a25760405162461bcd60e51b815260206004820152600b60248201526a139bc81c195d081b19599d60aa1b6044820152606401610c02565b33600090815260b2602052604090205460ff16156123ed5760405162461bcd60e51b81526020600482015260086024820152674d617820746f203160c01b6044820152606401610c02565b60985434906123fd90600161572d565b111561243c5760405162461bcd60e51b815260206004820152600e60248201526d27379032b737bab3b41032ba341760911b6044820152606401610c02565b6040516bffffffffffffffffffffffff193360601b1660208201526000906034016040516020818303038152906040528051906020012090506124b6838380806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250506097549150849050612ed4565b6124f25760405162461bcd60e51b815260206004820152600d60248201526c34b73b30b634b210383937b7b360991b6044820152606401610c02565b6112f9612d42565b61250261292a565b610b1960a1826003614138565b60ac54610100900460ff166125365760405162461bcd60e51b8152600401610c0290615689565b6099548190811180156125585750609954609a546125549190615701565b8111155b6125745760405162461bcd60e51b8152600401610c029061565f565b600082815260ae602090815260409182902042600390910155815184815233918101919091527fbae6551c0ddf25aa6805100ecbdc4535f2933a14d7ebafe9fab66af752e232ec9101611bb1565b6125ca61292a565b6001600160a01b03811661262f5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610c02565b61263881612aac565b50565b60ac54610100900460ff166126625760405162461bcd60e51b8152600401610c0290615689565b6099548190811180156126845750609954609a546126809190615701565b8111155b6126a05760405162461bcd60e51b8152600401610c029061565f565b600082815260ae602090815260409182902042600190910155815184815233918101919091527fd73f65a9b0fee6c2e3e08fd03cb4800137b36882554a7211fe8ce842b3d4f4fe9101611bb1565b82336126f98261165b565b6001600160a01b03161461274b5760405162461bcd60e51b81526020600482015260196024820152782cb7ba9030b932903737ba103a37b5b2b713b99037bbb732b960391b6044820152606401610c02565b60ac54610100900460ff166127725760405162461bcd60e51b8152600401610c0290615689565b6099548490811180156127945750609954609a546127909190615701565b8111155b6127b05760405162461bcd60e51b8152600401610c029061565f565b60b084846040516127c292919061485d565b9081526040519081900360200190205460ff161561280f5760405162461bcd60e51b815260206004820152600a60248201526913985b5948195e1a5cdd60b21b6044820152606401610c02565b600061285085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612eea92505050565b90506001811180156128625750601281105b61289f5760405162461bcd60e51b815260206004820152600e60248201526d4e6f742076616c6964206e616d6560901b6044820152606401610c02565b600086815260ae602052604090206128b89086866141a3565b50600160b086866040516128cd92919061485d565b908152604051908190036020019020805491151560ff19909216919091179055505050505050565b600081600111158015612909575060015482105b8015610a28575050600090815260056020526040902054600160e01b161590565b6000546001600160a01b03163314611c1e5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610c02565b60008061299260014361574c565b6040805191406020830152810184905233606090811b6bffffffffffffffffffffffff19169082015260740160408051601f1981840301815291905280516020909101209392505050565b60008180600111612a3457600154811015612a3457600081815260056020526040902054600160e01b8116612a32575b80612a2b575060001901600081815260056020526040902054612a0d565b9392505050565b505b604051636f96cda160e11b815260040160405180910390fd5b60005b81811015612aa1576000612a6560b554612984565b60b58054600090815260ad602052604081208390558154929350612a88836157c4565b9190505550508080612a99906157c4565b915050612a50565b50610b198282613027565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b604080516080810182526000808252602082018190529181018290526060810191909152600082815260056020526040902054610a2890604080516080810182526001600160a01b038316815260a083901c67ffffffffffffffff166020820152600160e01b831615159181019190915260e89190911c606082015290565b604051630a85bd0160e11b81526000906001600160a01b0385169063150b7a0290612bb09033908990889088906004016155aa565b602060405180830381600087803b158015612bca57600080fd5b505af1925050508015612bfa575060408051601f3d908101601f19168201909252612bf79181019061460c565b60015b612c55573d808015612c28576040519150601f19603f3d011682016040523d82523d6000602084013e612c2d565b606091505b508051612c4d576040516368d2bf6b60e11b815260040160405180910390fd5b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490505b949350505050565b60608160018110158015612c8d5750600154600019018111155b612cc85760405162461bcd60e51b815260206004820152600c60248201526b139bdd081d985b1a59081a5960a21b6044820152606401610c02565b609954600090841115612cfb5760ac54610100900460ff16612cf257612ced84613041565b612d17565b612ced846130ee565b60ac5460ff16612d0e57612ced84613265565b612d1784613285565b905080604051602001612d2a9190615409565b60405160208183030381529060405292505050919050565b6000612d516001546000190190565b612d5c906001615701565b905060b45460051415612df957600060b45560965460b354604051631c85d48f60e21b81526004810191909152600160248201526001600160a01b0390911690637217523c9060440160206040518083038186803b158015612dbd57600080fd5b505afa158015612dd1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612df59190614672565b60b3555b6040805160c081018252600060a082018181528252426020808401829052838501919091526060830182905260b354608084015284825260ae81529290208151805192938493612e4c9284920190614216565b5060208201516001820155604082015160028201556060820151600382015560809091015160049091015560b48054906000612e87836157c4565b91905055506000612e9783612984565b600084815260ad602052604090208190559050612eb5336001613027565b505033600090815260b260205260409020805460ff1916600117905550565b600082612ee1858461342a565b14949350505050565b600080825b8051821015613020576007818381518110612f0c57612f0c615835565b01602001516001600160f81b031990811690911c16612f3757612f30600183615701565b915061300e565b8051600360f91b90600590839085908110612f5457612f54615835565b01602001516001600160f81b031990811690911c161415612f7a57612f30600283615701565b8051600760f91b90600490839085908110612f9757612f97615835565b01602001516001600160f81b031990811690911c161415612fbd57612f30600383615701565b8051600f60f91b90600390839085908110612fda57612fda615835565b01602001516001600160f81b031990811690911c16141561300057612f30600483615701565b61300b600183615701565b91505b82613018816157c4565b935050612eef565b5050919050565b610b19828260405180602001604052806000815250613477565b606060008061304f84611ead565b600086815260ad60205260408120549294509092506130e4613070876134e4565b613079866134e4565b613082866134e4565b61308b886134e4565b613094886134e4565b6130bb601a6130a460038b6157df565b600381106130b4576130b4615835565b01546134e4565b6040516020016130d096959493929190615104565b6040516020818303038152906040526135e2565b9695505050505050565b60606000806000806130ff86610bd2565b935093509350935060008061311388611313565b91509150600061312289611788565b905060008680156131305750855b80156131395750845b806131415750815b61314c57600061314f565b60015b9050600061315c89613748565b905060006040518060e001604052808d815260200160ad60008f81526020019081526020016000205481526020018781526020018681526020018b8152602001841515815260200160af60008f815260200190815260200160002060009054906101000a900460ff161515815250905060006131ec60ad60008f81526020019081526020016000205484866137a8565b905060006131f983613b8a565b61320284613d1c565b61320b85613d62565b61321486613e5c565b61322561322087613e95565b6135e2565b6040516020016132399594939291906148f3565b6040516020818303038152906040529050613253816135e2565b9e9d5050505050505050505050505050565b60606000612a2b613275846134e4565b6040516020016130d09190614fd2565b600081815260ad6020526040812054606091600a6132a381846157df565b600a81106132b3576132b3615835565b015490506000601782600381106132cc576132cc615835565b0180546132d89061578f565b80601f01602080910402602001604051908101604052809291908181526020018280546133049061578f565b80156133515780601f1061332657610100808354040283529160200191613351565b820191906000526020600020905b81548152906001019060200180831161333457829003601f168201915b5050505050905060006014836003811061336d5761336d615835565b0180546133799061578f565b80601f01602080910402602001604051908101604052809291908181526020018280546133a59061578f565b80156133f25780601f106133c7576101008083540402835291602001916133f2565b820191906000526020600020905b8154815290600101906020018083116133d557829003601f168201915b50505050509050600061341f613407886134e4565b838585866040516020016130d0959493929190614e29565b979650505050505050565b600081815b845181101561346f5761345b8286838151811061344e5761344e615835565b6020026020010151613ebe565b915080613467816157c4565b91505061342f565b509392505050565b6134818383613eea565b6001600160a01b0383163b156112f9576001548281035b6134ab6000868380600101945086612b7b565b6134c8576040516368d2bf6b60e11b815260040160405180910390fd5b8181106134985781600154146134dd57600080fd5b5050505050565b6060816135085750506040805180820190915260018152600360fc1b602082015290565b8160005b8115613532578061351c816157c4565b915061352b9050600a83615719565b915061350c565b60008167ffffffffffffffff81111561354d5761354d61584b565b6040519080825280601f01601f191660200182016040528015613577576020820181803683370190505b5090505b8415612c6b5761358c60018361574c565b9150613599600a866157df565b6135a4906030615701565b60f81b8183815181106135b9576135b9615835565b60200101906001600160f81b031916908160001a9053506135db600a86615719565b945061357b565b606081516000141561360257505060408051602081019091526000815290565b600060405180606001604052806040815260200161587860409139905060006003845160026136319190615701565b61363b9190615719565b61364690600461572d565b90506000613655826020615701565b67ffffffffffffffff81111561366d5761366d61584b565b6040519080825280601f01601f191660200182016040528015613697576020820181803683370190505b509050818152600183018586518101602084015b81831015613703576003830192508251603f8160121c168501518253600182019150603f81600c1c168501518253600182019150603f8160061c168501518253600182019150603f81168501518253506001016136ab565b60038951066001811461371d576002811461372e5761373a565b613d3d60f01b60011983015261373a565b603d60f81b6000198301525b509398975050505050505050565b60a754600090821161376157602a60035b015492915050565b60a85482101561377457602a6000613759565b60a95482101561378757602a6001613759565b60aa5482101561379a57602a6002613759565b602a6004613759565b919050565b60606000608b600b6137bb600488615719565b6137c591906157df565b600b81106137d5576137d5615835565b0180546137e19061578f565b80601f016020809104026020016040519081016040528092919081815260200182805461380d9061578f565b801561385a5780601f1061382f5761010080835404028352916020019161385a565b820191906000526020600020905b81548152906001019060200180831161383d57829003601f168201915b5050505050905060006080600b6003886138749190615719565b61387e91906157df565b600b811061388e5761388e615835565b01805461389a9061578f565b80601f01602080910402602001604051908101604052809291908181526020018280546138c69061578f565b80156139135780601f106138e857610100808354040283529160200191613913565b820191906000526020600020905b8154815290600101906020018083116138f657829003601f168201915b505050505090506000606e600d60028961392d9190615719565b61393791906157df565b600d811061394757613947615835565b0180546139539061578f565b80601f016020809104026020016040519081016040528092919081815260200182805461397f9061578f565b80156139cc5780601f106139a1576101008083540402835291602001916139cc565b820191906000526020600020905b8154815290600101906020018083116139af57829003601f168201915b505050505090506000607b87600581106139e8576139e8615835565b0180546139f49061578f565b80601f0160208091040260200160405190810160405280929190818152602001828054613a209061578f565b8015613a6d5780601f10613a4257610100808354040283529160200191613a6d565b820191906000526020600020905b815481529060010190602001808311613a5057829003601f168201915b505050505090506000613a7f85613fe1565b613a8885613fe1565b613a9184613fe1565b613a9a86613fe1565b604051602001613aad949392919061489c565b60405160208183030381529060405290508615613b7e5780613b5b606d6000018054613ad89061578f565b80601f0160208091040260200160405190810160405280929190818152602001828054613b049061578f565b8015613b515780601f10613b2657610100808354040283529160200191613b51565b820191906000526020600020905b815481529060010190602001808311613b3457829003601f168201915b5050505050613fe1565b604051602001613b6c92919061486d565b60405160208183030381529060405290505b98975050505050505050565b6060600080613b9c8460000151611ead565b91509150600060ae6000866000015181526020019081526020016000206040518060a0016040529081600082018054613bd49061578f565b80601f0160208091040260200160405190810160405280929190818152602001828054613c009061578f565b8015613c4d5780601f10613c2257610100808354040283529160200191613c4d565b820191906000526020600020905b815481529060010190602001808311613c3057829003601f168201915b50505050508152602001600182015481526020016002820154815260200160038201548152602001600482015481525050905060006001613c918360000151612eea565b11613cab5760405180602001604052806000815250613ccd565b8151604051613cbd9190602001614aac565b6040516020818303038152906040525b905080613cdd87600001516134e4565b613ce6866134e4565b613cef866134e4565b604051602001613d0294939291906152bd565b604051602081830303815290604052945050505050919050565b60606000613d2d83604001516134e4565b613d3a84606001516134e4565b604051602001613d4b929190614ba7565b60408051601f198184030181529190529392505050565b606060008260a00151613d8f57604051806040016040528060028152602001616e6f60f01b815250613dac565b6040518060400160405280600381526020016279657360e81b8152505b905060008360c00151613dd957604051806040016040528060028152602001616e6f60f01b815250613df6565b6040518060400160405280600381526020016279657360e81b8152505b905060008282613e0987608001516134e4565b613e1288613ffc565b613e1b89614030565b613e248a614088565b613e2d8b6140e0565b604051602001613e439796959493929190614cd7565b60408051601f1981840301815291905295945050505050565b6060600080613e6e8460000151611ead565b91509150613e7b826134e4565b613e84826134e4565b604051602001612d2a929190615379565b606081604051602001613ea8919061544e565b6040516020818303038152906040529050919050565b6000818310613eda576000828152602084905260409020612a2b565b5060009182526020526040902090565b60015481613f0b5760405163b562e8dd60e01b815260040160405180910390fd5b6001600160a01b03831660008181526006602090815260408083208054680100000000000000018802019055848352600590915281206001851460e11b4260a01b178317905582840190839083907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8180a4600183015b818114613fba57808360007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a4600101613f82565b5081613fd857604051622e076360e81b815260040160405180910390fd5b60015550505050565b6060613fec826135e2565b604051602001613ea89190614ad3565b60606000605261400f8460800151613748565b6005811061401f5761401f615835565b01604051602001613d4b919061527c565b606060006045601d600d6002866020015161404b9190615719565b61405591906157df565b600d811061406557614065615835565b0154600d811061407757614077615835565b01604051602001613d4b9190614c88565b606060006057602f600b600386602001516140a39190615719565b6140ad91906157df565b600b81106140bd576140bd615835565b0154600b81106140cf576140cf615835565b01604051602001613d4b919061556d565b606060006062603a600b600486602001516140fb9190615719565b61410591906157df565b600b811061411557614115615835565b0154600b811061412757614127615835565b01604051602001613d4b91906153cc565b8260038101928215614166579160200282015b8281111561416657823582559160200191906001019061414b565b5061417292915061428a565b5090565b8260058101928215614166579160200282018281111561416657823582559160200191906001019061414b565b8280546141af9061578f565b90600052602060002090601f0160209004810192826141d15760008555614166565b82601f106141ea5782800160ff19823516178555614166565b82800160010185558215614166579182018281111561416657823582559160200191906001019061414b565b8280546142229061578f565b90600052602060002090601f0160209004810192826142445760008555614166565b82601f1061425d57805160ff1916838001178555614166565b82800160010185558215614166579182015b8281111561416657825182559160200191906001019061426f565b5b80821115614172576000815560010161428b565b600067ffffffffffffffff808411156142ba576142ba61584b565b604051601f8501601f19908116603f011681019082821181831017156142e2576142e261584b565b816040528093508581528686860111156142fb57600080fd5b858560208301376000602087830101525050509392505050565b80356001600160a01b03811681146137a357600080fd5b60008083601f84011261433e57600080fd5b50813567ffffffffffffffff81111561435657600080fd5b6020830191508360208260051b850101111561437157600080fd5b9250929050565b60006020828403121561438a57600080fd5b612a2b82614315565b600080604083850312156143a657600080fd5b6143af83614315565b91506143bd60208401614315565b90509250929050565b6000806000606084860312156143db57600080fd5b6143e484614315565b92506143f260208501614315565b9150604084013590509250925092565b6000806000806080858703121561441857600080fd5b61442185614315565b935061442f60208601614315565b925060408501359150606085013567ffffffffffffffff81111561445257600080fd5b8501601f8101871361446357600080fd5b6144728782356020840161429f565b91505092959194509250565b6000806040838503121561449157600080fd5b61449a83614315565b9150602083013580151581146144af57600080fd5b809150509250929050565b600080604083850312156144cd57600080fd5b6144d683614315565b946020939093013593505050565b600080600080604085870312156144fa57600080fd5b843567ffffffffffffffff8082111561451257600080fd5b61451e8883890161432c565b9096509450602087013591508082111561453757600080fd5b506145448782880161432c565b95989497509550505050565b6000806020838503121561456357600080fd5b823567ffffffffffffffff81111561457a57600080fd5b6145868582860161432c565b90969095509350505050565b6000606082840312156145a457600080fd5b82606083011115611afc57600080fd5b600060a082840312156145c657600080fd5b8260a083011115611afc57600080fd5b6000602082840312156145e857600080fd5b5035919050565b60006020828403121561460157600080fd5b8135612a2b81615861565b60006020828403121561461e57600080fd5b8151612a2b81615861565b60006020828403121561463b57600080fd5b813567ffffffffffffffff81111561465257600080fd5b8201601f8101841361466357600080fd5b612c6b8482356020840161429f565b60006020828403121561468457600080fd5b5051919050565b6000806000604084860312156146a057600080fd5b83359250602084013567ffffffffffffffff808211156146bf57600080fd5b818601915086601f8301126146d357600080fd5b8135818111156146e257600080fd5b8760208285010111156146f457600080fd5b6020830194508093505050509250925092565b6000815180845261471f816020860160208601615763565b601f01601f19169290920160200192915050565b60008151614745818560208601615763565b9290920192915050565b8054600090600181811c908083168061476957607f831692505b602080841082141561478b57634e487b7160e01b600052602260045260246000fd5b81801561479f57600181146147b0576147dd565b60ff198616895284890196506147dd565b60008881526020902060005b868110156147d55781548b8201529085019083016147bc565b505084890196505b50505050505092915050565b7f7b202274726169745f74797065223a202274797065222c202276616c7565223a81526808089c195d1cc89f4b60ba1b602082015260290190565b7f7b202274726169745f74797065223a2022626972746864617465222c20227661815266363ab2911d101160c91b602082015260270190565b8183823760009101908152919050565b6000835161487f818460208801615763565b835190830190614893818360208801615763565b01949350505050565b600085516148ae818460208a01615763565b8551908301906148c2818360208a01615763565b85519101906148d5818360208901615763565b84519101906148e8818360208801615763565b019695505050505050565b60008651614905818460208b01615763565b80830190507f226465736372697074696f6e223a202254616d61676f6769206973206120546181527f6d61676f74636869204461707020616e642066756c6c792067656e657261746560208201527f64206f6e2d636861696e2e2054686520636f6e747261637420696e746572616360408201527f74696f6e20616e642074696d652077696c6c206166666563742074686520737460608201527f6174757320616e64207265616374696f6e206f6620746865207065742e20496660808201527f20796f7520636f6c6c656374206f74686572206974656d732c2074686520706560a0820152721d081dda5b1b081cda1bddc81b1bdd9948488b606a1b60c08201526e2261747472696275746573223a205b60881b60d38201528651614a328160e2840160208b01615763565b614a9f614a91614a8b614a53614a4d60e2868801018c614733565b8a614733565b7f5d2c22696d616765223a2022646174613a696d6167652f7376672b786d6c3b62815265185cd94d8d0b60d21b602082015260260190565b87614733565b61227d60f01b815260020190565b9998505050505050505050565b60008251614abe818460208701615763565b6201017960ed1b920191825250600301919050565b7f3c696d61676520783d22302220793d2230222077696474683d2233322220686581527f696768743d2233322220696d6167652d72656e646572696e673d22706978656c60208201527f6174656422207072657365727665417370656374526174696f3d22784d69645960408201527f4d69642220786c696e6b3a687265663d22646174613a696d6167652f706e673b60608201526618985cd94d8d0b60ca1b608082015260008251614b8d816087850160208701615763565b6211179f60e91b6087939091019283015250608a01919050565b7f7b202274726169745f74797065223a202268756e676572222c2022646973706c81527f61795f74797065223a20226e756d626572222c202276616c7565223a20000000602082015260008351614c0581603d850160208801615763565b8083019050611f4b60f21b80603d8301527f7b202274726169745f74797065223a2022626f726564222c2022646973706c61603f8301527f795f74797065223a20226e756d626572222c202276616c7565223a2000000000605f8301528451614c7581607b850160208901615763565b607b920191820152607d01949350505050565b7f7b202274726169745f74797065223a2022656172222c202276616c7565223a208152601160f91b60208201526000614cc4602183018461474f565b62089f4b60ea1b81526003019392505050565b6000614ce2826147e9565b7f7b202274726169745f74797065223a20226d6173746572222c202276616c7565815263111d101160e11b60208201528951614d25816024840160208e01615763565b62089f4b60ea1b6024929091019182018190527f7b202274726169745f74797065223a20227265726f6c6c6564222c202276616c6027830152653ab2911d101160d11b60478301528951614d8081604d850160208e01615763565b604d9201918201527f7b202274726169745f74797065223a2022756e68617070696e657373222c202260508201527f646973706c61795f74797065223a20226e756d626572222c202276616c75652260708201526101d160f51b6090820152614e1b614e15614a8b614e0f614e09614dfb609287018e614733565b611f4b60f21b815260020190565b8b614733565b89614733565b85614733565b9a9950505050505050505050565b6a7b226e616d65223a20222360a81b81528551600090614e5081600b850160208b01615763565b6a040a8c2dac2cedeced240560ab1b600b918401918201528651614e7b816016840160208b01615763565b7314911610113232b9b1b934b83a34b7b7111d101160611b601692909101918201528551614eb081602a840160208a01615763565b61088b60f21b9101602a8101919091526e2261747472696275746573223a205b60881b602c8201527f7b202274726169745f74797065223a202274797065222c202276616c7565223a603b8201526908089c1c9bdc1cc89f4b60b21b605b8201527f7b202274726169745f74797065223a20227573616765222c202276616c7565226065820152621d101160e91b6085820152613b7e614fc0614fba614f6b614f5b60888601614a4d565b63089f574b60e21b815260040190565b7f22696d616765223a2022697066733a2f2f516d56784344666d7767593270734181527f683777746938614c43796b6b6a3939736e79674751383970327a6b664174662f602082015260400190565b86614733565b652e676966227d60d01b815260060190565b6a7b226e616d65223a20222360a81b81528151600090614ff981600b850160208701615763565b7f2054616d61676f67692028556e72657665616c2050726f707329222c20226465600b9390910192830152507f736372697074696f6e223a2022556e72657665616c2050726f7073222c000000602b8201526e2261747472696275746573223a205b60881b60488201527f7b202274726169745f74797065223a202274797065222c202276616c7565223a605782015268202270726f7073227d60b81b607782015261174b60f21b60808201527f22696d616765223a2022697066733a2f2f516d5462423644443277387433367a60828201527f4c50764245646f576f363252464d794a69394558636a39395a6978507278432260a2820152607d60f81b60c282015260c301919050565b6a7b226e616d65223a20222360a81b8152865160009061512b81600b850160208c01615763565b6e040a8c2dac2cedeced2408acece405608b1b600b91840191820152875161515a81601a840160208c01615763565b602f60f81b601a9290910191820152865161517c81601b840160208b01615763565b602960f81b9101601b8101919091527f222c20226465736372697074696f6e223a2022556e62726f6b656e2054616d61601c8201526d19dbd9da481959d9dccb8b8b888b60921b603c8201526e2261747472696275746573223a205b60881b604a820152614a9f614fc0614fba61522d61521f614a91614e0961521261520c61520760598b016147e9565b614824565b8e614733565b602f60f81b815260010190565b61174b60f21b815260020190565b7f22696d616765223a2022697066733a2f2f516d57317463635971426d534c514681527f54664e38725777384a4858787837685a53344d6969775757444e35747647382f602082015260400190565b7f7b202274726169745f74797065223a20227265616374696f6e222c202276616c8152653ab2911d101160d11b60208201526000614cc4602683018461474f565b693d913730b6b2911d101160b11b815284516000906152e381600a850160208a01615763565b602360f81b600a91840191820152855161530481600b840160208a01615763565b6a040a8c2dac2cedeced240560ab1b600b92909101918201528451615330816016840160208901615763565b602f60f81b601692909101918201528351615352816017840160208801615763565b602960f81b6017929091019182015261088b60f21b6018820152601a019695505050505050565b600061538482614824565b8451615394818360208901615763565b602f60f81b910190815283516153b1816001840160208801615763565b61227d60f01b60019290910191820152600301949350505050565b7f7b202274726169745f74797065223a2022626f6479222c202276616c7565223a815261101160f11b60208201526000614cc4602283018461474f565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c00000081526000825161544181601d850160208701615763565b91909101601d0192915050565b7f3c7376672077696474683d2239363022206865696768743d223936302220766581527f7273696f6e3d22312e31222076696577426f783d22302030203332203332222060208201527f786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f737660408201527f672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f7260608201526d3397989c9c9c97bc3634b735911f60911b60808201527f3c726563742077696474683d223130302522206865696768743d223130302522608e82015271103334b6361e9111b0b0b21c9c9c9110179f60711b60ae820152600082516155508160c0850160208701615763565b651e17b9bb339f60d11b60c093909101928301525060c601919050565b7f7b202274726169745f74797065223a202268656164222c202276616c7565223a815261101160f11b60208201526000614cc4602283018461474f565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906130e490830184614707565b6020808252825182820181905260009190848201906040850190845b81811015611dda578351835292840192918401916001016155f9565b602081526000612a2b6020830184614707565b60a08152600061563b60a0830188614707565b90508560208301528460408301528360608301528260808301529695505050505050565b60208082526010908201526f139bdd081d985b1a59081c195d081a5960821b604082015260600190565b6020808252600a9082015269139bdd081c995d99585b60b21b604082015260600190565b86815260208101869052604081018590528315156060820152821515608082015260c08101600483106156f057634e487b7160e01b600052602160045260246000fd5b8260a0830152979650505050505050565b60008219821115615714576157146157f3565b500190565b60008261572857615728615809565b500490565b6000816000190483118215151615615747576157476157f3565b500290565b60008282101561575e5761575e6157f3565b500390565b60005b8381101561577e578181015183820152602001615766565b838111156121735750506000910152565b600181811c908216806157a357607f821691505b60208210811415611afc57634e487b7160e01b600052602260045260246000fd5b60006000198214156157d8576157d86157f3565b5060010190565b6000826157ee576157ee615809565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160e01b03198116811461263857600080fdfe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa264697066735822122069c56940fd46b970901e4cefbf1663ce7fd9f697bb1b49a889da5193c1fc526564736f6c63430008070033608060405234801561001057600080fd5b5061152e806100206000396000f3fe608060405234801561001057600080fd5b506004361061030b5760003560e01c80638aa001fc1161019d578063c7b6fd6a116100e9578063de5101af116100a2578063f615ed541161007c578063f615ed541461068a578063f9fd52501461069d578063fa93f883146106a5578063ff2258cb146106b857600080fd5b8063de5101af1461065c578063e95564301461066f578063ea1c16901461067757600080fd5b8063c7b6fd6a1461060b578063c7edf88c1461061e578063c9d3462214610626578063cfbb9f3714610639578063d2b5074314610641578063d6582d0d1461064957600080fd5b80639e524caa11610156578063ad203bd411610130578063ad203bd4146105cc578063b05eb08d146105df578063b3bb8cd4146105f2578063b8d16dbc146105f857600080fd5b80639e524caa1461059c578063a324ad24146105af578063a3f144ae146105c257600080fd5b80638aa001fc146104f85780638bbf51b71461050b5780638d4a2d391461051357806390059aed146105265780639220d4261461055457806392d663131461058957600080fd5b80634355644d1161025c5780635e05bd6d116102155780637217523c116101ef5780637217523c146104b557806374f0314f146104c85780637be34109146104d257806389a3a00d146104e557600080fd5b80635e05bd6d1461047c57806362fb96971461048f57806365c72840146104a257600080fd5b80634355644d146104145780634371c46514610427578063442b8c791461043a578063444fda821461044d5780634b321502146104605780634df861261461047357600080fd5b80631f4f77b2116102c95780632af123b8116102a35780632af123b8146103c85780633293d007146103db5780633e239e1a146103ee5780633f9e0eb71461040157600080fd5b80631f4f77b21461039a57806322f8a2b8146103ad57806329441674146103c057600080fd5b80625015531461031057806302e98e0d1461033657806310848ddf14610349578063126702a01461035c57806314b2d6dc146103645780631e0582e914610387575b600080fd5b61032361031e366004611292565b6106cb565b6040519081526020015b60405180910390f35b610323610344366004611292565b6106de565b610323610357366004611279565b6106ea565b610323600281565b6103776103723660046112b4565b6106fb565b604051901515815260200161032d565b6103236103953660046112b4565b610710565b6103236103a83660046112b4565b61071d565b6103236103bb366004611279565b61072a565b610323600781565b6103236103d6366004611292565b610735565b6103776103e93660046112e0565b610741565b6103236103fc366004611279565b61075c565b61032361040f366004611292565b610767565b610323610422366004611292565b610773565b610377610435366004611279565b61077f565b610323610448366004611292565b61078a565b61032361045b366004611292565b610796565b61032361046e366004611292565b6107a2565b610323610e1081565b61032361048a3660046112e0565b6107ae565b61032361049d366004611292565b6107c8565b6103236104b0366004611279565b6107d4565b6103236104c3366004611292565b6107df565b6103236201518081565b6103236104e0366004611292565b6107eb565b6103236104f3366004611292565b6107f7565b610323610506366004611279565b610803565b610323600381565b610323610521366004611292565b61080e565b610539610534366004611279565b61081a565b6040805193845260208401929092529082015260600161032d565b61055c610835565b604080519687526020870195909552938501929092526060840152608083015260a082015260c00161032d565b610323610597366004611279565b61085a565b6103236105aa366004611292565b610865565b6103236105bd366004611279565b610871565b61032362253d8c81565b6103236105da366004611292565b61087c565b6103776105ed366004611279565b610888565b42610323565b610377610606366004611279565b610893565b610323610619366004611292565b61089e565b610323600681565b610323610634366004611292565b6108aa565b610323600481565b610323600581565b610377610657366004611279565b6108b6565b61053961066a366004611279565b6108c1565b610323603c81565b61055c610685366004611279565b6108dc565b610323610698366004611292565b610902565b610323600181565b6103236106b3366004611279565b61090e565b6103236106c6366004611292565b610919565b60006106d78383610925565b9392505050565b60006106d7838361094c565b60006106f582610971565b92915050565b6000610708848484610999565b949350505050565b60006107088484846109ef565b6000610708848484610b2c565b60006106f582610b47565b60006106d78383610b7b565b6000610751878787878787610b97565b979650505050505050565b60006106f582610bd7565b60006106d78383610bf5565b60006106d78383610c7b565b60006106f582610d4d565b60006106d78383610d62565b60006106d78383610d96565b60006106d78383610e17565b6000610751878787878787610e3e565b9695505050505050565b60006106d78383610e8f565b60006106f582610ea8565b60006106d78383610eba565b60006106d78383610ec9565b60006106d78383610f40565b60006106f582610f4d565b60006106d78383610f5a565b600080600061082884610f66565b9250925092509193909250565b60008060008060008061084742611002565b949b939a50919850965094509092509050565b60006106f582611043565b60006106d7838361105e565b60006106f58261106b565b60006106d7838361107d565b60006106f582611151565b60006106f58261118d565b60006106d783836111ad565b60006106d783836111bc565b60006106f5826111d9565b60008060006108cf846111ee565b9196909550909350915050565b6000806000806000806108ee87611002565b949c939b5091995097509550909350915050565b60006106d783836111ff565b60006106f58261120b565b60006106d78383611227565b6000610933610e1083611443565b61093d90846114a1565b9050828111156106f557600080fd5b60008183111561095b57600080fd5b603c61096784846114a1565b6106d791906113aa565b6000808061098a61098562015180866113aa565b610f66565b50915091506107088282610bf5565b60006107b284101580156109ad5750600083115b80156109ba5750600c8311155b156106d75760006109cb8585610bf5565b90506000831180156109dd5750808311155b156109e757600191505b509392505050565b60006107b2841015610a0057600080fd5b838383600062253d8c60046064600c610a1a600e88611462565b610a24919061137c565b610a3088611324611323565b610a3a9190611323565b610a44919061137c565b610a4f9060036113be565b610a59919061137c565b600c80610a67600e88611462565b610a71919061137c565b610a7c90600c6113be565b610a87600288611462565b610a919190611462565b610a9d9061016f6113be565b610aa7919061137c565b6004600c610ab6600e89611462565b610ac0919061137c565b610acc896112c0611323565b610ad69190611323565b610ae2906105b56113be565b610aec919061137c565b610af8617d4b87611462565b610b029190611323565b610b0c9190611323565b610b169190611462565b610b209190611462565b98975050505050505050565b600062015180610b3d8585856109ef565b6107089190611443565b600080610b5762015180846113aa565b90506007610b66826003611364565b610b7091906114b8565b6106d7906001611364565b600081831115610b8a57600080fd5b610e1061096784846114a1565b6000610ba4878787610999565b156107be57601884108015610bb95750603c83105b8015610bc55750603c82105b156107be575060019695505050505050565b600080610be762015180846114b8565b90506106d7610e10826113aa565b60008160011480610c065750816003145b80610c115750816005145b80610c1c5750816007145b80610c275750816008145b80610c32575081600a145b80610c3d575081600c145b15610c4a5750601f6106f5565b81600214610c5a5750601e6106f5565b610c6383611151565b610c6e57601c610c71565b601d5b60ff169392505050565b6000808080610c9061098562015180886113aa565b91945092509050610ca18583611364565b9150600c610cb06001846114a1565b610cba91906113aa565b610cc49084611364565b9250600c610cd36001846114a1565b610cdd91906114b8565b610ce8906001611364565b91506000610cf68484610bf5565b905080821115610d04578091505b610d1162015180886114b8565b62015180610d208686866109ef565b610d2a9190611443565b610d349190611364565b945086851015610d4357600080fd5b5050505092915050565b60006006610d5a83610b47565b101592915050565b6000808080610d7761098562015180886113aa565b91945092509050610d888584611364565b92506000610cf68484610bf5565b6000808080610dab61098562015180886113aa565b91945092509050610dbc85846114a1565b92506000610dca8484610bf5565b905080821115610dd8578091505b610de562015180886114b8565b62015180610df48686866109ef565b610dfe9190611443565b610e089190611364565b945086851115610d4357600080fd5b6000610e25610e1083611443565b610e2f9084611364565b9050828110156106f557600080fd5b600081610e4c603c85611443565b610e58610e1087611443565b62015180610e678b8b8b6109ef565b610e719190611443565b610e7b9190611364565b610e859190611364565b6107519190611364565b600081831115610e9e57600080fd5b6106d783836114a1565b600061070861098562015180846113aa565b6000610e256201518083611443565b600081831115610ed857600080fd5b600080610eeb61098562015180876113aa565b509092509050600080610f0461098562015180886113aa565b50909250905082610f1685600c611443565b82610f2285600c611443565b610f2c9190611364565b610f3691906114a1565b61075191906114a1565b6000610e25603c83611443565b60006106f5603c836114b8565b6000610e2f8284611364565b60008080836226496581018262023ab1600483020590506004600362023ab18302010590910390600062164b09610fa0600185010205905060046105b58202058303601f019250600061098f8460500281610fc357610fc36114e2565b0590506000605061098f83020585039050600b820560301994909401606402929092018301996002600c90940290910392909201975095509350505050565b6000808080808061101862015180885b04610f66565b91999098919750610e10620151809092068281049750603c9290068281049650919091069350915050565b600061105561098562015180846113aa565b50909392505050565b6000610933603c83611443565b60006109e761098562015180846113aa565b600080808061109261098562015180886113aa565b919450925090506000856110a76001856114a1565b6110b286600c611443565b6110bc9190611364565b6110c691906114a1565b90506110d3600c826113aa565b93506110e0600c826114b8565b6110eb906001611364565b925060006110f98585610bf5565b905080831115611107578092505b61111462015180896114b8565b620151806111238787876109ef565b61112d9190611443565b6111379190611364565b95508786111561114657600080fd5b505050505092915050565b600061115e6004836114b8565b15801561117457506111716064836114b8565b15155b806106f55750611186610190836114b8565b1592915050565b6000806111a061098562015180856113aa565b505090506106d781611151565b60006109336201518083611443565b6000818311156111cb57600080fd5b6201518061096784846114a1565b600060056111e683610b47565b111592915050565b600080806108cf6201518085611012565b600061093d82846114a1565b60008061121a610e10846114b8565b90506106d7603c826113aa565b60008183111561123657600080fd5b600061124861098562015180866113aa565b505090506000611260620151808561098591906113aa565b50509050818161127091906114a1565b95945050505050565b60006020828403121561128b57600080fd5b5035919050565b600080604083850312156112a557600080fd5b50508035926020909101359150565b6000806000606084860312156112c957600080fd5b505081359360208301359350604090920135919050565b60008060008060008060c087890312156112f957600080fd5b505084359660208601359650604086013595606081013595506080810135945060a0013592509050565b600080821280156001600160ff1b0384900385131615611345576113456114cc565b600160ff1b839003841281161561135e5761135e6114cc565b50500190565b60008219821115611377576113776114cc565b500190565b60008261138b5761138b6114e2565b600160ff1b8214600019841416156113a5576113a56114cc565b500590565b6000826113b9576113b96114e2565b500490565b60006001600160ff1b03818413828413808216868404861116156113e4576113e46114cc565b600160ff1b6000871282811687830589121615611403576114036114cc565b6000871292508782058712848416161561141f5761141f6114cc565b87850587128184161615611435576114356114cc565b505050929093029392505050565b600081600019048311821515161561145d5761145d6114cc565b500290565b60008083128015600160ff1b850184121615611480576114806114cc565b6001600160ff1b038401831381161561149b5761149b6114cc565b50500390565b6000828210156114b3576114b36114cc565b500390565b6000826114c7576114c76114e2565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fdfea26469706673582212202464ec77d55c0b8b938a36e973509d6bb0bb2d18b4f4c56e73bccd066d6eca6264736f6c6343000807003389504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c086488000000b9494441545847ed96c10e80200c4321faff5fec4139cce0dc68410c979178215bf7a81b21a794b6eb5bb672008403e14038100e8403e140384038705c31fbe08b05e6b20f1228640052390c0025e4380473110014207e4d53a30530a3b8f0b95a1ec08ce2b5c6278051189d67ea300e588965afac7a3cbd3d89e90228e2226815d2a22dbb2db0bb77d1140888770a298c00dc8b8c01d010f5e4590008fa31b97f01c0f193001640f70471ffbc9ad4cce901608b76c52d073801df502d81d35c52b50000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000060494441545847ed96410a00200804f3ff8f2e844e511a68e461bab74ea348d23e1ff95cbf0180010c9436d0e78e88429a39a770bd142dbceeb86d2600650d68ff32e7e098e50d5a068499e101444db80fb80178fa6500000318c00006308081013eee10210f9b3be30000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000089494441545847ed96b10ac0200c4423edff7f7187ea60493378977490c2096e313edf29d8ccece873db68029001199001199001199001c2c0d56bcee28f05ae653e24b0c9020eae4500b0016166d9230bc000c59a7f030cc3e3047ea00b99aa4711c4882b112cafc95780795a6f85817ca0b2003192b9b1d78e227a19a900102f8f2f11800c6c37700360131781b4054f830000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000080494441545847ed94410ac0200c04f5ff8f6ec921250475d7da22c87ad48d1927602d9b57dddcbf30005782ecd5e49c95c1fb51c02ecd196f14f75b3903e8ed3f6f1a01a0623f6773cd69af00f80b91ea21203382b70d284308c0b5cd6a8ef925032c401c4736f609c06fdf053b0201c8800cc8800cc8800cc8800cc8c0b9066edd51182171bab4cb0000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c0864880000007e494441545847ed92510ac0300843dbfb1f7a459820d22e993f52c8be0a33f1edad73343fb379ff60009e1792998ddf43e550a995f84c3c237174ee0b2097a0a5bbf7109e017095b6001973889c39da438595e52788ad410460a13fff3e2f81d92b002a978fce3006e8b2caa00064400664400664400664400664a0ddc00276971321672fab0a0000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000091494441545847ed96b10e80200c444be4ffbfd8411848c060efda05872371f2da3e5ed050ccec6acfb1550420033220033220033220038481bb656af2c6026bd90b096cb401a46a1800aad1872158fb7b00b803e26cb83d9081a30068f8fc3e925da47906224d23d934c07b8867c0cbd2003dc80e8dc084003c88dd507ae783027d0523d71b6716fc85b30099e1548d001e930027810fe7f6160000000049454e44ae426082466f6f642077696c6c2062652061626c6520746f2070726576656e7420796f7572207065742066726f6d2073746172766174696f6e2e89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c0864880000005e494441545847ed95390e00200cc3e8ff1fcd3180104294b64317334362792052928f24f717003080010c60c06aa0f6af5b7bf373672d8016769b8a5781a97c847b004e2873e91e100598e56e88284078cd01c000063080010c6020dd4003cbd40721aa0beb880000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000072494441545847ed94310e00210804f5ff8ff68ec2c4e2803d43a2c55859c0b219597b3b7cfae1f90d031080804260bc5155eabe129df666c2a980f08f841a91818ae1d39fabe519a81c1e9ac0c0b504ecdd2af7e0f712ae8b63f72cae5e1a6d70d8bf2b2cc45f2bc10004200001084000020fec3f1221ce89b1720000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000068494441545847ed94c10a00101404f9ff8f2607a5478c835cc64dedee5b4372fabcf2e7f9c902844019ae89e89b1c7b4e812d68d4c4fdea095d796e0bc4d3ad0ac4cc6de953813e90e8088d49438309fa188e3cb4c0b3efc20212908004242001094840021290400533b70d21044e4ab70000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000072494441545847ed94510a00210844ebfe876e290844dacd8996085e7fd1a8e353cae9f0c987eba7a881628cce62146dc8404d688bfabb85a8685bdcac9baa51922ada7b0d742aa3fdf544bfc6b544a02fd8dbe8fcfb1603b6e3c8ce48fa68c2dfbe0b0c40000210800004200001084000020fc5ac172190ff741b0000000049454e44ae426082546f79732063616e206b65657020796f7572207065742066726f6d206265696e6720626f7265642e89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000067494441545847ed954b0a00200805f3fe87eeb368994f2ab0605ae77318c3ac241f4bee5f00c00006be3050fbaed80595b5916019e22c33590b8032201506fe1237c303b8d17cf22db39e0618f4372c6c8f2030def32bea119e7710090060000318c00006d20d343af6102106b4da3d0000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000063494441545847ed954b0a00200844f3fe87eeb3898848cdc0cd6b6d33d3131a29c94792fd0b012000010840c04ba0f6af5bbb6399990da0899daae266e0321fe2de001603cb4c88c04a6598bd3ce45b80709b7b571036dc05080001084000021080400354df0721739252ba0000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c0864880000005b494441545847edd5310e0020080441f9ffa3550a3b20014968d69620e714226bf8c8f0fc450004104000818ac0bedfb7d717d5cc5f3f1be00db006453577e56403b4efaedf00fa6a3de57bca8d5d1404400001041040008171810356ee0721ed9f05790000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c086488000000a6494441545847ed96c10a80201883957aff27ee501e0493e9e6df218405dedcfcfe39c29c523a9ef5db970de0049c801370024ec009ec90c0f5409ec10703d5aaef016a0400258d0220190d12a25a06400d84ab997acc007ae10a8cac1d01208332ac5ac6a2eff7c30114802a8c24d06a96000a7d3f450400f9bc6ac34ad86e8e024c7bfa05a026540f68fb21c34601d001f4be51145b01d04281e2d2ffd44a02d42cb2c10037c7f12981ef4fbe3c0000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c0864880000008f494441545847ed93d10e80200845f5ff3fba461b8de80a526daeedf6a628f778b4de167f7d717efb05c0662c09b01d23817e4d78c8cc8084d9357e8c004a7b228052234732bd1701a8e2cc4ef5fdc2be5eaf34ad2acf40908d3347c3d0ddeadcccbd8f20a21e476d04f0263483d1fa054026fdef96a97d52bf657cfdd0ca5004a0011aa0011aa0011aa0011aa0811d3de21d21bb35e40a0000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c0864880000005b494441545847ed94db0900200cc474ffa17d2c604a058b10bfbdf408b4bd15bf5e3cbf5940031af8c2c058b7225b14b3044640e0901d195460f36f4a60960a2040031a7861203023ff85b6204f0e262da0010d6840031a283730013af6102192d097b20000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c0864880000005f494441545847edd5bb0a00200846617dff87ae961a44f042e0721a237fe51b5265f8e8707f61000410400081aac03a5f77549379f3364014665745263cf3a63d80b7bb4a0d6d4055c013b977adac56d1cf15ce0008208000020820302eb00182580621fa639d260000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000061494441545847ed94410e00100c04f5ff8f460f8eac20a926e3cc760cad95e065c1f50b0018c0400a03b5cf8a5350795605cb808d41b6ccf81ae0c5ed87a069d6ca403880d3bf80c8fb07e4fbdd76809f575db051e36e0b0018c000063080010c343af61021f9935c500000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000067494441545847ed93410a00200cc3f4ff8f56100411ba513d8810cfb5ed32ade5f1a98ff3cb1705da46292b6de95db3d945dddbc3337db80265a64c5dfdf08908b886aefebac03a40162e873d7d03eeef9539590137c8d6530002108000042000010840000210e80b6d0b213ce71b1e0000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c0864880000009e494441545847ed96410ac0200c0495f6ff2feea17a08b4c1646314bcacd05b930c936db19652aef61c3b9500344003344003344003341030f0b477eee48d05d6a20b496fd0cf0a805bef01ac0e17696e1f0b60d77008e10164b55b7119e621020083e404f45b3b05d07bca1a7684d0ec81be0201b1d68120a1bd1500dd7c346c1b80566835d63b87eb8b18d079404dd15a7e998d0224ffc4b88c00c70dbcedba1d81b2a5703a0000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af4000000017352474200aece1ce900000066494441545847edd5310e00100c85613d8efb1fc67108092961914a0dbfc540f25e3f0309ce4b9cf30305104000010410f84720c7982525e9fb8b5f7297d104eac11a58cb589638658c107dc13abc0fb2cb98a67cc9af4be8014d996f9e8c02082080000208145bcb2821effa51fe0000000049454e44ae426082536869656c6420746f2070726f7465637420796f7572207065742066726f6d206265696e67206869742e89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000049494441545847edd6410a00200804c0fcffa3ab17a40421c17857973988319a2b9af70f010810f84260ee5b711b34edad0c4e871c8e59da2b0001021581a72f8300040810204080c0023af610215e442abd0000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000098494441545847ed964b0ac0200c0523f5fe27eea26621049b98f82952784237d53c27038a8988aef21d1b090030000330000330000330e018b8cb7c5e7cad7433220f921508b7d60370030276a60decd8bcf2995996819d9b77217e033063a4ad5133a2062c00fecf433baa9f03c80d34c02500eeaa76573bec055a736dc6ebd47af7802c90619a766f5ebd3246000277cef812001c37f00086f72381b52e906c0000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000060494441545847edd6cb0a0020084451fdff8feeb16813e4580411dcd669c31124b7c7c71fbf6f044000812f044adb15a741656da6b16c122c33594b804860f049c6c408963dd4087ae138eaee9c23558bc02eebf5ef030110400001041040a0028cd31421444923dc0000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000070494441545847ed92410ac0200c04f5ff8f6e9b4341aa761772082de34590641d27f656bc7af1fded3300c7652a609ffb28d0a999843b0676c1713eae15e0ddbb9db4029001c61f7acd5000919f8190bd0a4006fcde80f1c05c891a412edde806000318c000063080010c600003e5064e048315215641d2fc0000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000074494441545847ed94310ec0200cc4e0ff8f2e4202d481e452a062317372674cd59c2e9f7cb93f298067027874c70b9b95771e6beff3ce4a9005e1959be03b0035b4ef47cadff3e365d57bd6c168b8f53dbb1d11801d08992f07dab5562dc87c39f0f77f02000c60000318c000063080010c60a000b8610b216fdcaceb0000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c086488000000a4494441545847ed964b0ac0200c05957aff1377515d0444f2796ac1169e20144c759c1831a794aeda8fb54c001aa0011aa0011aa0011a000cdc35a62cbe58c27f9107493f49fb9636426963db00e304b3000dd685f00c788b2319e90d991016c0eee25a9a5488cf0248ee10d5688c5a494815ecc084e5fb2b006d375296d6d86b06ac7ab600c20b480e0e9a0289ef2f22eff0853b5f05404f3c1c376b009e180d3c0ef000b15d1d81d94175870000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c0864880000006a494441545847ed944b0a00200844ebfe87eeb310dae88404153c5741cc383cc55a2e57bddcbf10000210f882401bb7221b546a95b134d83864a14714e04473cbe77a7901a6c04a515210422f083c4b605d9ef9ceee81cddfd5678dd5e26dff130002108000042000810e4ece1021878663410000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c086488000000a0494441545847ed96c10a8020104495faff2fee907b30ac5667b6840e8d10c4e2eaf3b98a39a5b494efb396052003322003322003322003a481adf45b83af162a877990500375e0602e02f006b098b5ab9151bc6b2f0ad00231ff063ab41001e84d58edb340a7dd8a00046bf0e83ecdc03f016011012daf8fa157606dac9ddf3b96f0f24245e81988dc03530dd4d5a2555540efb2baed1863e069f5537902d801343f25816dd4601b0000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000075494441545847ed92410ec0200804f5ff8f6ee381a4c12a0b1ebc8ce765990cf676f9f5cbfb5b04f038c0286f71796e57e84bac3c8248cdadca5625a7179bf6650046768029062ceb81cb00eaf2ef1ff88328016497ef206400af4e515f9a89ee79fae9c279003080010c60000318c0000630808117a9bd1321772d676e0000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000068494441545847ed94610b00100c44f9ff3f9a28b5165792d6eaf9a6e1eede965a82570dd62fe90c3443cc9b57b523e81b0243c09eb77b55935d4e63c0271ca914015f7f6e41a8819df84ab406efd44a7577be7133035fbe0c0c40000210800004200001084000021df3d61521c08b49860000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000064494441545847ed94490e00200803f1ff8f763978841a354193e16a6ceb80144bae92ec6f04800004be2050fbaed80d2aef2a6129b0b0c8428da703dc78fd04e46a79046e9a872108100de168c32835a8ea23843aa7e2ca5c9e13000210800004200081063eee1021a0220e8e0000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000092494441545847ed96410ac0200c0495f6ff2feea1061a0852bb9b40f1b282d0431227630af6d6da31f6b6d5052003322003322003322003a4816bc49dc9570b95c33e48ac586541680680ea644107731140b5f39967698201f0e42c4ccc2b0358277eb015612162ece71c2003b34a78a70f241c3e2f5c0160fe86df00e295d8f7db7cd0875b81ac01a6fb548c006460bb811b903311813716c23a0000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000065494441545847edd4dd0a00100c8661bbff8ba61d90ffad24a9d7216bfb3c8984c74b1ecf0fdf04889dd42ab8b7aeb4f30868d3beee64afb98b1560362837a8cfbc75c393238025a06416afd6ec1ee5768627c0d5af82000820800002082080000208209000f7ce15214de4787a0000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000092494441545847ed96d10ac02008458dedffbf780fab072142f3ea06637083bd44dae9e8a2262247ff3e1b8d0034400334400334400334001ab8faba33f96a816290070994c8810b63770023788cecc957966d1e0f20244f96632c377322004f60e6d87f01a832355ded03adbfdb4bc85fe0d56f4e6e6d0095ae0a60255fe708f0aa01b429c3a65bef0fb4070af70e1642801b8ad723816807111a0000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c0864880000006c494441545847edd4d10a4011108461deffa14951d2b2e342a8ff5c9d8bc98e8fc470f98b97e7876f0aa42aa51696f3ca8265b196ebff67a7b795f70a5803572576f3ee1d980d6bc4a382b5a1a5daf3026587cab92bf7c1cc7802c79f090a2080000208208000020820804006486e132187d8c7c60000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000074494441545847ed94410ec0200cc3e0ff8f66e3c01192954905c99c9bd432526b497e35797f01000318b8c6407befc557582be3945a45938326b30a4016189774d9b102f863f9e09b761d6d40d2efeaef7965a0cfec7c85cc3a005108b9dc3560988e8fb806e21b4412000c60000318c040ba81073af6102143c1dc740000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c0864880000006d494441545847ed93410ac0200c04f5ff8f5602e6225476410896e979b39d0cb1b7e2af17ffbf3d0130962517569a534ab32838947ce4e419a530ca22276db4e572f6f3d41c807db3d3fd66ef7500f7d1fc03c0dddaca2b376015ba61003080010c60000318c0000630506e6002f73b0f211a4494500000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c086488000000a2494441545847ed964b0ac030084413dafb9fb88bc642200dea980f94c204bad2eae4f92139a57494efb3932980044880044880044880040204aee2734ebe58e0bfe84102030484b9313c013b92577d66acdf098850d17cb612f04458b6ad02a4ae43b734fc9ffe18e981362912d0dba7086837954072acbda0d9a7c7108ed0ea0e402568e36b48b5fc2d99c8c4b83dd027a8782325f07c5e71d12a0e505e73a1801b9c8b2581c49959130000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c08648800000061494441545847ed95410a00200804ebff8f2e3a142115ae045ea6abad4e73b05a924f4d9e5f00c00006308001d540db56b7cdbe6ad78daf028c4663d02df7aa1d215400cf00cf9d05a302d8574cede13ee1e0af6f1c000c60000318c00006d20d745ccf0721d52fc6040000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af4000000017352474200aece1ce900000072494441545847ed943112c0200804cf49feffe214190a6752c1450a2dd65a605d9021e9d2c63300c000063060187824dd8bbbaa8cad165199c0004b73380051a363208dcf0082bc537cca49f31c6d205eb0750666f10e4499a36ac1b78f7f07d10277018cdfb67605000c60000318c000065e01921281db558cba0000000049454e44ae426082
Deployed Bytecode
0x6080604052600436106102c95760003560e01c806370a0823111610175578063b88d4fde116100dc578063e985e9c511610095578063f0503e801161006f578063f0503e801461094f578063f2fde38b1461097c578063f59dfdfb1461099c578063fe55932a146109bc57600080fd5b8063e985e9c5146108c6578063ebd799cc1461090f578063ebf6e91d1461092f57600080fd5b8063b88d4fde14610800578063c23c863b14610820578063c87b56dd14610850578063ca9c4b3314610870578063d3a2da3814610878578063df33fa31146108b357600080fd5b806391b7f5ed1161012e57806391b7f5ed1461073b57806395d89b411461075b5780639b993a1a14610770578063a22cb465146107a0578063a22d5823146107c0578063b6d22551146107e057600080fd5b806370a082311461063f578063715018a61461065f5780637908213d1461067457806379502c55146106a55780638462151c146106f05780638da5cb5b1461071d57600080fd5b806332063f52116102345780635a353cd3116101ed57806366d38ba9116101c757806366d38ba9146105bf57806367243482146105df5780636840690b146105ff5780636898f82b1461061f57600080fd5b80635a353cd3146105555780635d186c9f1461058a5780636352211e1461059f57600080fd5b806332063f521461049a57806335b34ca2146104b05780633cd434aa146104e057806341b3ba3d146104f557806342842e0e14610515578063439bbfd21461053557600080fd5b80630ea61c47116102865780630ea61c47146103bf57806318160ddd146104075780631c19c2151461042e5780631d80009a1461044e57806323b872dd1461046457806325b1f5ef1461048457600080fd5b806301ffc9a7146102ce57806306fdde0314610303578063081812fc1461032557806308a337331461035d578063095ea7b31461037f57806309a3849a1461039f575b600080fd5b3480156102da57600080fd5b506102ee6102e93660046145ef565b6109dc565b60405190151581526020015b60405180910390f35b34801561030f57600080fd5b50610318610a2e565b6040516102fa9190615615565b34801561033157600080fd5b506103456103403660046145d6565b610ac0565b6040516001600160a01b0390911681526020016102fa565b34801561036957600080fd5b5061037d610378366004614592565b610b04565b005b34801561038b57600080fd5b5061037d61039a3660046144ba565b610b1d565b3480156103ab57600080fd5b5061037d6103ba3660046145b4565b610bbd565b3480156103cb57600080fd5b506103df6103da3660046145d6565b610bd2565b60408051948552921515602085015290151591830191909152151560608201526080016102fa565b34801561041357600080fd5b5060025460015403600019015b6040519081526020016102fa565b34801561043a57600080fd5b5061037d6104493660046145d6565b610fe2565b34801561045a57600080fd5b5061042060975481565b34801561047057600080fd5b5061037d61047f3660046143c6565b611127565b34801561049057600080fd5b5061042060b75481565b3480156104a657600080fd5b5061042060b65481565b3480156104bc57600080fd5b506102ee6104cb366004614378565b60b26020526000908152604090205460ff1681565b3480156104ec57600080fd5b5061037d6112b8565b34801561050157600080fd5b5061037d6105103660046145d6565b6112d1565b34801561052157600080fd5b5061037d6105303660046143c6565b6112de565b34801561054157600080fd5b5061037d610550366004614592565b6112fe565b34801561056157600080fd5b506105756105703660046145d6565b611313565b604080519283526020830191909152016102fa565b34801561059657600080fd5b5061037d611644565b3480156105ab57600080fd5b506103456105ba3660046145d6565b61165b565b3480156105cb57600080fd5b5061037d6105da3660046145d6565b611666565b3480156105eb57600080fd5b5061037d6105fa3660046144e4565b6116a8565b34801561060b57600080fd5b506102ee61061a3660046145d6565b611788565b34801561062b57600080fd5b5061037d61063a3660046145d6565b611b02565b34801561064b57600080fd5b5061042061065a366004614378565b611bbd565b34801561066b57600080fd5b5061037d611c0c565b34801561068057600080fd5b5061069461068f3660046145d6565b611c20565b6040516102fa959493929190615628565b3480156106b157600080fd5b50609854609954609a5460ac546106de9392919060ff808216916101008104821691620100009091041686565b6040516102fa969594939291906156ad565b3480156106fc57600080fd5b5061071061070b366004614378565b611cd6565b6040516102fa91906155dd565b34801561072957600080fd5b506000546001600160a01b0316610345565b34801561074757600080fd5b5061037d6107563660046145d6565b611de6565b34801561076757600080fd5b50610318611df3565b34801561077c57600080fd5b506102ee61078b3660046145d6565b60af6020526000908152604090205460ff1681565b3480156107ac57600080fd5b5061037d6107bb36600461447e565b611e02565b3480156107cc57600080fd5b5061037d6107db366004614592565b611e98565b3480156107ec57600080fd5b506105756107fb3660046145d6565b611ead565b34801561080c57600080fd5b5061037d61081b366004614402565b61212f565b34801561082c57600080fd5b506102ee61083b366004614378565b60b16020526000908152604090205460ff1681565b34801561085c57600080fd5b5061031861086b3660046145d6565b612179565b61037d612184565b34801561088457600080fd5b506102ee610893366004614629565b805160208183018101805160b08252928201919093012091525460ff1681565b61037d6108c1366004614550565b6122e4565b3480156108d257600080fd5b506102ee6108e1366004614393565b6001600160a01b03918216600090815260086020908152604080832093909416825291909152205460ff1690565b34801561091b57600080fd5b5061037d61092a366004614592565b6124fa565b34801561093b57600080fd5b5061037d61094a3660046145d6565b61250f565b34801561095b57600080fd5b5061042061096a3660046145d6565b60ad6020526000908152604090205481565b34801561098857600080fd5b5061037d610997366004614378565b6125c2565b3480156109a857600080fd5b5061037d6109b73660046145d6565b61263b565b3480156109c857600080fd5b5061037d6109d736600461468b565b6126ee565b60006301ffc9a760e01b6001600160e01b031983161480610a0d57506380ac58cd60e01b6001600160e01b03198316145b80610a285750635b5e139f60e01b6001600160e01b03198316145b92915050565b606060038054610a3d9061578f565b80601f0160208091040260200160405190810160405280929190818152602001828054610a699061578f565b8015610ab65780601f10610a8b57610100808354040283529160200191610ab6565b820191906000526020600020905b815481529060010190602001808311610a9957829003601f168201915b5050505050905090565b6000610acb826128f5565b610ae8576040516333d1c03960e21b815260040160405180910390fd5b506000908152600760205260409020546001600160a01b031690565b610b0c61292a565b610b1960a4826003614138565b5050565b6000610b288261165b565b9050336001600160a01b03821614610b6157610b4481336108e1565b610b61576040516367d9dca160e11b815260040160405180910390fd5b60008281526007602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b610bc561292a565b610b1960a7826005614176565b60ac54600090819081908190610100900460ff16610c0b5760405162461bcd60e51b8152600401610c0290615689565b60405180910390fd5b609954859081118015610c2d5750609954609a54610c299190615701565b8111155b610c495760405162461bcd60e51b8152600401610c029061565f565b600086815260ae6020526040808220815160a081019092528054429392919082908290610c759061578f565b80601f0160208091040260200160405190810160405280929190818152602001828054610ca19061578f565b8015610cee5780601f10610cc357610100808354040283529160200191610cee565b820191906000526020600020905b815481529060010190602001808311610cd157829003601f168201915b5050505050815260200160018201548152602001600282015481526020016003820154815260200160048201548152505090506000609660009054906101000a90046001600160a01b03166001600160a01b0316632af123b88360200151856040518363ffffffff1660e01b8152600401610d73929190918252602082015260400190565b60206040518083038186803b158015610d8b57600080fd5b505afa158015610d9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc39190614672565b609654604080850151905163055e247760e31b81529293506000926001600160a01b0390921691632af123b891610e07918890600401918252602082015260400190565b60206040518083038186803b158015610e1f57600080fd5b505afa158015610e33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e579190614672565b905060008360600151600014610e8857603c846060015186610e79919061574c565b610e839190615719565b610e8b565b60005b9050600060a18101548211610eb25760a460005b0154610eab908361572d565b9050610ee6565b60a254821015610ec55760a46001610e9f565b60a354821015610ed85760a46002610e9f565b610ee382600061572d565b90505b6000610ef461070b8e61165b565b90506000806000805b8451811015610fb0576000858281518110610f1a57610f1a615835565b602002602001015190506098600101548111610f9d57600081815260ad602052604081205490600a610f4c81846157df565b600a8110610f5c57610f5c615835565b0154905080610f725760009b5060019650610f9a565b8060011415610f885760009a5060019550610f9a565b8060021415610f9a5760009850600194505b50505b5080610fa8816157c4565b915050610efd565b50600085610fbe898b615701565b610fc89190615701565b9f50929d50909b5099505050505050505050509193509193565b8033610fed8261165b565b6001600160a01b03161461103f5760405162461bcd60e51b81526020600482015260196024820152782cb7ba9030b932903737ba103a37b5b2b713b99037bbb732b960391b6044820152606401610c02565b60ac54610100900460ff166110665760405162461bcd60e51b8152600401610c0290615689565b6099548290811180156110885750609954609a546110849190615701565b8111155b6110a45760405162461bcd60e51b8152600401610c029061565f565b600083815260af602052604090205460ff16156110f35760405162461bcd60e51b815260206004820152600d60248201526c4e6f7420617661696c61626c6560981b6044820152606401610c02565b6110fc83612984565b600093845260ad602090815260408086209290925560af9052909220805460ff191660011790555050565b6000611132826129dd565b9050836001600160a01b0316816001600160a01b0316146111655760405162a1148160e81b815260040160405180910390fd5b60008281526007602052604090208054338082146001600160a01b038816909114176111b25761119586336108e1565b6111b257604051632ce44b5f60e11b815260040160405180910390fd5b6001600160a01b0385166111d957604051633a954ecd60e21b815260040160405180910390fd5b80156111e457600082555b6001600160a01b038681166000908152600660205260408082208054600019019055918716808252919020805460010190554260a01b17600160e11b17600085815260056020526040902055600160e11b831661126f576001840160008181526005602052604090205461126d57600154811461126d5760008181526005602052604090208490555b505b83856001600160a01b0316876001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050505050565b6112c061292a565b60ac805461ff001916610100179055565b6112d961292a565b609755565b6112f98383836040518060200160405280600081525061212f565b505050565b61130661292a565b610b19609e826003614138565b60ac546000908190610100900460ff1661133f5760405162461bcd60e51b8152600401610c0290615689565b6099548390811180156113615750609954609a5461135d9190615701565b8111155b61137d5760405162461bcd60e51b8152600401610c029061565f565b600084815260ae6020526040808220815160a0810190925280544293929190829082906113a99061578f565b80601f01602080910402602001604051908101604052809291908181526020018280546113d59061578f565b80156114225780601f106113f757610100808354040283529160200191611422565b820191906000526020600020905b81548152906001019060200180831161140557829003601f168201915b5050505050815260200160018201548152602001600282015481526020016003820154815260200160048201548152505090506000609660009054906101000a90046001600160a01b03166001600160a01b0316632af123b88360200151856040518363ffffffff1660e01b81526004016114a7929190918252602082015260400190565b60206040518083038186803b1580156114bf57600080fd5b505afa1580156114d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114f79190614672565b609654604080850151905163055e247760e31b81529293506000926001600160a01b0390921691632af123b89161153b918890600401918252602082015260400190565b60206040518083038186803b15801561155357600080fd5b505afa158015611567573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061158b9190614672565b9050600061159b61070b8a61165b565b905060005b81518110156116355760008282815181106115bd576115bd615835565b60200260200101519050609860010154811161162257600081815260ad602052604081205490600a6115ef81846157df565b600a81106115ff576115ff615835565b0154905080611611576000965061161f565b806001141561161f57600095505b50505b508061162d816157c4565b9150506115a0565b50919650945050505050915091565b61164c61292a565b60ac805460ff19166001179055565b6000610a28826129dd565b61166e61292a565b8060038111156116805761168061581f565b60ac805462ff00001916620100008360038111156116a0576116a061581f565b021790555050565b6116b061292a565b60b75460b6546116c1908590615701565b11156117025760405162461bcd60e51b815260206004820152601060248201526f115e18d95959081d1a19481b1a5b5a5d60821b6044820152606401610c02565b60005b838110156117675761175585858381811061172257611722615835565b90506020020160208101906117379190614378565b84848481811061174957611749615835565b90506020020135612a4d565b8061175f816157c4565b915050611705565b508383905060b6600082825461177d9190615701565b909155505050505050565b600081609860010154811180156117ae5750609954609a546117aa9190615701565b8111155b6117ca5760405162461bcd60e51b8152600401610c029061565f565b600083815260ae6020526040808220815160a081019092528054829082906117f19061578f565b80601f016020809104026020016040519081016040528092919081815260200182805461181d9061578f565b801561186a5780601f1061183f5761010080835404028352916020019161186a565b820191906000526020600020905b81548152906001019060200180831161184d57829003601f168201915b5050505050815260200160018201548152602001600282015481526020016003820154815260200160048201548152505090506000429050600060ad600087815260200190815260200160002054905060006301e13380826118cc91906157df565b60965460808601519192506001600160a01b0316906365c72840906118f2908490615701565b6040518263ffffffff1660e01b815260040161191091815260200190565b60206040518083038186803b15801561192857600080fd5b505afa15801561193c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119609190614672565b6096546040516301971ca160e61b8152600481018690526001600160a01b03909116906365c728409060240160206040518083038186803b1580156119a457600080fd5b505afa1580156119b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119dc9190614672565b148015611af5575060965460808501516001600160a01b039091169063a324ad2490611a09908490615701565b6040518263ffffffff1660e01b8152600401611a2791815260200190565b60206040518083038186803b158015611a3f57600080fd5b505afa158015611a53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a779190614672565b6096546040516328c92b4960e21b8152600481018690526001600160a01b039091169063a324ad249060240160206040518083038186803b158015611abb57600080fd5b505afa158015611acf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611af39190614672565b145b9550505050505b50919050565b60ac54610100900460ff16611b295760405162461bcd60e51b8152600401610c0290615689565b609954819081118015611b4b5750609954609a54611b479190615701565b8111155b611b675760405162461bcd60e51b8152600401610c029061565f565b600082815260ae602090815260409182902042600290910155815184815233918101919091527fd0017656a8c92d10b2fa3a77fa3c1e8e4c28817e89311616b8eed8e68f68a95091015b60405180910390a15050565b60006001600160a01b038216611be6576040516323d3ad8160e21b815260040160405180910390fd5b506001600160a01b031660009081526006602052604090205467ffffffffffffffff1690565b611c1461292a565b611c1e6000612aac565b565b60ae60205260009081526040902080548190611c3b9061578f565b80601f0160208091040260200160405190810160405280929190818152602001828054611c679061578f565b8015611cb45780601f10611c8957610100808354040283529160200191611cb4565b820191906000526020600020905b815481529060010190602001808311611c9757829003601f168201915b5050505050908060010154908060020154908060030154908060040154905085565b60606000806000611ce685611bbd565b905060008167ffffffffffffffff811115611d0357611d0361584b565b604051908082528060200260200182016040528015611d2c578160200160208202803683370190505b509050611d5960408051608081018252600080825260208201819052918101829052606081019190915290565b60015b838614611dda57611d6c81612afc565b9150816040015115611d7d57611dd2565b81516001600160a01b031615611d9257815194505b876001600160a01b0316856001600160a01b03161415611dd25780838780600101985081518110611dc557611dc5615835565b6020026020010181815250505b600101611d5c565b50909695505050505050565b611dee61292a565b609855565b606060048054610a3d9061578f565b6001600160a01b038216331415611e2c5760405163b06307db60e01b815260040160405180910390fd5b3360008181526008602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b611ea061292a565b610b19609b826003614138565b6000808260986001015481118015611ed45750609954609a54611ed09190615701565b8111155b611ef05760405162461bcd60e51b8152600401610c029061565f565b600084815260ae6020526040808220815160a08101909252805482908290611f179061578f565b80601f0160208091040260200160405190810160405280929190818152602001828054611f439061578f565b8015611f905780601f10611f6557610100808354040283529160200191611f90565b820191906000526020600020905b815481529060010190602001808311611f7357829003601f168201915b505050505081526020016001820154815260200160028201548152602001600382015481526020016004820154815250509050600060ad600087815260200190815260200160002054905060006301e1338082611fed91906157df565b60965460808501519192506000916001600160a01b039091169063a324ad2490612018908590615701565b6040518263ffffffff1660e01b815260040161203691815260200190565b60206040518083038186803b15801561204e57600080fd5b505afa158015612062573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120869190614672565b60965460808601519192506000916001600160a01b03909116906365c72840906120b1908690615701565b6040518263ffffffff1660e01b81526004016120cf91815260200190565b60206040518083038186803b1580156120e757600080fd5b505afa1580156120fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061211f9190614672565b9197509095505050505050915091565b61213a848484611127565b6001600160a01b0383163b156121735761215684848484612b7b565b612173576040516368d2bf6b60e11b815260040160405180910390fd5b50505050565b6060610a2882612c73565b600360ac5462010000900460ff1660038111156121a3576121a361581f565b146121f05760405162461bcd60e51b815260206004820152601960248201527f4e6f7420696e20737461676520746f206d696e7420544d4747000000000000006044820152606401610c02565b609954609a546122009190615701565b60015460001901106122425760405162461bcd60e51b815260206004820152600b60248201526a139bc81c195d081b19599d60aa1b6044820152606401610c02565b33600090815260b2602052604090205460ff161561228d5760405162461bcd60e51b81526020600482015260086024820152674d617820746f203160c01b6044820152606401610c02565b609854349061229d90600161572d565b11156122dc5760405162461bcd60e51b815260206004820152600e60248201526d27379032b737bab3b41032ba341760911b6044820152606401610c02565b611c1e612d42565b600260ac5462010000900460ff1660038111156123035761230361581f565b146123505760405162461bcd60e51b815260206004820181905260248201527f4e6f7420696e20737461676520746f206d696e74206d65726b6c6520544d47476044820152606401610c02565b609954609a546123609190615701565b60015460001901106123a25760405162461bcd60e51b815260206004820152600b60248201526a139bc81c195d081b19599d60aa1b6044820152606401610c02565b33600090815260b2602052604090205460ff16156123ed5760405162461bcd60e51b81526020600482015260086024820152674d617820746f203160c01b6044820152606401610c02565b60985434906123fd90600161572d565b111561243c5760405162461bcd60e51b815260206004820152600e60248201526d27379032b737bab3b41032ba341760911b6044820152606401610c02565b6040516bffffffffffffffffffffffff193360601b1660208201526000906034016040516020818303038152906040528051906020012090506124b6838380806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250506097549150849050612ed4565b6124f25760405162461bcd60e51b815260206004820152600d60248201526c34b73b30b634b210383937b7b360991b6044820152606401610c02565b6112f9612d42565b61250261292a565b610b1960a1826003614138565b60ac54610100900460ff166125365760405162461bcd60e51b8152600401610c0290615689565b6099548190811180156125585750609954609a546125549190615701565b8111155b6125745760405162461bcd60e51b8152600401610c029061565f565b600082815260ae602090815260409182902042600390910155815184815233918101919091527fbae6551c0ddf25aa6805100ecbdc4535f2933a14d7ebafe9fab66af752e232ec9101611bb1565b6125ca61292a565b6001600160a01b03811661262f5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610c02565b61263881612aac565b50565b60ac54610100900460ff166126625760405162461bcd60e51b8152600401610c0290615689565b6099548190811180156126845750609954609a546126809190615701565b8111155b6126a05760405162461bcd60e51b8152600401610c029061565f565b600082815260ae602090815260409182902042600190910155815184815233918101919091527fd73f65a9b0fee6c2e3e08fd03cb4800137b36882554a7211fe8ce842b3d4f4fe9101611bb1565b82336126f98261165b565b6001600160a01b03161461274b5760405162461bcd60e51b81526020600482015260196024820152782cb7ba9030b932903737ba103a37b5b2b713b99037bbb732b960391b6044820152606401610c02565b60ac54610100900460ff166127725760405162461bcd60e51b8152600401610c0290615689565b6099548490811180156127945750609954609a546127909190615701565b8111155b6127b05760405162461bcd60e51b8152600401610c029061565f565b60b084846040516127c292919061485d565b9081526040519081900360200190205460ff161561280f5760405162461bcd60e51b815260206004820152600a60248201526913985b5948195e1a5cdd60b21b6044820152606401610c02565b600061285085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612eea92505050565b90506001811180156128625750601281105b61289f5760405162461bcd60e51b815260206004820152600e60248201526d4e6f742076616c6964206e616d6560901b6044820152606401610c02565b600086815260ae602052604090206128b89086866141a3565b50600160b086866040516128cd92919061485d565b908152604051908190036020019020805491151560ff19909216919091179055505050505050565b600081600111158015612909575060015482105b8015610a28575050600090815260056020526040902054600160e01b161590565b6000546001600160a01b03163314611c1e5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610c02565b60008061299260014361574c565b6040805191406020830152810184905233606090811b6bffffffffffffffffffffffff19169082015260740160408051601f1981840301815291905280516020909101209392505050565b60008180600111612a3457600154811015612a3457600081815260056020526040902054600160e01b8116612a32575b80612a2b575060001901600081815260056020526040902054612a0d565b9392505050565b505b604051636f96cda160e11b815260040160405180910390fd5b60005b81811015612aa1576000612a6560b554612984565b60b58054600090815260ad602052604081208390558154929350612a88836157c4565b9190505550508080612a99906157c4565b915050612a50565b50610b198282613027565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b604080516080810182526000808252602082018190529181018290526060810191909152600082815260056020526040902054610a2890604080516080810182526001600160a01b038316815260a083901c67ffffffffffffffff166020820152600160e01b831615159181019190915260e89190911c606082015290565b604051630a85bd0160e11b81526000906001600160a01b0385169063150b7a0290612bb09033908990889088906004016155aa565b602060405180830381600087803b158015612bca57600080fd5b505af1925050508015612bfa575060408051601f3d908101601f19168201909252612bf79181019061460c565b60015b612c55573d808015612c28576040519150601f19603f3d011682016040523d82523d6000602084013e612c2d565b606091505b508051612c4d576040516368d2bf6b60e11b815260040160405180910390fd5b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490505b949350505050565b60608160018110158015612c8d5750600154600019018111155b612cc85760405162461bcd60e51b815260206004820152600c60248201526b139bdd081d985b1a59081a5960a21b6044820152606401610c02565b609954600090841115612cfb5760ac54610100900460ff16612cf257612ced84613041565b612d17565b612ced846130ee565b60ac5460ff16612d0e57612ced84613265565b612d1784613285565b905080604051602001612d2a9190615409565b60405160208183030381529060405292505050919050565b6000612d516001546000190190565b612d5c906001615701565b905060b45460051415612df957600060b45560965460b354604051631c85d48f60e21b81526004810191909152600160248201526001600160a01b0390911690637217523c9060440160206040518083038186803b158015612dbd57600080fd5b505afa158015612dd1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612df59190614672565b60b3555b6040805160c081018252600060a082018181528252426020808401829052838501919091526060830182905260b354608084015284825260ae81529290208151805192938493612e4c9284920190614216565b5060208201516001820155604082015160028201556060820151600382015560809091015160049091015560b48054906000612e87836157c4565b91905055506000612e9783612984565b600084815260ad602052604090208190559050612eb5336001613027565b505033600090815260b260205260409020805460ff1916600117905550565b600082612ee1858461342a565b14949350505050565b600080825b8051821015613020576007818381518110612f0c57612f0c615835565b01602001516001600160f81b031990811690911c16612f3757612f30600183615701565b915061300e565b8051600360f91b90600590839085908110612f5457612f54615835565b01602001516001600160f81b031990811690911c161415612f7a57612f30600283615701565b8051600760f91b90600490839085908110612f9757612f97615835565b01602001516001600160f81b031990811690911c161415612fbd57612f30600383615701565b8051600f60f91b90600390839085908110612fda57612fda615835565b01602001516001600160f81b031990811690911c16141561300057612f30600483615701565b61300b600183615701565b91505b82613018816157c4565b935050612eef565b5050919050565b610b19828260405180602001604052806000815250613477565b606060008061304f84611ead565b600086815260ad60205260408120549294509092506130e4613070876134e4565b613079866134e4565b613082866134e4565b61308b886134e4565b613094886134e4565b6130bb601a6130a460038b6157df565b600381106130b4576130b4615835565b01546134e4565b6040516020016130d096959493929190615104565b6040516020818303038152906040526135e2565b9695505050505050565b60606000806000806130ff86610bd2565b935093509350935060008061311388611313565b91509150600061312289611788565b905060008680156131305750855b80156131395750845b806131415750815b61314c57600061314f565b60015b9050600061315c89613748565b905060006040518060e001604052808d815260200160ad60008f81526020019081526020016000205481526020018781526020018681526020018b8152602001841515815260200160af60008f815260200190815260200160002060009054906101000a900460ff161515815250905060006131ec60ad60008f81526020019081526020016000205484866137a8565b905060006131f983613b8a565b61320284613d1c565b61320b85613d62565b61321486613e5c565b61322561322087613e95565b6135e2565b6040516020016132399594939291906148f3565b6040516020818303038152906040529050613253816135e2565b9e9d5050505050505050505050505050565b60606000612a2b613275846134e4565b6040516020016130d09190614fd2565b600081815260ad6020526040812054606091600a6132a381846157df565b600a81106132b3576132b3615835565b015490506000601782600381106132cc576132cc615835565b0180546132d89061578f565b80601f01602080910402602001604051908101604052809291908181526020018280546133049061578f565b80156133515780601f1061332657610100808354040283529160200191613351565b820191906000526020600020905b81548152906001019060200180831161333457829003601f168201915b5050505050905060006014836003811061336d5761336d615835565b0180546133799061578f565b80601f01602080910402602001604051908101604052809291908181526020018280546133a59061578f565b80156133f25780601f106133c7576101008083540402835291602001916133f2565b820191906000526020600020905b8154815290600101906020018083116133d557829003601f168201915b50505050509050600061341f613407886134e4565b838585866040516020016130d0959493929190614e29565b979650505050505050565b600081815b845181101561346f5761345b8286838151811061344e5761344e615835565b6020026020010151613ebe565b915080613467816157c4565b91505061342f565b509392505050565b6134818383613eea565b6001600160a01b0383163b156112f9576001548281035b6134ab6000868380600101945086612b7b565b6134c8576040516368d2bf6b60e11b815260040160405180910390fd5b8181106134985781600154146134dd57600080fd5b5050505050565b6060816135085750506040805180820190915260018152600360fc1b602082015290565b8160005b8115613532578061351c816157c4565b915061352b9050600a83615719565b915061350c565b60008167ffffffffffffffff81111561354d5761354d61584b565b6040519080825280601f01601f191660200182016040528015613577576020820181803683370190505b5090505b8415612c6b5761358c60018361574c565b9150613599600a866157df565b6135a4906030615701565b60f81b8183815181106135b9576135b9615835565b60200101906001600160f81b031916908160001a9053506135db600a86615719565b945061357b565b606081516000141561360257505060408051602081019091526000815290565b600060405180606001604052806040815260200161587860409139905060006003845160026136319190615701565b61363b9190615719565b61364690600461572d565b90506000613655826020615701565b67ffffffffffffffff81111561366d5761366d61584b565b6040519080825280601f01601f191660200182016040528015613697576020820181803683370190505b509050818152600183018586518101602084015b81831015613703576003830192508251603f8160121c168501518253600182019150603f81600c1c168501518253600182019150603f8160061c168501518253600182019150603f81168501518253506001016136ab565b60038951066001811461371d576002811461372e5761373a565b613d3d60f01b60011983015261373a565b603d60f81b6000198301525b509398975050505050505050565b60a754600090821161376157602a60035b015492915050565b60a85482101561377457602a6000613759565b60a95482101561378757602a6001613759565b60aa5482101561379a57602a6002613759565b602a6004613759565b919050565b60606000608b600b6137bb600488615719565b6137c591906157df565b600b81106137d5576137d5615835565b0180546137e19061578f565b80601f016020809104026020016040519081016040528092919081815260200182805461380d9061578f565b801561385a5780601f1061382f5761010080835404028352916020019161385a565b820191906000526020600020905b81548152906001019060200180831161383d57829003601f168201915b5050505050905060006080600b6003886138749190615719565b61387e91906157df565b600b811061388e5761388e615835565b01805461389a9061578f565b80601f01602080910402602001604051908101604052809291908181526020018280546138c69061578f565b80156139135780601f106138e857610100808354040283529160200191613913565b820191906000526020600020905b8154815290600101906020018083116138f657829003601f168201915b505050505090506000606e600d60028961392d9190615719565b61393791906157df565b600d811061394757613947615835565b0180546139539061578f565b80601f016020809104026020016040519081016040528092919081815260200182805461397f9061578f565b80156139cc5780601f106139a1576101008083540402835291602001916139cc565b820191906000526020600020905b8154815290600101906020018083116139af57829003601f168201915b505050505090506000607b87600581106139e8576139e8615835565b0180546139f49061578f565b80601f0160208091040260200160405190810160405280929190818152602001828054613a209061578f565b8015613a6d5780601f10613a4257610100808354040283529160200191613a6d565b820191906000526020600020905b815481529060010190602001808311613a5057829003601f168201915b505050505090506000613a7f85613fe1565b613a8885613fe1565b613a9184613fe1565b613a9a86613fe1565b604051602001613aad949392919061489c565b60405160208183030381529060405290508615613b7e5780613b5b606d6000018054613ad89061578f565b80601f0160208091040260200160405190810160405280929190818152602001828054613b049061578f565b8015613b515780601f10613b2657610100808354040283529160200191613b51565b820191906000526020600020905b815481529060010190602001808311613b3457829003601f168201915b5050505050613fe1565b604051602001613b6c92919061486d565b60405160208183030381529060405290505b98975050505050505050565b6060600080613b9c8460000151611ead565b91509150600060ae6000866000015181526020019081526020016000206040518060a0016040529081600082018054613bd49061578f565b80601f0160208091040260200160405190810160405280929190818152602001828054613c009061578f565b8015613c4d5780601f10613c2257610100808354040283529160200191613c4d565b820191906000526020600020905b815481529060010190602001808311613c3057829003601f168201915b50505050508152602001600182015481526020016002820154815260200160038201548152602001600482015481525050905060006001613c918360000151612eea565b11613cab5760405180602001604052806000815250613ccd565b8151604051613cbd9190602001614aac565b6040516020818303038152906040525b905080613cdd87600001516134e4565b613ce6866134e4565b613cef866134e4565b604051602001613d0294939291906152bd565b604051602081830303815290604052945050505050919050565b60606000613d2d83604001516134e4565b613d3a84606001516134e4565b604051602001613d4b929190614ba7565b60408051601f198184030181529190529392505050565b606060008260a00151613d8f57604051806040016040528060028152602001616e6f60f01b815250613dac565b6040518060400160405280600381526020016279657360e81b8152505b905060008360c00151613dd957604051806040016040528060028152602001616e6f60f01b815250613df6565b6040518060400160405280600381526020016279657360e81b8152505b905060008282613e0987608001516134e4565b613e1288613ffc565b613e1b89614030565b613e248a614088565b613e2d8b6140e0565b604051602001613e439796959493929190614cd7565b60408051601f1981840301815291905295945050505050565b6060600080613e6e8460000151611ead565b91509150613e7b826134e4565b613e84826134e4565b604051602001612d2a929190615379565b606081604051602001613ea8919061544e565b6040516020818303038152906040529050919050565b6000818310613eda576000828152602084905260409020612a2b565b5060009182526020526040902090565b60015481613f0b5760405163b562e8dd60e01b815260040160405180910390fd5b6001600160a01b03831660008181526006602090815260408083208054680100000000000000018802019055848352600590915281206001851460e11b4260a01b178317905582840190839083907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8180a4600183015b818114613fba57808360007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a4600101613f82565b5081613fd857604051622e076360e81b815260040160405180910390fd5b60015550505050565b6060613fec826135e2565b604051602001613ea89190614ad3565b60606000605261400f8460800151613748565b6005811061401f5761401f615835565b01604051602001613d4b919061527c565b606060006045601d600d6002866020015161404b9190615719565b61405591906157df565b600d811061406557614065615835565b0154600d811061407757614077615835565b01604051602001613d4b9190614c88565b606060006057602f600b600386602001516140a39190615719565b6140ad91906157df565b600b81106140bd576140bd615835565b0154600b81106140cf576140cf615835565b01604051602001613d4b919061556d565b606060006062603a600b600486602001516140fb9190615719565b61410591906157df565b600b811061411557614115615835565b0154600b811061412757614127615835565b01604051602001613d4b91906153cc565b8260038101928215614166579160200282015b8281111561416657823582559160200191906001019061414b565b5061417292915061428a565b5090565b8260058101928215614166579160200282018281111561416657823582559160200191906001019061414b565b8280546141af9061578f565b90600052602060002090601f0160209004810192826141d15760008555614166565b82601f106141ea5782800160ff19823516178555614166565b82800160010185558215614166579182018281111561416657823582559160200191906001019061414b565b8280546142229061578f565b90600052602060002090601f0160209004810192826142445760008555614166565b82601f1061425d57805160ff1916838001178555614166565b82800160010185558215614166579182015b8281111561416657825182559160200191906001019061426f565b5b80821115614172576000815560010161428b565b600067ffffffffffffffff808411156142ba576142ba61584b565b604051601f8501601f19908116603f011681019082821181831017156142e2576142e261584b565b816040528093508581528686860111156142fb57600080fd5b858560208301376000602087830101525050509392505050565b80356001600160a01b03811681146137a357600080fd5b60008083601f84011261433e57600080fd5b50813567ffffffffffffffff81111561435657600080fd5b6020830191508360208260051b850101111561437157600080fd5b9250929050565b60006020828403121561438a57600080fd5b612a2b82614315565b600080604083850312156143a657600080fd5b6143af83614315565b91506143bd60208401614315565b90509250929050565b6000806000606084860312156143db57600080fd5b6143e484614315565b92506143f260208501614315565b9150604084013590509250925092565b6000806000806080858703121561441857600080fd5b61442185614315565b935061442f60208601614315565b925060408501359150606085013567ffffffffffffffff81111561445257600080fd5b8501601f8101871361446357600080fd5b6144728782356020840161429f565b91505092959194509250565b6000806040838503121561449157600080fd5b61449a83614315565b9150602083013580151581146144af57600080fd5b809150509250929050565b600080604083850312156144cd57600080fd5b6144d683614315565b946020939093013593505050565b600080600080604085870312156144fa57600080fd5b843567ffffffffffffffff8082111561451257600080fd5b61451e8883890161432c565b9096509450602087013591508082111561453757600080fd5b506145448782880161432c565b95989497509550505050565b6000806020838503121561456357600080fd5b823567ffffffffffffffff81111561457a57600080fd5b6145868582860161432c565b90969095509350505050565b6000606082840312156145a457600080fd5b82606083011115611afc57600080fd5b600060a082840312156145c657600080fd5b8260a083011115611afc57600080fd5b6000602082840312156145e857600080fd5b5035919050565b60006020828403121561460157600080fd5b8135612a2b81615861565b60006020828403121561461e57600080fd5b8151612a2b81615861565b60006020828403121561463b57600080fd5b813567ffffffffffffffff81111561465257600080fd5b8201601f8101841361466357600080fd5b612c6b8482356020840161429f565b60006020828403121561468457600080fd5b5051919050565b6000806000604084860312156146a057600080fd5b83359250602084013567ffffffffffffffff808211156146bf57600080fd5b818601915086601f8301126146d357600080fd5b8135818111156146e257600080fd5b8760208285010111156146f457600080fd5b6020830194508093505050509250925092565b6000815180845261471f816020860160208601615763565b601f01601f19169290920160200192915050565b60008151614745818560208601615763565b9290920192915050565b8054600090600181811c908083168061476957607f831692505b602080841082141561478b57634e487b7160e01b600052602260045260246000fd5b81801561479f57600181146147b0576147dd565b60ff198616895284890196506147dd565b60008881526020902060005b868110156147d55781548b8201529085019083016147bc565b505084890196505b50505050505092915050565b7f7b202274726169745f74797065223a202274797065222c202276616c7565223a81526808089c195d1cc89f4b60ba1b602082015260290190565b7f7b202274726169745f74797065223a2022626972746864617465222c20227661815266363ab2911d101160c91b602082015260270190565b8183823760009101908152919050565b6000835161487f818460208801615763565b835190830190614893818360208801615763565b01949350505050565b600085516148ae818460208a01615763565b8551908301906148c2818360208a01615763565b85519101906148d5818360208901615763565b84519101906148e8818360208801615763565b019695505050505050565b60008651614905818460208b01615763565b80830190507f226465736372697074696f6e223a202254616d61676f6769206973206120546181527f6d61676f74636869204461707020616e642066756c6c792067656e657261746560208201527f64206f6e2d636861696e2e2054686520636f6e747261637420696e746572616360408201527f74696f6e20616e642074696d652077696c6c206166666563742074686520737460608201527f6174757320616e64207265616374696f6e206f6620746865207065742e20496660808201527f20796f7520636f6c6c656374206f74686572206974656d732c2074686520706560a0820152721d081dda5b1b081cda1bddc81b1bdd9948488b606a1b60c08201526e2261747472696275746573223a205b60881b60d38201528651614a328160e2840160208b01615763565b614a9f614a91614a8b614a53614a4d60e2868801018c614733565b8a614733565b7f5d2c22696d616765223a2022646174613a696d6167652f7376672b786d6c3b62815265185cd94d8d0b60d21b602082015260260190565b87614733565b61227d60f01b815260020190565b9998505050505050505050565b60008251614abe818460208701615763565b6201017960ed1b920191825250600301919050565b7f3c696d61676520783d22302220793d2230222077696474683d2233322220686581527f696768743d2233322220696d6167652d72656e646572696e673d22706978656c60208201527f6174656422207072657365727665417370656374526174696f3d22784d69645960408201527f4d69642220786c696e6b3a687265663d22646174613a696d6167652f706e673b60608201526618985cd94d8d0b60ca1b608082015260008251614b8d816087850160208701615763565b6211179f60e91b6087939091019283015250608a01919050565b7f7b202274726169745f74797065223a202268756e676572222c2022646973706c81527f61795f74797065223a20226e756d626572222c202276616c7565223a20000000602082015260008351614c0581603d850160208801615763565b8083019050611f4b60f21b80603d8301527f7b202274726169745f74797065223a2022626f726564222c2022646973706c61603f8301527f795f74797065223a20226e756d626572222c202276616c7565223a2000000000605f8301528451614c7581607b850160208901615763565b607b920191820152607d01949350505050565b7f7b202274726169745f74797065223a2022656172222c202276616c7565223a208152601160f91b60208201526000614cc4602183018461474f565b62089f4b60ea1b81526003019392505050565b6000614ce2826147e9565b7f7b202274726169745f74797065223a20226d6173746572222c202276616c7565815263111d101160e11b60208201528951614d25816024840160208e01615763565b62089f4b60ea1b6024929091019182018190527f7b202274726169745f74797065223a20227265726f6c6c6564222c202276616c6027830152653ab2911d101160d11b60478301528951614d8081604d850160208e01615763565b604d9201918201527f7b202274726169745f74797065223a2022756e68617070696e657373222c202260508201527f646973706c61795f74797065223a20226e756d626572222c202276616c75652260708201526101d160f51b6090820152614e1b614e15614a8b614e0f614e09614dfb609287018e614733565b611f4b60f21b815260020190565b8b614733565b89614733565b85614733565b9a9950505050505050505050565b6a7b226e616d65223a20222360a81b81528551600090614e5081600b850160208b01615763565b6a040a8c2dac2cedeced240560ab1b600b918401918201528651614e7b816016840160208b01615763565b7314911610113232b9b1b934b83a34b7b7111d101160611b601692909101918201528551614eb081602a840160208a01615763565b61088b60f21b9101602a8101919091526e2261747472696275746573223a205b60881b602c8201527f7b202274726169745f74797065223a202274797065222c202276616c7565223a603b8201526908089c1c9bdc1cc89f4b60b21b605b8201527f7b202274726169745f74797065223a20227573616765222c202276616c7565226065820152621d101160e91b6085820152613b7e614fc0614fba614f6b614f5b60888601614a4d565b63089f574b60e21b815260040190565b7f22696d616765223a2022697066733a2f2f516d56784344666d7767593270734181527f683777746938614c43796b6b6a3939736e79674751383970327a6b664174662f602082015260400190565b86614733565b652e676966227d60d01b815260060190565b6a7b226e616d65223a20222360a81b81528151600090614ff981600b850160208701615763565b7f2054616d61676f67692028556e72657665616c2050726f707329222c20226465600b9390910192830152507f736372697074696f6e223a2022556e72657665616c2050726f7073222c000000602b8201526e2261747472696275746573223a205b60881b60488201527f7b202274726169745f74797065223a202274797065222c202276616c7565223a605782015268202270726f7073227d60b81b607782015261174b60f21b60808201527f22696d616765223a2022697066733a2f2f516d5462423644443277387433367a60828201527f4c50764245646f576f363252464d794a69394558636a39395a6978507278432260a2820152607d60f81b60c282015260c301919050565b6a7b226e616d65223a20222360a81b8152865160009061512b81600b850160208c01615763565b6e040a8c2dac2cedeced2408acece405608b1b600b91840191820152875161515a81601a840160208c01615763565b602f60f81b601a9290910191820152865161517c81601b840160208b01615763565b602960f81b9101601b8101919091527f222c20226465736372697074696f6e223a2022556e62726f6b656e2054616d61601c8201526d19dbd9da481959d9dccb8b8b888b60921b603c8201526e2261747472696275746573223a205b60881b604a820152614a9f614fc0614fba61522d61521f614a91614e0961521261520c61520760598b016147e9565b614824565b8e614733565b602f60f81b815260010190565b61174b60f21b815260020190565b7f22696d616765223a2022697066733a2f2f516d57317463635971426d534c514681527f54664e38725777384a4858787837685a53344d6969775757444e35747647382f602082015260400190565b7f7b202274726169745f74797065223a20227265616374696f6e222c202276616c8152653ab2911d101160d11b60208201526000614cc4602683018461474f565b693d913730b6b2911d101160b11b815284516000906152e381600a850160208a01615763565b602360f81b600a91840191820152855161530481600b840160208a01615763565b6a040a8c2dac2cedeced240560ab1b600b92909101918201528451615330816016840160208901615763565b602f60f81b601692909101918201528351615352816017840160208801615763565b602960f81b6017929091019182015261088b60f21b6018820152601a019695505050505050565b600061538482614824565b8451615394818360208901615763565b602f60f81b910190815283516153b1816001840160208801615763565b61227d60f01b60019290910191820152600301949350505050565b7f7b202274726169745f74797065223a2022626f6479222c202276616c7565223a815261101160f11b60208201526000614cc4602283018461474f565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c00000081526000825161544181601d850160208701615763565b91909101601d0192915050565b7f3c7376672077696474683d2239363022206865696768743d223936302220766581527f7273696f6e3d22312e31222076696577426f783d22302030203332203332222060208201527f786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f737660408201527f672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f7260608201526d3397989c9c9c97bc3634b735911f60911b60808201527f3c726563742077696474683d223130302522206865696768743d223130302522608e82015271103334b6361e9111b0b0b21c9c9c9110179f60711b60ae820152600082516155508160c0850160208701615763565b651e17b9bb339f60d11b60c093909101928301525060c601919050565b7f7b202274726169745f74797065223a202268656164222c202276616c7565223a815261101160f11b60208201526000614cc4602283018461474f565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906130e490830184614707565b6020808252825182820181905260009190848201906040850190845b81811015611dda578351835292840192918401916001016155f9565b602081526000612a2b6020830184614707565b60a08152600061563b60a0830188614707565b90508560208301528460408301528360608301528260808301529695505050505050565b60208082526010908201526f139bdd081d985b1a59081c195d081a5960821b604082015260600190565b6020808252600a9082015269139bdd081c995d99585b60b21b604082015260600190565b86815260208101869052604081018590528315156060820152821515608082015260c08101600483106156f057634e487b7160e01b600052602160045260246000fd5b8260a0830152979650505050505050565b60008219821115615714576157146157f3565b500190565b60008261572857615728615809565b500490565b6000816000190483118215151615615747576157476157f3565b500290565b60008282101561575e5761575e6157f3565b500390565b60005b8381101561577e578181015183820152602001615766565b838111156121735750506000910152565b600181811c908216806157a357607f821691505b60208210811415611afc57634e487b7160e01b600052602260045260246000fd5b60006000198214156157d8576157d86157f3565b5060010190565b6000826157ee576157ee615809565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160e01b03198116811461263857600080fdfe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa264697066735822122069c56940fd46b970901e4cefbf1663ce7fd9f697bb1b49a889da5193c1fc526564736f6c63430008070033
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.