ETH Price: $3,284.63 (+0.59%)
Gas: 34 Gwei

Token

Mystic Forest (MFS)
 

Overview

Max Total Supply

410 MFS

Holders

81

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Filtered by Token Holder
913.eth
Balance
3 MFS
0x65654ef196d92ff739a4de49a133887002a08df2
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
MysticForest

Compiler Version
v0.8.7+commit.e28d00a7

Optimization Enabled:
Yes with 100 runs

Other Settings:
default evmVersion
File 1 of 15 : forrest.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";

contract MysticForest is ERC721, ERC721Enumerable, Ownable {
    using Counters for Counters.Counter;
    using SafeMath for uint256;

    Counters.Counter private _tokenIdCounter;
    uint256 private tokenPrice = 30000000000000000; //0.03 ETH
    uint256 private constant nftsNumber = 3333;

    constructor() ERC721("Mystic Forest", "MFS") {
        _tokenIdCounter.increment();
    }
     
    function safeMint(address to) public onlyOwner {
        _safeMint(to, _tokenIdCounter.current());
        _tokenIdCounter.increment();
    }

    function _beforeTokenTransfer(address from, address to, uint256 tokenId)
        internal
        override(ERC721, ERC721Enumerable)
    {
        super._beforeTokenTransfer(from, to, tokenId);
    }

    function supportsInterface(bytes4 interfaceId)
        public
        view
        override(ERC721, ERC721Enumerable)
        returns (bool)
    {
        return super.supportsInterface(interfaceId);
    }
    
    function random(string memory input) internal pure returns (uint256) {
        return uint256(keccak256(abi.encodePacked(input)));
    }
    
    function toHashCode(uint256 value) internal pure returns (string memory) {
        uint256 i;

        bytes memory buffer = "000000";
        for(i=6;i>0;i--) {
            if (value % 16 < 10)
                buffer[i-1] = bytes1(uint8(48 + uint256(value % 16)));
            else
                buffer[i-1] = bytes1(uint8(55 + uint256(value % 16)));

            value /= 16;
        }
        return string(buffer);
    }
    
    
    function getSun(uint256 num) internal pure returns (string memory) {
        uint256 suns;

        suns = 733410643314582114512314603012454017743510734712492414;

        if (num > 0)
            suns = suns / (100 ** (num*3));

        return string(abi.encodePacked('cx="',toString(10*((suns/10000)%100)),'" cy="',toString(10*((suns/100)%100)),  '" r="',toString(10*(suns%100)),'"'));
    }

    function toString(uint256 value) internal pure returns (string memory) {
        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);
    }
    
    function toStringSgn(int256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0";
        }
        int256 temp = value >= 0 ? value : -value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        if (value < 0) {
            digits++;
        }
        bytes memory buffer = new bytes(digits);
        if (value < 0) {
            //digits -= 1;
            value = -value;
            buffer[0] = bytes1(uint8(45));
        }
        
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        
        return string(buffer);
    }
    
    function getPoints(uint256 num, uint256 dir) public pure returns (string memory ) {
        uint256[181]memory xtypes =[
            451793160510049142483918980479775049983908311004982111838287590179673737989,
            14118699526057964743410206948092109528394018437505512525414365549665044271,
            2990036367364346621795866131653571121699026289141046,
            2846959607925562073345508372401376781316743025224824348287758227432596905387,
            2992194365839321942769086036007447618697968584327369,
            3753734288543931459086705196516412049375550376183621772483166746286184606530,
            3597369614550173525007166796257012767273641370844282701925507925543792285476,
            3075761135342858797770537856738277071188091692804336596343286722299200667402,
            3271440244353497429621230532185176914974600625852871336223639350182882160947,
            3567277993316903498903678063180104354953965719249179472654654856748081471205,
            14116380865331896385391450086178179633152641401541680509438725334071115455,
            2928482646864365553151142455467482501976710809299108047461350705223466036572,
            3821675339075292395182255302395855070914232488246053891403721248044174656656,
            3115984019240715960323244328181115455415043147489357163259133709542708861632,
            3244496427842502701626018574735712370044808469909759174473139369101112483559,
            2987353119357672916579205987982357504557173396589332,
            2324379648625379036385613574183488699472078952337521869568077904426458695082,
            1217389987403007936526409203484901692820865472055694339022933326868434208476,
            2417010777913069026691127,
            3441913708957137518381877344345889930126595129725057885264505170531043574126,
            2917600651716002271669893996375613785659812323984791490780495802912166578946,
            3708293718636760152364718089342064469940324999664627799228079694530507806907,
            14110665356844149303507105224900996936092881811303175606715491365591308984,
            3158444373777377413788230076701033876397915336301543208713906208600121680810,
            2817275567468375932596139929010515239344556343459808531647085207214086288099,
            6033198342414225328300838243277501079158001050375815138405344997606103814822,
            511,
            2720100494981947149539386702781528929757544005649907703010181904670973973504,
            2408277705204458091040044302132094573526111473190295366598038857750651699947,
            14107169532839929700752091609538676282944105693729639298668804927339193532,
            1221861636475146439091757024136704920792770829275233582034370279380946780480,
            1929745078649056008424622866595262801745570856914548905876583021709899361596,
            4191612511679389882886921941088289735083347780575901480897275437039305163532,
            4343672155361759899968976175801058502330943465806784759312473237134593393414,
            3566948221669800087678086064374772626813770766313968875691818267877922725523,
            2844054930834458621500612357249982365132495895267457727130737277089430495386,
            2831495325425439623070653177758459898886181703506414534104480167890488760425,
            1939784730250891792929893416777521507641579746635591985114370828684217120906,
            710500672182797626540852971474592761735170912982147831611021980890913641100,
            669528245421993200021192424975553018500427455508620586550532192993530410145,
            2786907874801123243278384440540569289884967736012447883743896884908079991958,
            783107716654838027593076735110698867723631140942751048784,
            1223742098789066363086146454490327367432992460366389926123382679180957712679,
            2989461533470413134394949618378485716466310952657952709026655806765503873313,
            4078587196827700236148252441598457738652016331251713638460871880042585108753,
            4093662014144226772182022731933318239401904060323200219570934945711682620714,
            4418350303103987658838040236072521517526306626247445323272330839020818545973,
            4643374242505799556552622217641105384457783205137552427483606424730257476378,
            4486704919427852534038064683873585202257802529007438651353378708385046889726,
            4499817856359707397730280519483643102692499149107402831319735562894054958274,
            4485047847576554290163471944750006657681399132671410856687041433809695181498,
            3339683520300060376447863508244732503262915016529560249180018002256610357913,
            4314878010312732853382723482941746333872906915161246828553891387663095579798,
            4074365359127156374762978298570824350410250584226094189806368457852740328077,
            2436326669430798195291140631745346883464912839142971982342415690991918792828,
            2844633605229433334766034265509774244631325963311003701214089162068265098949,
            6021414796764815790125087145808661297551719617535403347668275848711477729927,
            35115764503978,
            2294397700659397197699685406473997836554794841367326523950238727322888134340,
            2025283187394261770417930627778433871681276905838016306264739971388040888997,
            2139603985908275075394494527883218115071698703519051893093505600987932723858,
            1602149956337663419398244079233223101532761471563090164321742541338988053665,
            738518038087913997980297120834578920434720559540340738145828685906757868759,
            1021903637670771945756436204332950418418658165449833330825908986328191100032,
            680321428688133661527588016944122147941545355974128538876479717265524186287,
            2913459048355080754922760102631198697031511036604646793395992893426023029303,
            3479130709408447676265801231112877966675791703322346548396001197341351923258,
            3253854748105555120936084797666487228976513545459761200829578045966826558534,
            1699189092874344557865822570537512574159152442335308490674709866561864328806,
            667400986628054122756790148927330777523787572677566916314191737094336736856,
            2873236813626440676171292303262262666143114256158109036142099440858322466905,
            2463849106514764934759999084079940125420965362783417301190030635058228465285,
            205438914033105927166860879746299341319617056510616058071714482,
            1038298747581850190237060263176966035035230656825643754185710646059835386620,
            3732457000988826922007756981740258362491522747964965354310174111752044251,
            3438103229906894537734127924212645170137014733982627380114740921114531725405,
            6026623316013678363917195968975149767749651216939496676609297726456481298556,
            2241115314331019743849717121383702017708454573017073812756468592096814519488,
            2681337874473351023978523739001495494271733781408597532984622975686384632096,
            2001763240303821190799393538957491125291823459084909037776275767301748935526,
            783413015098298932391713953208811102504075259788668508482,
            2776969648718084143666140509500198189279833454686509566456828797242640011984,
            2414986924677709585549545,
            2464981860802702008248797613075615501215516799470075317970249081860416421077,
            2790303763375407904938366532926037490714110175281242670150366813065796212937,
            2465617633008893670180232371899505684333818314842213059041399293168815016146,
            11401324657414517125554847765234191730741173982,
            2007586617321629222923565623524787798034647400175032804774855609950202812116,
            1672990505318255906211175434427645236074840599879267478213906817477142731280,
            9209241678118184635,
            3468278804203466157829532655206811853319359876474512079669760097188562518207,
            3368092997782354757286082990925204154758011631855831233655982736879923093696,
            3466927620119320294039074189203980316785782842647169496311690405307103440018,
            5997944131679293691663553390168068182099797190984646160656605843082062729358,
            166052324687270284571457507386895010,
            3085920706480894367934793525780658400280345745353555300919491971404221773981,
            3381923554997078344785988371461154782062075902541709693502099696739921014948,
            3325992182572119952955425236755568253968694395336855696455540407431783377038,
            3580226521759520107286065368001833307388687503078515293404116916742493691037,
            9214447060903921835,
            1264984556772872115799239535623524884253620648193824583495524875928754752372,
            1518694096269015099096880765822086114228988044590962307891613193926223639292,
            14108292701559715841792991169612211414500920245362129234577009518961809647,
            4402309342509142896983013934442726920810334999082253451627659966777804363614,
            5166666755085030868803444639761683845012503598362881109034321078214982796000,
            5209789353333249880387445761925302865630999691231556305081968356544667639561,
            4687711984736242421744479873093886204824147798593512993564205989451328829754,
            633401437854182220628048116557,
            4160112497456759832337992694410202976874104741130252497257247851041788420278,
            3891799183155487259340119950380455072303927206702853094379188893373129184420,
            4032319059663099998613520512820426697785970979928996764016646343459105024168,
            6009124949811886177795131206969081357356598945839022389523915066407043351690,
            4372824752384694282188496870332751107712575766430818661088545374422765321323,
            511,
            4572783505867648305281967398068273625119110075055536844749714995321564755266,
            4911328827335463014379332819972782815283711440757324548670808260875358996733,
            4954975634469296598514925777471018546955821345030274703468035996303540008180,
            9218679515535855434,
            3452321906512025464371802897836094518801199388935465272003231966772078459556,
            3748795261402758157788885492974445466658083400195392878155357454986132445816,
            3693223752333072151459562658612960597342516520193788012145779387957259162222,
            166100478298923491154776583125472921,
            4106912717246667397226625890641599430529090592382302926370216293486154887481,
            3908087369193035517127117204590882787971039887165197271342261232177579172126,
            4019730387115211301930848795814057164513472405301479405129673201161948762874,
            4018018908936592607058282959488975987548663007885063821141157517257090944708,
            4089300309602240007959434644505762866602904250751726411778648112543795920524,
            4315071312289070109850147802022436970240917711138035951472706131873335498401,
            4725202305958257607474266791898393255878424154030894468088061083124026994324,
            4683680110174487984206714084092740316576662890866513069791112855826925306027,
            4457910940450972001776820480444395513452836462258651691797388206013323572411,
            5914901893015460913288455038769590541213807873541693763162803986498813334735,
            5873017302155366219580613819295633263556778663954408054822111840194936602855,
            4785246056814329393415455871264870088767110637544142448838340819902228544776,
            53873736278750663526986526463830033766076938107653441239559073616152,
            3961230583850472195613434616701520650168113370266317092807283110795912059980,
            4159974300347659916450908224181423693787057029892764815291476147123686097536,
            4696849232163410979886557344830309530276030548981272388554922402907907053214,
            4555252517360058801235317977916661134159115037001481971805637241651654724760,
            4555280178158998160895654468742184453035832431543937761396878704524961674893,
            4682797599279848964386326277705955728837885892369600134905466615452314795661,
            2991124662820466729985366582785995318337604215546002,
            4094794229538461950196996980986282399454829575579897639099107199351723801495,
            4488498896934177163671566746299360720998703618133128471784444635917868747625,
            4870470494855650238260992884771850191437967751124123170685490486885430760267,
            4996414205762082127019268313479351099601209822643463938109046716488425055526,
            4374315480207661070076200965843976990402875250847505604199786248963436759813,
            4993487853199467340812965741758286970078604087317064681517188962153421756119,
            4611709501646942332033416691737330215799267808709507583702922506831535976105,
            4553457678274957529173455164972517555198985209347470674437518245996323048065,
            3983655792221959106678542874491535023802240994398748708194091973432699153987,
            511,
            2751764049184355665970427661834368826893000635972708917258254524379653095834,
            3996762043688216515082017709646178332496394459296666445946293863156097062241,
            3854557703404383100840836971486404259590598414489461376417567508339986407800,
            3401413784224831724878919757846841118321199606089710978620901144409073395044,
            4419424766817352224692370267239741687023769241515970830156920086838702632782,
            3669119147830135099252246142986051209252166546386211128736251135120952430949,
            4036708964316911879340196539985070616330457410477349779590474447422696063757,
            4786904208120125539628028421123318453534542575865124491913205630904344135979,
            4927010409629265575240327547968006977797442604613099202290221307456865605964,
            4530848496956884285912366022076978316699445255927116468642440159401239554349,
            4897830200248151060304598534559494633163927757987279030443661669629025228570,
            4982141284371903555041559258627467217052791415694756268205937693649074559228,
            5051104011357210160921999575117301746262595505134723231406126068278101469919,
            4428758230533668701111108424422998856252086733747575715414198910256133618362,
            4555916003654641992253243995961629462190195338819898436721465933797476443822,
            4922316665112551244551227182538960607585056393399270553803496721819810573972,
            4526017686709248224619740044776819724367225939391434944440434506284260568183,
            3904388555610503058690726102571162509580816304148758661208200338363226694753,
            4610329741180249610163619688882547569496715425741848059399482580093453349996,
            4369816174511426972967861755239262887278514684876866413910128789616023209563,
            3677346549089972577976174802446580897876944132670129399346325781540561909838,
            3408261474405718409088466451838629603401564969655245534647691783341921921622,
            165976556783559723167202694497953337,
            2990235126345283631822877804924730718839988305133692,
            43513319658703679254636568203538827443336,
            43522980609105388572596600985827531712216,
            43522146275689570242343825481909074813128,
            11408759685182567224012020944406186655893315218,
            11408934930604125130349902336635238117986951321
            ];
        uint256 i;
        uint256 first_index;
        uint256 cur_num;
        uint256 k;
        int256 dir_y;
        uint256 pos;
        string memory res;
        uint256 result;
        
        first_index = num < 3 ? num+1 :  (xtypes[0] / (256 ** (num-3)))%256;
        
        if (dir==1)
            dir_y = 140;
        else
            dir_y = 900;
        res = '';
    
        for(i = first_index; i<=181; i++) {
            if (xtypes[i] == 0)
                break;
    
            cur_num= xtypes[i];    
            k=0;
            for(pos=0;pos<=27;pos++) {
                result = (cur_num /  (512 ** pos)) % 512;
                if (result == 511)
                    break;
    
                if (k%2 == 0) {
                    if (dir==1)
                        res = string(abi.encodePacked(res, toStringSgn(int256((result*3))-140), ','));
                    else
                        res = string(abi.encodePacked(res, toStringSgn(1250-int256((result*3))), ','));

                }
                else {
                    res = string(abi.encodePacked(res, toStringSgn(int256((result*3*dir))-dir_y), ' '));

                }
                k++;
             }   
            if (result == 511)
                break;
        }

        return res;
    }
    
    function tokenURI(uint256 tokenId) pure public override(ERC721)  returns (string memory) {
        uint256[19] memory xtypes;
        string[5] memory colors;

        string[15] memory parts;
        uint256[12] memory params;

        uint256 pos;

        uint256 rand = random(string(abi.encodePacked('Forest',toString(tokenId))));

        params[0] = 1 + (rand % 36); // pallette=
        params[1] = 1 + ((rand/100) % 9);// mount
        params[2] = 1 + ((rand/1000) % 2); // savanna
        params[3] = 1 + ((rand/10000) % 2); // tree1
        params[4] = 1 + ((rand/100000) % 2); // tree2
        params[5] = 1 + ((rand/1000000) % 9); // animal
        params[6] = 1 + ((rand/10000000) % 9); // monster
        params[7] = 1 + ((rand/100000000) % 2); // grass
        params[8] = 1 + ((rand/1000000000) % 9); // sun
        params[9] = 1 + ((rand/10000000000) % 20); // METEOR
        if (((rand/10000000000) % 20) == 1) // rare palette
            params[0] = 37 + params[0]%2;

        xtypes[0] = 1380184997384756203389348097935548270238418335313894369135963045576512;
        xtypes[1] = 83202958701067158272510542586996495922438516550026878711368311707271070;
        xtypes[2] = 110890097058345544686991556799584296435994298503832019423597570805434368;
        xtypes[3] = 124747513234871200025641583470717623407926130169324315491794011723611968;
        xtypes[4] = 172545869938643596635233103058992932872987519665270880114754418406014784;
        xtypes[5] = 62901452128639038462844002121514286276591308821405480058892378347355968;
        xtypes[6] = 6906312258075195189521669129432903118929838785118276903637969883103134;
        xtypes[7] = 34644103446304817287021645401906549158943647054285149371488762479984448;
        xtypes[8] = 460428004036880295485476712922934712833987410898445681727580956905712;
        xtypes[9] = 165644650256154674906236099093466854341981357834224037341526031155019069;
        xtypes[10] = 568830213016122120965376512587328509977555256782756811911715291660190;
        xtypes[11] = 408475849166444685717692499863891921759522907256683076899882642964479;
        xtypes[12] = 138036611714692334195370901026278071274391887700961563656694752681606976;
        xtypes[13] = 138036611664120373689974417613175875397870210537061667156895429971376248;
        xtypes[14] = 164484919190898338221032560993011736145912193578603571776097733172223;
        xtypes[15] = 262270363244384067749521393870671431072564228073668465975395327494012736;
        xtypes[16] = 372697461957250082012985360966108567877767279094447770984938832788406080;
        xtypes[17] = 404941104510058468213265706796467786427704521430213011681667002136491;
        xtypes[18] = 33834578429608361535043529526350847219631511783612495748003004329;

        if (params[9] <= 7) {
            for(pos=0;pos<1+params[9]/2;pos++) {
                parts[14] = string(abi.encodePacked(parts[14], '<circle opacity="0.4" fill="#FFFF9E" cx="',toString(400 + pos*150),'" cy="-',toString((69+pos*200)%275),'" r="4"/>'));
            }
            parts[14] = string(abi.encodePacked('<g>',parts[14],'<animateMotion path="M 0 0 l ',(params[9]%2==0?'':'-'),'10000 10000 20 Z" dur="20s" repeatCount="indefinite" /> </g>'));
        }
    
        pos = (params[0]-1) * 5;
        colors[0] = toHashCode(xtypes[pos/10] / (16777216 ** (pos%10)) % 16777216);
    
        pos = (params[0]-1) * 5 + 1;
        colors[1] = toHashCode(xtypes[pos/10] / (16777216 ** (pos%10)) % 16777216);
        
        pos = (params[0]-1) * 5 + 2;
        colors[4] = toHashCode(xtypes[pos/10] / (16777216 ** (pos%10)) % 16777216);
        
        pos = (params[0]-1) * 5 + 3;
        colors[3] = toHashCode(xtypes[pos/10] / (16777216 ** (pos%10)) % 16777216);
        
        pos = (params[0]-1) * 5 + 4;
        colors[2] = toHashCode(xtypes[pos/10] / (16777216 ** (pos%10)) % 16777216);
        
        parts[0] = '<?xml version="1.0" encoding="utf-8"?> <svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="1000px" height="1000px" viewBox="0 0 1000 1000"> <linearGradient id="B" gradientUnits="userSpaceOnUse" x1="500" y1="1000" x2="500" y2="0"> <stop offset="0" style="stop-color:#'; // 1
        parts[1] = '"/> <stop offset="0.5" style="stop-color:#'; // 2
        parts[2] = '"/> <stop offset="1" style="stop-color:#'; // 1
        parts[3] = string(abi.encodePacked('"/> </linearGradient> <rect fill="url(#B)" width="1000" height="1000"/> <radialGradient id="S" ',getSun(params[8]-1),' gradientUnits="userSpaceOnUse"> <stop offset="0.75" style="stop-color:#FFFF9E"/> <stop offset="1" style="stop-color:#')); // 2
        parts[4] = string(abi.encodePacked('"/> </radialGradient> <circle opacity="0.9" fill="url(#S)" ',getSun(params[8]-1),'/> ',parts[14], '<polygon opacity="0.14" fill="#')); // 3
        parts[5] = string(abi.encodePacked('" points="',getPoints(0+params[1]-1,1),'"/> <polygon opacity="0.6" fill="#')); // 3
        parts[6] = string(abi.encodePacked('" points="',getPoints(9+params[2]-1,1),'"/> <polygon fill="#')); // 3
        parts[7] = string(abi.encodePacked('" points="',getPoints(11+params[3]-1,1),'"> <animateMotion path="M 0 0 l 15 20 l 12 15 Z" dur="19s" repeatCount="indefinite" /> </polygon> <polygon fill="#')); // 3
        parts[8] = string(abi.encodePacked('" points="',getPoints(11+params[4]-1,2),'"> <animateMotion path="M 0 0 l 15 19 l 13 14 Z" dur="17s" repeatCount="indefinite" /> </polygon> <polygon fill="#')); // 3
        parts[9] = string(abi.encodePacked('" points="',getPoints(25+params[7]-1,1),'"> <animateMotion path="M 0 0 l 10 0Z" dur="16s" repeatCount="indefinite" /> </polygon>  <rect opacity="0" fill="#')); // 3
        parts[10] = string(abi.encodePacked('" width="1000" height="1100">',(params[6]<=3 ? '<animate attributeName="opacity" values="0;.3;.3;.4;.3;.3;0" dur="10s" repeatCount="1" begin="monster.end-10" restart="whenNotActive" />' : ''),'</rect><g opacity="0"> <polygon fill="#')); // 3
        parts[11] = string(abi.encodePacked('" points="',getPoints((params[6]<=3 ? 22 : 13)+params[(params[6]<=3 ? 6 : 5)]-1 ,1),'"/> ')); // 3
        if (params[6]<=3)
            parts[12] = string(abi.encodePacked('<polygon fill="#',colors[0],'" points="',getPoints(26+params[6]*2-1,1),'"> <animate attributeName="opacity" values="1;1;1;1;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1" dur="3s" repeatCount="indefinite" begin="0s" /> </polygon> <polygon fill="#',colors[0],'" points="',getPoints(26+params[6]*2,1),'"> <animate attributeName="opacity" values="1;1;1;1;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1" dur="3s" repeatCount="indefinite" begin="0s" /> </polygon>')); // 3
        else
            parts[12] = '<rect opacity="0" x="250" y="250" width="500" height="500"/>';
        parts[13] = '<animate attributeName="opacity" id="monster" values="0;1;1;1;1;0" dur="10s" repeatCount="1" begin="click" restart="whenNotActive" /><animate attributeName="opacity" values="0;1;0;0;0;0;0;0" dur="60s" repeatCount="indefinite" begin="30s" end="monster.start"/> <animateMotion path="M 0 0 l 0 -15Z" dur="30s" repeatCount="indefinite" /> </g></svg>';
                
        string memory output = string(abi.encodePacked(parts[0],colors[4],parts[1],colors[3],parts[2]));
        output = string(abi.encodePacked(output,colors[4],parts[3],colors[3],parts[4]));
        output = string(abi.encodePacked(output,colors[2],parts[5],colors[2],parts[6]));
        output = string(abi.encodePacked(output,colors[2],parts[7],colors[2],parts[8]));
        output = string(abi.encodePacked(output,colors[2],parts[9],colors[2],parts[10]));
        output = string(abi.encodePacked(output,colors[2],parts[11],parts[12],parts[13]));


        
        parts[0] = '[{ "trait_type": "Far", "value": "';
        parts[1] = toString(params[1]);
        parts[2] = '" }, { "trait_type": "Palette", "value": "';
        parts[3] = toString(params[0]);
        parts[4] = '" }, { "trait_type": "Savanna", "value": "';
        parts[5] = toString(params[7]*1000 + params[2] * 100 + params[3] * 10 + params[4]);
        if (params[6]<=3) {
            parts[6] = '" }, { "trait_type": "Monster", "value": "';
            parts[7] = toString(params[6]);
        } else {
            parts[6] = '" }, { "trait_type": "Animal", "value": "';
            parts[7] = toString(params[5]);
        }
        parts[8] = '" }, { "trait_type": "Sun", "value": "';
        parts[9] = toString(params[8]);
        if (params[9]<=7) {
            parts[9] = string(abi.encodePacked(parts[9],'" }, { "trait_type": "Meteor", "value": "', toString(params[9])));
        }
        parts[10] = '" }]';
        
        string memory strparams = string(abi.encodePacked(parts[0], parts[1], parts[2], parts[3], parts[4], parts[5]));
        strparams = string(abi.encodePacked(strparams, parts[6], parts[7], parts[8], parts[9], parts[10]));



        string memory json = Base64.encode(bytes(string(abi.encodePacked('{"name": "Mystic Forest", "description": "Mystic Forest - interactive game, completely generated OnChain","attributes":', strparams, ', "image": "data:image/svg+xml;base64,', Base64.encode(bytes(output)), '"}'))));
        output = string(abi.encodePacked('data:application/json;base64,', json));

        return output;
    }
    
    function claim() public  {
        require(_tokenIdCounter.current() <= 300, "No more free tokens");
        _safeMint(msg.sender, _tokenIdCounter.current());
        _tokenIdCounter.increment();

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

    function buyTokens(uint tokensNumber) public payable {
        require(tokensNumber > 0, "Wrong amount");
        require(tokensNumber <= 30, "Not more 30");
        require(_tokenIdCounter.current().add(tokensNumber) <= nftsNumber, "Sale finished");
        require(tokenPrice.mul(tokensNumber) <= msg.value, "Need more ETH");

        for(uint i = 0; i < tokensNumber; i++) {
            _safeMint(msg.sender, _tokenIdCounter.current());
            _tokenIdCounter.increment();
        }
    }

    
}




/// [MIT License]
/// @title Base64
/// @notice Provides a function for encoding some bytes in base64
/// @author Brecht Devos <[email protected]>
library Base64 {
    bytes internal constant TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

    /// @notice Encodes some bytes to the base64 representation
    function encode(bytes memory data) internal pure returns (string memory) {
        uint256 len = data.length;
        if (len == 0) return "";

        // multiply by 4/3 rounded up
        uint256 encodedLen = 4 * ((len + 2) / 3);

        // Add some extra buffer at the end
        bytes memory result = new bytes(encodedLen + 32);

        bytes memory table = TABLE;

        assembly {
            let tablePtr := add(table, 1)
            let resultPtr := add(result, 32)

            for {
                let i := 0
            } lt(i, len) {

            } {
                i := add(i, 3)
                let input := and(mload(add(data, i)), 0xffffff)

                let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))
                out := shl(8, out)
                out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))
                out := shl(8, out)
                out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))
                out := shl(8, out)
                out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))
                out := shl(224, out)

                mstore(resultPtr, out)

                resultPtr := add(resultPtr, 4)
            }

            switch mod(len, 3)
            case 1 {
                mstore(sub(resultPtr, 2), shl(240, 0x3d3d))
            }
            case 2 {
                mstore(sub(resultPtr, 1), shl(248, 0x3d))
            }

            mstore(result, encodedLen)
        }

        return string(result);
    }
}

File 2 of 15 : SafeMath.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

File 3 of 15 : Counters.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title Counters
 * @author Matt Condon (@shrugs)
 * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number
 * of elements in a mapping, issuing ERC721 ids, or counting request ids.
 *
 * Include with `using Counters for Counters.Counter;`
 */
library Counters {
    struct Counter {
        // This variable should never be directly accessed by users of the library: interactions must be restricted to
        // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
        // this feature: see https://github.com/ethereum/solidity/issues/4637
        uint256 _value; // default: 0
    }

    function current(Counter storage counter) internal view returns (uint256) {
        return counter._value;
    }

    function increment(Counter storage counter) internal {
        unchecked {
            counter._value += 1;
        }
    }

    function decrement(Counter storage counter) internal {
        uint256 value = counter._value;
        require(value > 0, "Counter: decrement overflow");
        unchecked {
            counter._value = value - 1;
        }
    }

    function reset(Counter storage counter) internal {
        counter._value = 0;
    }
}

File 4 of 15 : Ownable.sol
// SPDX-License-Identifier: MIT

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() {
        _setOwner(_msgSender());
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _setOwner(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _setOwner(newOwner);
    }

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

File 5 of 15 : ERC721Enumerable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../ERC721.sol";
import "./IERC721Enumerable.sol";

/**
 * @dev This implements an optional extension of {ERC721} defined in the EIP that adds
 * enumerability of all the token ids in the contract as well as all token ids owned by each
 * account.
 */
abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {
    // Mapping from owner to list of owned token IDs
    mapping(address => mapping(uint256 => uint256)) private _ownedTokens;

    // Mapping from token ID to index of the owner tokens list
    mapping(uint256 => uint256) private _ownedTokensIndex;

    // Array with all token ids, used for enumeration
    uint256[] private _allTokens;

    // Mapping from token id to position in the allTokens array
    mapping(uint256 => uint256) private _allTokensIndex;

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {
        return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);
    }

    /**
     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {
        require(index < ERC721.balanceOf(owner), "ERC721Enumerable: owner index out of bounds");
        return _ownedTokens[owner][index];
    }

    /**
     * @dev See {IERC721Enumerable-totalSupply}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        return _allTokens.length;
    }

    /**
     * @dev See {IERC721Enumerable-tokenByIndex}.
     */
    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {
        require(index < ERC721Enumerable.totalSupply(), "ERC721Enumerable: global index out of bounds");
        return _allTokens[index];
    }

    /**
     * @dev Hook that is called before any token transfer. This includes minting
     * and burning.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
     * transferred to `to`.
     * - When `from` is zero, `tokenId` will be minted for `to`.
     * - When `to` is zero, ``from``'s `tokenId` will be burned.
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual override {
        super._beforeTokenTransfer(from, to, tokenId);

        if (from == address(0)) {
            _addTokenToAllTokensEnumeration(tokenId);
        } else if (from != to) {
            _removeTokenFromOwnerEnumeration(from, tokenId);
        }
        if (to == address(0)) {
            _removeTokenFromAllTokensEnumeration(tokenId);
        } else if (to != from) {
            _addTokenToOwnerEnumeration(to, tokenId);
        }
    }

    /**
     * @dev Private function to add a token to this extension's ownership-tracking data structures.
     * @param to address representing the new owner of the given token ID
     * @param tokenId uint256 ID of the token to be added to the tokens list of the given address
     */
    function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
        uint256 length = ERC721.balanceOf(to);
        _ownedTokens[to][length] = tokenId;
        _ownedTokensIndex[tokenId] = length;
    }

    /**
     * @dev Private function to add a token to this extension's token tracking data structures.
     * @param tokenId uint256 ID of the token to be added to the tokens list
     */
    function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
        _allTokensIndex[tokenId] = _allTokens.length;
        _allTokens.push(tokenId);
    }

    /**
     * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
     * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for
     * gas optimizations e.g. when performing a transfer operation (avoiding double writes).
     * This has O(1) time complexity, but alters the order of the _ownedTokens array.
     * @param from address representing the previous owner of the given token ID
     * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
     */
    function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
        // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and
        // then delete the last slot (swap and pop).

        uint256 lastTokenIndex = ERC721.balanceOf(from) - 1;
        uint256 tokenIndex = _ownedTokensIndex[tokenId];

        // When the token to delete is the last token, the swap operation is unnecessary
        if (tokenIndex != lastTokenIndex) {
            uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];

            _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
            _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
        }

        // This also deletes the contents at the last position of the array
        delete _ownedTokensIndex[tokenId];
        delete _ownedTokens[from][lastTokenIndex];
    }

    /**
     * @dev Private function to remove a token from this extension's token tracking data structures.
     * This has O(1) time complexity, but alters the order of the _allTokens array.
     * @param tokenId uint256 ID of the token to be removed from the tokens list
     */
    function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
        // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and
        // then delete the last slot (swap and pop).

        uint256 lastTokenIndex = _allTokens.length - 1;
        uint256 tokenIndex = _allTokensIndex[tokenId];

        // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so
        // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding
        // an 'if' statement (like in _removeTokenFromOwnerEnumeration)
        uint256 lastTokenId = _allTokens[lastTokenIndex];

        _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
        _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index

        // This also deletes the contents at the last position of the array
        delete _allTokensIndex[tokenId];
        _allTokens.pop();
    }
}

File 6 of 15 : ERC721.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC721.sol";
import "./IERC721Receiver.sol";
import "./extensions/IERC721Metadata.sol";
import "../../utils/Address.sol";
import "../../utils/Context.sol";
import "../../utils/Strings.sol";
import "../../utils/introspection/ERC165.sol";

/**
 * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
 * the Metadata extension, but not including the Enumerable extension, which is available separately as
 * {ERC721Enumerable}.
 */
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
    using Address for address;
    using Strings for uint256;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // Mapping from token ID to owner address
    mapping(uint256 => address) private _owners;

    // Mapping owner address to token count
    mapping(address => uint256) private _balances;

    // Mapping from token ID to approved address
    mapping(uint256 => address) private _tokenApprovals;

    // Mapping from owner to operator approvals
    mapping(address => mapping(address => bool)) private _operatorApprovals;

    /**
     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
        return
            interfaceId == type(IERC721).interfaceId ||
            interfaceId == type(IERC721Metadata).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    /**
     * @dev See {IERC721-balanceOf}.
     */
    function balanceOf(address owner) public view virtual override returns (uint256) {
        require(owner != address(0), "ERC721: balance query for the zero address");
        return _balances[owner];
    }

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId) public view virtual override returns (address) {
        address owner = _owners[tokenId];
        require(owner != address(0), "ERC721: owner query for nonexistent token");
        return owner;
    }

    /**
     * @dev See {IERC721Metadata-name}.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev See {IERC721Metadata-symbol}.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");

        string memory baseURI = _baseURI();
        return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
    }

    /**
     * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
     * token will be the concatenation of the `baseURI` and the `tokenId`. Empty
     * by default, can be overriden in child contracts.
     */
    function _baseURI() internal view virtual returns (string memory) {
        return "";
    }

    /**
     * @dev See {IERC721-approve}.
     */
    function approve(address to, uint256 tokenId) public virtual override {
        address owner = ERC721.ownerOf(tokenId);
        require(to != owner, "ERC721: approval to current owner");

        require(
            _msgSender() == owner || isApprovedForAll(owner, _msgSender()),
            "ERC721: approve caller is not owner nor approved for all"
        );

        _approve(to, tokenId);
    }

    /**
     * @dev See {IERC721-getApproved}.
     */
    function getApproved(uint256 tokenId) public view virtual override returns (address) {
        require(_exists(tokenId), "ERC721: approved query for nonexistent token");

        return _tokenApprovals[tokenId];
    }

    /**
     * @dev See {IERC721-setApprovalForAll}.
     */
    function setApprovalForAll(address operator, bool approved) public virtual override {
        require(operator != _msgSender(), "ERC721: approve to caller");

        _operatorApprovals[_msgSender()][operator] = approved;
        emit ApprovalForAll(_msgSender(), operator, approved);
    }

    /**
     * @dev See {IERC721-isApprovedForAll}.
     */
    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
        return _operatorApprovals[owner][operator];
    }

    /**
     * @dev See {IERC721-transferFrom}.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        //solhint-disable-next-line max-line-length
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");

        _transfer(from, to, tokenId);
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        safeTransferFrom(from, to, tokenId, "");
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) public virtual override {
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
        _safeTransfer(from, to, tokenId, _data);
    }

    /**
     * @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.
     *
     * `_data` is additional data, it has no specified format and it is sent in call to `to`.
     *
     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
     * implement alternative mechanisms to perform token transfer, such as signature-based.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeTransfer(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) internal virtual {
        _transfer(from, to, tokenId);
        require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
    }

    /**
     * @dev Returns whether `tokenId` exists.
     *
     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
     *
     * Tokens start existing when they are minted (`_mint`),
     * and stop existing when they are burned (`_burn`).
     */
    function _exists(uint256 tokenId) internal view virtual returns (bool) {
        return _owners[tokenId] != address(0);
    }

    /**
     * @dev Returns whether `spender` is allowed to manage `tokenId`.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
        require(_exists(tokenId), "ERC721: operator query for nonexistent token");
        address owner = ERC721.ownerOf(tokenId);
        return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
    }

    /**
     * @dev Safely mints `tokenId` and transfers it to `to`.
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeMint(address to, uint256 tokenId) internal virtual {
        _safeMint(to, tokenId, "");
    }

    /**
     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
     */
    function _safeMint(
        address to,
        uint256 tokenId,
        bytes memory _data
    ) internal virtual {
        _mint(to, tokenId);
        require(
            _checkOnERC721Received(address(0), to, tokenId, _data),
            "ERC721: transfer to non ERC721Receiver implementer"
        );
    }

    /**
     * @dev Mints `tokenId` and transfers it to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - `to` cannot be the zero address.
     *
     * Emits a {Transfer} event.
     */
    function _mint(address to, uint256 tokenId) internal virtual {
        require(to != address(0), "ERC721: mint to the zero address");
        require(!_exists(tokenId), "ERC721: token already minted");

        _beforeTokenTransfer(address(0), to, tokenId);

        _balances[to] += 1;
        _owners[tokenId] = to;

        emit Transfer(address(0), to, tokenId);
    }

    /**
     * @dev Destroys `tokenId`.
     * The approval is cleared when the token is burned.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     *
     * Emits a {Transfer} event.
     */
    function _burn(uint256 tokenId) internal virtual {
        address owner = ERC721.ownerOf(tokenId);

        _beforeTokenTransfer(owner, address(0), tokenId);

        // Clear approvals
        _approve(address(0), tokenId);

        _balances[owner] -= 1;
        delete _owners[tokenId];

        emit Transfer(owner, address(0), tokenId);
    }

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     *
     * Emits a {Transfer} event.
     */
    function _transfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {
        require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer of token that is not own");
        require(to != address(0), "ERC721: transfer to the zero address");

        _beforeTokenTransfer(from, to, tokenId);

        // Clear approvals from the previous owner
        _approve(address(0), tokenId);

        _balances[from] -= 1;
        _balances[to] += 1;
        _owners[tokenId] = to;

        emit Transfer(from, to, tokenId);
    }

    /**
     * @dev Approve `to` to operate on `tokenId`
     *
     * Emits a {Approval} event.
     */
    function _approve(address to, uint256 tokenId) internal virtual {
        _tokenApprovals[tokenId] = to;
        emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
    }

    /**
     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
     * The call is not executed if the target address is not a contract.
     *
     * @param from address representing the previous owner of the given token ID
     * @param to target address that will receive the tokens
     * @param tokenId uint256 ID of the token to be transferred
     * @param _data bytes optional data to send along with the call
     * @return bool whether the call correctly returned the expected magic value
     */
    function _checkOnERC721Received(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) private returns (bool) {
        if (to.isContract()) {
            try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {
                return retval == IERC721Receiver.onERC721Received.selector;
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert("ERC721: transfer to non ERC721Receiver implementer");
                } else {
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        } else {
            return true;
        }
    }

    /**
     * @dev Hook that is called before any token transfer. This includes minting
     * and burning.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
     * transferred to `to`.
     * - When `from` is zero, `tokenId` will be minted for `to`.
     * - When `to` is zero, ``from``'s `tokenId` will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {}
}

File 7 of 15 : IERC721Enumerable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../IERC721.sol";

/**
 * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Enumerable is IERC721 {
    /**
     * @dev Returns the total amount of tokens stored by the contract.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.
     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);

    /**
     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
     * Use along with {totalSupply} to enumerate all tokens.
     */
    function tokenByIndex(uint256 index) external view returns (uint256);
}

File 8 of 15 : ERC165.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC165.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

File 9 of 15 : Strings.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _HEX_SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }
}

File 10 of 15 : Context.sol
// SPDX-License-Identifier: MIT

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;
    }
}

File 11 of 15 : Address.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

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

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

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

File 12 of 15 : IERC721Metadata.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../IERC721.sol";

/**
 * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Metadata is IERC721 {
    /**
     * @dev Returns the token collection name.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the token collection symbol.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
     */
    function tokenURI(uint256 tokenId) external view returns (string memory);
}

File 13 of 15 : IERC721Receiver.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
interface IERC721Receiver {
    /**
     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
     * by `operator` from `from`, this function is called.
     *
     * It must return its Solidity selector to confirm the token transfer.
     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
     *
     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

File 14 of 15 : IERC721.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../../utils/introspection/IERC165.sol";

/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool _approved) external;

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes calldata data
    ) external;
}

File 15 of 15 : IERC165.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 100
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokensNumber","type":"uint256"}],"name":"buyTokens","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"claim","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":"num","type":"uint256"},{"internalType":"uint256","name":"dir","type":"uint256"}],"name":"getPoints","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"safeMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6080604052666a94d74f430000600c553480156200001c57600080fd5b50604080518082018252600d81526c135e5cdd1a58c8119bdc995cdd609a1b6020808301918252835180850190945260038452624d465360e81b9084015281519192916200006d916000916200011c565b508051620000839060019060208401906200011c565b505050620000a06200009a620000bd60201b60201c565b620000c1565b620000b7600b6200011360201b6200380a1760201c565b620001ff565b3390565b600a80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b80546001019055565b8280546200012a90620001c2565b90600052602060002090601f0160209004810192826200014e576000855562000199565b82601f106200016957805160ff191683800117855562000199565b8280016001018555821562000199579182015b82811115620001995782518255916020019190600101906200017c565b50620001a7929150620001ab565b5090565b5b80821115620001a75760008155600101620001ac565b600181811c90821680620001d757607f821691505b60208210811415620001f957634e487b7160e01b600052602260045260246000fd5b50919050565b615ff7806200020f6000396000f3fe60806040526004361061014b5760003560e01c80634e71d92d116100b657806395d89b411161006f57806395d89b4114610387578063a22cb4651461039c578063b88d4fde146103bc578063c87b56dd146103dc578063e985e9c5146103fc578063f2fde38b1461041c57600080fd5b80634e71d92d146102e85780634f6ccce7146102fd5780636352211e1461031d57806370a082311461033d578063715018a61461035d5780638da5cb5b1461037257600080fd5b80632f745c59116101085780632f745c59146102405780633610724e146102605780633ccfd60b1461027357806340d097c31461028857806342842e0e146102a85780634d4c71a3146102c857600080fd5b806301ffc9a71461015057806306fdde0314610185578063081812fc146101a7578063095ea7b3146101df57806318160ddd1461020157806323b872dd14610220575b600080fd5b34801561015c57600080fd5b5061017061016b36600461492f565b61043c565b60405190151581526020015b60405180910390f35b34801561019157600080fd5b5061019a61044d565b60405161017c91906156e7565b3480156101b357600080fd5b506101c76101c2366004614969565b6104df565b6040516001600160a01b03909116815260200161017c565b3480156101eb57600080fd5b506101ff6101fa366004614905565b61056c565b005b34801561020d57600080fd5b506008545b60405190815260200161017c565b34801561022c57600080fd5b506101ff61023b3660046147b1565b61067d565b34801561024c57600080fd5b5061021261025b366004614905565b6106ae565b6101ff61026e366004614969565b610744565b34801561027f57600080fd5b506101ff6108a4565b34801561029457600080fd5b506101ff6102a3366004614763565b610902565b3480156102b457600080fd5b506101ff6102c33660046147b1565b61094f565b3480156102d457600080fd5b5061019a6102e3366004614982565b61096a565b3480156102f457600080fd5b506101ff61249a565b34801561030957600080fd5b50610212610318366004614969565b612507565b34801561032957600080fd5b506101c7610338366004614969565b61259a565b34801561034957600080fd5b50610212610358366004614763565b612611565b34801561036957600080fd5b506101ff612698565b34801561037e57600080fd5b506101c76126d1565b34801561039357600080fd5b5061019a6126e0565b3480156103a857600080fd5b506101ff6103b73660046148c9565b6126ef565b3480156103c857600080fd5b506101ff6103d73660046147ed565b6127b0565b3480156103e857600080fd5b5061019a6103f7366004614969565b6127e8565b34801561040857600080fd5b5061017061041736600461477e565b61373f565b34801561042857600080fd5b506101ff610437366004614763565b61376d565b600061044782613813565b92915050565b60606000805461045c906159cf565b80601f0160208091040260200160405190810160405280929190818152602001828054610488906159cf565b80156104d55780601f106104aa576101008083540402835291602001916104d5565b820191906000526020600020905b8154815290600101906020018083116104b857829003601f168201915b5050505050905090565b60006104ea82613838565b6105505760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b60648201526084015b60405180910390fd5b506000908152600460205260409020546001600160a01b031690565b60006105778261259a565b9050806001600160a01b0316836001600160a01b031614156105e55760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610547565b336001600160a01b03821614806106015750610601813361373f565b61066e5760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f776044820152771b995c881b9bdc88185c1c1c9bdd995908199bdc88185b1b60421b6064820152608401610547565b6106788383613855565b505050565b61068733826138c3565b6106a35760405162461bcd60e51b815260040161054790615781565b61067883838361398d565b60006106b983612611565b821061071b5760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b6064820152608401610547565b506001600160a01b03919091166000908152600660209081526040808320938352929052205490565b600081116107835760405162461bcd60e51b815260206004820152600c60248201526b15dc9bdb99c8185b5bdd5b9d60a21b6044820152606401610547565b601e8111156107c25760405162461bcd60e51b815260206004820152600b60248201526a04e6f74206d6f72652033360ac1b6044820152606401610547565b610d056107d8826107d2600b5490565b90613b38565b11156108165760405162461bcd60e51b815260206004820152600d60248201526c14d85b1948199a5b9a5cda1959609a1b6044820152606401610547565b600c5434906108259083613b4b565b11156108635760405162461bcd60e51b815260206004820152600d60248201526c09ccacac840dadee4ca408aa89609b1b6044820152606401610547565b60005b818110156108a0576108803361087b600b5490565b613b57565b61088e600b80546001019055565b8061089881615a0a565b915050610866565b5050565b336108ad6126d1565b6001600160a01b0316146108d35760405162461bcd60e51b81526004016105479061574c565b6040514790339082156108fc029083906000818181858888f193505050501580156108a0573d6000803e3d6000fd5b3361090b6126d1565b6001600160a01b0316146109315760405162461bcd60e51b81526004016105479061574c565b61093e8161087b600b5490565b61094c600b80546001019055565b50565b610678838383604051806020016040528060008152506127b0565b60606000604051806116a001604052807effb4b3b2b1b0af988e877a76726c67645f5a575351493a2a1e1b1713100b0581526020017e07fdababd4eaf52005000198467a9a61c9f6f305ded179bae0af884c05c72f81526020017507fdddabd5eaf560079801a8c267355bd006cca5a53681526020017f064b5270e27fb9df2f7713f9b7168e44dd32470cc187365d5221d487ed811dab81526020017507ff57abd580000000021544727b9edca88772b580c981526020017f084c89cf1c734adef2e7bd31f94c7e525ff497fcfe273c7fcf1ff2f8b4d22b4281526020017f07f409ff017fbda24f482bc63aec7fbadfed79234646f18d4022f248748a172481526020017f06ccd1b1366c561cd4e72d29cf4a73cfde53d73ce9cf057bc15ef1f7fc85ff0a81526020017f073b91cec276b01cebf73ad5e4b373ac9cea96c279b0ad6d2b9b4b36c2e1b13381526020017f07e301febd7fac9fab07daa9eeaa7bb21ceca73b69eed87bbc5cef173ba1dee581526020017e07fd55aad4eab52005c001be878828240c08cb0a2cc484b1a14c47fb19febf81526020017f06797662759522272b3c338354e0d50000000000ad284f61a9194d465c052d5c81526020017f0872fdd8bc7d2e5d8b87225dc09d62a8934505f965be9e72a71c6937fa45c49081526020017f06e3959ee567b61dad676b419cd364ad5b2b3642c58ca470a81d4d376b49dac081526020017f072c51e50f74435d9047340d874e4dd6d9d0376415d8d675359cd0267bfd9ee781526020017507fc07aad56ab54ef9a42a21366652dc51a81c61cb1481526020017f05238d60e4633c9aee763bd962eb55bc973059b44e671e62551cd5e5ed8045aa81526020017f02b104b04a651a1fa949125e7ea6a12b5d6b175af5c8b26cacdb4b8602d146dc81526020016a01ffd26ab480000000483781526020017f079c0ddafe763d656f0773be02dfcab6b212c80cd9db296fccdd13c94519016e81526020017f06734daed3713699cdb68491af246fca9d32774c8df32075481dd18c443b0b0281526020017f0832d1e2b27daa714a5c3265f49b7ca65c29570a319c8f66ab5aab5692e598bb81526020017e07fc81aad56ab54000000000456822e107b8f227328ecab4df2c976305dab881526020017f06fb9dbcfa6abe9a30068c25af0c6dc4235248fc864b2967cc55d4b5052c23aa81526020017f063a857ea15eae1d0ba5f2f182ca633258ec466b119cc26eb05b8dc73385f2e381526020017f0d56ab540000000001b731cdf06c8b9e1c4816f229a68a6b275baa466aa192a681526020016101ff81526020017f060385b6dd603717ed45b33950cc52be163065946d55290cdcc37aad56ab540081526020017f05530970c45f33592cb69b0622bf8dbba650984471a9196241584f075bb582eb81526020017e07fc0000000002c25541517673791e99c7c6c2296090562653e9b502dd64bc81526020017f02b38c96f9183d460ff23c085b3a18b905af5003c000fa153f8451b0f504014081526020017f0444326f265bd29a74b984c6553b7c53ddf4c35d18bd412ad0c95423bcb46d3c81526020017f09445e5d18a043a6f196cc31a10964c29110041bf8feff273e497023d429030c81526020017f099a6e6ac09baaa84d0a1bc63ccba1bf686fd99bde38f69b40a1f0b97436830681526020017f07e2d236d47ba7a0aac93afe18a879a39f6828fa1e229e94a2e38b59627e5e9381526020017f0649ad946c669ade27f6a99daa67761ddf08076211ee8375a59e8c87a2b1e09a81526020017f064291cec461239a09c752a17e7e631c98a705f1e97861631c9ca9461181986981526020017f0449e1168649a952083451d5166c5a98d6a695d9fd767f5b21980b860271788a81526020017f0192210ea21ea00867c451b504783f22cfe99429e912724222d12a448acd128c81526020017f017af086dc1aaec4e8c1bab49ebf19268ded523a88beab2127072942826cf4a181526020017f0629557e4e5d9396a594b98122604518c0081002304e830f2ac4ecc122a04c968152602001771ff006ab55aad5000000000185404b4898126605112da45081526020017f02b49d0d3263cdda9356dd1da54954529194457d04f340204d0cd3110cb8012781526020017f069bf9ab126949c6f17004440116694a5a32d6a4d18f3641cc0b92600470012181526020017f090466072a774a9ad276b4a9e52c804b1fd2d6dcc9af2b6bc81bf206bc79b11181526020017f090cee3b378ccda353c8fcf9d745714f5eb396fce1bb347fcba072b97ca60d2a81526020017f09c4b299339f4c24f3197cd6913597cf25737954f6553892cd64d3d91cda3d3581526020017f0a440e8300a141a9909a1c2e8d0fa543e8f1aa14567910a3482952c9fc8e4b1a81526020017f09eb628ed5a932ea4d1a138e9adda935aa4e0a73f68cfba6c0a8cfda0bf284fe81526020017f09f2ce80b2a4ab284b4a52cea0a9a7ad6a4b2a92e290b894b1274c6a5b16a4c281526020017f09ea72769fa328a74a69caae86aa9dac25ca39729274b19cad67ab3a22ee8aba81526020017f076231a28c68239c88f7923e4a9b952864ea99c2727299a1a36929a9d25a729981526020017f098a22688d9d2226a8d9ca3a649096236548f982525e979925e589b95a7e449681526020017f090202528091a12508790a1a3c8b83219ae826aa16388e8d24a4c8f952425a8d81526020017f0562e97aac61a8db6a16327db47d771e232787c9d62c6d921d6267b8e9fe407c81526020017f064a016ca6522e564e357bd54f0a59be56ee459b5586d35934960c85c3195ec581526020017f0d500000000033068ac21aac72a920294f0a223a80b0963f22d868e622311a878152602001651ff006ab55aa81526020017f05129544a253aa542a550aa156b656aed46b0512a944a950aa142b451ae55ec481526020017f047a45088e40241068243219108d4421d208f4a29128a64baa5229050a8142a581526020017f04baf912a54a2b130b74c30148ea4e3016af45132152d34d2bd42b3402450a9281526020017f038ac8e4b945380ecb548b60f4af39ab0f89b3f2a522bf41298fc963fa5104a181526020017f01a1fc847e212089482241f8c2832b9f4f47a41204fc91362d8d4d739b90dcd781526020017f02426080952425092992626c969426a509a942b284b4a42a250fc9225208648081526020017f01810c5c4700118005512954247508a343cb81db94469837ba44c8e24aa0dcaf81526020017f0670f59a38270d0923f2e120a648248fcb220218c45c2b170c80032000d85a3781526020017f07b11e42438a9035444d50f5de388888598386791d48484f11d2a4946924ce3a81526020017f07319dd4737f9ca2c89829cb5466d51664a637e195e4578a16e1856d515f544681526020017f03c1b4fa583e960fe6d439b50658489b12c6b45961aa5878215c25872161e66681526020017f0179bc4e721d1608e682419c805625958e06d2e95cd45730970c8603795cee5881526020017f065a31c49d66a09d88a659d5cc736f19d526a281c0c2632d17c6e6d1f170785981526020017f05727d3a9a3d9e90679432151087439e530784e20144874d9dd72776aab98e858152602001797fd84ea5d35990e657ae9ace95cb0984c9592c952ab50a798ab281526020017f024ba8010200424a2ef2cba8d8e92fb98cce137354f0cf39338eec843b08eafc81526020017e021ccc864f9f5328f2a230668a0024800981da40ec964b26118b037ae8bedb81526020017f0799e5c0787f1a3543fd5005984346934d43d4e0e4c83716000320038148005d81526020017f0d52f2aab7622996ca964251be8e87202d48bd524f548b9d9f6187b67a31b87c81526020017f04f46d23154a3b13ad75535140d150b3d76c951b295cb263ab2cabcb8aff54c081526020017f05ed955d5c55525cd507f54e9b68c76ab21aaa6591ed4e54d19432458c89412081526020017f046cf5353b46ce521204c481515e516a951aa575857d69725a691aaa7ea9cb668152602001771ff336a901aa45d3d515e53d65174a46515474851515194281526020017f0623b5890352448c30c294b811a004e34bb014ec297cfe5c3a176dc6234192d081526020016a01ff64b4196d464b7988e981526020017f0573215acb523413a8852a3152965aa6156925321d388044000e6004aa253cd581526020017f062b4186d0613457aca61b1988c762b2188c962b218ac760b0d72c358b1958c981526020017f05737d78e5603918ae062b7d88dd623798ae05f37182d76136188d86235988d281526020017301ff40c9d11384249530f352bf536ef5235d5ede81526020017f047040f64a421ecdeaf302c0aaba2ab10aece2fb50bacc2f300d2c136af8d6d481526020017f03b2e10ab9432dd0ab443ab90aaa39ab9147b4216518654d1b51a62419295a108152602001677fcdcc837af4e6bb81526020017f07aaf9eaba7f2e1feb37face02b383abe12ab8a2aa32a58e26a809fa5abec0bf81526020017f077245e8a276289ceaa722a5c0ad71ac9cab1732c5ccb5742e1dabb76af9e0c081526020017f07aa3624867d21df4878a9f1f68072231c69075259d09180255fa977da6dec9281526020017f0d42b750a5a4a66a695b221e9e8ea2256b27ca223e8297a02621c9085a3a108e81526020016e1ffb02fea2aba428e9ca6b72b6aaa281526020017f06d291b8a66ea95bca67028dc29f72a79d6a17a299eaa979ab9c2c07b2c5f89d81526020017f077a19d48374a05d87e7b9f9f6807b9f5d87d741fdcc8373221b6996b279b0a481526020017f075a71e29b7b269ee9e7ba81f2997aa59d8977623de6937ba49f6917ea29e88e81526020017f07ea561e5a8892e4864909ca4e77919c64c638910a3c008400610597b291dc9d8152602001677fe04ac81ad208ab81526020017f02cbf4b4fc2d3ecbafd32bf4ccfd35bf0dd162a584936e23d447b3a21d508b7481526020017f035b8ce6d435380c8c034bb8c6ef2f3c0b8f22cbccaef52b3e0b2fa2cbe8b2fc81526020017e07fc29a91fea4b96a38c5cdcfb3a3e102f7413d8fcf540bd100f1393c4d8ef81526020017f09bb9e68e7963b64eec953ce56f996406610f97cce5d3b99d267150a0562975e81526020017f0b6c3ad110acc3ad104b5c0ee4fdb9bced0ffab41a94fea2bd680f0a1b9282e081526020017f0b84a2e321b6c92d729aecc69d29a7c929f16a9c5ed115b6c52e30fb8c1adf0981526020017f0a5d26a543ac512bb47b54eee335b8cbadb31b5cd6bd3ca84dea536ac4deb93a81526020016c07fea163acd8ea959a65467b4d81526020017f09328a4ca19528a56a4962824e9b94a5e5697962625898952a65cb49630660b681526020017f089aae26ac8baae32aa8d2aa38aa8faa644a892a9650a694aa254a995a9654a481526020017f08ea3632938ca66369d8ca7a329f8c27e2e9f89a7e249f89a8e26a489a9a28a881526020017f0d490b503dac996867b9b1ea627d9b1f2847e9b2226a879821e5a8993a22448a81526020017f09aaee5cac9aaba5aa998246668e9aa42808e9c22ab66dad1fea88cae202bc6b81526020016101ff81526020017f0a1c1a8f0ea8c4e9f1ea7486a12daac86ab1daac46b10bacc72ed3eb5502f54281526020017f0adbb6aef1aabb29ce7a6b969ae1a638296dfa2b8e88e5a23a292f2a4bd688fd81526020017f0af46ab4ffb13dab6faaf376bed7ac3fab107ab426ad06a9c0ea502aa3eab4f48152602001677fef542d3daf4f4a81526020017f07a1f1e87f749fdce8375205e8837a219d88a7a225ea8c7823dec8d8229a3aa481526020017f0849be3069a219a4466a615f5c6ad697a985280991ec75789cdea777a1e9da7881526020017f082a4a6294872423c8c99247589ad5a4e5e88d621f586a991de3877879ca526e81526020016e1ffd62c758a787a761c9caca6a169981526020017f09146e231c89c6a451989c662b16914662b148b44a2ef9953ca470a8ecc6313981526020017f08a3e6291285499f13284ca61b338649e1b2490c961d238847e43238847a211e81526020017f08e31636c28ab0234c38bb3632c99132632c88d31a3cd1913424cec8abda12fa81526020017f08e21e3c818d2120c8b8d21e40938f2a62aaa902b650bf92b163ecb8eb1a4ec481526020017f090a76429a95a7a429890a5e5c9591256449290a42609090a3e3e8d98a363e8c81526020017f098a3e6a85a020e6a82989de68859527250b39029e40a59628a40a390a7e56a181526020017f0a725ea690a5a5664bf97af65ab996a7a829096a6a60939a25a609198a466e9481526020017f0a5ade76b9a12b6a2ada12b288a9b42a68aa7a3296a4a5a3a8e989acfad340ab81526020017f09db1692cb9db0e84c1aab068ebfaaaef40cdcfb1aacb8adacaa8b89bb0674bb81526020017f0d13b740d2a6b4284d89d36688d59db568cd39e34690d19db3692d09d32294cf81526020017f0cfc028f00a2beea6f8a23e686f7adbca84f5a03baa0ed9fbb296ea9eba680e781526020017f0a945a71109c43ac30d9c4327104a141271039b3aa8b03a2c0e8709a4c0f3d0881526020017c01ff8fcc64d0e9744a4d09983b26d129ac7a7313d24b74b25adc62d11881526020017f08c1fa2075871de1e72871a6126b86982205a8a1222a548f1227843971269c4c81526020017f093276469d922824e9f8f2923caa8da963e978da3e348c8823a229486a2e428081526020017f0a62528c9ba0a7e7c9e9e2867ca29da8a70a09ba86649c98a7a669f9827e569e81526020017f0a122e7a8da2a327e8ea1a3a8290a4a3a8491a52428893a6a428a95a5a4a8c9881526020017f0a12327c8ca022e768a9ea2a6a899d22272889a226688a9e22a6e8b9fa2e768d81526020017f0a5a5e9893a4a5a9891a4a52988fa2a46968ea0a3e908da02368a8ca22327e8d81526020017507fe9c4cb110b2042c82568a849f21e8889a8236a09281526020017f090d92476b875d2597397dc65b76965ca4973946024d848b5da3d86815b23b9781526020017f09ec667d289b4aa7d29a254a71378fc66774b8dce279587cd4273609b5924b6981526020017f0ac496af29a046a9724a049e8129a749eab2ea8cce9f2aa74da933ca74ea934b81526020017f0b0bdec708b0c3ea8f7afc52bd15ab42e86feae45e8d12adc7ab520a748ea52681526020017f09abc65ad7a33d25ad29c3529ad19833eceb5a1b8ad4bbae39edcc1b4be6cb0581526020017f0b0a36c695af27eca9bb4abeb8a89bacaceb3973365acf94b464ed295b4656d781526020017f0a3222947ca7176b274a49f29080a99eea67ba2252ae85ae9f6ba7dac22aaea981526020017f0a112a6c45828e6724c9192a06539714e2a649e956428ea19768a80a120e8a8181526020017f08ceab55aad50025000990ea703d9e0c284419c0f220289a10668449b1166e4381526020016101ff81526020017f061571795d605859562615998b686759d8f6c695b5b5677cdc2097b72dce419a81526020017f08d6164f8d85d920f6587dda0f737f59db7557b5b9b96666d519f5d62d65956181526020017f08859a336a9ddb227708a5ce3773975c23b779a602518f93e32217e84dda217881526020017f078521c94b77d4deb5378565fb5a7cd7a09608159621668d57a7d6a95d96256481526020017f09c54e47469a55a7b638e55a3b468ad221f4386d2a03448153603487ad11ef4e81526020017f081ca5d91b7c4a5d7297e4b9bd3781cca11349ed4675539f54e7f58a6d7e916581526020017f08ecb24130964ce4f3491cda4d399ace25f3994cfa693f9bcfa774a84cbe030d81526020017f0a954ab150aad52793b9f4eaa544ab50e7f39994966930994b6512896cca492b81526020017f0ae496cd28b2cc2c72dadca2c739afcd6832ba54dec143a35129d49ab526994c81526020017f0a045e8f20a0c82731c9947a6f22a2c8a7d27a1ca69b24a9c929b28a44b6a92d81526020017f0ad412db09af41e8f0aa7c36d90ca24529f15b6436cf26af4929b17a8c82971a81526020017f0b03cac2f4b33caeae2b6c0eaae5aebd6b6f7af3dac0f9b2bfebcfaa1bce98fc81526020017f0b2ad2d4aab8b1aaabab432ae2ceb433294d4abb66d2daba35ab4e9b13a6eadf81526020017f09ca969caf9fada94b3a2aee98b5a5b06a2b1b0a9aacb4af2c2d2a4b4a9ebaba81526020017f0a128e9ca0b1a36c68db2a5ac695ada4eb295b126abc9aa4296a6a7b0a92a6ae81526020017f0ae1eeb87fa89f264829fa1ea489b0a1eae8aa02629497b022eb293aa24aae9481526020017f0a01a29e6aa79b6a66aad9a6b86eac9c68869a89d27677a31e6a876a81e6ac7781526020017f08a1ce3c73919ba4675951c25474991be68699a1a66a739f1b68062ab962a46181526020017f0a315aaa53ab15a7e609b966585998182585d909825066921923666911b2346c81526020017f09a93a72519715e7057a61228e4fa593e9e49aa93a844e9e14e80569e16a865b81526020017f08214dec618514a0e75861425c3e9a8f680419b106304c9313e724da511a784e81526020017f078901f43d7b90a04408011a20418a0ea46358a10a4a408413de24982145ea5681526020016e1ff746ab55aad5001e800728d5e63981526020017507fe007c7f1f2007f809f20a7c809edfc797f1ee007c8152602001707fdfc887f22e02877fa15fe8680a1dfc888152602001707fe70d2993725cdc98b6a64d999b6266d88152602001707fe66c79c33a6acb9b32e68ca9932660c881526020017301ff96236649199a56609598252629397a465e9281526020017301ff98266649997a765e9b9826a609a98a66609981525090506000806000806000806060600060038c106122d3576101006122ac60038e615975565b6122b89061010061586f565b8a516122c49190615818565b6122ce9190615a39565b6122de565b6122de8c60016157d2565b96508a600114156122f257608c93506122f8565b61038493505b6040518060200160405280600081525091508697505b60b5881161248b57888860b5811061232857612328615aac565b60200201516123365761248b565b888860b5811061234857612348615aac565b6020020151955060009450600092505b601b831161246a5761020061236d848261586f565b6123779088615818565b6123819190615a39565b9050806101ff14156123925761246a565b61239d600286615a39565b61240c578a600114156123f157816123ca608c6123bb846003615917565b6123c59190615936565b613b71565b6040516020016123db929190614af2565b604051602081830303815290604052915061244a565b816123ca612400836003615917565b6123c5906104e2615936565b81612427858d61241d856003615917565b6123bb9190615917565b604051602001612438929190614b2d565b60405160208183030381529060405291505b8461245481615a0a565b955050828061246290615a0a565b935050612358565b806101ff14156124795761248b565b8761248381615a0a565b98505061230e565b509a9950505050505050505050565b61012c6124a6600b5490565b11156124ea5760405162461bcd60e51b81526020600482015260136024820152724e6f206d6f7265206672656520746f6b656e7360681b6044820152606401610547565b6124f73361087b600b5490565b612505600b80546001019055565b565b600061251260085490565b82106125755760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b6064820152608401610547565b6008828154811061258857612588615aac565b90600052602060002001549050919050565b6000818152600260205260408120546001600160a01b0316806104475760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b6064820152608401610547565b60006001600160a01b03821661267c5760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b6064820152608401610547565b506001600160a01b031660009081526003602052604090205490565b336126a16126d1565b6001600160a01b0316146126c75760405162461bcd60e51b81526004016105479061574c565b6125056000613ce4565b600a546001600160a01b031690565b60606001805461045c906159cf565b6001600160a01b0382163314156127445760405162461bcd60e51b815260206004820152601960248201527822a9219b99189d1030b8383937bb32903a379031b0b63632b960391b6044820152606401610547565b3360008181526005602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6127ba33836138c3565b6127d65760405162461bcd60e51b815260040161054790615781565b6127e284848484613d36565b50505050565b60606127f26146c7565b6127fa6146e6565b61280261470d565b61280a614728565b60008061283d61281989613d69565b6040516020016128299190615378565b604051602081830303815290604052613e67565b905061284a602482615a39565b6128559060016157d2565b83526009612864606483615818565b61286e9190615a39565b6128799060016157d2565b6020840152600261288c6103e883615818565b6128969190615a39565b6128a19060016157d2565b604084015260026128b461271083615818565b6128be9190615a39565b6128c99060016157d2565b606084015260026128dd620186a083615818565b6128e79190615a39565b6128f29060016157d2565b60808401526009612906620f424083615818565b6129109190615a39565b61291b9060016157d2565b60a0840152600961292f6298968083615818565b6129399190615a39565b6129449060016157d2565b60c084015260026129596305f5e10083615818565b6129639190615a39565b61296e9060016157d2565b60e08401526009612983633b9aca0083615818565b61298d9190615a39565b6129989060016157d2565b61010084015260146129af6402540be40083615818565b6129b99190615a39565b6129c49060016157d2565b61012084015260146129db6402540be40083615818565b6129e59190615a39565b60011415612a095782516129fb90600290615a39565b612a069060256157d2565b83525b7c3331a3e080008277ffff9efff53f18283d1c8c94335582ffff9eff3f4086527d0c0e2b54bbffc200ccffffeaff88001e2900e0d78074a11affff9effff9e60208701527d1011246dcfc248667dffffeaff88000c0e2bff5454c200ccffffeaff880060408701527d1213247689942f354affff9eff3f401011246dcfc248667dffff9eff3f4060608701527d190014ff4c00870041ffff9eff3f400a0d00ffaa00004a01ffff9eff3f4060808701527d091d24ffff9e009e71ffff9effd080111c2b00c483004a61ffff9eff3f4060a08701527d01002b5b1d91731045ff3030ff30300c190a71bd46008037ffff9effff9e60c08701527d0505056e676a696969f0e8e4f0e8e41b002487003df02222ff5500ff3f4060e08701527c1114067a59005c4999f0e7ff993d00111427596b00809999d0f099d0f06101008701527d180019ff8c006900a6fff08cff8c0018001930579168248fffa6efff3d3d610120808801919091527c15195da69c5f969efff8c7fff8c70300197e91965f759eedebdaffff9e6101408801527c0f26b5c90000949effff9effffff121900c9a071939e5fffff9effffff6101608801527d14000fff7878bf0060ffffa8ff7878170000d4a200bf5300ffff9eff3f406101808801527d14000fff59002b00a1ffffa8ff590014000fe58ca1644aa1ffffa8ff78786101a08801527c0619e0b082a12848ffffebffb482000d1400c5db2840a1ffffeb3ddbff6101c08801527d260026007bffd40071ffc4c4ffc4c4260000ff4c00780002ffdc69ff3f406101e08801527d36001dffaa00ff0000ffed4fffed4f260006ff0000630035ffad4fff3f406102008801527c0f05254c00006330a7ff63a7ff63361900b090829c5454fff7abfff7ab6102208801527a523f4f523f4fd94141d9414100010f91007e00635a63ffa963ffa9610240880152830151600710612de557600091505b610120830151612cd990600290615818565b612ce49060016157d2565b821015612d70576101c0840151612d10612cff846096615917565b612d0b906101906157d2565b613d69565b612d36610113612d218660c8615917565b612d2c9060456157d2565b612d0b9190615a39565b604051602001612d4893929190614bd3565b60408051808303601f190181529190526101c085015281612d6881615a0a565b925050612cc7565b6101c0840151610120840151612d8890600290615a39565b15612dac57604051806040016040528060018152602001602d60f81b815250612dbd565b604051806020016040528060008152505b604051602001612dce929190614c7d565b60408051808303601f190181529190526101c08501525b8251612df390600190615975565b612dfe906005615917565b9150612e5b6301000000612e13600a85615a39565b612e2190630100000061586f565b88612e2d600a87615818565b60138110612e3d57612e3d615aac565b6020020151612e4c9190615818565b612e569190615a39565b613e98565b85528251612e6b90600190615975565b612e76906005615917565b612e819060016157d2565b9150612e966301000000612e13600a85615a39565b60208601528251612ea990600190615975565b612eb4906005615917565b612ebf9060026157d2565b9150612ed46301000000612e13600a85615a39565b60808601528251612ee790600190615975565b612ef2906005615917565b612efd9060036157d2565b9150612f126301000000612e13600a85615a39565b60608601528251612f2590600190615975565b612f30906005615917565b612f3b9060046157d2565b9150612f506301000000612e13600a85615a39565b60408087019190915280516101408101909152610115808252615bc9602083013984526040805160608101909152602a808252615b7760208301398460016020020181905250604051806060016040528060288152602001615ba1602891396040850152612fd160018460085b6020020151612fcc9190615975565b613f90565b604051602001612fe19190615255565b60408051808303601f1901815291905260608501526130036001846008612fbd565b6101c085015160405161301a929190602001615159565b60408051808303601f1901815291905260808501526020830151613057906001906130469060006157d2565b6130509190615975565b600161096a565b60405160200161306791906155b3565b60408051601f198184030181529190528460056020020152613097600184600260200201516130469060096157d2565b6040516020016130a79190615659565b60408051808303601f1901815291905260c085015260608301516130d39060019061304690600b6157d2565b6040516020016130e39190615504565b60408051808303601f1901815291905260e085015260808301516131209060019061310f90600b6157d2565b6131199190615975565b600261096a565b60405160200161313091906153a6565b60408051808303601f1901815291905261010085015260e083015161315d906001906130469060196157d2565b60405160200161316d9190615455565b60408051808303601f1901815291905261012085015260c0830151600310156131a557604051806020016040528060008152506131bf565b6040518060c0016040528060888152602001615aef608891395b6040516020016131cf9190614dbc565b60408051601f1981840301815291905284600a6020020152613243600184600381600660200201511115613204576005613207565b60065b60ff16600c811061321a5761321a615aac565b602002015160c08601516003101561323357600d613236565b60165b60ff1661304691906157d2565b6040516020016132539190615618565b60408051808303601f1901815291905261016085015260c08301516003106132e857845160c08401516132999060019061328e906002615917565b61304690601a6157d2565b865160c08601516132ba906132af906002615917565b61305090601a6157d2565b6040516020016132cd9493929190614e38565b60408051808303601f19018152919052610180850152613308565b6040518060600160405280603c8152602001615f16603c91396101808501525b6040518061018001604052806101598152602001615d0861015991396101a08501528351608086015160208087015160608901516040808a01519051600096613358969095909493929101614a08565b60408051808303601f19018152908290526080808901516060808a0151908b0151928a01519395506133939486949293919290602001614a08565b60408051808303601f190181528282529088015160a088015160c08901519294506133c49385938391602001614a08565b60408051808303601f190181528282529088015160e08801516101008901519294506133f69385938391602001614a08565b60408051808303601f19018152828252908801516101208801516101408901519294506134299385938391602001614a08565b60408051808303601f19018152828252908801516101608801516101808901516101a08a015193955061346194869490602001614a08565b60408051601f19818403018152606083019091526022808352909250615e61602083013985526134988460015b6020020151613d69565b85600160200201819052506040518060600160405280602a8152602001615cde602a913960408601526134cc84600061348e565b606080870191909152604080519182019052602a808252615f726020830139608080870191909152840151606085015161354b919061350c90600a615917565b604087015161351c906064615917565b60e088015161352d906103e8615917565b61353791906157d2565b61354191906157d2565b612d0b91906157d2565b60a086015260c084015160031061358f576040518060600160405280602a8152602001615ec3602a913960c086015261358584600661348e565b60e08601526135be565b604051806060016040528060298152602001615eed6029913960c08601526135b884600561348e565b60e08601525b604051806060016040528060268152602001615f9c602691396101008601526135e884600861348e565b856009602002015260078460096020020151116136385761012085015161361085600961348e565b604051602001613621929190614b68565b60408051808303601f190181529190526101208601525b604080518082018252600481526322207d5d60e01b6020808301919091526101408801919091528651878201518884015160608a015160808b015160a08c0151965160009761368997909101614a73565b60408051808303601f190181529082905260c088015160e08901516101008a01516101208b01516101408c01519496506136c895879590602001614a73565b6040516020818303038152906040529050600061370d826136e88561403f565b6040516020016136f992919061504e565b60405160208183030381529060405261403f565b9050806040516020016137209190615210565b60408051601f198184030181529190529b9a5050505050505050505050565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b336137766126d1565b6001600160a01b03161461379c5760405162461bcd60e51b81526004016105479061574c565b6001600160a01b0381166138015760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610547565b61094c81613ce4565b80546001019055565b60006001600160e01b0319821663780e9d6360e01b14806104475750610447826141a5565b6000908152600260205260409020546001600160a01b0316151590565b600081815260046020526040902080546001600160a01b0319166001600160a01b038416908117909155819061388a8261259a565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60006138ce82613838565b61392f5760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610547565b600061393a8361259a565b9050806001600160a01b0316846001600160a01b031614806139755750836001600160a01b031661396a846104df565b6001600160a01b0316145b806139855750613985818561373f565b949350505050565b826001600160a01b03166139a08261259a565b6001600160a01b031614613a085760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201526839903737ba1037bbb760b91b6064820152608401610547565b6001600160a01b038216613a6a5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610547565b613a758383836141f5565b613a80600082613855565b6001600160a01b0383166000908152600360205260408120805460019290613aa9908490615975565b90915550506001600160a01b0382166000908152600360205260408120805460019290613ad79084906157d2565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6000613b4482846157d2565b9392505050565b6000613b448284615917565b6108a0828260405180602001604052806000815250614200565b606081613b955750506040805180820190915260018152600360fc1b602082015290565b600080831215613bad57613ba883615a4d565b613baf565b825b905060005b8115613bda5780613bc481615a0a565b9150613bd39050600a836157ea565b9150613bb4565b6000841215613bf15780613bed81615a0a565b9150505b60008167ffffffffffffffff811115613c0c57613c0c615ac2565b6040519080825280601f01601f191660200182016040528015613c36576020820181803683370190505b5090506000851215613c7d57613c4b85615a4d565b9450602d60f81b81600081518110613c6557613c65615aac565b60200101906001600160f81b031916908160001a9053505b841561398557613c8e600183615975565b9150613c9b600a86615a25565b613ca69060306157d2565b60f81b818381518110613cbb57613cbb615aac565b60200101906001600160f81b031916908160001a905350613cdd600a866157ea565b9450613c7d565b600a80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b613d4184848461398d565b613d4d84848484614233565b6127e25760405162461bcd60e51b8152600401610547906156fa565b606081613d8d5750506040805180820190915260018152600360fc1b602082015290565b8160005b8115613db75780613da181615a0a565b9150613db09050600a83615818565b9150613d91565b60008167ffffffffffffffff811115613dd257613dd2615ac2565b6040519080825280601f01601f191660200182016040528015613dfc576020820181803683370190505b5090505b841561398557613e11600183615975565b9150613e1e600a86615a39565b613e299060306157d2565b60f81b818381518110613e3e57613e3e615aac565b60200101906001600160f81b031916908160001a905350613e60600a86615818565b9450613e00565b600081604051602001613e7a91906149ec565b60408051601f19818403018152919052805160209091012092915050565b6040805180820190915260068082526503030303030360d41b60208301526060915b8115613b4457600a613ecd601086615a39565b1015613f2457613ede601085615a39565b613ee99060306157d2565b60f81b81613ef8600185615975565b81518110613f0857613f08615aac565b60200101906001600160f81b031916908160001a905350613f71565b613f2f601085615a39565b613f3a9060376157d2565b60f81b81613f49600185615975565b81518110613f5957613f59615aac565b60200101906001600160f81b031916908160001a9053505b613f7c601085615818565b935081613f88816159b8565b925050613eba565b60607607a83bed064745656509338218136736845df65e9e517e8215613fd357613fbb836003615917565b613fc690606461586f565b613fd09082615818565b90505b613ff96064613fe461271084615818565b613fee9190615a39565b612d0b90600a615917565b6140086064613fe48185615818565b614016613fee606485615a39565b60405160200161402893929190614d35565b604051602081830303815290604052915050919050565b80516060908061405f575050604080516020810190915260008152919050565b6000600361406e8360026157d2565b6140789190615818565b614083906004615917565b905060006140928260206157d2565b67ffffffffffffffff8111156140aa576140aa615ac2565b6040519080825280601f01601f1916602001820160405280156140d4576020820181803683370190505b5090506000604051806060016040528060408152602001615e83604091399050600181016020830160005b86811015614160576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b8352600490920191016140ff565b50600386066001811461417a576002811461418b57614197565b613d3d60f01b600119830152614197565b603d60f81b6000198301525b505050918152949350505050565b60006001600160e01b031982166380ac58cd60e01b14806141d657506001600160e01b03198216635b5e139f60e01b145b8061044757506301ffc9a760e01b6001600160e01b0319831614610447565b610678838383614340565b61420a83836143f8565b6142176000848484614233565b6106785760405162461bcd60e51b8152600401610547906156fa565b60006001600160a01b0384163b1561433557604051630a85bd0160e11b81526001600160a01b0385169063150b7a02906142779033908990889088906004016156aa565b602060405180830381600087803b15801561429157600080fd5b505af19250505080156142c1575060408051601f3d908101601f191682019092526142be9181019061494c565b60015b61431b573d8080156142ef576040519150601f19603f3d011682016040523d82523d6000602084013e6142f4565b606091505b5080516143135760405162461bcd60e51b8152600401610547906156fa565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050613985565b506001949350505050565b6001600160a01b03831661439b5761439681600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b6143be565b816001600160a01b0316836001600160a01b0316146143be576143be8382614537565b6001600160a01b0382166143d557610678816145d4565b826001600160a01b0316826001600160a01b031614610678576106788282614683565b6001600160a01b03821661444e5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610547565b61445781613838565b156144a45760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610547565b6144b0600083836141f5565b6001600160a01b03821660009081526003602052604081208054600192906144d99084906157d2565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6000600161454484612611565b61454e9190615975565b6000838152600760205260409020549091508082146145a1576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b6008546000906145e690600190615975565b6000838152600960205260408120546008805493945090928490811061460e5761460e615aac565b90600052602060002001549050806008838154811061462f5761462f615aac565b600091825260208083209091019290925582815260099091526040808220849055858252812055600880548061466757614667615a96565b6001900381819060005260206000200160009055905550505050565b600061468e83612611565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b6040518061026001604052806013906020820280368337509192915050565b6040518060a001604052806005905b60608152602001906001900390816146f55790505090565b604080516101e0810190915260608152600e602082016146f5565b604051806101800160405280600c906020820280368337509192915050565b80356001600160a01b038116811461475e57600080fd5b919050565b60006020828403121561477557600080fd5b613b4482614747565b6000806040838503121561479157600080fd5b61479a83614747565b91506147a860208401614747565b90509250929050565b6000806000606084860312156147c657600080fd5b6147cf84614747565b92506147dd60208501614747565b9150604084013590509250925092565b6000806000806080858703121561480357600080fd5b61480c85614747565b935061481a60208601614747565b925060408501359150606085013567ffffffffffffffff8082111561483e57600080fd5b818701915087601f83011261485257600080fd5b81358181111561486457614864615ac2565b604051601f8201601f19908116603f0116810190838211818310171561488c5761488c615ac2565b816040528281528a60208487010111156148a557600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b600080604083850312156148dc57600080fd5b6148e583614747565b9150602083013580151581146148fa57600080fd5b809150509250929050565b6000806040838503121561491857600080fd5b61492183614747565b946020939093013593505050565b60006020828403121561494157600080fd5b8135613b4481615ad8565b60006020828403121561495e57600080fd5b8151613b4481615ad8565b60006020828403121561497b57600080fd5b5035919050565b6000806040838503121561499557600080fd5b50508035926020909101359150565b600081518084526149bc81602086016020860161598c565b601f01601f19169290920160200192915050565b600081516149e281856020860161598c565b9290920192915050565b600082516149fe81846020870161598c565b9190910192915050565b60008651614a1a818460208b0161598c565b865190830190614a2e818360208b0161598c565b8651910190614a41818360208a0161598c565b8551910190614a5481836020890161598c565b8451910190614a6781836020880161598c565b01979650505050505050565b600087516020614a868285838d0161598c565b885191840191614a998184848d0161598c565b8851920191614aab8184848c0161598c565b8751920191614abd8184848b0161598c565b8651920191614acf8184848a0161598c565b8551920191614ae1818484890161598c565b919091019998505050505050505050565b60008351614b0481846020880161598c565b835190830190614b1881836020880161598c565b600b60fa1b9101908152600101949350505050565b60008351614b3f81846020880161598c565b835190830190614b5381836020880161598c565b600160fd1b9101908152600101949350505050565b60008351614b7a81846020880161598c565b80830190507f22207d2c207b202274726169745f74797065223a20224d6574656f72222c20228152683b30b63ab2911d101160b91b60208201528351614bc781602984016020880161598c565b01602901949350505050565b60008451614be581846020890161598c565b80830190507f3c636972636c65206f7061636974793d22302e34222066696c6c3d2223464646815268231ca2911031bc1e9160b91b60208201528451614c3281602984016020890161598c565b66222063793d222d60c81b602992909101918201528351614c5a81603084016020880161598c565b681110391e911a11179f60b91b6030929091019182015260390195945050505050565b621e339f60e91b815260008351614c9b81600385016020880161598c565b80830190507f3c616e696d6174654d6f74696f6e20706174683d224d20302030206c2000000060038201528351614cd981602084016020880161598c565b7f3130303030203130303030203230205a22206475723d22323073222072657065602092909101918201527f6174436f756e743d22696e646566696e69746522202f3e203c2f673e000000006040820152605c01949350505050565b6331bc1e9160e11b81528351600090614d5581600485016020890161598c565b65111031bc9e9160d11b6004918401918201528451614d7b81600a84016020890161598c565b641110391e9160d91b600a92909101918201528351614da181600f84016020880161598c565b601160f91b600f929091019182015260100195945050505050565b7f222077696474683d223130303022206865696768743d2231313030223e000000815260008251614df481601d85016020870161598c565b7f3c2f726563743e3c67206f7061636974793d2230223e203c706f6c79676f6e20601d9390910192830152506666696c6c3d222360c81b603d820152604401919050565b6f3c706f6c79676f6e2066696c6c3d222360801b81528451600090614e64816010850160208a0161598c565b6911103837b4b73a399e9160b11b6010918401918201528551614e8e81601a840160208a0161598c565b7f223e203c616e696d617465206174747269627574654e616d653d226f70616369601a92909101918201527f7479222076616c7565733d22313b313b313b313b303b313b313b313b313b313b603a8201527f313b313b313b313b313b313b313b313b313b313b3122206475723d2233732220605a8201527f726570656174436f756e743d22696e646566696e6974652220626567696e3d22607a8201527f307322202f3e203c2f706f6c79676f6e3e203c706f6c79676f6e2066696c6c3d609a82015261222360f01b60ba820152615043614f8e614f88614f7260bc8501896149d0565b6911103837b4b73a399e9160b11b8152600a0190565b866149d0565b7f223e203c616e696d617465206174747269627574654e616d653d226f7061636981527f7479222076616c7565733d22313b313b313b313b303b313b313b313b313b313b60208201527f313b313b313b313b313b313b313b313b313b313b3122206475723d223373222060408201527f726570656174436f756e743d22696e646566696e6974652220626567696e3d2260608201527018399110179f101e17b837b63cb3b7b71f60791b608082015260910190565b979650505050505050565b7f7b226e616d65223a20224d797374696320466f72657374222c2022646573637281527f697074696f6e223a20224d797374696320466f72657374202d20696e7465726160208201527f63746976652067616d652c20636f6d706c6574656c792067656e6572617465646040820152761027b721b430b4b711161130ba3a3934b13aba32b9911d60491b6060820152600083516150f281607785016020880161598c565b7f2c2022696d616765223a2022646174613a696d6167652f7376672b786d6c3b6260779184019182015265185cd94d8d0b60d21b6097820152835161513e81609d84016020880161598c565b61227d60f01b609d9290910191820152609f01949350505050565b7f222f3e203c2f72616469616c4772616469656e743e203c636972636c65206f7081527f61636974793d22302e39222066696c6c3d2275726c28235329222000000000006020820152600083516151b781603b85016020880161598c565b620179f160ed1b603b9184019182015283516151da81603e84016020880161598c565b7f3c706f6c79676f6e206f7061636974793d22302e3134222066696c6c3d222300603e9290910191820152605d01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c00000081526000825161524881601d85016020870161598c565b91909101601d0192915050565b7f222f3e203c2f6c696e6561724772616469656e743e203c726563742066696c6c81527f3d2275726c28234229222077696474683d223130303022206865696768743d2260208201527f31303030222f3e203c72616469616c4772616469656e742069643d22532220006040820152600082516152d981605f85016020870161598c565b7f206772616469656e74556e6974733d227573657253706163654f6e557365223e605f9390910192830152507f203c73746f70206f66667365743d22302e373522207374796c653d2273746f70607f8201527f2d636f6c6f723a23464646463945222f3e203c73746f70206f66667365743d22609f820152753122207374796c653d2273746f702d636f6c6f723a2360501b60bf82015260d501919050565b65119bdc995cdd60d21b81526000825161539981600685016020870161598c565b9190910160060192915050565b6911103837b4b73a399e9160b11b815281516000906153cc81600a85016020870161598c565b600080516020615f52833981519152600a9390910192830152507f3135203139206c203133203134205a22206475723d2231377322207265706561602a8201527f74436f756e743d22696e646566696e69746522202f3e203c2f706f6c79676f6e604a820152713e203c706f6c79676f6e2066696c6c3d222360701b606a820152607c01919050565b6911103837b4b73a399e9160b11b8152815160009061547b81600a85016020870161598c565b600080516020615f52833981519152600a9390910192830152507f313020305a22206475723d223136732220726570656174436f756e743d22696e602a8201527f646566696e69746522202f3e203c2f706f6c79676f6e3e20203c72656374206f604a820152717061636974793d2230222066696c6c3d222360701b606a820152607c01919050565b6911103837b4b73a399e9160b11b8152815160009061552a81600a85016020870161598c565b600080516020615f52833981519152600a9390910192830152507f3135203230206c203132203135205a22206475723d2231397322207265706561602a8201527f74436f756e743d22696e646566696e69746522202f3e203c2f706f6c79676f6e604a820152713e203c706f6c79676f6e2066696c6c3d222360701b606a820152607c01919050565b6911103837b4b73a399e9160b11b815281516000906155d981600a85016020870161598c565b7f222f3e203c706f6c79676f6e206f7061636974793d22302e36222066696c6c3d600a93909101928301525061222360f01b602a820152602c01919050565b6911103837b4b73a399e9160b11b8152815160009061563e81600a85016020870161598c565b63011179f160e51b600a939091019283015250600e01919050565b6911103837b4b73a399e9160b11b8152815160009061567f81600a85016020870161598c565b73222f3e203c706f6c79676f6e2066696c6c3d222360601b600a939091019283015250601e01919050565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906156dd908301846149a4565b9695505050505050565b602081526000613b4460208301846149a4565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b600082198211156157e5576157e5615a6a565b500190565b6000826157f9576157f9615a80565b600160ff1b82146000198414161561581357615813615a6a565b500590565b60008261582757615827615a80565b500490565b600181815b8085111561586757816000190482111561584d5761584d615a6a565b8085161561585a57918102915b93841c9390800290615831565b509250929050565b6000613b44838360008261588557506001610447565b8161589257506000610447565b81600181146158a857600281146158b2576158ce565b6001915050610447565b60ff8411156158c3576158c3615a6a565b50506001821b610447565b5060208310610133831016604e8410600b84101617156158f1575081810a610447565b6158fb838361582c565b806000190482111561590f5761590f615a6a565b029392505050565b600081600019048311821515161561593157615931615a6a565b500290565b60008083128015600160ff1b85018412161561595457615954615a6a565b6001600160ff1b038401831381161561596f5761596f615a6a565b50500390565b60008282101561598757615987615a6a565b500390565b60005b838110156159a757818101518382015260200161598f565b838111156127e25750506000910152565b6000816159c7576159c7615a6a565b506000190190565b600181811c908216806159e357607f821691505b60208210811415615a0457634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415615a1e57615a1e615a6a565b5060010190565b600082615a3457615a34615a80565b500790565b600082615a4857615a48615a80565b500690565b6000600160ff1b821415615a6357615a63615a6a565b5060000390565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160e01b03198116811461094c57600080fdfe3c616e696d617465206174747269627574654e616d653d226f706163697479222076616c7565733d22303b2e333b2e333b2e343b2e333b2e333b3022206475723d223130732220726570656174436f756e743d22312220626567696e3d226d6f6e737465722e656e642d31302220726573746172743d227768656e4e6f7441637469766522202f3e222f3e203c73746f70206f66667365743d22302e3522207374796c653d2273746f702d636f6c6f723a23222f3e203c73746f70206f66667365743d223122207374796c653d2273746f702d636f6c6f723a233c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d227574662d38223f3e203c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220783d223070782220793d22307078222077696474683d2231303030707822206865696768743d22313030307078222076696577426f783d2230203020313030302031303030223e203c6c696e6561724772616469656e742069643d224222206772616469656e74556e6974733d227573657253706163654f6e557365222078313d22353030222079313d2231303030222078323d22353030222079323d2230223e203c73746f70206f66667365743d223022207374796c653d2273746f702d636f6c6f723a2322207d2c207b202274726169745f74797065223a202250616c65747465222c202276616c7565223a20223c616e696d617465206174747269627574654e616d653d226f706163697479222069643d226d6f6e73746572222076616c7565733d22303b313b313b313b313b3022206475723d223130732220726570656174436f756e743d22312220626567696e3d22636c69636b2220726573746172743d227768656e4e6f7441637469766522202f3e3c616e696d617465206174747269627574654e616d653d226f706163697479222076616c7565733d22303b313b303b303b303b303b303b3022206475723d223630732220726570656174436f756e743d22696e646566696e6974652220626567696e3d223330732220656e643d226d6f6e737465722e7374617274222f3e203c616e696d6174654d6f74696f6e20706174683d224d20302030206c2030202d31355a22206475723d223330732220726570656174436f756e743d22696e646566696e69746522202f3e203c2f673e3c2f7376673e5b7b202274726169745f74797065223a2022466172222c202276616c7565223a20224142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f22207d2c207b202274726169745f74797065223a20224d6f6e73746572222c202276616c7565223a202222207d2c207b202274726169745f74797065223a2022416e696d616c222c202276616c7565223a20223c72656374206f7061636974793d22302220783d223235302220793d22323530222077696474683d2235303022206865696768743d22353030222f3e223e203c616e696d6174654d6f74696f6e20706174683d224d20302030206c2022207d2c207b202274726169745f74797065223a2022536176616e6e61222c202276616c7565223a202222207d2c207b202274726169745f74797065223a202253756e222c202276616c7565223a2022a26469706673582212205e3aef1e70f659889240519774f4f261268438514c37a075020cfd2040c31c0e64736f6c63430008070033

Deployed Bytecode

0x60806040526004361061014b5760003560e01c80634e71d92d116100b657806395d89b411161006f57806395d89b4114610387578063a22cb4651461039c578063b88d4fde146103bc578063c87b56dd146103dc578063e985e9c5146103fc578063f2fde38b1461041c57600080fd5b80634e71d92d146102e85780634f6ccce7146102fd5780636352211e1461031d57806370a082311461033d578063715018a61461035d5780638da5cb5b1461037257600080fd5b80632f745c59116101085780632f745c59146102405780633610724e146102605780633ccfd60b1461027357806340d097c31461028857806342842e0e146102a85780634d4c71a3146102c857600080fd5b806301ffc9a71461015057806306fdde0314610185578063081812fc146101a7578063095ea7b3146101df57806318160ddd1461020157806323b872dd14610220575b600080fd5b34801561015c57600080fd5b5061017061016b36600461492f565b61043c565b60405190151581526020015b60405180910390f35b34801561019157600080fd5b5061019a61044d565b60405161017c91906156e7565b3480156101b357600080fd5b506101c76101c2366004614969565b6104df565b6040516001600160a01b03909116815260200161017c565b3480156101eb57600080fd5b506101ff6101fa366004614905565b61056c565b005b34801561020d57600080fd5b506008545b60405190815260200161017c565b34801561022c57600080fd5b506101ff61023b3660046147b1565b61067d565b34801561024c57600080fd5b5061021261025b366004614905565b6106ae565b6101ff61026e366004614969565b610744565b34801561027f57600080fd5b506101ff6108a4565b34801561029457600080fd5b506101ff6102a3366004614763565b610902565b3480156102b457600080fd5b506101ff6102c33660046147b1565b61094f565b3480156102d457600080fd5b5061019a6102e3366004614982565b61096a565b3480156102f457600080fd5b506101ff61249a565b34801561030957600080fd5b50610212610318366004614969565b612507565b34801561032957600080fd5b506101c7610338366004614969565b61259a565b34801561034957600080fd5b50610212610358366004614763565b612611565b34801561036957600080fd5b506101ff612698565b34801561037e57600080fd5b506101c76126d1565b34801561039357600080fd5b5061019a6126e0565b3480156103a857600080fd5b506101ff6103b73660046148c9565b6126ef565b3480156103c857600080fd5b506101ff6103d73660046147ed565b6127b0565b3480156103e857600080fd5b5061019a6103f7366004614969565b6127e8565b34801561040857600080fd5b5061017061041736600461477e565b61373f565b34801561042857600080fd5b506101ff610437366004614763565b61376d565b600061044782613813565b92915050565b60606000805461045c906159cf565b80601f0160208091040260200160405190810160405280929190818152602001828054610488906159cf565b80156104d55780601f106104aa576101008083540402835291602001916104d5565b820191906000526020600020905b8154815290600101906020018083116104b857829003601f168201915b5050505050905090565b60006104ea82613838565b6105505760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b60648201526084015b60405180910390fd5b506000908152600460205260409020546001600160a01b031690565b60006105778261259a565b9050806001600160a01b0316836001600160a01b031614156105e55760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610547565b336001600160a01b03821614806106015750610601813361373f565b61066e5760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f776044820152771b995c881b9bdc88185c1c1c9bdd995908199bdc88185b1b60421b6064820152608401610547565b6106788383613855565b505050565b61068733826138c3565b6106a35760405162461bcd60e51b815260040161054790615781565b61067883838361398d565b60006106b983612611565b821061071b5760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b6064820152608401610547565b506001600160a01b03919091166000908152600660209081526040808320938352929052205490565b600081116107835760405162461bcd60e51b815260206004820152600c60248201526b15dc9bdb99c8185b5bdd5b9d60a21b6044820152606401610547565b601e8111156107c25760405162461bcd60e51b815260206004820152600b60248201526a04e6f74206d6f72652033360ac1b6044820152606401610547565b610d056107d8826107d2600b5490565b90613b38565b11156108165760405162461bcd60e51b815260206004820152600d60248201526c14d85b1948199a5b9a5cda1959609a1b6044820152606401610547565b600c5434906108259083613b4b565b11156108635760405162461bcd60e51b815260206004820152600d60248201526c09ccacac840dadee4ca408aa89609b1b6044820152606401610547565b60005b818110156108a0576108803361087b600b5490565b613b57565b61088e600b80546001019055565b8061089881615a0a565b915050610866565b5050565b336108ad6126d1565b6001600160a01b0316146108d35760405162461bcd60e51b81526004016105479061574c565b6040514790339082156108fc029083906000818181858888f193505050501580156108a0573d6000803e3d6000fd5b3361090b6126d1565b6001600160a01b0316146109315760405162461bcd60e51b81526004016105479061574c565b61093e8161087b600b5490565b61094c600b80546001019055565b50565b610678838383604051806020016040528060008152506127b0565b60606000604051806116a001604052807effb4b3b2b1b0af988e877a76726c67645f5a575351493a2a1e1b1713100b0581526020017e07fdababd4eaf52005000198467a9a61c9f6f305ded179bae0af884c05c72f81526020017507fdddabd5eaf560079801a8c267355bd006cca5a53681526020017f064b5270e27fb9df2f7713f9b7168e44dd32470cc187365d5221d487ed811dab81526020017507ff57abd580000000021544727b9edca88772b580c981526020017f084c89cf1c734adef2e7bd31f94c7e525ff497fcfe273c7fcf1ff2f8b4d22b4281526020017f07f409ff017fbda24f482bc63aec7fbadfed79234646f18d4022f248748a172481526020017f06ccd1b1366c561cd4e72d29cf4a73cfde53d73ce9cf057bc15ef1f7fc85ff0a81526020017f073b91cec276b01cebf73ad5e4b373ac9cea96c279b0ad6d2b9b4b36c2e1b13381526020017f07e301febd7fac9fab07daa9eeaa7bb21ceca73b69eed87bbc5cef173ba1dee581526020017e07fd55aad4eab52005c001be878828240c08cb0a2cc484b1a14c47fb19febf81526020017f06797662759522272b3c338354e0d50000000000ad284f61a9194d465c052d5c81526020017f0872fdd8bc7d2e5d8b87225dc09d62a8934505f965be9e72a71c6937fa45c49081526020017f06e3959ee567b61dad676b419cd364ad5b2b3642c58ca470a81d4d376b49dac081526020017f072c51e50f74435d9047340d874e4dd6d9d0376415d8d675359cd0267bfd9ee781526020017507fc07aad56ab54ef9a42a21366652dc51a81c61cb1481526020017f05238d60e4633c9aee763bd962eb55bc973059b44e671e62551cd5e5ed8045aa81526020017f02b104b04a651a1fa949125e7ea6a12b5d6b175af5c8b26cacdb4b8602d146dc81526020016a01ffd26ab480000000483781526020017f079c0ddafe763d656f0773be02dfcab6b212c80cd9db296fccdd13c94519016e81526020017f06734daed3713699cdb68491af246fca9d32774c8df32075481dd18c443b0b0281526020017f0832d1e2b27daa714a5c3265f49b7ca65c29570a319c8f66ab5aab5692e598bb81526020017e07fc81aad56ab54000000000456822e107b8f227328ecab4df2c976305dab881526020017f06fb9dbcfa6abe9a30068c25af0c6dc4235248fc864b2967cc55d4b5052c23aa81526020017f063a857ea15eae1d0ba5f2f182ca633258ec466b119cc26eb05b8dc73385f2e381526020017f0d56ab540000000001b731cdf06c8b9e1c4816f229a68a6b275baa466aa192a681526020016101ff81526020017f060385b6dd603717ed45b33950cc52be163065946d55290cdcc37aad56ab540081526020017f05530970c45f33592cb69b0622bf8dbba650984471a9196241584f075bb582eb81526020017e07fc0000000002c25541517673791e99c7c6c2296090562653e9b502dd64bc81526020017f02b38c96f9183d460ff23c085b3a18b905af5003c000fa153f8451b0f504014081526020017f0444326f265bd29a74b984c6553b7c53ddf4c35d18bd412ad0c95423bcb46d3c81526020017f09445e5d18a043a6f196cc31a10964c29110041bf8feff273e497023d429030c81526020017f099a6e6ac09baaa84d0a1bc63ccba1bf686fd99bde38f69b40a1f0b97436830681526020017f07e2d236d47ba7a0aac93afe18a879a39f6828fa1e229e94a2e38b59627e5e9381526020017f0649ad946c669ade27f6a99daa67761ddf08076211ee8375a59e8c87a2b1e09a81526020017f064291cec461239a09c752a17e7e631c98a705f1e97861631c9ca9461181986981526020017f0449e1168649a952083451d5166c5a98d6a695d9fd767f5b21980b860271788a81526020017f0192210ea21ea00867c451b504783f22cfe99429e912724222d12a448acd128c81526020017f017af086dc1aaec4e8c1bab49ebf19268ded523a88beab2127072942826cf4a181526020017f0629557e4e5d9396a594b98122604518c0081002304e830f2ac4ecc122a04c968152602001771ff006ab55aad5000000000185404b4898126605112da45081526020017f02b49d0d3263cdda9356dd1da54954529194457d04f340204d0cd3110cb8012781526020017f069bf9ab126949c6f17004440116694a5a32d6a4d18f3641cc0b92600470012181526020017f090466072a774a9ad276b4a9e52c804b1fd2d6dcc9af2b6bc81bf206bc79b11181526020017f090cee3b378ccda353c8fcf9d745714f5eb396fce1bb347fcba072b97ca60d2a81526020017f09c4b299339f4c24f3197cd6913597cf25737954f6553892cd64d3d91cda3d3581526020017f0a440e8300a141a9909a1c2e8d0fa543e8f1aa14567910a3482952c9fc8e4b1a81526020017f09eb628ed5a932ea4d1a138e9adda935aa4e0a73f68cfba6c0a8cfda0bf284fe81526020017f09f2ce80b2a4ab284b4a52cea0a9a7ad6a4b2a92e290b894b1274c6a5b16a4c281526020017f09ea72769fa328a74a69caae86aa9dac25ca39729274b19cad67ab3a22ee8aba81526020017f076231a28c68239c88f7923e4a9b952864ea99c2727299a1a36929a9d25a729981526020017f098a22688d9d2226a8d9ca3a649096236548f982525e979925e589b95a7e449681526020017f090202528091a12508790a1a3c8b83219ae826aa16388e8d24a4c8f952425a8d81526020017f0562e97aac61a8db6a16327db47d771e232787c9d62c6d921d6267b8e9fe407c81526020017f064a016ca6522e564e357bd54f0a59be56ee459b5586d35934960c85c3195ec581526020017f0d500000000033068ac21aac72a920294f0a223a80b0963f22d868e622311a878152602001651ff006ab55aa81526020017f05129544a253aa542a550aa156b656aed46b0512a944a950aa142b451ae55ec481526020017f047a45088e40241068243219108d4421d208f4a29128a64baa5229050a8142a581526020017f04baf912a54a2b130b74c30148ea4e3016af45132152d34d2bd42b3402450a9281526020017f038ac8e4b945380ecb548b60f4af39ab0f89b3f2a522bf41298fc963fa5104a181526020017f01a1fc847e212089482241f8c2832b9f4f47a41204fc91362d8d4d739b90dcd781526020017f02426080952425092992626c969426a509a942b284b4a42a250fc9225208648081526020017f01810c5c4700118005512954247508a343cb81db94469837ba44c8e24aa0dcaf81526020017f0670f59a38270d0923f2e120a648248fcb220218c45c2b170c80032000d85a3781526020017f07b11e42438a9035444d50f5de388888598386791d48484f11d2a4946924ce3a81526020017f07319dd4737f9ca2c89829cb5466d51664a637e195e4578a16e1856d515f544681526020017f03c1b4fa583e960fe6d439b50658489b12c6b45961aa5878215c25872161e66681526020017f0179bc4e721d1608e682419c805625958e06d2e95cd45730970c8603795cee5881526020017f065a31c49d66a09d88a659d5cc736f19d526a281c0c2632d17c6e6d1f170785981526020017f05727d3a9a3d9e90679432151087439e530784e20144874d9dd72776aab98e858152602001797fd84ea5d35990e657ae9ace95cb0984c9592c952ab50a798ab281526020017f024ba8010200424a2ef2cba8d8e92fb98cce137354f0cf39338eec843b08eafc81526020017e021ccc864f9f5328f2a230668a0024800981da40ec964b26118b037ae8bedb81526020017f0799e5c0787f1a3543fd5005984346934d43d4e0e4c83716000320038148005d81526020017f0d52f2aab7622996ca964251be8e87202d48bd524f548b9d9f6187b67a31b87c81526020017f04f46d23154a3b13ad75535140d150b3d76c951b295cb263ab2cabcb8aff54c081526020017f05ed955d5c55525cd507f54e9b68c76ab21aaa6591ed4e54d19432458c89412081526020017f046cf5353b46ce521204c481515e516a951aa575857d69725a691aaa7ea9cb668152602001771ff336a901aa45d3d515e53d65174a46515474851515194281526020017f0623b5890352448c30c294b811a004e34bb014ec297cfe5c3a176dc6234192d081526020016a01ff64b4196d464b7988e981526020017f0573215acb523413a8852a3152965aa6156925321d388044000e6004aa253cd581526020017f062b4186d0613457aca61b1988c762b2188c962b218ac760b0d72c358b1958c981526020017f05737d78e5603918ae062b7d88dd623798ae05f37182d76136188d86235988d281526020017301ff40c9d11384249530f352bf536ef5235d5ede81526020017f047040f64a421ecdeaf302c0aaba2ab10aece2fb50bacc2f300d2c136af8d6d481526020017f03b2e10ab9432dd0ab443ab90aaa39ab9147b4216518654d1b51a62419295a108152602001677fcdcc837af4e6bb81526020017f07aaf9eaba7f2e1feb37face02b383abe12ab8a2aa32a58e26a809fa5abec0bf81526020017f077245e8a276289ceaa722a5c0ad71ac9cab1732c5ccb5742e1dabb76af9e0c081526020017f07aa3624867d21df4878a9f1f68072231c69075259d09180255fa977da6dec9281526020017f0d42b750a5a4a66a695b221e9e8ea2256b27ca223e8297a02621c9085a3a108e81526020016e1ffb02fea2aba428e9ca6b72b6aaa281526020017f06d291b8a66ea95bca67028dc29f72a79d6a17a299eaa979ab9c2c07b2c5f89d81526020017f077a19d48374a05d87e7b9f9f6807b9f5d87d741fdcc8373221b6996b279b0a481526020017f075a71e29b7b269ee9e7ba81f2997aa59d8977623de6937ba49f6917ea29e88e81526020017f07ea561e5a8892e4864909ca4e77919c64c638910a3c008400610597b291dc9d8152602001677fe04ac81ad208ab81526020017f02cbf4b4fc2d3ecbafd32bf4ccfd35bf0dd162a584936e23d447b3a21d508b7481526020017f035b8ce6d435380c8c034bb8c6ef2f3c0b8f22cbccaef52b3e0b2fa2cbe8b2fc81526020017e07fc29a91fea4b96a38c5cdcfb3a3e102f7413d8fcf540bd100f1393c4d8ef81526020017f09bb9e68e7963b64eec953ce56f996406610f97cce5d3b99d267150a0562975e81526020017f0b6c3ad110acc3ad104b5c0ee4fdb9bced0ffab41a94fea2bd680f0a1b9282e081526020017f0b84a2e321b6c92d729aecc69d29a7c929f16a9c5ed115b6c52e30fb8c1adf0981526020017f0a5d26a543ac512bb47b54eee335b8cbadb31b5cd6bd3ca84dea536ac4deb93a81526020016c07fea163acd8ea959a65467b4d81526020017f09328a4ca19528a56a4962824e9b94a5e5697962625898952a65cb49630660b681526020017f089aae26ac8baae32aa8d2aa38aa8faa644a892a9650a694aa254a995a9654a481526020017f08ea3632938ca66369d8ca7a329f8c27e2e9f89a7e249f89a8e26a489a9a28a881526020017f0d490b503dac996867b9b1ea627d9b1f2847e9b2226a879821e5a8993a22448a81526020017f09aaee5cac9aaba5aa998246668e9aa42808e9c22ab66dad1fea88cae202bc6b81526020016101ff81526020017f0a1c1a8f0ea8c4e9f1ea7486a12daac86ab1daac46b10bacc72ed3eb5502f54281526020017f0adbb6aef1aabb29ce7a6b969ae1a638296dfa2b8e88e5a23a292f2a4bd688fd81526020017f0af46ab4ffb13dab6faaf376bed7ac3fab107ab426ad06a9c0ea502aa3eab4f48152602001677fef542d3daf4f4a81526020017f07a1f1e87f749fdce8375205e8837a219d88a7a225ea8c7823dec8d8229a3aa481526020017f0849be3069a219a4466a615f5c6ad697a985280991ec75789cdea777a1e9da7881526020017f082a4a6294872423c8c99247589ad5a4e5e88d621f586a991de3877879ca526e81526020016e1ffd62c758a787a761c9caca6a169981526020017f09146e231c89c6a451989c662b16914662b148b44a2ef9953ca470a8ecc6313981526020017f08a3e6291285499f13284ca61b338649e1b2490c961d238847e43238847a211e81526020017f08e31636c28ab0234c38bb3632c99132632c88d31a3cd1913424cec8abda12fa81526020017f08e21e3c818d2120c8b8d21e40938f2a62aaa902b650bf92b163ecb8eb1a4ec481526020017f090a76429a95a7a429890a5e5c9591256449290a42609090a3e3e8d98a363e8c81526020017f098a3e6a85a020e6a82989de68859527250b39029e40a59628a40a390a7e56a181526020017f0a725ea690a5a5664bf97af65ab996a7a829096a6a60939a25a609198a466e9481526020017f0a5ade76b9a12b6a2ada12b288a9b42a68aa7a3296a4a5a3a8e989acfad340ab81526020017f09db1692cb9db0e84c1aab068ebfaaaef40cdcfb1aacb8adacaa8b89bb0674bb81526020017f0d13b740d2a6b4284d89d36688d59db568cd39e34690d19db3692d09d32294cf81526020017f0cfc028f00a2beea6f8a23e686f7adbca84f5a03baa0ed9fbb296ea9eba680e781526020017f0a945a71109c43ac30d9c4327104a141271039b3aa8b03a2c0e8709a4c0f3d0881526020017c01ff8fcc64d0e9744a4d09983b26d129ac7a7313d24b74b25adc62d11881526020017f08c1fa2075871de1e72871a6126b86982205a8a1222a548f1227843971269c4c81526020017f093276469d922824e9f8f2923caa8da963e978da3e348c8823a229486a2e428081526020017f0a62528c9ba0a7e7c9e9e2867ca29da8a70a09ba86649c98a7a669f9827e569e81526020017f0a122e7a8da2a327e8ea1a3a8290a4a3a8491a52428893a6a428a95a5a4a8c9881526020017f0a12327c8ca022e768a9ea2a6a899d22272889a226688a9e22a6e8b9fa2e768d81526020017f0a5a5e9893a4a5a9891a4a52988fa2a46968ea0a3e908da02368a8ca22327e8d81526020017507fe9c4cb110b2042c82568a849f21e8889a8236a09281526020017f090d92476b875d2597397dc65b76965ca4973946024d848b5da3d86815b23b9781526020017f09ec667d289b4aa7d29a254a71378fc66774b8dce279587cd4273609b5924b6981526020017f0ac496af29a046a9724a049e8129a749eab2ea8cce9f2aa74da933ca74ea934b81526020017f0b0bdec708b0c3ea8f7afc52bd15ab42e86feae45e8d12adc7ab520a748ea52681526020017f09abc65ad7a33d25ad29c3529ad19833eceb5a1b8ad4bbae39edcc1b4be6cb0581526020017f0b0a36c695af27eca9bb4abeb8a89bacaceb3973365acf94b464ed295b4656d781526020017f0a3222947ca7176b274a49f29080a99eea67ba2252ae85ae9f6ba7dac22aaea981526020017f0a112a6c45828e6724c9192a06539714e2a649e956428ea19768a80a120e8a8181526020017f08ceab55aad50025000990ea703d9e0c284419c0f220289a10668449b1166e4381526020016101ff81526020017f061571795d605859562615998b686759d8f6c695b5b5677cdc2097b72dce419a81526020017f08d6164f8d85d920f6587dda0f737f59db7557b5b9b96666d519f5d62d65956181526020017f08859a336a9ddb227708a5ce3773975c23b779a602518f93e32217e84dda217881526020017f078521c94b77d4deb5378565fb5a7cd7a09608159621668d57a7d6a95d96256481526020017f09c54e47469a55a7b638e55a3b468ad221f4386d2a03448153603487ad11ef4e81526020017f081ca5d91b7c4a5d7297e4b9bd3781cca11349ed4675539f54e7f58a6d7e916581526020017f08ecb24130964ce4f3491cda4d399ace25f3994cfa693f9bcfa774a84cbe030d81526020017f0a954ab150aad52793b9f4eaa544ab50e7f39994966930994b6512896cca492b81526020017f0ae496cd28b2cc2c72dadca2c739afcd6832ba54dec143a35129d49ab526994c81526020017f0a045e8f20a0c82731c9947a6f22a2c8a7d27a1ca69b24a9c929b28a44b6a92d81526020017f0ad412db09af41e8f0aa7c36d90ca24529f15b6436cf26af4929b17a8c82971a81526020017f0b03cac2f4b33caeae2b6c0eaae5aebd6b6f7af3dac0f9b2bfebcfaa1bce98fc81526020017f0b2ad2d4aab8b1aaabab432ae2ceb433294d4abb66d2daba35ab4e9b13a6eadf81526020017f09ca969caf9fada94b3a2aee98b5a5b06a2b1b0a9aacb4af2c2d2a4b4a9ebaba81526020017f0a128e9ca0b1a36c68db2a5ac695ada4eb295b126abc9aa4296a6a7b0a92a6ae81526020017f0ae1eeb87fa89f264829fa1ea489b0a1eae8aa02629497b022eb293aa24aae9481526020017f0a01a29e6aa79b6a66aad9a6b86eac9c68869a89d27677a31e6a876a81e6ac7781526020017f08a1ce3c73919ba4675951c25474991be68699a1a66a739f1b68062ab962a46181526020017f0a315aaa53ab15a7e609b966585998182585d909825066921923666911b2346c81526020017f09a93a72519715e7057a61228e4fa593e9e49aa93a844e9e14e80569e16a865b81526020017f08214dec618514a0e75861425c3e9a8f680419b106304c9313e724da511a784e81526020017f078901f43d7b90a04408011a20418a0ea46358a10a4a408413de24982145ea5681526020016e1ff746ab55aad5001e800728d5e63981526020017507fe007c7f1f2007f809f20a7c809edfc797f1ee007c8152602001707fdfc887f22e02877fa15fe8680a1dfc888152602001707fe70d2993725cdc98b6a64d999b6266d88152602001707fe66c79c33a6acb9b32e68ca9932660c881526020017301ff96236649199a56609598252629397a465e9281526020017301ff98266649997a765e9b9826a609a98a66609981525090506000806000806000806060600060038c106122d3576101006122ac60038e615975565b6122b89061010061586f565b8a516122c49190615818565b6122ce9190615a39565b6122de565b6122de8c60016157d2565b96508a600114156122f257608c93506122f8565b61038493505b6040518060200160405280600081525091508697505b60b5881161248b57888860b5811061232857612328615aac565b60200201516123365761248b565b888860b5811061234857612348615aac565b6020020151955060009450600092505b601b831161246a5761020061236d848261586f565b6123779088615818565b6123819190615a39565b9050806101ff14156123925761246a565b61239d600286615a39565b61240c578a600114156123f157816123ca608c6123bb846003615917565b6123c59190615936565b613b71565b6040516020016123db929190614af2565b604051602081830303815290604052915061244a565b816123ca612400836003615917565b6123c5906104e2615936565b81612427858d61241d856003615917565b6123bb9190615917565b604051602001612438929190614b2d565b60405160208183030381529060405291505b8461245481615a0a565b955050828061246290615a0a565b935050612358565b806101ff14156124795761248b565b8761248381615a0a565b98505061230e565b509a9950505050505050505050565b61012c6124a6600b5490565b11156124ea5760405162461bcd60e51b81526020600482015260136024820152724e6f206d6f7265206672656520746f6b656e7360681b6044820152606401610547565b6124f73361087b600b5490565b612505600b80546001019055565b565b600061251260085490565b82106125755760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b6064820152608401610547565b6008828154811061258857612588615aac565b90600052602060002001549050919050565b6000818152600260205260408120546001600160a01b0316806104475760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b6064820152608401610547565b60006001600160a01b03821661267c5760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b6064820152608401610547565b506001600160a01b031660009081526003602052604090205490565b336126a16126d1565b6001600160a01b0316146126c75760405162461bcd60e51b81526004016105479061574c565b6125056000613ce4565b600a546001600160a01b031690565b60606001805461045c906159cf565b6001600160a01b0382163314156127445760405162461bcd60e51b815260206004820152601960248201527822a9219b99189d1030b8383937bb32903a379031b0b63632b960391b6044820152606401610547565b3360008181526005602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6127ba33836138c3565b6127d65760405162461bcd60e51b815260040161054790615781565b6127e284848484613d36565b50505050565b60606127f26146c7565b6127fa6146e6565b61280261470d565b61280a614728565b60008061283d61281989613d69565b6040516020016128299190615378565b604051602081830303815290604052613e67565b905061284a602482615a39565b6128559060016157d2565b83526009612864606483615818565b61286e9190615a39565b6128799060016157d2565b6020840152600261288c6103e883615818565b6128969190615a39565b6128a19060016157d2565b604084015260026128b461271083615818565b6128be9190615a39565b6128c99060016157d2565b606084015260026128dd620186a083615818565b6128e79190615a39565b6128f29060016157d2565b60808401526009612906620f424083615818565b6129109190615a39565b61291b9060016157d2565b60a0840152600961292f6298968083615818565b6129399190615a39565b6129449060016157d2565b60c084015260026129596305f5e10083615818565b6129639190615a39565b61296e9060016157d2565b60e08401526009612983633b9aca0083615818565b61298d9190615a39565b6129989060016157d2565b61010084015260146129af6402540be40083615818565b6129b99190615a39565b6129c49060016157d2565b61012084015260146129db6402540be40083615818565b6129e59190615a39565b60011415612a095782516129fb90600290615a39565b612a069060256157d2565b83525b7c3331a3e080008277ffff9efff53f18283d1c8c94335582ffff9eff3f4086527d0c0e2b54bbffc200ccffffeaff88001e2900e0d78074a11affff9effff9e60208701527d1011246dcfc248667dffffeaff88000c0e2bff5454c200ccffffeaff880060408701527d1213247689942f354affff9eff3f401011246dcfc248667dffff9eff3f4060608701527d190014ff4c00870041ffff9eff3f400a0d00ffaa00004a01ffff9eff3f4060808701527d091d24ffff9e009e71ffff9effd080111c2b00c483004a61ffff9eff3f4060a08701527d01002b5b1d91731045ff3030ff30300c190a71bd46008037ffff9effff9e60c08701527d0505056e676a696969f0e8e4f0e8e41b002487003df02222ff5500ff3f4060e08701527c1114067a59005c4999f0e7ff993d00111427596b00809999d0f099d0f06101008701527d180019ff8c006900a6fff08cff8c0018001930579168248fffa6efff3d3d610120808801919091527c15195da69c5f969efff8c7fff8c70300197e91965f759eedebdaffff9e6101408801527c0f26b5c90000949effff9effffff121900c9a071939e5fffff9effffff6101608801527d14000fff7878bf0060ffffa8ff7878170000d4a200bf5300ffff9eff3f406101808801527d14000fff59002b00a1ffffa8ff590014000fe58ca1644aa1ffffa8ff78786101a08801527c0619e0b082a12848ffffebffb482000d1400c5db2840a1ffffeb3ddbff6101c08801527d260026007bffd40071ffc4c4ffc4c4260000ff4c00780002ffdc69ff3f406101e08801527d36001dffaa00ff0000ffed4fffed4f260006ff0000630035ffad4fff3f406102008801527c0f05254c00006330a7ff63a7ff63361900b090829c5454fff7abfff7ab6102208801527a523f4f523f4fd94141d9414100010f91007e00635a63ffa963ffa9610240880152830151600710612de557600091505b610120830151612cd990600290615818565b612ce49060016157d2565b821015612d70576101c0840151612d10612cff846096615917565b612d0b906101906157d2565b613d69565b612d36610113612d218660c8615917565b612d2c9060456157d2565b612d0b9190615a39565b604051602001612d4893929190614bd3565b60408051808303601f190181529190526101c085015281612d6881615a0a565b925050612cc7565b6101c0840151610120840151612d8890600290615a39565b15612dac57604051806040016040528060018152602001602d60f81b815250612dbd565b604051806020016040528060008152505b604051602001612dce929190614c7d565b60408051808303601f190181529190526101c08501525b8251612df390600190615975565b612dfe906005615917565b9150612e5b6301000000612e13600a85615a39565b612e2190630100000061586f565b88612e2d600a87615818565b60138110612e3d57612e3d615aac565b6020020151612e4c9190615818565b612e569190615a39565b613e98565b85528251612e6b90600190615975565b612e76906005615917565b612e819060016157d2565b9150612e966301000000612e13600a85615a39565b60208601528251612ea990600190615975565b612eb4906005615917565b612ebf9060026157d2565b9150612ed46301000000612e13600a85615a39565b60808601528251612ee790600190615975565b612ef2906005615917565b612efd9060036157d2565b9150612f126301000000612e13600a85615a39565b60608601528251612f2590600190615975565b612f30906005615917565b612f3b9060046157d2565b9150612f506301000000612e13600a85615a39565b60408087019190915280516101408101909152610115808252615bc9602083013984526040805160608101909152602a808252615b7760208301398460016020020181905250604051806060016040528060288152602001615ba1602891396040850152612fd160018460085b6020020151612fcc9190615975565b613f90565b604051602001612fe19190615255565b60408051808303601f1901815291905260608501526130036001846008612fbd565b6101c085015160405161301a929190602001615159565b60408051808303601f1901815291905260808501526020830151613057906001906130469060006157d2565b6130509190615975565b600161096a565b60405160200161306791906155b3565b60408051601f198184030181529190528460056020020152613097600184600260200201516130469060096157d2565b6040516020016130a79190615659565b60408051808303601f1901815291905260c085015260608301516130d39060019061304690600b6157d2565b6040516020016130e39190615504565b60408051808303601f1901815291905260e085015260808301516131209060019061310f90600b6157d2565b6131199190615975565b600261096a565b60405160200161313091906153a6565b60408051808303601f1901815291905261010085015260e083015161315d906001906130469060196157d2565b60405160200161316d9190615455565b60408051808303601f1901815291905261012085015260c0830151600310156131a557604051806020016040528060008152506131bf565b6040518060c0016040528060888152602001615aef608891395b6040516020016131cf9190614dbc565b60408051601f1981840301815291905284600a6020020152613243600184600381600660200201511115613204576005613207565b60065b60ff16600c811061321a5761321a615aac565b602002015160c08601516003101561323357600d613236565b60165b60ff1661304691906157d2565b6040516020016132539190615618565b60408051808303601f1901815291905261016085015260c08301516003106132e857845160c08401516132999060019061328e906002615917565b61304690601a6157d2565b865160c08601516132ba906132af906002615917565b61305090601a6157d2565b6040516020016132cd9493929190614e38565b60408051808303601f19018152919052610180850152613308565b6040518060600160405280603c8152602001615f16603c91396101808501525b6040518061018001604052806101598152602001615d0861015991396101a08501528351608086015160208087015160608901516040808a01519051600096613358969095909493929101614a08565b60408051808303601f19018152908290526080808901516060808a0151908b0151928a01519395506133939486949293919290602001614a08565b60408051808303601f190181528282529088015160a088015160c08901519294506133c49385938391602001614a08565b60408051808303601f190181528282529088015160e08801516101008901519294506133f69385938391602001614a08565b60408051808303601f19018152828252908801516101208801516101408901519294506134299385938391602001614a08565b60408051808303601f19018152828252908801516101608801516101808901516101a08a015193955061346194869490602001614a08565b60408051601f19818403018152606083019091526022808352909250615e61602083013985526134988460015b6020020151613d69565b85600160200201819052506040518060600160405280602a8152602001615cde602a913960408601526134cc84600061348e565b606080870191909152604080519182019052602a808252615f726020830139608080870191909152840151606085015161354b919061350c90600a615917565b604087015161351c906064615917565b60e088015161352d906103e8615917565b61353791906157d2565b61354191906157d2565b612d0b91906157d2565b60a086015260c084015160031061358f576040518060600160405280602a8152602001615ec3602a913960c086015261358584600661348e565b60e08601526135be565b604051806060016040528060298152602001615eed6029913960c08601526135b884600561348e565b60e08601525b604051806060016040528060268152602001615f9c602691396101008601526135e884600861348e565b856009602002015260078460096020020151116136385761012085015161361085600961348e565b604051602001613621929190614b68565b60408051808303601f190181529190526101208601525b604080518082018252600481526322207d5d60e01b6020808301919091526101408801919091528651878201518884015160608a015160808b015160a08c0151965160009761368997909101614a73565b60408051808303601f190181529082905260c088015160e08901516101008a01516101208b01516101408c01519496506136c895879590602001614a73565b6040516020818303038152906040529050600061370d826136e88561403f565b6040516020016136f992919061504e565b60405160208183030381529060405261403f565b9050806040516020016137209190615210565b60408051601f198184030181529190529b9a5050505050505050505050565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b336137766126d1565b6001600160a01b03161461379c5760405162461bcd60e51b81526004016105479061574c565b6001600160a01b0381166138015760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610547565b61094c81613ce4565b80546001019055565b60006001600160e01b0319821663780e9d6360e01b14806104475750610447826141a5565b6000908152600260205260409020546001600160a01b0316151590565b600081815260046020526040902080546001600160a01b0319166001600160a01b038416908117909155819061388a8261259a565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60006138ce82613838565b61392f5760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610547565b600061393a8361259a565b9050806001600160a01b0316846001600160a01b031614806139755750836001600160a01b031661396a846104df565b6001600160a01b0316145b806139855750613985818561373f565b949350505050565b826001600160a01b03166139a08261259a565b6001600160a01b031614613a085760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201526839903737ba1037bbb760b91b6064820152608401610547565b6001600160a01b038216613a6a5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610547565b613a758383836141f5565b613a80600082613855565b6001600160a01b0383166000908152600360205260408120805460019290613aa9908490615975565b90915550506001600160a01b0382166000908152600360205260408120805460019290613ad79084906157d2565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6000613b4482846157d2565b9392505050565b6000613b448284615917565b6108a0828260405180602001604052806000815250614200565b606081613b955750506040805180820190915260018152600360fc1b602082015290565b600080831215613bad57613ba883615a4d565b613baf565b825b905060005b8115613bda5780613bc481615a0a565b9150613bd39050600a836157ea565b9150613bb4565b6000841215613bf15780613bed81615a0a565b9150505b60008167ffffffffffffffff811115613c0c57613c0c615ac2565b6040519080825280601f01601f191660200182016040528015613c36576020820181803683370190505b5090506000851215613c7d57613c4b85615a4d565b9450602d60f81b81600081518110613c6557613c65615aac565b60200101906001600160f81b031916908160001a9053505b841561398557613c8e600183615975565b9150613c9b600a86615a25565b613ca69060306157d2565b60f81b818381518110613cbb57613cbb615aac565b60200101906001600160f81b031916908160001a905350613cdd600a866157ea565b9450613c7d565b600a80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b613d4184848461398d565b613d4d84848484614233565b6127e25760405162461bcd60e51b8152600401610547906156fa565b606081613d8d5750506040805180820190915260018152600360fc1b602082015290565b8160005b8115613db75780613da181615a0a565b9150613db09050600a83615818565b9150613d91565b60008167ffffffffffffffff811115613dd257613dd2615ac2565b6040519080825280601f01601f191660200182016040528015613dfc576020820181803683370190505b5090505b841561398557613e11600183615975565b9150613e1e600a86615a39565b613e299060306157d2565b60f81b818381518110613e3e57613e3e615aac565b60200101906001600160f81b031916908160001a905350613e60600a86615818565b9450613e00565b600081604051602001613e7a91906149ec565b60408051601f19818403018152919052805160209091012092915050565b6040805180820190915260068082526503030303030360d41b60208301526060915b8115613b4457600a613ecd601086615a39565b1015613f2457613ede601085615a39565b613ee99060306157d2565b60f81b81613ef8600185615975565b81518110613f0857613f08615aac565b60200101906001600160f81b031916908160001a905350613f71565b613f2f601085615a39565b613f3a9060376157d2565b60f81b81613f49600185615975565b81518110613f5957613f59615aac565b60200101906001600160f81b031916908160001a9053505b613f7c601085615818565b935081613f88816159b8565b925050613eba565b60607607a83bed064745656509338218136736845df65e9e517e8215613fd357613fbb836003615917565b613fc690606461586f565b613fd09082615818565b90505b613ff96064613fe461271084615818565b613fee9190615a39565b612d0b90600a615917565b6140086064613fe48185615818565b614016613fee606485615a39565b60405160200161402893929190614d35565b604051602081830303815290604052915050919050565b80516060908061405f575050604080516020810190915260008152919050565b6000600361406e8360026157d2565b6140789190615818565b614083906004615917565b905060006140928260206157d2565b67ffffffffffffffff8111156140aa576140aa615ac2565b6040519080825280601f01601f1916602001820160405280156140d4576020820181803683370190505b5090506000604051806060016040528060408152602001615e83604091399050600181016020830160005b86811015614160576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b8352600490920191016140ff565b50600386066001811461417a576002811461418b57614197565b613d3d60f01b600119830152614197565b603d60f81b6000198301525b505050918152949350505050565b60006001600160e01b031982166380ac58cd60e01b14806141d657506001600160e01b03198216635b5e139f60e01b145b8061044757506301ffc9a760e01b6001600160e01b0319831614610447565b610678838383614340565b61420a83836143f8565b6142176000848484614233565b6106785760405162461bcd60e51b8152600401610547906156fa565b60006001600160a01b0384163b1561433557604051630a85bd0160e11b81526001600160a01b0385169063150b7a02906142779033908990889088906004016156aa565b602060405180830381600087803b15801561429157600080fd5b505af19250505080156142c1575060408051601f3d908101601f191682019092526142be9181019061494c565b60015b61431b573d8080156142ef576040519150601f19603f3d011682016040523d82523d6000602084013e6142f4565b606091505b5080516143135760405162461bcd60e51b8152600401610547906156fa565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050613985565b506001949350505050565b6001600160a01b03831661439b5761439681600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b6143be565b816001600160a01b0316836001600160a01b0316146143be576143be8382614537565b6001600160a01b0382166143d557610678816145d4565b826001600160a01b0316826001600160a01b031614610678576106788282614683565b6001600160a01b03821661444e5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610547565b61445781613838565b156144a45760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610547565b6144b0600083836141f5565b6001600160a01b03821660009081526003602052604081208054600192906144d99084906157d2565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6000600161454484612611565b61454e9190615975565b6000838152600760205260409020549091508082146145a1576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b6008546000906145e690600190615975565b6000838152600960205260408120546008805493945090928490811061460e5761460e615aac565b90600052602060002001549050806008838154811061462f5761462f615aac565b600091825260208083209091019290925582815260099091526040808220849055858252812055600880548061466757614667615a96565b6001900381819060005260206000200160009055905550505050565b600061468e83612611565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b6040518061026001604052806013906020820280368337509192915050565b6040518060a001604052806005905b60608152602001906001900390816146f55790505090565b604080516101e0810190915260608152600e602082016146f5565b604051806101800160405280600c906020820280368337509192915050565b80356001600160a01b038116811461475e57600080fd5b919050565b60006020828403121561477557600080fd5b613b4482614747565b6000806040838503121561479157600080fd5b61479a83614747565b91506147a860208401614747565b90509250929050565b6000806000606084860312156147c657600080fd5b6147cf84614747565b92506147dd60208501614747565b9150604084013590509250925092565b6000806000806080858703121561480357600080fd5b61480c85614747565b935061481a60208601614747565b925060408501359150606085013567ffffffffffffffff8082111561483e57600080fd5b818701915087601f83011261485257600080fd5b81358181111561486457614864615ac2565b604051601f8201601f19908116603f0116810190838211818310171561488c5761488c615ac2565b816040528281528a60208487010111156148a557600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b600080604083850312156148dc57600080fd5b6148e583614747565b9150602083013580151581146148fa57600080fd5b809150509250929050565b6000806040838503121561491857600080fd5b61492183614747565b946020939093013593505050565b60006020828403121561494157600080fd5b8135613b4481615ad8565b60006020828403121561495e57600080fd5b8151613b4481615ad8565b60006020828403121561497b57600080fd5b5035919050565b6000806040838503121561499557600080fd5b50508035926020909101359150565b600081518084526149bc81602086016020860161598c565b601f01601f19169290920160200192915050565b600081516149e281856020860161598c565b9290920192915050565b600082516149fe81846020870161598c565b9190910192915050565b60008651614a1a818460208b0161598c565b865190830190614a2e818360208b0161598c565b8651910190614a41818360208a0161598c565b8551910190614a5481836020890161598c565b8451910190614a6781836020880161598c565b01979650505050505050565b600087516020614a868285838d0161598c565b885191840191614a998184848d0161598c565b8851920191614aab8184848c0161598c565b8751920191614abd8184848b0161598c565b8651920191614acf8184848a0161598c565b8551920191614ae1818484890161598c565b919091019998505050505050505050565b60008351614b0481846020880161598c565b835190830190614b1881836020880161598c565b600b60fa1b9101908152600101949350505050565b60008351614b3f81846020880161598c565b835190830190614b5381836020880161598c565b600160fd1b9101908152600101949350505050565b60008351614b7a81846020880161598c565b80830190507f22207d2c207b202274726169745f74797065223a20224d6574656f72222c20228152683b30b63ab2911d101160b91b60208201528351614bc781602984016020880161598c565b01602901949350505050565b60008451614be581846020890161598c565b80830190507f3c636972636c65206f7061636974793d22302e34222066696c6c3d2223464646815268231ca2911031bc1e9160b91b60208201528451614c3281602984016020890161598c565b66222063793d222d60c81b602992909101918201528351614c5a81603084016020880161598c565b681110391e911a11179f60b91b6030929091019182015260390195945050505050565b621e339f60e91b815260008351614c9b81600385016020880161598c565b80830190507f3c616e696d6174654d6f74696f6e20706174683d224d20302030206c2000000060038201528351614cd981602084016020880161598c565b7f3130303030203130303030203230205a22206475723d22323073222072657065602092909101918201527f6174436f756e743d22696e646566696e69746522202f3e203c2f673e000000006040820152605c01949350505050565b6331bc1e9160e11b81528351600090614d5581600485016020890161598c565b65111031bc9e9160d11b6004918401918201528451614d7b81600a84016020890161598c565b641110391e9160d91b600a92909101918201528351614da181600f84016020880161598c565b601160f91b600f929091019182015260100195945050505050565b7f222077696474683d223130303022206865696768743d2231313030223e000000815260008251614df481601d85016020870161598c565b7f3c2f726563743e3c67206f7061636974793d2230223e203c706f6c79676f6e20601d9390910192830152506666696c6c3d222360c81b603d820152604401919050565b6f3c706f6c79676f6e2066696c6c3d222360801b81528451600090614e64816010850160208a0161598c565b6911103837b4b73a399e9160b11b6010918401918201528551614e8e81601a840160208a0161598c565b7f223e203c616e696d617465206174747269627574654e616d653d226f70616369601a92909101918201527f7479222076616c7565733d22313b313b313b313b303b313b313b313b313b313b603a8201527f313b313b313b313b313b313b313b313b313b313b3122206475723d2233732220605a8201527f726570656174436f756e743d22696e646566696e6974652220626567696e3d22607a8201527f307322202f3e203c2f706f6c79676f6e3e203c706f6c79676f6e2066696c6c3d609a82015261222360f01b60ba820152615043614f8e614f88614f7260bc8501896149d0565b6911103837b4b73a399e9160b11b8152600a0190565b866149d0565b7f223e203c616e696d617465206174747269627574654e616d653d226f7061636981527f7479222076616c7565733d22313b313b313b313b303b313b313b313b313b313b60208201527f313b313b313b313b313b313b313b313b313b313b3122206475723d223373222060408201527f726570656174436f756e743d22696e646566696e6974652220626567696e3d2260608201527018399110179f101e17b837b63cb3b7b71f60791b608082015260910190565b979650505050505050565b7f7b226e616d65223a20224d797374696320466f72657374222c2022646573637281527f697074696f6e223a20224d797374696320466f72657374202d20696e7465726160208201527f63746976652067616d652c20636f6d706c6574656c792067656e6572617465646040820152761027b721b430b4b711161130ba3a3934b13aba32b9911d60491b6060820152600083516150f281607785016020880161598c565b7f2c2022696d616765223a2022646174613a696d6167652f7376672b786d6c3b6260779184019182015265185cd94d8d0b60d21b6097820152835161513e81609d84016020880161598c565b61227d60f01b609d9290910191820152609f01949350505050565b7f222f3e203c2f72616469616c4772616469656e743e203c636972636c65206f7081527f61636974793d22302e39222066696c6c3d2275726c28235329222000000000006020820152600083516151b781603b85016020880161598c565b620179f160ed1b603b9184019182015283516151da81603e84016020880161598c565b7f3c706f6c79676f6e206f7061636974793d22302e3134222066696c6c3d222300603e9290910191820152605d01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c00000081526000825161524881601d85016020870161598c565b91909101601d0192915050565b7f222f3e203c2f6c696e6561724772616469656e743e203c726563742066696c6c81527f3d2275726c28234229222077696474683d223130303022206865696768743d2260208201527f31303030222f3e203c72616469616c4772616469656e742069643d22532220006040820152600082516152d981605f85016020870161598c565b7f206772616469656e74556e6974733d227573657253706163654f6e557365223e605f9390910192830152507f203c73746f70206f66667365743d22302e373522207374796c653d2273746f70607f8201527f2d636f6c6f723a23464646463945222f3e203c73746f70206f66667365743d22609f820152753122207374796c653d2273746f702d636f6c6f723a2360501b60bf82015260d501919050565b65119bdc995cdd60d21b81526000825161539981600685016020870161598c565b9190910160060192915050565b6911103837b4b73a399e9160b11b815281516000906153cc81600a85016020870161598c565b600080516020615f52833981519152600a9390910192830152507f3135203139206c203133203134205a22206475723d2231377322207265706561602a8201527f74436f756e743d22696e646566696e69746522202f3e203c2f706f6c79676f6e604a820152713e203c706f6c79676f6e2066696c6c3d222360701b606a820152607c01919050565b6911103837b4b73a399e9160b11b8152815160009061547b81600a85016020870161598c565b600080516020615f52833981519152600a9390910192830152507f313020305a22206475723d223136732220726570656174436f756e743d22696e602a8201527f646566696e69746522202f3e203c2f706f6c79676f6e3e20203c72656374206f604a820152717061636974793d2230222066696c6c3d222360701b606a820152607c01919050565b6911103837b4b73a399e9160b11b8152815160009061552a81600a85016020870161598c565b600080516020615f52833981519152600a9390910192830152507f3135203230206c203132203135205a22206475723d2231397322207265706561602a8201527f74436f756e743d22696e646566696e69746522202f3e203c2f706f6c79676f6e604a820152713e203c706f6c79676f6e2066696c6c3d222360701b606a820152607c01919050565b6911103837b4b73a399e9160b11b815281516000906155d981600a85016020870161598c565b7f222f3e203c706f6c79676f6e206f7061636974793d22302e36222066696c6c3d600a93909101928301525061222360f01b602a820152602c01919050565b6911103837b4b73a399e9160b11b8152815160009061563e81600a85016020870161598c565b63011179f160e51b600a939091019283015250600e01919050565b6911103837b4b73a399e9160b11b8152815160009061567f81600a85016020870161598c565b73222f3e203c706f6c79676f6e2066696c6c3d222360601b600a939091019283015250601e01919050565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906156dd908301846149a4565b9695505050505050565b602081526000613b4460208301846149a4565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b600082198211156157e5576157e5615a6a565b500190565b6000826157f9576157f9615a80565b600160ff1b82146000198414161561581357615813615a6a565b500590565b60008261582757615827615a80565b500490565b600181815b8085111561586757816000190482111561584d5761584d615a6a565b8085161561585a57918102915b93841c9390800290615831565b509250929050565b6000613b44838360008261588557506001610447565b8161589257506000610447565b81600181146158a857600281146158b2576158ce565b6001915050610447565b60ff8411156158c3576158c3615a6a565b50506001821b610447565b5060208310610133831016604e8410600b84101617156158f1575081810a610447565b6158fb838361582c565b806000190482111561590f5761590f615a6a565b029392505050565b600081600019048311821515161561593157615931615a6a565b500290565b60008083128015600160ff1b85018412161561595457615954615a6a565b6001600160ff1b038401831381161561596f5761596f615a6a565b50500390565b60008282101561598757615987615a6a565b500390565b60005b838110156159a757818101518382015260200161598f565b838111156127e25750506000910152565b6000816159c7576159c7615a6a565b506000190190565b600181811c908216806159e357607f821691505b60208210811415615a0457634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415615a1e57615a1e615a6a565b5060010190565b600082615a3457615a34615a80565b500790565b600082615a4857615a48615a80565b500690565b6000600160ff1b821415615a6357615a63615a6a565b5060000390565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160e01b03198116811461094c57600080fdfe3c616e696d617465206174747269627574654e616d653d226f706163697479222076616c7565733d22303b2e333b2e333b2e343b2e333b2e333b3022206475723d223130732220726570656174436f756e743d22312220626567696e3d226d6f6e737465722e656e642d31302220726573746172743d227768656e4e6f7441637469766522202f3e222f3e203c73746f70206f66667365743d22302e3522207374796c653d2273746f702d636f6c6f723a23222f3e203c73746f70206f66667365743d223122207374796c653d2273746f702d636f6c6f723a233c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d227574662d38223f3e203c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220783d223070782220793d22307078222077696474683d2231303030707822206865696768743d22313030307078222076696577426f783d2230203020313030302031303030223e203c6c696e6561724772616469656e742069643d224222206772616469656e74556e6974733d227573657253706163654f6e557365222078313d22353030222079313d2231303030222078323d22353030222079323d2230223e203c73746f70206f66667365743d223022207374796c653d2273746f702d636f6c6f723a2322207d2c207b202274726169745f74797065223a202250616c65747465222c202276616c7565223a20223c616e696d617465206174747269627574654e616d653d226f706163697479222069643d226d6f6e73746572222076616c7565733d22303b313b313b313b313b3022206475723d223130732220726570656174436f756e743d22312220626567696e3d22636c69636b2220726573746172743d227768656e4e6f7441637469766522202f3e3c616e696d617465206174747269627574654e616d653d226f706163697479222076616c7565733d22303b313b303b303b303b303b303b3022206475723d223630732220726570656174436f756e743d22696e646566696e6974652220626567696e3d223330732220656e643d226d6f6e737465722e7374617274222f3e203c616e696d6174654d6f74696f6e20706174683d224d20302030206c2030202d31355a22206475723d223330732220726570656174436f756e743d22696e646566696e69746522202f3e203c2f673e3c2f7376673e5b7b202274726169745f74797065223a2022466172222c202276616c7565223a20224142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f22207d2c207b202274726169745f74797065223a20224d6f6e73746572222c202276616c7565223a202222207d2c207b202274726169745f74797065223a2022416e696d616c222c202276616c7565223a20223c72656374206f7061636974793d22302220783d223235302220793d22323530222077696474683d2235303022206865696768743d22353030222f3e223e203c616e696d6174654d6f74696f6e20706174683d224d20302030206c2022207d2c207b202274726169745f74797065223a2022536176616e6e61222c202276616c7565223a202222207d2c207b202274726169745f74797065223a202253756e222c202276616c7565223a2022a26469706673582212205e3aef1e70f659889240519774f4f261268438514c37a075020cfd2040c31c0e64736f6c63430008070033

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.