ETH Price: $2,549.36 (-6.35%)

Transaction Decoder

Block:
18754207 at Dec-10-2023 07:05:47 AM +UTC
Transaction Fee:
0.085709270375581425 ETH $218.50
Gas Used:
3,515,775 Gas / 24.378485647 Gwei

Emitted Events:

242 Anizuki.OwnershipTransferred( previousOwner=0x00000000...000000000, newOwner=[Sender] 0x7286c8e0e28a2ff9351486d56195f7ea55aa9046 )

Account State Difference:

  Address   Before After State Difference Code
0x7286C8e0...a55AA9046
0.195 Eth
Nonce: 0
0.109290729624418575 Eth
Nonce: 1
0.085709270375581425
(beaverbuild)
9.921557410831646778 Eth9.925073185831646778 Eth0.003515775
0xC640Ec20...d6a1F43F6
0 Eth
Nonce: 0
0 Eth
Nonce: 1
From: 0 To: 689584806442362074129029679958910303263605191353583159353765500224632786538570076732747501724696022618539718122294804420781734605554834479086941662046837208882804302199670931589456385213680719717251654372589821705498707661383576406662920386291533721305524200393024208193630517416358122155081597349144567360483248200071702276633798463621400639503419353934379457552071307419361128847724920074360344442890436851198697755474995381259929890961372152422642434853006895293661210211876918274182240152001565090596116958256193927251080267976909731871032790024441063189515011185202108990148709873406976292809486149518819465186419630935430357736169195294443992582773762491394446582599819783812285467134784707539481497238889584363666927308131888822863862675248086232724070208998177393609522777284190286083303045416284127642992205935704365904838033261048667678385821721380509203967406994248019782806901925581414880304359102644066029116132093439282006433981414902492386174409454351776867391565201119710252877872661526372989516357153622299522510520510673864567338138396460844444423416908107271339119137565639331118689518620583081259195731715646042842229594460834113796606670453994957391294008004612579085754688755701904607932367482310848705893771342197341759667404487781365579115069995935530836817908842408439384121946723366263448572105961082065470496758460962528001656531569195822611693539009846836203826042934146134976767112534211374237838416697147629519702496554147268621639740433498849749222968706723278826129605365087788353074660484664527589181468392554879130573235612492880505605289813345710416301977032009374480171187622117733252832442149287836413812701916131839088177319044672913277605370196271068146036860126150168880091863210799937916885368719096111263981870101882587653979895915835008858452446045020551635235579585487382578459952041930937748520235797785557542041694026496325655667827297812549525592863461210703414650953492700588496284831928883813251909550580588422586497143959318882928943411987799551692638094727361823939641077959464299944796019033744651474948027103527439751990032239728738654763906183103384893850459471588002260858913572741361975642311441137144043171466334548015274599388956893343039651970392509583337695251284637703942132956098581999106778663697142784805251706964817531527310872896146934195067996913208850101648823441996245780597537808049874111312946575777053541957040732076562030047757631584697147080641714087791740256563030396013749028752089373656935790068688469407766424469690888041102285452699152825991149061774366357748696199063057346872000956573441954155724193252662051215976246542809410290292733564813865746403962721179562740567682027823973564234096314162779896565784705186463907119140903141337037953562526979751455353801967444308580331209562101730483858806761611126443310553298098749556984681013481252706245234841257786109299393837375012816057077916512474475393298501770412225940130366364176066320814530166404592073162796988120870767436382943361794262411901426348333302709351087225144866106583167986039996484340561437257245910099716117601554464962565859181990931169452884158136865718953380628235906244209276150879908843978108646676855546739756397000211300112880637802923369092804308665137644887798529302289658877875718105048299147163432690810524958293244245302377645781524574253900401511462515342504325457443617451008321907495406102774494905900377743432392341997046729827128091952064971027312233343792024666569589062569572948689069137387855603039421623950032892411771530432442738963485684020630699441540258995499553290633890633828434903861663665834776798988363978872556237815461609979560808028875218901044620171071385727843271416670720038145824123757549232684906029143038540345053038872483866907073206561183761102526457326535992116888485785411450742250372032689637111999880731086694284428024651485087701775170236589696614466752514996227419697321865423546642991752616272744145746377801699028726168950152273568490788643432830827839122891969928987315590129783999064567872787206280922266393288692046912529695886215389129091707490749664544681150124764249909015969285372144488546685997795669638382916117635568237093562212288362557244589862598414250511582205632464179038629282065589447286797634129067560690234398435802308134433392659618453327886208235356990382060557344788467034952271735433517578908602638761284714462094385850011519479208704283530910680257702273103720853290492281695436622289623469153643464059130648771349853274152527323571188772282213049475969225121088521394476948218869046727115814338793368573524372862931514497066409640064184738226070813511711133664142569799166556242190490768876365454619584970945318561890393763439427659818106881053189928402013398322602504336354814716666946035082591817954872571755975571714938304920410059446411236651256027867017639753584120353317936100076271672858770136145713111982031295147850906025211449608990401514322252746388435267777501906270289601528067278778817165400939425779533688543384095649471748125564518226109019233147571891712525945517919554394206153525953468530904042054234214856571342391839909485594989122482727568036123803272671243630426764415802416284783133733579582242849325724174535759708565355304646174554437590520352719927804976352422653404425023912932879194315283338876602574870876801554399937238622269083259462656154579866236874259677786739763223012241739626022582972000793484758455001936617879330538218353872820103797844305895644890158577581495233365696279847467668442562122026729221884550892881624401159384212675743577363290546059248512032777758224851544251162281983134399619143863321961593400411555557535203837635160801962343147653594899633116964023827759357572188387610498027694803479993101325665965267147593275614586740036292323750447698461421013645972716083508362565302337505017346665335999407259280595274942763818785863381597969073208297004126385078038628424318671368827210008842010100227011244351589322802917012657028239022723811124359811340240224991903172566805888878772353304379348801418845747753741698126163316299714337185040187856848429743446798098212626933500757461554244785882547782981091509755049818592884212415480388054747019871334509290269137848963655429763195291795154088309584156389331834365230894566731811383540135307828411025311731140949866902719821815130211845933452219433632653939697163619695466739007627521448837937639079189855482332867358719508451246478296418495250035991298246318536295138836471347623314405662667454448797973993850355700675430158035717179315722947637928786928918043128572975999066770729632431357495657898792516684670161514908654776114666534360032061981725766612904336014315000253813208601983519060252397642503611075781382304443453517513616287925360416955073043185050668280993861138159996675323700139242262469385606298645869929231901786413060900411986489157363988709193161838164731383563856909389091706432211819400252193015805703844261061183370194693223296206684001007869294444857313715824564228066256405264596927696176162169685896370350906416979965546949970759435439161747002280448990286659987423316315900696672932635502606692794479602851124345985103154834868578511909888084667468267046630906873352306016765368844381455682671465640804250227692963792069695052947990972450057202004421630787122011101983498909171431610834703338193305119525385114691629312862310126443467212334644024447636493446141472302434301868187053401307964754641892467455648064194773606651503923213118347243587201340136534594917463303106411358481516645668027013339116471933586566406445248998337226159391964461725091885124745376563025974331108341874408709577102061466224964492422393104515347961308580697820499061335491835851090823154742146221876201101732736328432081074129252396934287946440140075574294054170617699180445031865048411917934220439925924416056464769601633039496574846346709058810358856583420136804121317171342553975604946677893874062765657456285156128884345975154044005922530911292472820123215168059122516146028184684773858787174985313252724926751299901889029264871496908564767382781566246528442126958421564508852867113838824797417888267041339151364054399743937095121214307115782678423202982744973691824845087715342677303948565792669406740388142826121462306210800292784175813297393445708768340654761617461942490315402482599159990115514532383729834012008542839219453644366261418234030051758258325952289747908962805590159961112504575311783922218033876232245786541011817087823819628072829113104627691572902925781307889112365237328871557559357078615096941299868882473032859915581905984112711655249537195062816505102591389857134208492371920630308956375880573470240939266543410509720619131573106845239677984792507276578129652276302953258246563413919343734296316550467167164926237084564383365646129556310455974952416030970624371417226628621760074058149926971463139469335890814601472217762530955574291902962645098014891478053887397024229509150002385683223631281365603501662648746214908391928662373247125305101629998586266871842756168844944803202022020675658612945384556420574197391666787977479597700033015707803051062263940762416928733640708898229401751595049015920499845000268264483753639303102973999268099719911647958874522329878119458225355049915938437603596344626520068848712898797544748210797822763333025616824640165854483677687765030208344164714738238598769844603010547537121099318430341973359105274150307767844109652678969057088175382387097348140716694046312773642924296803857928693143004025315045215594128738534628324351811570189616672861569512586301994564596675089194416663220359960020218752575849900116851497971276404015422350725654924429663285641143399301193611670726979159368508612490926642454332738206788553432913828235943559435958015209762675244746147121098539066515572507068355167866207341081089055759281825062660661147831369500555731467017541156735585404320935492671789643811117753080351466633763956291050733338116899589542834720766039330342591098828087992916351963269039035406919346941690355752771628092068914187715369021737406804406495386945578920672953757468875398417096045083110715667393820768810844682609010982770869169397284715463829196800699857099042512650657467777946992150105811727868624258765598256873683462953407586268635456502687018979506230965471170536945186545967019757023561767585550684056202648222814958257598274473041339368676895842552439264272919729406947765910586756030041449587933412357881363633068146107535358902266690839259179442189796705587547130147633453816934900985518091526845660290823551149586198060417051820869552036952064687489802026747372213261281454752178619900032253296050055784705774001850400511705484477452680468732376739210973397451138406920159160973909737676703836736716819887841515891640537047649942550176854963652550791659035656244727822575381132230000663986802075921731113148813348380461698566065028111945350916131888986516034488401905444313077606869425187481951901645504653584107179043440551054116267117038961441138144540013872771601095558448763069865344907309494625955791551854483521782149370620541577166505099152585090606609619298050947770611676905141603805844003887038649726753037718387809701397511025008396741327891806318482810433775706919159548120022376990531403212819764417278531644577767586205227116089368432974729363650066977409570945174697157144598014641034513663783523100070567624771590464894432591978908146505522603427179139209003159763954442719480730979838218356028593101739707963321158419405053446333903560240379226404950659609017454721890932507371462442210066112741952314953068758548386748573597234666432124234911514086428765640799543728322967393541138584857558129003445603736916619813901155728917243230764480879959439997254683050544046536731036651351517978545336210606691945349042682310244571267197768894058747357688251179993834680286845105587928369177284688249986881044790189456656463844027375020629402743469585888150801229086046200848751934591954060701057253429433828409269344336285004243010654781850087751270066421339478381220678739691430257707225219296905884983018594886549407954189247642551255354641125249678090326090314370783940582270918319381362909753872683247637315671256053728971617617104814832737836583785702258800550130126403172734901780394283586385893313835053511672612161459118631750798424688138529787600905237139312541548254834659088082114518343578374393521180161777343691870164540026921911511827216633066593994492836151065133515447803550366598343858661877419128889079116442026400194696269217822610241190614687633340073496096855535271335129606164955373177949206057040080189509495240506571415918862168384931636693385483546310335356109711003754484502857429225928576122750795259385486353241836763263569007363994251527846237298437939568987260010468542381051503802019182082509777837202891464069676492382903015670990501153874627302962266927627402814443674580044195287478833224232905548116510172525253811873709782438514226985855883248396536138131234639001380155518387743634573025815516807304224121869884482058769977271515635520405535179842752841280731130621916907915774923796737019415974687954395778691995406945725038657445976269343375651610976923874080859914988072332313892106308587483285035664694929498193197477406057458917383138439376332327789773272248759822411197948061861156248342849517657328871395770174627239712732754270580573426202567372161054387206826947237693037493922954979913013278850907226582132221890213250874144934249429599630073295365929315768402786557027990365169591821664726322293938983306709998048449461158654646751054680791328748079857210810462148596586164323179933392523368876054443011180756308346515934302136853028502761978609695652701369276421776863793716169795420354049366353233099607618472162034639368692640065441733307780953943071541978146650893117410381024917188640327318781521702368279933293071025900587139376617029616324221274546669417728074345763975308886244551874611281127389047677741533157441289553514043205915602435313106198117813080890414509015625108420597021334117701834024380244601296097096248507422168189414778771511549796058206513875840654473217084532243823630466261871089464028443147422996072127807315448628068913873788258730986079244912062405306576595792091422579336363351385213309695724490183352509724791619436408523495175183387503844370749395948661810832224854399435832587706967170725632743777810786674605457397551921163661962184701937153199485322701868133332855832255284520712809580357094585874688268969566816963192952604548977547618644261117904744181817252863094381704803352205817341479019396284131451456923321222174984639622274417270291295943964626196002016674164035538068244103957783440648436096545865691939197320011592888467358089754755984609630938137890843586511995023282113472196556267532554015605018059746579482258802375299047382545638102256569170187488775083164700333476777787100180916647900775477577466168066855636362196458479178801083865356155502007756174088735664216777978889296444973911131786327769952896221479460126769697106962514735259761502976392512901280777382710919268183925319764417200478538974964711722664484131371371212197478749817570005238523611370026152868761742408330750866572490644042727941323727156398261738288196830311656237408381740650880370099464114788876314921359332919762644180591564751292901202078538836635676545756376661703169468880633963434224753649502603804331894156465127388278814495563888987071837663672087740547633406074946365559540917037575741306442109863800096529866939098671690681388070574609019014547789771727353327812961385159674251210065796153318421038805342379790462424753739137943812498723823317978428306666252021750159484661173571249092467594038761510743543987007678468201515021933154579568741133282008410915434230559106338352153280356810046038089249651798299655281137498958929431297113013454713355162826751091451327104994981493087916179978030850640452688867146122239475283242451531918700890221371420903588504915696255142513979847037566107919450459998834823943836342649481239706031803757157371014073298657678769381027278324349326248244798540475355402914150791794709537495698133105034047061191370828831618507474374468646226117873455333540950664242758079769225765380116958567654204190909238399762786385626000478137078548469872661502887242885372624136163742377715347376462578800357026453048970879095832444573519318284121039804330829485267106033251164784107094131263876920989104643200029100925847554014729454309278738817481785685695894101698206950691321184952611685125346941546011079224710363170211531969140586017127115491594168846590867555032465117297883893654837732110930338355158386339524719345910231019805731667487972775501628518455325686431680198915627263002089155693435226453931986497325716916490707819650268612848419135720916116796155675309931818030547942430927739339655452631724744533169155589557882924679227585867445965858002059051851779389271014205727976989274662430507061639318154007293466021192915030676033266382196271210902330817106448448521262946979687391167744985187238083008936471728169296417879267877258339195383715240626963029262528038549389002856171186843768365562889536274793011548874154606063034676853253370422093676582991084913692167581477428656838155154222877966282334157912405311375057115292307742993827851739711000762818939701750559627451134569976718449208400075746927351885544000243897966260370608329375536842844834806397714912520229432080279303731719015095796636884081893455106543963411614825964927680683273752564851028693672957104649745600578326285103331721001435090300145003008762768522589935748150502231532596159867447158714446558867261835924709494217531818504224554785074655541811905561563067545378373593485049224635716087470091839807219259498742179238698958037751435787976622621163495552407587575789180245318564655680887075614703974325835120243999850498503945235201618497973704768226784235477778957786807791819023132844311659734627857879631395612198958316834500050367811598655488827905886944840955029882053738301472203912087970063976204869897578060663431347753865391742222057106510652560077873784654111297407633992628752247011511767976871038808995566721498637453295476604879075562919602112873558835088448592839195558109825991451483168279614124619589283536746596844428284108759671350628194704653663395680992093740873404296159715401060084854449431478449920595760827162446079152368046489351470197626775959787862082864431369437206405050936780544239369612459304352474164318345526529081344936513645838019438326247460623753067426551992061610451820511190352130506944156371316400998557639243353170448162726841292290142054130823082756122438421449320785770054230098025175703691339370135996258775187693763843260662622407759407293410131259864936517885773898287267180445458321775407898632575837531306217228639809150554917648452810464441276084551564067268809562323368560131478325023157843397909192104923214551311208578678456130519269278782289136980166715131816151023977074213540142002185562781778113449272418604556149424709281771269632595187203572191502252794108164891084733994619667822085706894857866719142607265583651219350137609049000436356358611185940590786881949329943987974355449848466816392548132448312265582243520322974159493038608753986083288825885163766873108729976409072537229352494389913303961301397408125160252152651415564146162812283857905636667029749061690940905019828857169787544077316005887808043325244111271003523625501127168914636611549063084087140447637612948235146305225775781538075379194158946664313293867784732730086074330473842951030539577450212217511061819704292755433397727825603266143006630838809005050069283922627180733333988034153523548620080626567234281583037798124120556670129137410511012488287185251511071472273174186391612101329899060940362853468779475712836251737305667914919529323831145330812236836996844739792560216731784307835885379997605658709900854001063557395572930057534420400280310630450104134051441615740053304351610721249545867599915870872454423820700587291489181157123291699285888431445314505188951949075283059179989301271739338222611084318581647359213842434427141938614645642153907682248645396194197914391277285827820020825749602687202373681866888238380505880118925396683883449758738959782564373043380985913582703603543923491197262904003546704547449823705541784525822625899998955180696481318870508584780851782965606807825488663233346564749786202068299110265770795340020763888692310791671521125845553780870624214904327501996539809750030459489264045613120442026361470016451585767440375098962241644166223764057699229641628891805703182600804482815806582443183926969797367960952300449479708771155257565181463343424377839972769550087150721668373200308106419388276807941208903700935528216933060392009341413567888375124598840282195211422061405230384143348546932505844592009981643596615985534071452045842046602185049652857155774354070850291046551694407698998784868887284311966705437068554507667080868089431416939453979486818851614792251731971613765161290607598373546147189786434531963023203187776951702807450789518827477383580729841775877153096494171175537498945528495896378839598275369884895040979876245693380660587317986054247626686426534153553908213518851291171427842198661684147135617766938623962868122995690775061913655023867525370377600873625377453357790335538409413324337775036690151340791368087319142349600072001319133814052315486797216472027213314084772073700810183625226858641937433567331179562569809087724841570983002591965425444413463248442031683779444404250417450691684817782633434371888690555296322891336409476832769121669631164573105375735768839301913290218982120853761010428187640247615462359618222810688101796057786549818416998779730809550413926331346319742054753034590607070469319140870280592722276091760685518582653719228478375427751655356748495147755790171639413220721161514531227397886992309022354751965331916694610536323528174952911572706418805385902013949284163314417874620971861191906442395442395017072221312534393096124987730577746473033711488538905799604908431788362545341258078732021142617358415498649379137873068223221624298725265256569327718145377825641247432345547629833420466419520278310255508214923384622022405379927191611269972069352564180625925211742165495265827842919982222027818379419986372044494660935800120702804413931578204548225740637747886231535768716074426935030157334252349442456471322668198322208956653095522315714947888505962060503999347991142839949027185333036556662303671687830835947565769062925965154975015474694978355672013711180488833687423343067597214883820938896145809997356482369315955462667647210119726191850482525865801642066343275378538333366854460879488203879378036570425585605105519986510601274838217481521179155772155160787230867899414334589514248139924718439261197004032627491532036274436670152656312526842447173292244693975859676585912291633359280402687312202423417608269607344260896417914910566614759010066631202808260180512066283883331768845315434699190639311670216550956579261867901047539667190019118434809063760620024181892698861211970785899365185739765586607762718007617562287244103531355455882364048852484430615546144312406332710819484193679233745579556460582975551296081691389473623380385699548280341628876384015998386439433833908397652837903592703318124777156955472238707695721179328338136252323849749855705708863647782935799730277920712675919427350568338726420071383528145391151267867666910817495517662957119870311713871870837383127337847345106670061868873811620815278639406395842201494028477066634495337387096734343296922146408345938190773548094613298599886937580094805249628186067040239258538708385377504642181934506351646726439452102615595738448544461475906122865957983946541036959025931402380453454213060784426748397339230739111327841790135217252045811770781158983745608783624010978967316681674824171836668571591086509340480212200899228936198183248992833919692323152999922988404793141645933997050134373777418842204743761081437539200714948208292948621157810841088720833088863962689432619548288754237696770523070092615991818161387379344247532485465197767908969897611877786424901431725928860142892542225133963094701490181247123761497952578081073802053884560050437685005258333655167591723294291286870422346905538576791763267908995012737440441825473707210399425114792004898732557566788580384062515694190760846587351049834854803900628895889607192083487317726354603304416880343623525429420207974616467591107445275727189424902695616730312011731424357282826696845635199835663925005278289251111933143179879441868180097449104605764678234265669868013551092550753386205196627086630949860923483593732115116475716649776924438662317964112083299603563246786259267024122152414587866149002992486763448865487251872899641718665225646101058309672738623921069862034173505431447107805875871676910834973482210182069820448287252488202291786739637081992303826685571325340395158700091619673549173991983385285285411327672577583205440250463386907635698105099122197837218139782356472529731018420656048420313238427539520866667966551823901282437681248766836304323778003164542720721948365707999579471929944515157944062365325732415964970373760070073703166055568597077236653907378178158131660401739343663976209252752570737743126469504531313968782587575320298268711638264398683975590588117862913791334188976887217207912066266117869382054804031348000794482408840519193414833617384769397167948014913898969825813936785085698074076445824522044421710978593230106862717356502803617079260071374852168570311592022308185674240921477730150306880798894236322096142874029289054595418504167791009667907184915740801631714575569383920603287008295141129059408142104095550479572305551906866115469238127641276273923591385403108426132952332642111471411552076117582535711552292299596995599467203678452102393443721009902442963619933704190940652154035567199922803091769549956963851605310596738254608340294220664538902337218962498991963961501772788528150954487252803607330475738602436967688683533910059211568509225597844471251870000590503546372634463598160365214860782491854493576076101374828892878513970395821397435675259187023939716310144268456898414462758310723912861176474816930467569869738607246937671992825527891348757062024656483886845271302007849528984361761264415180920136520507815281195879909531728720155077364638616310966327617837809869192127384979567954884098273409477704631301600283337956312135458522773805676265039065487323021902887311351512330146006359349992262138687565263501679760004913669532107643261633926866623015611892934722104080452505721490013295058902973069711143550665428515795611591609083306885110395061719352693370938020501164732298694860257347259535777535422438379023143325131846970241151149134551650063350447496333772138795781285534130206138448058200577567497526040610048744527074693505560811347845819243282676802034539396208103193219206906522610598668019471738598010890556037662847434998476956479021184490517443077596733695899824920154345686736909033118655236207155728408635623008211569457278806499591065115393479653694446874146324310795458504695590479235949505436781342793134529808172466229648095194945252247391723978895803644102637618214190788217789839766565111997725254360584719284508250801559624175350560540769120463568222562655854502349678408498440102002896216462977553676840660649662352170879378213550553030452839602805345701812491029135356707902311058528302548120800686610666558874576143673578268880929766593226668784402895550119697265559821328136689637419388942337228329453046610991202345220080294680696582653913315444448443723290699683038741782711897120006505980467562275155083563540006907825573331901200666188666319998531429908090774740007417405174915788181165025985850512340118212270737446983744876223042124045218030383959362677542656145418743779567752622708087903900881590078556667511391439902760783174040922989742640411971028247811265896512256826444202320603704370039790820921786846185625694306332394349090865119504215992425267434876929465343210711133195308488968717415680884261605522407132936957621129972437928946664907477662461974249799065969095083497443972035925243006236960339362179015848841761303560022215962428117088281422544445085966331255604606022235203091783254348260969164173971720336196532505452053910788731100027540551702784935505508160846486286773041657308326599682982938533562274510380500119753390066340698320202858667390313419030276153326454325116385265308336982482761278379356767404197441182937278758774078380996756031682873821029912223825365261195449258368009058460979714936221430320455147250269038566228218888128991283835586912140745947843995052465728890785502937275394329689219601809143296261507220489509589572014824489517861037887571009030092592263253584778757723702014671666364685537371694829791879208186727721271552186030540553266936073774627828700189790541248283310988213624855886652622164463234749304443980654321494071336967151492579655868179568740149880903609784211959736421177679074227445442015551859093940124052474760677707215010379591677026574989962820645145622075165268331904942092875596712453025166828966626744106238022567379428484186380070923116619185176918746092224429632328382897329302783144491536455660886019309182104361369056255475279620422609754521646236774449564407004397261372990291498232220085738241166952655550097833030894394454458325130285213967966362409529043497889703764464404006607181908033636532731434832352543073247356777944294010193370726098398868037181387950519295512870840406474852857617354158263331717174331698321911442781807255071534481020345851005552546928401286511670168034534999153088751337258497812880517809111771587585996788083647984409543942018643407662640452126857323414196577088710894796400674158082106145971630083170202630950498677062185661660702753061881018333609394143191911524412028050973908914453793702717367228425168009928936449698307897103263166325362979077264840742596960379841827669163143334640524189785740893633977267472648785769316395048132274203078170983998050528736863074540968467804607573310946391810106533565156767809753222210977090829758973809967691955264863837579748840908034262756712103024489181620177675330410890213462484121784064302571540505405925493024680334954442740539989273320832554649176018332190231424454787067717679061771165285024064163165665720182320927816497298426846321684683156208954912454999321690967632302233315641991721662583029231369313773808961569692391643379688186475674763604001564168194880464356373391038684015365630332001157338008109663025337326186864628005449609869179476081526176939665766763418448268167782283809295941678127609248031190788719212530847751662242969738768928971218568884822097986598766987245299572426694636866388710482513806420156218938246296448594089914116707556000743738302547560987739713233597688844407682713672138548019583203170537086659911305695258807829290053235044686208375409532626216362506429770613032016069054629493309700490121530865841116368378475049178073472760266645949831662251313378007967974964099555922905956967557517415982721353613076822711185949997185474164494344318710116981764149241970672280115904761707326574663902138169395149728290362942596220003818099051663513037604294755516145681567592955657395550684044408947001224457773674087951582791855973312708000352067515571521313278015406111483345795993646038185952422084808434440371325493201317176869229120316608480996284052490426633861266180443602349613286202668317336701833529885772593519736962898087456177646967792167001692323751488755997297839733621364596034408453128241640747606009622745676646275401179848123677518934543392493503246288232449903463561980861299550576578459386637942800447503069530195248975288500806629655108408286538931786933371890641584567538957183411780800050444216210438901502688867407507938318626452676246333111894884643164219361345654991114099386457943023599873572867713799034109775949683307786595134856754295447709302193921789004032424499661228528498647202474951653635442237129988439631920244762523789057139748800194869196676603625879635353018167663303594106033921829349177994016206311687899079014071527570661816023793085656041544722956958522895051621669038538846445502609443409788761738306307494371254221655294182457701012267714413912311052020720825469906608750214521591558702293807260195112412065239973770288116517455584483802742934253077208802273503133939691098675632527634652529831374595165767647887901110532843035938145789317267537986731875521682135400025273944235217275918443129889978840453548578939209562228436431292293149746840175872862793493861733634480248173667379496943143616884163636331819309032179523512613807715036666388150749540574258419611282034132920230783907513932331016641021628901553561425238027665853337364838847470890315371583046797834749346793972973213358257140569714836846081437994173658463286573902913845858075001110044166475501537398197642387660026208153615313415341938303477139661909094622761451466287998103020732626501438159244225608170903645363806656081413976903612829224015174675905551876943872561619578264268461804648191081408450244815448848510021036184226403896668132196262703024798332267979729567234650769254508932375966565052453122684892572681612183976843170768815587397246527505262391937900728366562159545209406356379736101962230218254851803854142685595903100312011858288701837579599275164051785421698713212336294295519186934460641822756128135149660105151502565589549280618594102780425542334653672941201399952480628884330564591010143194296455466589936861105602050003244313304206865742844786010501731940981520650601682546527130356913690647650383565783672656682402134503400516202239180996216635345778767485238656391681035177591443860357557837697850508396807219463666908470296016340044925365052754681986610395787604840618108025971187515405116484093905107261098115095804598278655189926421311892376595524882312297150395987763963583955547280164623621381102407676592845621821058663184123815943644359167586612779235885708738972265419906943787455722202584721228800637691202543298764707569474206121613375222165190911904342871054084839426354353711537619040555773460339656961799272638174120998817030473907041195550354074546769103622601295531374837760038498047433907861641506233673476980535747665999640601356386191058778631648341860451016544504098227191820897578277888332612687189867014795142457443390437002113636124631493858330552574702394173809955777732323145069924772453074875917229747611992784007847893928429881127523768596836452543181693569600550848382728739030706999595956165514483824402416513436604976781781574288272626173906142504099811476134646672563436748144606658663473009824877259831704835064087559534317401557966052568583281070584414733990751330500650047298536953612086490304207799442035073216471771033146964187652100277204800659591526433904729567165210218452564224509931740825320247540296033479691289090565432966101099666620134389678914797552422773286875608664841565012042420913911588829791413263742429826153014762640402169062220841880764616479433241505403062984727009481752349209807088612595643296382514799760232207668360102965098384098206162359671825086423628306463120078781250089395406075172711298451355129724987191041113322519073956359473217181941489961738335976103062775128764195327990836219603504385316354574459334412239727532363531203241795981217908967655168211130652264235173815623424841968301983936617741558347362758492991865825466519127160735563982875884714660531763066548562243691968744442295622049333387996975102944975644655667

Execution Trace

Anizuki.60806040( )
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.13;

// File: erc721a/contracts/IERC721A.sol

// ERC721A Contracts v4.2.3
// Creator: Chiru Labs

/**
 * @dev Interface of ERC721A.
 */
interface IERC721A {
    /**
     * The caller must own the token or be an approved operator.
     */
    error ApprovalCallerNotOwnerNorApproved();

    /**
     * The token does not exist.
     */
    error ApprovalQueryForNonexistentToken();

    /**
     * Cannot query the balance for the zero address.
     */
    error BalanceQueryForZeroAddress();

    /**
     * Cannot mint to the zero address.
     */
    error MintToZeroAddress();

    /**
     * The quantity of tokens minted must be more than zero.
     */
    error MintZeroQuantity();

    /**
     * The token does not exist.
     */
    error OwnerQueryForNonexistentToken();

    /**
     * The caller must own the token or be an approved operator.
     */
    error TransferCallerNotOwnerNorApproved();

    /**
     * The token must be owned by `from`.
     */
    error TransferFromIncorrectOwner();

    /**
     * Cannot safely transfer to a contract that does not implement the
     * ERC721Receiver interface.
     */
    error TransferToNonERC721ReceiverImplementer();

    /**
     * Cannot transfer to the zero address.
     */
    error TransferToZeroAddress();

    /**
     * The token does not exist.
     */
    error URIQueryForNonexistentToken();

    /**
     * The `quantity` minted with ERC2309 exceeds the safety limit.
     */
    error MintERC2309QuantityExceedsLimit();

    /**
     * The `extraData` cannot be set on an unintialized ownership slot.
     */
    error OwnershipNotInitializedForExtraData();

    // =============================================================
    //                            STRUCTS
    // =============================================================

    struct TokenOwnership {
        // The address of the owner.
        address addr;
        // Stores the start time of ownership with minimal overhead for tokenomics.
        uint64 startTimestamp;
        // Whether the token has been burned.
        bool burned;
        // Arbitrary data similar to `startTimestamp` that can be set via {_extraData}.
        uint24 extraData;
    }

    // =============================================================
    //                         TOKEN COUNTERS
    // =============================================================

    /**
     * @dev Returns the total number of tokens in existence.
     * Burned tokens will reduce the count.
     * To get the total number of tokens minted, please see {_totalMinted}.
     */
    function totalSupply() external view returns (uint256);

    // =============================================================
    //                            IERC165
    // =============================================================

    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified)
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);

    // =============================================================
    //                            IERC721
    // =============================================================

    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(
        address indexed from,
        address indexed to,
        uint256 indexed tokenId
    );

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

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

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

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

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

    /**
     * @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external payable;

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

    /**
     * @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 payable;

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

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

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

    // =============================================================
    //                        IERC721Metadata
    // =============================================================

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

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

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

    // =============================================================
    //                           IERC2309
    // =============================================================

    /**
     * @dev Emitted when tokens in `fromTokenId` to `toTokenId`
     * (inclusive) is transferred from `from` to `to`, as defined in the
     * [ERC2309](https://eips.ethereum.org/EIPS/eip-2309) standard.
     *
     * See {_mintERC2309} for more details.
     */
    event ConsecutiveTransfer(
        uint256 indexed fromTokenId,
        uint256 toTokenId,
        address indexed from,
        address indexed to
    );
}

// File: erc721a/contracts/ERC721A.sol

// ERC721A Contracts v4.2.3
// Creator: Chiru Labs

pragma solidity ^0.8.4;

/**
 * @dev Interface of ERC721 token receiver.
 */
interface ERC721A__IERC721Receiver {
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

/**
 * @title ERC721A
 *
 * @dev Implementation of the [ERC721](https://eips.ethereum.org/EIPS/eip-721)
 * Non-Fungible Token Standard, including the Metadata extension.
 * Optimized for lower gas during batch mints.
 *
 * Token IDs are minted in sequential order (e.g. 0, 1, 2, 3, ...)
 * starting from `_startTokenId()`.
 *
 * Assumptions:
 *
 * - An owner cannot have more than 2**64 - 1 (max value of uint64) of supply.
 * - The maximum token ID cannot exceed 2**256 - 1 (max value of uint256).
 */
contract ERC721A is IERC721A {
    // Bypass for a `--via-ir` bug (https://github.com/chiru-labs/ERC721A/pull/364).
    struct TokenApprovalRef {
        address value;
    }

    // =============================================================
    //                           CONSTANTS
    // =============================================================

    // Mask of an entry in packed address data.
    uint256 private constant _BITMASK_ADDRESS_DATA_ENTRY = (1 << 64) - 1;

    // The bit position of `numberMinted` in packed address data.
    uint256 private constant _BITPOS_NUMBER_MINTED = 64;

    // The bit position of `numberBurned` in packed address data.
    uint256 private constant _BITPOS_NUMBER_BURNED = 128;

    // The bit position of `aux` in packed address data.
    uint256 private constant _BITPOS_AUX = 192;

    // Mask of all 256 bits in packed address data except the 64 bits for `aux`.
    uint256 private constant _BITMASK_AUX_COMPLEMENT = (1 << 192) - 1;

    // The bit position of `startTimestamp` in packed ownership.
    uint256 private constant _BITPOS_START_TIMESTAMP = 160;

    // The bit mask of the `burned` bit in packed ownership.
    uint256 private constant _BITMASK_BURNED = 1 << 224;

    // The bit position of the `nextInitialized` bit in packed ownership.
    uint256 private constant _BITPOS_NEXT_INITIALIZED = 225;

    // The bit mask of the `nextInitialized` bit in packed ownership.
    uint256 private constant _BITMASK_NEXT_INITIALIZED = 1 << 225;

    // The bit position of `extraData` in packed ownership.
    uint256 private constant _BITPOS_EXTRA_DATA = 232;

    // Mask of all 256 bits in a packed ownership except the 24 bits for `extraData`.
    uint256 private constant _BITMASK_EXTRA_DATA_COMPLEMENT = (1 << 232) - 1;

    // The mask of the lower 160 bits for addresses.
    uint256 private constant _BITMASK_ADDRESS = (1 << 160) - 1;

    // The maximum `quantity` that can be minted with {_mintERC2309}.
    // This limit is to prevent overflows on the address data entries.
    // For a limit of 5000, a total of 3.689e15 calls to {_mintERC2309}
    // is required to cause an overflow, which is unrealistic.
    uint256 private constant _MAX_MINT_ERC2309_QUANTITY_LIMIT = 5000;

    // The `Transfer` event signature is given by:
    // `keccak256(bytes("Transfer(address,address,uint256)"))`.
    bytes32 private constant _TRANSFER_EVENT_SIGNATURE =
        0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef;

    // =============================================================
    //                            STORAGE
    // =============================================================

    // The next token ID to be minted.
    uint256 private _currentIndex;

    // The number of tokens burned.
    uint256 private _burnCounter;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // Mapping from token ID to ownership details
    // An empty struct value does not necessarily mean the token is unowned.
    // See {_packedOwnershipOf} implementation for details.
    //
    // Bits Layout:
    // - [0..159]   `addr`
    // - [160..223] `startTimestamp`
    // - [224]      `burned`
    // - [225]      `nextInitialized`
    // - [232..255] `extraData`
    mapping(uint256 => uint256) private _packedOwnerships;

    // Mapping owner address to address data.
    //
    // Bits Layout:
    // - [0..63]    `balance`
    // - [64..127]  `numberMinted`
    // - [128..191] `numberBurned`
    // - [192..255] `aux`
    mapping(address => uint256) private _packedAddressData;

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

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

    // =============================================================
    //                          CONSTRUCTOR
    // =============================================================

    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
        _currentIndex = _startTokenId();
    }

    // =============================================================
    //                   TOKEN COUNTING OPERATIONS
    // =============================================================

    /**
     * @dev Returns the starting token ID.
     * To change the starting token ID, please override this function.
     */
    function _startTokenId() internal view virtual returns (uint256) {
        return 0;
    }

    /**
     * @dev Returns the next token ID to be minted.
     */
    function _nextTokenId() internal view virtual returns (uint256) {
        return _currentIndex;
    }

    /**
     * @dev Returns the total number of tokens in existence.
     * Burned tokens will reduce the count.
     * To get the total number of tokens minted, please see {_totalMinted}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        // Counter underflow is impossible as _burnCounter cannot be incremented
        // more than `_currentIndex - _startTokenId()` times.
        unchecked {
            return _currentIndex - _burnCounter - _startTokenId();
        }
    }

    /**
     * @dev Returns the total amount of tokens minted in the contract.
     */
    function _totalMinted() internal view virtual returns (uint256) {
        // Counter underflow is impossible as `_currentIndex` does not decrement,
        // and it is initialized to `_startTokenId()`.
        unchecked {
            return _currentIndex - _startTokenId();
        }
    }

    /**
     * @dev Returns the total number of tokens burned.
     */
    function _totalBurned() internal view virtual returns (uint256) {
        return _burnCounter;
    }

    // =============================================================
    //                    ADDRESS DATA OPERATIONS
    // =============================================================

    /**
     * @dev Returns the number of tokens in `owner`'s account.
     */
    function balanceOf(address owner)
        public
        view
        virtual
        override
        returns (uint256)
    {
        if (owner == address(0)) revert BalanceQueryForZeroAddress();
        return _packedAddressData[owner] & _BITMASK_ADDRESS_DATA_ENTRY;
    }

    /**
     * Returns the number of tokens minted by `owner`.
     */
    function _numberMinted(address owner) internal view returns (uint256) {
        return
            (_packedAddressData[owner] >> _BITPOS_NUMBER_MINTED) &
            _BITMASK_ADDRESS_DATA_ENTRY;
    }

    /**
     * Returns the number of tokens burned by or on behalf of `owner`.
     */
    function _numberBurned(address owner) internal view returns (uint256) {
        return
            (_packedAddressData[owner] >> _BITPOS_NUMBER_BURNED) &
            _BITMASK_ADDRESS_DATA_ENTRY;
    }

    /**
     * Returns the auxiliary data for `owner`. (e.g. number of whitelist mint slots used).
     */
    function _getAux(address owner) internal view returns (uint64) {
        return uint64(_packedAddressData[owner] >> _BITPOS_AUX);
    }

    /**
     * Sets the auxiliary data for `owner`. (e.g. number of whitelist mint slots used).
     * If there are multiple variables, please pack them into a uint64.
     */
    function _setAux(address owner, uint64 aux) internal virtual {
        uint256 packed = _packedAddressData[owner];
        uint256 auxCasted;
        // Cast `aux` with assembly to avoid redundant masking.
        assembly {
            auxCasted := aux
        }
        packed =
            (packed & _BITMASK_AUX_COMPLEMENT) |
            (auxCasted << _BITPOS_AUX);
        _packedAddressData[owner] = packed;
    }

    // =============================================================
    //                            IERC165
    // =============================================================

    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified)
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30000 gas.
     */
    function supportsInterface(bytes4 interfaceId)
        public
        view
        virtual
        override
        returns (bool)
    {
        // The interface IDs are constants representing the first 4 bytes
        // of the XOR of all function selectors in the interface.
        // See: [ERC165](https://eips.ethereum.org/EIPS/eip-165)
        // (e.g. `bytes4(i.functionA.selector ^ i.functionB.selector ^ ...)`)
        return
            interfaceId == 0x01ffc9a7 || // ERC165 interface ID for ERC165.
            interfaceId == 0x80ac58cd || // ERC165 interface ID for ERC721.
            interfaceId == 0x5b5e139f; // ERC165 interface ID for ERC721Metadata.
    }

    // =============================================================
    //                        IERC721Metadata
    // =============================================================

    /**
     * @dev Returns the token collection name.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the token collection symbol.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
     */
    function tokenURI(uint256 tokenId)
        public
        view
        virtual
        override
        returns (string memory)
    {
        if (!_exists(tokenId)) revert URIQueryForNonexistentToken();

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

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

    // =============================================================
    //                     OWNERSHIPS OPERATIONS
    // =============================================================

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId)
        public
        view
        virtual
        override
        returns (address)
    {
        return address(uint160(_packedOwnershipOf(tokenId)));
    }

    /**
     * @dev Gas spent here starts off proportional to the maximum mint batch size.
     * It gradually moves to O(1) as tokens get transferred around over time.
     */
    function _ownershipOf(uint256 tokenId)
        internal
        view
        virtual
        returns (TokenOwnership memory)
    {
        return _unpackedOwnership(_packedOwnershipOf(tokenId));
    }

    /**
     * @dev Returns the unpacked `TokenOwnership` struct at `index`.
     */
    function _ownershipAt(uint256 index)
        internal
        view
        virtual
        returns (TokenOwnership memory)
    {
        return _unpackedOwnership(_packedOwnerships[index]);
    }

    /**
     * @dev Initializes the ownership slot minted at `index` for efficiency purposes.
     */
    function _initializeOwnershipAt(uint256 index) internal virtual {
        if (_packedOwnerships[index] == 0) {
            _packedOwnerships[index] = _packedOwnershipOf(index);
        }
    }

    /**
     * Returns the packed ownership data of `tokenId`.
     */
    function _packedOwnershipOf(uint256 tokenId)
        private
        view
        returns (uint256)
    {
        uint256 curr = tokenId;

        unchecked {
            if (_startTokenId() <= curr)
                if (curr < _currentIndex) {
                    uint256 packed = _packedOwnerships[curr];
                    // If not burned.
                    if (packed & _BITMASK_BURNED == 0) {
                        // Invariant:
                        // There will always be an initialized ownership slot
                        // (i.e. `ownership.addr != address(0) && ownership.burned == false`)
                        // before an unintialized ownership slot
                        // (i.e. `ownership.addr == address(0) && ownership.burned == false`)
                        // Hence, `curr` will not underflow.
                        //
                        // We can directly compare the packed value.
                        // If the address is zero, packed will be zero.
                        while (packed == 0) {
                            packed = _packedOwnerships[--curr];
                        }
                        return packed;
                    }
                }
        }
        revert OwnerQueryForNonexistentToken();
    }

    /**
     * @dev Returns the unpacked `TokenOwnership` struct from `packed`.
     */
    function _unpackedOwnership(uint256 packed)
        private
        pure
        returns (TokenOwnership memory ownership)
    {
        ownership.addr = address(uint160(packed));
        ownership.startTimestamp = uint64(packed >> _BITPOS_START_TIMESTAMP);
        ownership.burned = packed & _BITMASK_BURNED != 0;
        ownership.extraData = uint24(packed >> _BITPOS_EXTRA_DATA);
    }

    /**
     * @dev Packs ownership data into a single uint256.
     */
    function _packOwnershipData(address owner, uint256 flags)
        private
        view
        returns (uint256 result)
    {
        assembly {
            // Mask `owner` to the lower 160 bits, in case the upper bits somehow aren't clean.
            owner := and(owner, _BITMASK_ADDRESS)
            // `owner | (block.timestamp << _BITPOS_START_TIMESTAMP) | flags`.
            result := or(
                owner,
                or(shl(_BITPOS_START_TIMESTAMP, timestamp()), flags)
            )
        }
    }

    /**
     * @dev Returns the `nextInitialized` flag set if `quantity` equals 1.
     */
    function _nextInitializedFlag(uint256 quantity)
        private
        pure
        returns (uint256 result)
    {
        // For branchless setting of the `nextInitialized` flag.
        assembly {
            // `(quantity == 1) << _BITPOS_NEXT_INITIALIZED`.
            result := shl(_BITPOS_NEXT_INITIALIZED, eq(quantity, 1))
        }
    }

    // =============================================================
    //                      APPROVAL OPERATIONS
    // =============================================================

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

        if (_msgSenderERC721A() != owner)
            if (!isApprovedForAll(owner, _msgSenderERC721A())) {
                revert ApprovalCallerNotOwnerNorApproved();
            }

        _tokenApprovals[tokenId].value = to;
        emit Approval(owner, to, tokenId);
    }

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId)
        public
        view
        virtual
        override
        returns (address)
    {
        if (!_exists(tokenId)) revert ApprovalQueryForNonexistentToken();

        return _tokenApprovals[tokenId].value;
    }

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom}
     * for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool approved)
        public
        virtual
        override
    {
        _operatorApprovals[_msgSenderERC721A()][operator] = approved;
        emit ApprovalForAll(_msgSenderERC721A(), operator, approved);
    }

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

    /**
     * @dev Returns whether `tokenId` exists.
     *
     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
     *
     * Tokens start existing when they are minted. See {_mint}.
     */
    function _exists(uint256 tokenId) internal view virtual returns (bool) {
        return
            _startTokenId() <= tokenId &&
            tokenId < _currentIndex && // If within bounds,
            _packedOwnerships[tokenId] & _BITMASK_BURNED == 0; // and not burned.
    }

    /**
     * @dev Returns whether `msgSender` is equal to `approvedAddress` or `owner`.
     */
    function _isSenderApprovedOrOwner(
        address approvedAddress,
        address owner,
        address msgSender
    ) private pure returns (bool result) {
        assembly {
            // Mask `owner` to the lower 160 bits, in case the upper bits somehow aren't clean.
            owner := and(owner, _BITMASK_ADDRESS)
            // Mask `msgSender` to the lower 160 bits, in case the upper bits somehow aren't clean.
            msgSender := and(msgSender, _BITMASK_ADDRESS)
            // `msgSender == owner || msgSender == approvedAddress`.
            result := or(eq(msgSender, owner), eq(msgSender, approvedAddress))
        }
    }

    /**
     * @dev Returns the storage slot and value for the approved address of `tokenId`.
     */
    function _getApprovedSlotAndAddress(uint256 tokenId)
        private
        view
        returns (uint256 approvedAddressSlot, address approvedAddress)
    {
        TokenApprovalRef storage tokenApproval = _tokenApprovals[tokenId];
        // The following is equivalent to `approvedAddress = _tokenApprovals[tokenId].value`.
        assembly {
            approvedAddressSlot := tokenApproval.slot
            approvedAddress := sload(approvedAddressSlot)
        }
    }

    // =============================================================
    //                      TRANSFER OPERATIONS
    // =============================================================

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token
     * by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public payable virtual override {
        uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId);

        if (address(uint160(prevOwnershipPacked)) != from)
            revert TransferFromIncorrectOwner();

        (
            uint256 approvedAddressSlot,
            address approvedAddress
        ) = _getApprovedSlotAndAddress(tokenId);

        // The nested ifs save around 20+ gas over a compound boolean condition.
        if (
            !_isSenderApprovedOrOwner(
                approvedAddress,
                from,
                _msgSenderERC721A()
            )
        )
            if (!isApprovedForAll(from, _msgSenderERC721A()))
                revert TransferCallerNotOwnerNorApproved();

        if (to == address(0)) revert TransferToZeroAddress();

        _beforeTokenTransfers(from, to, tokenId, 1);

        // Clear approvals from the previous owner.
        assembly {
            if approvedAddress {
                // This is equivalent to `delete _tokenApprovals[tokenId]`.
                sstore(approvedAddressSlot, 0)
            }
        }

        // Underflow of the sender's balance is impossible because we check for
        // ownership above and the recipient's balance can't realistically overflow.
        // Counter overflow is incredibly unrealistic as `tokenId` would have to be 2**256.
        unchecked {
            // We can directly increment and decrement the balances.
            --_packedAddressData[from]; // Updates: `balance -= 1`.
            ++_packedAddressData[to]; // Updates: `balance += 1`.

            // Updates:
            // - `address` to the next owner.
            // - `startTimestamp` to the timestamp of transfering.
            // - `burned` to `false`.
            // - `nextInitialized` to `true`.
            _packedOwnerships[tokenId] = _packOwnershipData(
                to,
                _BITMASK_NEXT_INITIALIZED |
                    _nextExtraData(from, to, prevOwnershipPacked)
            );

            // If the next slot may not have been initialized (i.e. `nextInitialized == false`) .
            if (prevOwnershipPacked & _BITMASK_NEXT_INITIALIZED == 0) {
                uint256 nextTokenId = tokenId + 1;
                // If the next slot's address is zero and not burned (i.e. packed value is zero).
                if (_packedOwnerships[nextTokenId] == 0) {
                    // If the next slot is within bounds.
                    if (nextTokenId != _currentIndex) {
                        // Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`.
                        _packedOwnerships[nextTokenId] = prevOwnershipPacked;
                    }
                }
            }
        }

        emit Transfer(from, to, tokenId);
        _afterTokenTransfers(from, to, tokenId, 1);
    }

    /**
     * @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public payable virtual override {
        safeTransferFrom(from, to, tokenId, "");
    }

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token
     * by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement
     * {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) public payable virtual override {
        transferFrom(from, to, tokenId);
        if (to.code.length != 0)
            if (!_checkContractOnERC721Received(from, to, tokenId, _data)) {
                revert TransferToNonERC721ReceiverImplementer();
            }
    }

    /**
     * @dev Hook that is called before a set of serially-ordered token IDs
     * are about to be transferred. This includes minting.
     * And also called before burning one token.
     *
     * `startTokenId` - the first token ID to be transferred.
     * `quantity` - the amount to be transferred.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, `from`'s `tokenId` will be
     * transferred to `to`.
     * - When `from` is zero, `tokenId` will be minted for `to`.
     * - When `to` is zero, `tokenId` will be burned by `from`.
     * - `from` and `to` are never both zero.
     */
    function _beforeTokenTransfers(
        address from,
        address to,
        uint256 startTokenId,
        uint256 quantity
    ) internal virtual {}

    /**
     * @dev Hook that is called after a set of serially-ordered token IDs
     * have been transferred. This includes minting.
     * And also called after one token has been burned.
     *
     * `startTokenId` - the first token ID to be transferred.
     * `quantity` - the amount to be transferred.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, `from`'s `tokenId` has been
     * transferred to `to`.
     * - When `from` is zero, `tokenId` has been minted for `to`.
     * - When `to` is zero, `tokenId` has been burned by `from`.
     * - `from` and `to` are never both zero.
     */
    function _afterTokenTransfers(
        address from,
        address to,
        uint256 startTokenId,
        uint256 quantity
    ) internal virtual {}

    /**
     * @dev Private function to invoke {IERC721Receiver-onERC721Received} on a target contract.
     *
     * `from` - Previous owner of the given token ID.
     * `to` - Target address that will receive the token.
     * `tokenId` - Token ID to be transferred.
     * `_data` - Optional data to send along with the call.
     *
     * Returns whether the call correctly returned the expected magic value.
     */
    function _checkContractOnERC721Received(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) private returns (bool) {
        try
            ERC721A__IERC721Receiver(to).onERC721Received(
                _msgSenderERC721A(),
                from,
                tokenId,
                _data
            )
        returns (bytes4 retval) {
            return
                retval ==
                ERC721A__IERC721Receiver(to).onERC721Received.selector;
        } catch (bytes memory reason) {
            if (reason.length == 0) {
                revert TransferToNonERC721ReceiverImplementer();
            } else {
                assembly {
                    revert(add(32, reason), mload(reason))
                }
            }
        }
    }

    // =============================================================
    //                        MINT OPERATIONS
    // =============================================================

    /**
     * @dev Mints `quantity` tokens and transfers them to `to`.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `quantity` must be greater than 0.
     *
     * Emits a {Transfer} event for each mint.
     */
    function _mint(address to, uint256 quantity) internal virtual {
        uint256 startTokenId = _currentIndex;
        if (quantity == 0) revert MintZeroQuantity();

        _beforeTokenTransfers(address(0), to, startTokenId, quantity);

        // Overflows are incredibly unrealistic.
        // `balance` and `numberMinted` have a maximum limit of 2**64.
        // `tokenId` has a maximum limit of 2**256.
        unchecked {
            // Updates:
            // - `balance += quantity`.
            // - `numberMinted += quantity`.
            //
            // We can directly add to the `balance` and `numberMinted`.
            _packedAddressData[to] +=
                quantity *
                ((1 << _BITPOS_NUMBER_MINTED) | 1);

            // Updates:
            // - `address` to the owner.
            // - `startTimestamp` to the timestamp of minting.
            // - `burned` to `false`.
            // - `nextInitialized` to `quantity == 1`.
            _packedOwnerships[startTokenId] = _packOwnershipData(
                to,
                _nextInitializedFlag(quantity) |
                    _nextExtraData(address(0), to, 0)
            );

            uint256 toMasked;
            uint256 end = startTokenId + quantity;

            // Use assembly to loop and emit the `Transfer` event for gas savings.
            // The duplicated `log4` removes an extra check and reduces stack juggling.
            // The assembly, together with the surrounding Solidity code, have been
            // delicately arranged to nudge the compiler into producing optimized opcodes.
            assembly {
                // Mask `to` to the lower 160 bits, in case the upper bits somehow aren't clean.
                toMasked := and(to, _BITMASK_ADDRESS)
                // Emit the `Transfer` event.
                log4(
                    0, // Start of data (0, since no data).
                    0, // End of data (0, since no data).
                    _TRANSFER_EVENT_SIGNATURE, // Signature.
                    0, // `address(0)`.
                    toMasked, // `to`.
                    startTokenId // `tokenId`.
                )

                // The `iszero(eq(,))` check ensures that large values of `quantity`
                // that overflows uint256 will make the loop run out of gas.
                // The compiler will optimize the `iszero` away for performance.
                for {
                    let tokenId := add(startTokenId, 1)
                } iszero(eq(tokenId, end)) {
                    tokenId := add(tokenId, 1)
                } {
                    // Emit the `Transfer` event. Similar to above.
                    log4(0, 0, _TRANSFER_EVENT_SIGNATURE, 0, toMasked, tokenId)
                }
            }
            if (toMasked == 0) revert MintToZeroAddress();

            _currentIndex = end;
        }
        _afterTokenTransfers(address(0), to, startTokenId, quantity);
    }

    /**
     * @dev Mints `quantity` tokens and transfers them to `to`.
     *
     * This function is intended for efficient minting only during contract creation.
     *
     * It emits only one {ConsecutiveTransfer} as defined in
     * [ERC2309](https://eips.ethereum.org/EIPS/eip-2309),
     * instead of a sequence of {Transfer} event(s).
     *
     * Calling this function outside of contract creation WILL make your contract
     * non-compliant with the ERC721 standard.
     * For full ERC721 compliance, substituting ERC721 {Transfer} event(s) with the ERC2309
     * {ConsecutiveTransfer} event is only permissible during contract creation.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `quantity` must be greater than 0.
     *
     * Emits a {ConsecutiveTransfer} event.
     */
    function _mintERC2309(address to, uint256 quantity) internal virtual {
        uint256 startTokenId = _currentIndex;
        if (to == address(0)) revert MintToZeroAddress();
        if (quantity == 0) revert MintZeroQuantity();
        if (quantity > _MAX_MINT_ERC2309_QUANTITY_LIMIT)
            revert MintERC2309QuantityExceedsLimit();

        _beforeTokenTransfers(address(0), to, startTokenId, quantity);

        // Overflows are unrealistic due to the above check for `quantity` to be below the limit.
        unchecked {
            // Updates:
            // - `balance += quantity`.
            // - `numberMinted += quantity`.
            //
            // We can directly add to the `balance` and `numberMinted`.
            _packedAddressData[to] +=
                quantity *
                ((1 << _BITPOS_NUMBER_MINTED) | 1);

            // Updates:
            // - `address` to the owner.
            // - `startTimestamp` to the timestamp of minting.
            // - `burned` to `false`.
            // - `nextInitialized` to `quantity == 1`.
            _packedOwnerships[startTokenId] = _packOwnershipData(
                to,
                _nextInitializedFlag(quantity) |
                    _nextExtraData(address(0), to, 0)
            );

            emit ConsecutiveTransfer(
                startTokenId,
                startTokenId + quantity - 1,
                address(0),
                to
            );

            _currentIndex = startTokenId + quantity;
        }
        _afterTokenTransfers(address(0), to, startTokenId, quantity);
    }

    /**
     * @dev Safely mints `quantity` tokens and transfers them to `to`.
     *
     * Requirements:
     *
     * - If `to` refers to a smart contract, it must implement
     * {IERC721Receiver-onERC721Received}, which is called for each safe transfer.
     * - `quantity` must be greater than 0.
     *
     * See {_mint}.
     *
     * Emits a {Transfer} event for each mint.
     */
    function _safeMint(
        address to,
        uint256 quantity,
        bytes memory _data
    ) internal virtual {
        _mint(to, quantity);

        unchecked {
            if (to.code.length != 0) {
                uint256 end = _currentIndex;
                uint256 index = end - quantity;
                do {
                    if (
                        !_checkContractOnERC721Received(
                            address(0),
                            to,
                            index++,
                            _data
                        )
                    ) {
                        revert TransferToNonERC721ReceiverImplementer();
                    }
                } while (index < end);
                // Reentrancy protection.
                if (_currentIndex != end) revert();
            }
        }
    }

    /**
     * @dev Equivalent to `_safeMint(to, quantity, '')`.
     */
    function _safeMint(address to, uint256 quantity) internal virtual {
        _safeMint(to, quantity, "");
    }

    // =============================================================
    //                        BURN OPERATIONS
    // =============================================================

    /**
     * @dev Equivalent to `_burn(tokenId, false)`.
     */
    function _burn(uint256 tokenId) internal virtual {
        _burn(tokenId, false);
    }

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

        address from = address(uint160(prevOwnershipPacked));

        (
            uint256 approvedAddressSlot,
            address approvedAddress
        ) = _getApprovedSlotAndAddress(tokenId);

        if (approvalCheck) {
            // The nested ifs save around 20+ gas over a compound boolean condition.
            if (
                !_isSenderApprovedOrOwner(
                    approvedAddress,
                    from,
                    _msgSenderERC721A()
                )
            )
                if (!isApprovedForAll(from, _msgSenderERC721A()))
                    revert TransferCallerNotOwnerNorApproved();
        }

        _beforeTokenTransfers(from, address(0), tokenId, 1);

        // Clear approvals from the previous owner.
        assembly {
            if approvedAddress {
                // This is equivalent to `delete _tokenApprovals[tokenId]`.
                sstore(approvedAddressSlot, 0)
            }
        }

        // Underflow of the sender's balance is impossible because we check for
        // ownership above and the recipient's balance can't realistically overflow.
        // Counter overflow is incredibly unrealistic as `tokenId` would have to be 2**256.
        unchecked {
            // Updates:
            // - `balance -= 1`.
            // - `numberBurned += 1`.
            //
            // We can directly decrement the balance, and increment the number burned.
            // This is equivalent to `packed -= 1; packed += 1 << _BITPOS_NUMBER_BURNED;`.
            _packedAddressData[from] += (1 << _BITPOS_NUMBER_BURNED) - 1;

            // Updates:
            // - `address` to the last owner.
            // - `startTimestamp` to the timestamp of burning.
            // - `burned` to `true`.
            // - `nextInitialized` to `true`.
            _packedOwnerships[tokenId] = _packOwnershipData(
                from,
                (_BITMASK_BURNED | _BITMASK_NEXT_INITIALIZED) |
                    _nextExtraData(from, address(0), prevOwnershipPacked)
            );

            // If the next slot may not have been initialized (i.e. `nextInitialized == false`) .
            if (prevOwnershipPacked & _BITMASK_NEXT_INITIALIZED == 0) {
                uint256 nextTokenId = tokenId + 1;
                // If the next slot's address is zero and not burned (i.e. packed value is zero).
                if (_packedOwnerships[nextTokenId] == 0) {
                    // If the next slot is within bounds.
                    if (nextTokenId != _currentIndex) {
                        // Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`.
                        _packedOwnerships[nextTokenId] = prevOwnershipPacked;
                    }
                }
            }
        }

        emit Transfer(from, address(0), tokenId);
        _afterTokenTransfers(from, address(0), tokenId, 1);

        // Overflow not possible, as _burnCounter cannot be exceed _currentIndex times.
        unchecked {
            _burnCounter++;
        }
    }

    // =============================================================
    //                     EXTRA DATA OPERATIONS
    // =============================================================

    /**
     * @dev Directly sets the extra data for the ownership data `index`.
     */
    function _setExtraDataAt(uint256 index, uint24 extraData) internal virtual {
        uint256 packed = _packedOwnerships[index];
        if (packed == 0) revert OwnershipNotInitializedForExtraData();
        uint256 extraDataCasted;
        // Cast `extraData` with assembly to avoid redundant masking.
        assembly {
            extraDataCasted := extraData
        }
        packed =
            (packed & _BITMASK_EXTRA_DATA_COMPLEMENT) |
            (extraDataCasted << _BITPOS_EXTRA_DATA);
        _packedOwnerships[index] = packed;
    }

    /**
     * @dev Called during each token transfer to set the 24bit `extraData` field.
     * Intended to be overridden by the cosumer contract.
     *
     * `previousExtraData` - the value of `extraData` before transfer.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, `from`'s `tokenId` will be
     * transferred to `to`.
     * - When `from` is zero, `tokenId` will be minted for `to`.
     * - When `to` is zero, `tokenId` will be burned by `from`.
     * - `from` and `to` are never both zero.
     */
    function _extraData(
        address from,
        address to,
        uint24 previousExtraData
    ) internal view virtual returns (uint24) {}

    /**
     * @dev Returns the next extra data for the packed ownership data.
     * The returned result is shifted into position.
     */
    function _nextExtraData(
        address from,
        address to,
        uint256 prevOwnershipPacked
    ) private view returns (uint256) {
        uint24 extraData = uint24(prevOwnershipPacked >> _BITPOS_EXTRA_DATA);
        return uint256(_extraData(from, to, extraData)) << _BITPOS_EXTRA_DATA;
    }

    // =============================================================
    //                       OTHER OPERATIONS
    // =============================================================

    /**
     * @dev Returns the message sender (defaults to `msg.sender`).
     *
     * If you are writing GSN compatible contracts, you need to override this function.
     */
    function _msgSenderERC721A() internal view virtual returns (address) {
        return msg.sender;
    }

    /**
     * @dev Converts a uint256 to its ASCII string decimal representation.
     */
    function _toString(uint256 value)
        internal
        pure
        virtual
        returns (string memory str)
    {
        assembly {
            // The maximum value of a uint256 contains 78 digits (1 byte per digit), but
            // we allocate 0xa0 bytes to keep the free memory pointer 32-byte word aligned.
            // We will need 1 word for the trailing zeros padding, 1 word for the length,
            // and 3 words for a maximum of 78 digits. Total: 5 * 0x20 = 0xa0.
            let m := add(mload(0x40), 0xa0)
            // Update the free memory pointer to allocate.
            mstore(0x40, m)
            // Assign the `str` to the end.
            str := sub(m, 0x20)
            // Zeroize the slot after the string.
            mstore(str, 0)

            // Cache the end of the memory to calculate the length later.
            let end := str

            // We write the string from rightmost digit to leftmost digit.
            // The following is essentially a do-while loop that also handles the zero case.
            // prettier-ignore
            for { let temp := value } 1 {} {
                str := sub(str, 1)
                // Write the character to the pointer.
                // The ASCII index of the '0' character is 48.
                mstore8(str, add(48, mod(temp, 10)))
                // Keep dividing `temp` until zero.
                temp := div(temp, 10)
                // prettier-ignore
                if iszero(temp) { break }
            }

            let length := sub(end, str)
            // Move the pointer 32 bytes leftwards to make room for the length.
            str := sub(str, 0x20)
            // Store the length.
            mstore(str, length)
        }
    }
}

// File: @openzeppelin/contracts/security/ReentrancyGuard.sol

// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be _NOT_ENTERED
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
}

// File: @openzeppelin/contracts/utils/Context.sol

// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

// File: @openzeppelin/contracts/access/Ownable.sol

// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(
        address indexed previousOwner,
        address indexed newOwner
    );

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

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

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

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

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

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)

pragma solidity ^0.8.0;

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

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

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

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

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

////////////////////////
///// Anizuki /////
////////////////////////
pragma solidity ^0.8.17;

contract Anizuki is ERC721A, Ownable, ReentrancyGuard {
    using Strings for uint256;

    // ================== VARAIBLES =======================

    string private uriPrefix = "";
    string private uriSuffix = ".json";
    string private hiddenMetadataUri;
    bool public paused = true;
    bool public revealed = true;

    uint256 public salePrice = 0.001 ether;
    uint256 public maxFree = 5;
    uint256 public maxTx = 30;
    uint256 public maxFreeSupply = 5000;
    uint256 public maxSupply = 5000;

    uint256 public FREE_MINTED = 0;
    mapping(address => uint256) public CLAIMED;

    // ================== CONTRUCTOR =======================

    constructor() ERC721A("Anizuki", "ANZK") {
        setHiddenMetadataUri("ipfs://__CID__/hidden.json");
    }

    // ================== MINT FUNCTIONS =======================

    /**
     * @notice Mint
     */
    function mint(uint256 _quantity) external payable {
        // Normal requirements
        require(!paused, "The contract is paused!");
        require(
            _quantity > 0,
            "Minimum 1 NFT has to be minted per transaction"
        );
        require(_quantity + balanceOf(msg.sender) <= maxTx, "No more!");
        require(_quantity + totalSupply() <= maxSupply, "Sold out");

        if (msg.sender != owner()) {
            if (
                !(CLAIMED[msg.sender] >= maxFree) &&
                FREE_MINTED + maxFree <= maxFreeSupply
            ) {
                if (_quantity <= maxFree - CLAIMED[msg.sender]) {
                    require(msg.value >= 0, "Please send the exact amount.");
                } else {
                    require(
                        msg.value >=
                            salePrice *
                                (_quantity - (maxFree - CLAIMED[msg.sender])),
                        "Please send the exact amount."
                    );
                }
                FREE_MINTED += _quantity;
                CLAIMED[msg.sender] += _quantity;
            } else {
                require(
                    msg.value >= salePrice * _quantity,
                    "Please send the exact amount."
                );
            }
        }

        // Mint
        _safeMint(msg.sender, _quantity);
    }

    /**
     * @notice Team Mint
     */
    function teamMint(uint256 _quantity) external onlyOwner {
        require(totalSupply() + _quantity <= maxSupply, "Sold out");
        _safeMint(msg.sender, _quantity);
    }

    /**
     * @notice airdrop
     */
    function airdrop(address _to, uint256 _quantity) external onlyOwner {
        require(!paused, "The contract is paused!");
        require(_quantity + totalSupply() <= maxSupply, "Sold out");
        _safeMint(_to, _quantity);
    }

    // ================== SETUP FUNCTIONS =======================

    function setPaused(bool _state) public onlyOwner {
        paused = _state;
    }

    function setRevealed(bool _state) public onlyOwner {
        revealed = _state;
    }

    function setSalePrice(uint256 _newPrice) external onlyOwner {
        salePrice = _newPrice;
    }

    function setMaxFree(uint256 _maxFree) public onlyOwner {
        maxFree = _maxFree;
    }

    function setMaxTx(uint256 _maxTx) public onlyOwner {
        maxTx = _maxTx;
    }

    function setmaxFreeSupply(uint256 _maxFreeSupply) public onlyOwner {
        maxFreeSupply = _maxFreeSupply;
    }

    function setMaxSupply(uint256 _maxSupply) public onlyOwner {
        maxSupply = _maxSupply;
    }

    function setHiddenMetadataUri(string memory _hiddenMetadataUri)
        public
        onlyOwner
    {
        hiddenMetadataUri = _hiddenMetadataUri;
    }

    function setUriPrefix(string memory _uriPrefix) public onlyOwner {
        uriPrefix = _uriPrefix;
    }

    function _baseURI() internal view virtual override returns (string memory) {
        return uriPrefix;
    }

    function walletOfOwner(address _owner)
        public
        view
        returns (uint256[] memory)
    {
        uint256 ownerTokenCount = balanceOf(_owner);
        uint256[] memory ownedTokenIds = new uint256[](ownerTokenCount);
        uint256 currentTokenId = 1;
        uint256 ownedTokenIndex = 0;

        while (
            ownedTokenIndex < ownerTokenCount && currentTokenId <= maxSupply
        ) {
            address currentTokenOwner = ownerOf(currentTokenId);
            if (currentTokenOwner == _owner) {
                ownedTokenIds[ownedTokenIndex] = currentTokenId;
                ownedTokenIndex++;
            }
            currentTokenId++;
        }
        return ownedTokenIds;
    }

    function _startTokenId() internal view virtual override returns (uint256) {
        return 1;
    }

    function tokenURI(uint256 _tokenId)
        public
        view
        virtual
        override
        returns (string memory)
    {
        require(
            _exists(_tokenId),
            "ERC721Metadata: URI query for nonexistent token"
        );
        if (revealed == false) {
            return hiddenMetadataUri;
        }
        string memory currentBaseURI = _baseURI();
        return
            bytes(currentBaseURI).length > 0
                ? string(
                    abi.encodePacked(
                        currentBaseURI,
                        _tokenId.toString(),
                        uriSuffix
                    )
                )
                : "";
    }

    function withdraw() external onlyOwner {
        (bool success, ) = payable(msg.sender).call{
            value: address(this).balance
        }("");
        require(success, "Transfer failed.");
    }
}