ETH Price: $3,718.48 (+6.32%)

Transaction Decoder

Block:
18675661 at Nov-29-2023 07:04:59 AM +UTC
Transaction Fee:
0.097079936 ETH $360.99
Gas Used:
3,347,584 Gas / 29 Gwei

Account State Difference:

  Address   Before After State Difference Code
0x326490A8...5b0834D9B
0 Eth
Nonce: 0
0 Eth
Nonce: 1
From: 0 To: 3430024117010706954095442360718814931052342541539548460289871522475368534055166837909706450898290579125915149508834882739232529823208862792750331276169924220644292520141878849862605010780972125449539056109729569937639043596071602716845857299310467570951082387724733819106466217140349419872260221215896207840791036080173811037137903425714014063326925839099961192707201626428036395941897245810812696688143482396194903603772297597646007808914206774343130567056334869956942555551103915169904673501979907229273407425192343569371701332993648186400899194880348113055291515084952066523725215089548797961656472567273266881107071516820399795019241817591914211894591712310421386689698968114308578629935446387404013703831883728468387674615884979419817896270063018987709119025386633056209597957755605688544228084664757250769085998482036948578597975958983818218523875125063688074919155448743673579597068112131324419408639711160587022441500230979974420000737170225461108216322669639202203666294877190379558431134120250536825809775352585687030712755410125679839495012047256690817674277785017302996488057365022703932388108164479865602918974560261214450297894134284734585551818764474738272006929377492202055916904244363740751153728198412046174814390641263657123717563330043556286506217250751235022169989554243119282239594792051867832045310130694902542589581434076217458580387166376373470044073578060641173272219716632328644390146708868675573191964735527969038775182353965113722439613049977111980783449524284525894760825427662391400113567241765074734436630792634078708761890309277294061911766002552728107720331623147982340196186561240620657153304187760893634827381502333892424677548501480810842278441143360935595860412381992072700706033789074977957732764244822239206256562721195291021848897043379325084182418037595060020494287691943920180996676005287488948457161679317864802196308194900139469728402008385800693366958086856513168786157512066093762470421349628192249083536474898189710533515525155055744470144527173144236230687668337712383759609108292550532136490536497916091521596680041055334708774881152943739819164006283598685450667360133212989193626099132152223231814563099307912725906636414610932234623681821854603513793047728959239747597053164336228763136692187138159690279604594556237183330551887664745919437501703671444166207243097252644966056548963374942557429459265088740012867408160073619093235745725360791767335472413842951773589621868446030589393555551508169588250284889068706077164769496716007123817884665572778292499779941483243763275620085400912686232216839322529794120519090508139274415818978124240749981542691683689294290552391001062598866325360501464654601867251772856311518442861373040953679956331012388430617139354356345055856730769253544781532988274147741010226224176800290521690608845182987971124490146431441839451527221877995431719099944746564199890649184638667754013967157676264598527157371649217528495594301316772267305243667310847020012539613171465986122733281939479952094304906101037302950800245097485996518664068617035677613258031572037988253583719389684375239524019133517738764228432116115410797926567721319110716268011071322874939659024813051643398140323655538656450862580764286804662355250952762037974387970920565076839118243349935401058581392505550375163046283326894128465195886900415660753574111522408501567855382802185744307179402720120128858359798162173120173720314596590610866501125041248708553969563969174410014666873544043879995648809690786531880530206637275710993348230154369183011258817917148047104351286988283286195443973366434538783297854626277136671359434453449672580923932789237232675971186945205393711849198358710610238760885431380998196544941285831218877487072858433899098893192162284618962391644836578187431847976272602590893231508738389626626768644460939462338746831655545677705777256887309893372250552759109523032444083089983015909437298704624065537855215423639459518219420352176764357830228683619719647037181355798421716933458498161230227773420751828360049465894507372184444905391746149498883767510910323606463766683594620151580745676397823480413899544310626172664862913124478268368779707777326446646555972483804779186670456177744394536507876130294550623341441106862244144394522208785924966803242702319653402689953291687563337913106186234756022558744400990480045258848961354941153838134691256963407653454434869623580738742502046816167424511498368629123795105430171748034679844188863752676687614605785182454792357797934440604967226281859584190591030067209233147625482779293027151327138086998606305414338787182094907474873579164205411500886517423710278957962147308930043098068859611241429412877260319160177660583666879167049601547294385182682139321921595956379652912504557954524927011372201323010096159473121458965436415040879357252395064452329065559977503897612077280136957368973111368966308441131618855706944759440473601287295682904741053584912707882543263242592066963910088991351249235430850936948725962111534199906106968938344332341161794846723710263883589203271012071907378369408686221281296201381995607379200710320089044729877180818415911505300829102101954483989736852977396872488504071372782679080207117377719547238249201356702318213737766093880974151989754704344570091765462379848123087001620437372722225154893654046418697352963015425511163612698641400337434408940590248970459003194711289791996607769006974157592133393925746657524324370935987063019111891396978565988558760872759201474097395189115900423103637523459183352276996534078817296836744068119499917729259809351312240100214483139062999750467304465878026865961957389499067264207040707103339112288903265298125751409427530023932296057693652023416840110066254429967568756253827597100275897550775507483530678179862393731090740980112591360911166027533143461686606124054098395500988824331200664668265658399724477705841867716913214960586875235015790671862464899595976938405960772791316720520802077303950400028904843626908965029155562727957530605824998525669814703166841903991506025492314181457382061076185519075693989348728690987932068312801516827171131291889555714127550122474620487174750859357610225235840192954780171929519019308256076216479206782124590085254325301875557040928119997917817736927834042574094190210626264697821514102815608974485361467269730597392788189025581001741231429228644106723180421857474522184171154440771376607998311435642839688154937242831346283604677228783778762415969188204882403491282511459704208430722194480884842875602203340843510215981634442427449737424584548938371337799805699745089454594409047213950021066437370458199846191519162815006010315540354892644692951344893661910641277295512836120980337917785709386536886596353710116359045509014585851760620696604463575217728812134330572288829791245407529322175804526249649581008472157670419224451934688143524016587485717382263633414350219692506343645568552144400969736160231156849121041672097995737790694170354889244639816068880531691455630247740718492579053350382566392877376633246377750792638778762963142510727389012455089163385261793593327921537144207748970346345590658238068702009656774394860682893519454149341175687440561412448211822160535165118839360335300380918624191532769285624036861769022872379826571868378071609724775219181482089627535690330282374563257412252801438119289111810227119866842969495142706703685787704844884757898090505193523092817005059414078073741051963796132237194307696879412499324876780651045650760941531917323384714960188055655305731968827275189705150599543572546170410774035017449897580530452973286954559871003918062647266173343818645614286436538142956302852690951378715584149003742333445741534559134382865927731550295869154295526287421581697141892778838888435678040720896028926843541029392377293714221700187853306680682969978972037652829864373833835203522868925040780010917971071507421499926817871393148217875741489872941704253155251904813012999454485854815727513355990026380312695023854439688489794410362832176043160434309831755594910028159420494599354460355659414253512863013132031409049381287362544023680616298234033190094992121377418957699724248117428347285827899955769930732140827181360012989095876811731951766390703267887532255351025148015242682696091831608151847705152311421181710599056386138872670632430504236138342250377576070608726444923964104020492244987494389958206061449687976895133801867818976150420514834676536616323610877775192625884124407833759485342634702249320929982786101686713056480728459600081940219722297417639403617495580629336426132006652759520920200043452988268421360414432236581517552504519988622145092123484419219263805002923600370897033295605725876319194049534642900265168773596021752678792997935756795861267325287562812510239057160798765792869497726495444128730645918862218258328012328458761755345940107548325164110197981194829495159340334486917076948624671064048213041475408720990649469521426798238661148815916752791668714397950304091167442583701355931604830150519363480594903335870578369979657620660354177775794740995841775693616793878214274674916097898534338823598570892430483590734398687799061409721636150439868922215020147597657701023637407919527681687878119861791925755279115531743573962670230942943219812617791165349482892796199632407886898156231605957135399937674927387318397629740545639750669225982205690998167059618576247889575125067437519870235654960432449494549422996025924299246843242652185496866582809734601523098679041233247842279960896223310682072374297942839510801675967622027749682450014695688490770905646963006168752072401869174431982213827230249122077776244302906791193546207693033733338252889441261263473127962395798551959198165355520793126426459326121003533472682738841278495215181426532772715593699763626576586085040541230604851014704226584456505261094493332769054419270093707903482128397359908788526530024968211628197122332679891979603082256021318475568337733915270419271293646553764055216779348280119149822866219663752883580451646953759062762436439279854999354976576834674947675372809545753050222618977055898177325242164613469723827358661158827450977016081233827850132303657624650390935796390753717489656313513636864465898332212990690879719180876939654416047465641424182361981963033872403244010578597369699328285426701989106125825689197133913747375172889771224119618659679904715235095125099997676855279598615952564827445979668383016877128354935535296498503160519163749277206342180552228901688733917408564185961199288675910189000906195916660821014273795361469521927361820731210047291707693171458020230589702598638535359587708378232210984611149716498185558756270349941005923162014143769914753670000022151437983096963712995925457569103164038762672908399254965935778062493773813979193035127771755551842299654311469907036692485478279928977083235001112621601882528733172918182633174074187664856704819487230781228187079315707732910711361925089718120996522234864303851503031278679899107070365226109083243921346138339622230530502826166033657028058566232360245764005592116811514814509899802158004928035098401015934194500473792509549911236008193795285602412338769954268315034085939826560739824462642902780000765575009429371012045026467453808551226429388529196865471104998948660834340783324645800000912828993643694600762117550657618401447560429325075023364815949125907158191194093132559872651841749601989869258593948787317954926621807471130203210086526840389682198005125858362159805587144602816265494444235026076200365908968048897527859725325666647075998922140309422880432355543902050675785438929961072195221310126819487474321274275904920295820864264409280803969892440342145329732820876932767166116491288432273516004368918774091025893652374707736736185017022422920322256713511360477259962633368534453152972735519204621207341202638550557773487311060130558297265181351952760894366341795804297987818752798347660722569471638110713899810802324109792258727225958516705650821195589741800506912165764644381065522101860817623139179290049413674176480592898422071592050130889248253169550351867631767522241855925674980636644124052002428807689106596657817444373964166516698625978880401917814314432659071868248923627923768359018042449872474411096095709038300597710212367619356248119398579401119366258028438308995252221929538123507313497616618494751107208441702779582553544233856137826365870979288099933225150114268256830960809405097945222702263606683124150970003089787984413582870629557672467651122149821138450894134025187950739876383356559494316212569355107259442489845680388888150246800007539297116997670423325491630101958693127422494383158706335504488778211655040176674076135727462338060102630391590588693258007707416055107001703408160144453613119728083973286523488845663159984142183688519287017381181774114149455070956624206864402481423068440130592774203601383347436707746904657076464807795738186826450776299017608973329747018624032558913045975755853222842147667696708133569230205780538797629899619922415433169095296884670650183647971884601390766041996889236632860310215324559648334886545756929439362386344581132978183176834885770389049968931682814006124972243173824491026591975112515091341105118439599557835453671949163102814146523696219305502709090151657062317549476767097978845015098586979744394413389004370223910599616288262846459178469888653000889991948567892251982436326253431461173480360007857040058548571493157533887698327342705770898629984323357065586879653284935573062254581752057991127961573194201729471381387819497222458106700549395518647940982957462242319102942410294800519590688108577471490497698857873693207702230036882102524042144941858440226503034783944870707757106391694953394086640565865329737215752848090401516172093808215248863902978942963003243462881911497139929230004626701212187514105359002228296928603004597262929378334140736009454160661393556773426160361887552716429657381306171713898963735085392568636800817377977149880991503053607937324480993924533531921051125844769369896054167510704924921984774740477947723918899547256795553970627648127274901487455413753246851598271633113435774994893258648795116405827526859711854461612573303745030804038105913978191021579094260818595230882076658925864860836554925731382061839159905016235700077575635072896218330586799322845094995496138354555776180777615459687240756739220940823013523067950440078440094748253615869251468677027051275033059487765778732254431626728898068214263257648845968683717678510722203978408139934320323088678410504306314312650323373253273763726984892988176655242579505007619705342620249335523248102218345032893838667489033037071170085303940244829916418891744235649817052531068991735277765129479889606597778280436199112972466809463687433129941852131046962705037114513860838731752338182529786941898354181309766357609403450857293292834637679879221492475571088404286122661243238888667506164810614083728815038707018563375982463667213614684492895920594523481949864396585657746033183671221646530743503299879521804025715506747929954740111957016432273060086888254191336672342172177537948100166566567357793181857185527367913533998986529139212069310038136864013537260206054619714435032080727450168645646001049522461440535064444346924195627176729960664357679660228738307137027759913463893554583385529613690566005873081955649301612241403202742426577344733333666721884888132521078627411489338552566245670600531837084773767205957641297112066190715477565255497729841213373537409587672887727873447157730740287708299532083862023012701362277325296821306301884965959251141955727989429471393560123955225962729175061810014639999863194936912970317645383789396288461173517428510455587224146121959183397318135012887583624128171811309931322654144550429010942815869660610763649846384942778092365130420384960056813775077848786247196371693946982963102953606545054622818213542988660690665042074136800093828331147516642702260930208591817971523169672494471441443422548190154127950272906979223863946059709495728476468316213364118900908674034777226800580103225652410998163734304739182808055817682173973813398198552465034807893493154794850072000945596442109845635455268236957882179144601662820611537563903608055773764063967465123912595909416114216234039010054313572640558399252589251293129205625735409973246909627449725861216839562501123556100401373378045961708243374181885103409004342592122138825163013903764786160158047464650079628657414829794166933820106808842572547817411375123025213854273394894708360563986628399329425730695909577713011441875737046928985076194203727356543878532941516469376993598025419589303602175930036893632332697358462029169332052509124356615552665776855697445631045441538653371657945059035626180136897118096442951073145932156176107547016181484490869935692378259315945582096457810616303619326965776777817120856249590151067430386717580760399867206931540760957359820086429901299608815078803530377689375648928065155136437653537118114347184828598908227504934239142554097212210416675669640317083145233972949956333934477899851633368405641269528165808210863070980652659640435327236976475459897817801896120597551989505306513464433541111448196450908227255560533295601204756650028589388033030213580257536205283623208616878794103586782949099035491812650591198240561051764009822002737961203354852401050713109271626625327040317451716043604026911035093240228354651421316567523597489623457782599352432457040675253981623982810634708683063093774510265019041630888385510987401224450506238983223370050023380766000954663595493772724369935953610718960287035746616181741699581508190746463564234081640273046033149687683634331193545857075763864726715666389586682479052597486711842505660872184698841231089598752807017068161180006019623175140473570081856928983445566719865449978514524925151485047912714047852211454992511423868979211000136051503575615652334926809315980233716554666258712495468649715379538839561533419036557805864533897702460999233176606944892459072386971543573021743698679131324971566695690722757872140676144415855579192867419366462606750909883967458460436611500174457067696975717353547066985026056278650583308412210369987657497973304314122699816672058421646114517258812467325415847325115847767334464178563940452521867504701683245994715463518190137477108391324343205560612973884436263592506943597188958543230597372996638521826581218342768964610716563805311274541209109695051003382514017376100903968009140433958385618844062366703218249036712799950130868812116360529854325948588148825789424581936743005671847717273207415950461847451028323062477247671428304699813660022826548032675785192794659781577047213539811507690837971988521438106159800682460592105815949737443359261758035527875300494093034378510403110540808804924748901799395978727963557057317361380095340129114319649597581768295399209656876590889088865831062027595769049797923012283751174985023055136991368621797095468617267919955963364350462188127596811809331281826073363867656820087228294396970269903849079499883731610753200294103438050585733829184645083168895936804636910984080279466588228045600840150526791559563042369775870363226345251411469406183170357913176614458996997519452744334692570534423085182999430099112654425143466827580037870706237146466593451638839773330935166314662881299554214108650066390636509192887398994164904278981676537740960030256485355994067714337340054623155138853367853993076191069586912592045046242993930904247078351338174075144443723113810697386244490974057985379372433196616663649497267686249480955292743324826209686732912846461029361681319831103156417580281206877722231420539374359475929392721387939666461047226920017004577769802417753502311515188933586430318178957580932671183609869329497804550234363244704695426682965361318024340496391536195358776898232191744232019926892806514036632810796319879184354649992973019955960664533078716124589382797004030734315462968334476338852691840367878068316801252469578192807261347885044114532305665788200432457098213084205616707961696333169433154492155186663783452405466052434951406733502135150596645328156500778500996015088833813747526910303878786803049455242520880596841827571724749283339409523563966884630689139542566631019145298936715781149883290154726498624280602537733826424988801792575186583423893699085234386979861798611624810458611945818318842401306193386051976101530637539182511473741619187991478172764567954784491563134968281360799593268216739112112959779783918309241624551049880852912723589369396764077332947815752190997251454016153429875494664796000806796823842624811035911542098805459776567077491253513448501302495779380447298907348110792495444264358334318325586683598861508707174774052435053791752721929227834861461059988767285788561341947606662404596502611518599748801162491220371644884039699157952267934002818806488548779897258434275060363091736464350257929083490728901011183127287222941605747000045700588855062305644464945592880539865300520224647863884682939413850175474257114589381924228563984304166926544405924098775814339128731871344010759260724461623302562329113584787160840328034771042568192410389203060184278295682482500124999590994130131127886743597380427842591619063941836289352344316536839635687059642722282006241349198561101740829722702865868458608992285752855440112805676871357927836426827866259396362939597470124898828029221714354871069627796914803884723179753606214500671158299916609363981291803590920208782843025560840085274650255612591361737311358136259646576969556627968194955799077100385712346344808496904108718486009400188515998466118920654644624494610876345344906303991917371297270861576729526559445332882270682159852287774632059209004205959643230087519574574202020210036995004137057460291261026196696099088401697195966105555810087386618905978382075836144699838813945326961859152890142782534226439626398425588192742668763848947422320567381702035656199468283176789612258619245504155305026504696733256239580473315225327086307158669127744356094760543074733222061264546972688352837911122088754500070663885649049590475238718869109392898187491764508465376276069790102340937296429981280904046881340676799447366978354675121707107618148323308211601455768276611255356400148472536271647489117637091120704539155766165377524421909979924895192979706287232909079344002524487407471130044383889917102585332805678520240651798846286068698016416914314285134193437324556233545011777131059170970284505422870858083653328456690503219746848815172919002062064438294613797225507447151258288139754451818504039007688146008205636336124883144464169847754683250246804141837678821678749146046438749173077836800897488653327157591651858755163329376739540606020019642162670065741632669414224919816257587615108111012199854188554890644850412197769591428888490680749050393367775370043288675135684475715676750020468394192737842895650009923291525996710907521477620200982476669368855473684280562873007530506323948123679140350292266075415793736881028082735214265917349372370545528480158749259886905584146343309595322542860930139821131513317405152041117544851361114271134701874392969810156669695924508577687957951757045505545663545631277965078475795593107003050007651016439646538030721566385317211608719535135288047389765073533956394144614689855906014464956226555726613494198117312513663950405408549688565256488448007867931138089612162708868888089857898832739075788910782709884641212799494524222455250721392619276210829669228532030367418623208160287352699395353444877810661128294621880305036712683728940081254960021474725662359574380190666839672312417470798828962192697691150466017595420466900263615477417645619140318790658375965270655650476227353793643089589027230857267814011541483969100969877415105252709900903972028085694296681559450314828410185664844355212285702209077467142700676707894223261580650916940694572615145280856657903646502201546897486957114781397955192501971147434173649735905023840334515870121106898826320646274354669370546894138218588181532899009738186628331506583971905705690374657225838379708003943803281109994063781525692306849679367240961791437110584088260974374276444313958556721628356037592314851822920885888992275446940271421323964050720372076347061585941203417424889070572510303005016693676069421418197007589875124663538104238057721555371962441462850927808339625718827971486751024463140912923529801534164737695394382949645712933780992071238851704716826868049338928876157067317061508241944468111945650655766828239911976442312324768391263282854754494790087179396535136983515186243396779878277333074524815531449977932498320322842008032803398379729005973794342168440340301490655980247282691813884397449693898845163482611692252998181280959131267118366397769297107258703796834739721615250076218983800861913146248848234549818724559333315820364238721322656008501986309238805694492034630943063036125376895065998315403573102668489309568614343987479228659344485390411943295801349984355413618829923165038065382099494144282565705813290888347570255749505122814708180845932791039768263350221777435367993849098610532879225921783976600816952062561141291666450766638741876083950589905165245417252471204398605387438669859955366019109002874198917821893708420913622544546960066129481271193254456118442673504047410246260283547890511871468633762056482076173891306855607579105382629741309389834496786703170382899992404239565257169573067544889934680188405805065257423111994792308534022377393137344504110018365144302171615776591834098505874382089249037179434389904695472602295559418177718472352414602342661043809266718989959971958695664445126624422062727501388861366421983573787319724405522760652140579327607950896275487813472519527134919206240167124662807963245835178266135331016569025929204276272669565583488586004875609261339237322660608116977888800285054594593485281560901955457799875365609223740345894383134037093780084100588242281534735808540091148999117510169962948217202221337535783909678335132991767715281868383778425758993091971221753322442639257293684278786848474630453272366783315915958134587925557391073655358707409237241579136536335493620679627478903172850241159269507746688454631085502944318412616287562997442897111493519161273760584342482218743905535353280579970203059039262235146429021422174934899889462201027364797091975731541020419245336601077871632287038973939916524160872494029293310686839244077954754948075565037820159299704443057388369142825987159870108877982631252200626258259554983566069875582643601985281730945634538691327202774340154209184929931644786969744889858087985432033781642390999264061582998223005260066575394402486787758203135679216648134539917728356555096195656870388860037792389895044443719111045289613035118833434021140662520172191548465441815945207280476391854394803993625963598572706205361901489080568126711960463765092856302254869822003822620695801211924747348576091835787317820270911993768219135874751710698065621696830618510305905607876456628414486162477143117775183633335134846865541745600154664869130234595253324031447443742785140384700940023336335828859065098458882451127206947614179136529531741027133140450309517837225904101622124376963242485237069002973678439601072256911367291117280742244922392722126979814021878170503193174070787315188984182070644210717508834137137051473756823738795944989956198654090882196300622147934004036702392023775529472805306929238175106654194257457704237051821143197378840007337735987766254894834088823464179014666309706927632699198303242894776648740571779626390583766232567905564513873122107584553319386340219219600371198805548282403253277153667839603753141843372695276408168943152815711345060150583236968734321226337404173640761819115294413190090017811398943252621652670743415703593820910176868709819812452227422883741574514599359641427561997903847552343570758896276035362354899907777438369197861633383654068197864464236902659778366748478107610947348524477640482312583639190717066009374172383920150274577147249151493366127966927835864054098623846771199646877441659495807193592784479142502749491719361264448708261780744119067225698293602373566519014509245031503374993990097749902927903667910367627378281048720231540715428341237334943998140733366540973468827481637023262513972348166773133632002926268341589672191595181375400027158128842190221972784128220768773104133916667114837171635984168098626010322236797930617592469549815015156583713140092602436213767817902648307527638140175555306899010082328302677707743256157969462562069566504938968043872588066626342404928338172765071506216897414731130641136238340474923700253626718314772495146977774901680746437173608867080360466896482469172153481489663125231730803152016979559853830420865747489880977145976234237006872242439421787871976063491413809087718924557110433457840900874495965997676170044944560526050860214599993358283826786452050069730345308657111099875457677692523597179434473659767946533102578803338921076284789508936832308697093054991715529648736096275502010821440630518994119179640915533010639869927395093021268945226506424763999726855670245184566049433852837640366269100263174223906015358912006105722807369421120912966198631469635596463919767397475846330616877367828445172492238218034972995212674929404152841104510393288468516386839094870371155028132498988349655918735257047563926342177673635810174227417403253565628411843958104419300585308206852361570095596172548041928371681900604753022177542717192983269846162995992604578501889228252676266530569912957214141664822272864579711870577984239477344065740519265347789698755746071340240556038753262093244267163009258286512783953861684104600560736837218890500097550698465289759140586738606157482853077601018128611136134760736996736708914669937146003550846356979192945132190031888313790252710854150238563087974124905120218725093018158547851214443336746416586781446034022431396044589401951670461020288544965698611748518611351331540370424111979753003843450545350245715831552504769422759114422983287014247315401494117220393422078506225011241233682714489934629024385529754469887377519621580182774163949251077527936457913801190121394730342272291913516599426029918486797126187996899642776051522338835434381563104216806838375313271583885403954043283505786432473998761057613912904106266911279470776278994044713599060023358711078188378023706627445075272211654635537815823533515407620803223473239726524940952504484829943966640850241885186604646060676111751908599524032529616805374697702490211063336390606636257715558737567876974288533629701605664879210832889239370190416434964505578619004144031396929930939153154261783826371055464505227549019183264071600165054981765877413194228874574914220693429080695523110135337328995014930446520865677793227702707671001810829708179764989028499247801196408542583881991412485026695097947247238201731029476061522964525387487230653794555245249558983520920460510477371513556640233890589112686985341437602214002842828064071650894562189109005023094842138317248472466995374938441962144670786326383914958717058211422918603455850169271666646080733034699759024082223181938165137101369825912000005720037409219381526928541461254208884300207439354108650470646550379701947472064769849457345194342409966028423785550491374822642080549759719299717985602117517206911413359868630908519477943110948540893056322147514496734409427674718631663074259023980756427430576172885400680049274263932500708084601624326500103299297364583249552487268538548222924656477435505587748461664087206741613925795623926374276592266628844384907218209814535981242989498857862854898394827558502995351620386345469837324121533443432251091400677542146914618402570065155425272118022815080514919641949162543889650107896682455133326631579290157632208529028438096399688848764329602216489146462009986592227509027506060834025384255627987942476041262642639477746924059375553851387615199908633999984002639791322588096455742500514057150893364859624873140335625787824492577334922517090051539609216342754585025929129119506301592930665956496887481672355381649522897749453921350504004715897528967908023031966701930392259327904924354643788784028331580514845064832481381865841573037392090699160446068393494870209756649105011198957166212419306441831494023681916039427964707024301195643661697104992103401457312363258781328735762064606732854540808169202221747884463085103761749629975185372277145319112017345870678047568626648542756943203428723276921655179353679714404205557346386860743727495188078104777387343569214420341210452242116454584727576115044033600321930489388336297597275699045004035054305046529029498368357588208839160044316442059911493447060295351860933789786219772464343460170080249649868978057751182004167248575583651405539536533451033475538632034077942301589160479404327755493925515607182961131827949483557813948092198475761373455007401492152954128659893628356963218051918179246057063800595141247579923395212533809521385831410718672365643550211171576025876744030864388972648347296379102917411030004686813801317804148147916804312596010156421074638965692165470964127627676247686639688719957932659103400778312089661494567273347670113877876737429032259805567169410931180483408389439803575320480784783766954247650907301498322554800941822284249425536316632618084296681609576288054660333664581927942762671208622962152664371924623671996777166646879935801526687984451889641525498049720571227260530617559216915407915320060551396088152057325004446246304102947963719183575768191430937905497564890749008777754375008010071475612773395038076547547383334475655390151875081576872635972599294604222498339098493620844029414836386593806317703009639055489578792899981974962025073652937790109970726683790316173612039520393632733378637145126962765847943614005441198084235346100538976093820209832167148661977428591095145639439523185522891904418982527228513245178013943569042846642895944446619847772796245153511574265917153888028770153982204794435688878870876825365005839474574247983370256859356797724554543032802399359759298118160482591648290672436920302640130736893390836128819541220604022882421023645649577768595960097842534422718303301383294148660492704561100651451905463443193038431994139586615355861510997313632041625828794335529825473013755442910402523816563587586480680089059351762102945481630530089245881895679364830374305573319086715884656652853778281683853490107113386049826027166318116013528592175655898395786138571525252539557732120462988114593115010199842916633988310222164973942794909461123806168793801877408670063643481588910595972756419454018168213564848531382969175525964941684387036296102316552018626758561202797387141648479000351754506785497842185044501504628173200028998734439813103514764577157774201078140162561664977005837940729777113344056046692472747053350245604622509537969226469130547459660902176006159570425666793396842423289718910608469391533307512279356986522049618839498670271056192958322290649776517118571625151522258627624812376933716197826919180680104994809366575910311929430860359812113640993989329728642660677176311738655570797118727406970314938281744449249726058606455706827074513540742019116863520450562268279233118617355486862467327401642672209848345107072114149031905330802213059666515242606145846549353970539106364023364804058467213490835066516958950259719319279701641614126500076982874019621168436680983488172250330704226652020351480046599332356261260339872151603592474362070208231544459677454537725621414807941599095869291794495279513360759239172930108704254851523136139669894056952267516575031428376513863384139490847211347519094447015849719869451320749845907536084408983645280768238874361313712487096333600484371972634965657595827144119221633235190011676472136229404978247423901503130152182510943275657821874130780441327043681499613325695973087590113960803861032212055003017508585142429581528521292237854758816139307078345422069351877855122470416014556840765960774072679484240449362138975344495498484814780572287981583173130180593884818325427258146543918705615878309361265108258404118402532489432424934391369501351587233489966325299627018404278324921598170750857392104103416965646712648353470171172359618328794319803980203199237327500536088783000865593531947047338350004989736495636975195720788358838788680228019674906061039950885668250146192615621353999603534536307861716639097410530406022406799411
0x77d23407...41A1eF090
0.789813443294215641 Eth
Nonce: 2
0.692733507294215641 Eth
Nonce: 3
0.097079936
(beaverbuild)
13.146080629010385716 Eth13.146840308509705908 Eth0.000759679499320192

Execution Trace

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

// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

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


// File @openzeppelin/contracts/token/ERC1155/[email protected]

// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol)

pragma solidity ^0.8.0;

/**
 * @dev Required interface of an ERC1155 compliant contract, as defined in the
 * https://eips.ethereum.org/EIPS/eip-1155[EIP].
 *
 * _Available since v3.1._
 */
interface IERC1155 is IERC165 {
    /**
     * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.
     */
    event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);

    /**
     * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
     * transfers.
     */
    event TransferBatch(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256[] ids,
        uint256[] values
    );

    /**
     * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
     * `approved`.
     */
    event ApprovalForAll(address indexed account, address indexed operator, bool approved);

    /**
     * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
     *
     * If an {URI} event was emitted for `id`, the standard
     * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
     * returned by {IERC1155MetadataURI-uri}.
     */
    event URI(string value, uint256 indexed id);

    /**
     * @dev Returns the amount of tokens of token type `id` owned by `account`.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function balanceOf(address account, uint256 id) external view returns (uint256);

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
     *
     * Requirements:
     *
     * - `accounts` and `ids` must have the same length.
     */
    function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)
        external
        view
        returns (uint256[] memory);

    /**
     * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
     *
     * Emits an {ApprovalForAll} event.
     *
     * Requirements:
     *
     * - `operator` cannot be the caller.
     */
    function setApprovalForAll(address operator, bool approved) external;

    /**
     * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
     *
     * See {setApprovalForAll}.
     */
    function isApprovedForAll(address account, address operator) external view returns (bool);

    /**
     * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
     *
     * Emits a {TransferSingle} event.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.
     * - `from` must have a balance of tokens of type `id` of at least `amount`.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
     * acceptance magic value.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        uint256 amount,
        bytes calldata data
    ) external;

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
     *
     * Emits a {TransferBatch} event.
     *
     * Requirements:
     *
     * - `ids` and `amounts` must have the same length.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
     * acceptance magic value.
     */
    function safeBatchTransferFrom(
        address from,
        address to,
        uint256[] calldata ids,
        uint256[] calldata amounts,
        bytes calldata data
    ) external;
}


// File @openzeppelin/contracts/token/ERC1155/extensions/[email protected]

// OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/IERC1155MetadataURI.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the optional ERC1155MetadataExtension interface, as defined
 * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].
 *
 * _Available since v3.1._
 */
interface IERC1155MetadataURI is IERC1155 {
    /**
     * @dev Returns the URI for token type `id`.
     *
     * If the `\{id\}` substring is present in the URI, it must be replaced by
     * clients with the actual token type ID.
     */
    function uri(uint256 id) external view returns (string memory);
}


// File @openzeppelin/contracts/token/ERC1155/[email protected]

// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)

pragma solidity ^0.8.0;

/**
 * @dev _Available since v3.1._
 */
interface IERC1155Receiver is IERC165 {
    /**
     * @dev Handles the receipt of a single ERC1155 token type. This function is
     * called at the end of a `safeTransferFrom` after the balance has been updated.
     *
     * NOTE: To accept the transfer, this must return
     * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
     * (i.e. 0xf23a6e61, or its own function selector).
     *
     * @param operator The address which initiated the transfer (i.e. msg.sender)
     * @param from The address which previously owned the token
     * @param id The ID of the token being transferred
     * @param value The amount of tokens being transferred
     * @param data Additional data with no specified format
     * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
     */
    function onERC1155Received(
        address operator,
        address from,
        uint256 id,
        uint256 value,
        bytes calldata data
    ) external returns (bytes4);

    /**
     * @dev Handles the receipt of a multiple ERC1155 token types. This function
     * is called at the end of a `safeBatchTransferFrom` after the balances have
     * been updated.
     *
     * NOTE: To accept the transfer(s), this must return
     * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
     * (i.e. 0xbc197c81, or its own function selector).
     *
     * @param operator The address which initiated the batch transfer (i.e. msg.sender)
     * @param from The address which previously owned the token
     * @param ids An array containing ids of each token being transferred (order and length must match values array)
     * @param values An array containing amounts of each token being transferred (order and length must match ids array)
     * @param data Additional data with no specified format
     * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
     */
    function onERC1155BatchReceived(
        address operator,
        address from,
        uint256[] calldata ids,
        uint256[] calldata values,
        bytes calldata data
    ) external returns (bytes4);
}


// File @openzeppelin/contracts/utils/[email protected]

// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

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

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

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

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

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

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

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

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

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

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
     *
     * _Available since v4.8._
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                // only check isContract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason or using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    function _revert(bytes memory returndata, string memory errorMessage) private pure {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert(errorMessage);
        }
    }
}


// File @openzeppelin/contracts/utils/[email protected]

// 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/utils/introspection/[email protected]

// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

pragma solidity ^0.8.0;

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


// File @openzeppelin/contracts/token/ERC1155/[email protected]

// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC1155/ERC1155.sol)

pragma solidity ^0.8.0;






/**
 * @dev Implementation of the basic standard multi-token.
 * See https://eips.ethereum.org/EIPS/eip-1155
 * Originally based on code by Enjin: https://github.com/enjin/erc-1155
 *
 * _Available since v3.1._
 */
contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {
    using Address for address;

    // Mapping from token ID to account balances
    mapping(uint256 => mapping(address => uint256)) private _balances;

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

    // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json
    string private _uri;

    /**
     * @dev See {_setURI}.
     */
    constructor(string memory uri_) {
        _setURI(uri_);
    }

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

    /**
     * @dev See {IERC1155MetadataURI-uri}.
     *
     * This implementation returns the same URI for *all* token types. It relies
     * on the token type ID substitution mechanism
     * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].
     *
     * Clients calling this function must replace the `\{id\}` substring with the
     * actual token type ID.
     */
    function uri(uint256) public view virtual override returns (string memory) {
        return _uri;
    }

    /**
     * @dev See {IERC1155-balanceOf}.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {
        require(account != address(0), "ERC1155: address zero is not a valid owner");
        return _balances[id][account];
    }

    /**
     * @dev See {IERC1155-balanceOfBatch}.
     *
     * Requirements:
     *
     * - `accounts` and `ids` must have the same length.
     */
    function balanceOfBatch(address[] memory accounts, uint256[] memory ids)
        public
        view
        virtual
        override
        returns (uint256[] memory)
    {
        require(accounts.length == ids.length, "ERC1155: accounts and ids length mismatch");

        uint256[] memory batchBalances = new uint256[](accounts.length);

        for (uint256 i = 0; i < accounts.length; ++i) {
            batchBalances[i] = balanceOf(accounts[i], ids[i]);
        }

        return batchBalances;
    }

    /**
     * @dev See {IERC1155-setApprovalForAll}.
     */
    function setApprovalForAll(address operator, bool approved) public virtual override {
        _setApprovalForAll(_msgSender(), operator, approved);
    }

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

    /**
     * @dev See {IERC1155-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        uint256 amount,
        bytes memory data
    ) public virtual override {
        require(
            from == _msgSender() || isApprovedForAll(from, _msgSender()),
            "ERC1155: caller is not token owner or approved"
        );
        _safeTransferFrom(from, to, id, amount, data);
    }

    /**
     * @dev See {IERC1155-safeBatchTransferFrom}.
     */
    function safeBatchTransferFrom(
        address from,
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) public virtual override {
        require(
            from == _msgSender() || isApprovedForAll(from, _msgSender()),
            "ERC1155: caller is not token owner or approved"
        );
        _safeBatchTransferFrom(from, to, ids, amounts, data);
    }

    /**
     * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
     *
     * Emits a {TransferSingle} event.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `from` must have a balance of tokens of type `id` of at least `amount`.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
     * acceptance magic value.
     */
    function _safeTransferFrom(
        address from,
        address to,
        uint256 id,
        uint256 amount,
        bytes memory data
    ) internal virtual {
        require(to != address(0), "ERC1155: transfer to the zero address");

        address operator = _msgSender();
        uint256[] memory ids = _asSingletonArray(id);
        uint256[] memory amounts = _asSingletonArray(amount);

        _beforeTokenTransfer(operator, from, to, ids, amounts, data);

        uint256 fromBalance = _balances[id][from];
        require(fromBalance >= amount, "ERC1155: insufficient balance for transfer");
        unchecked {
            _balances[id][from] = fromBalance - amount;
        }
        _balances[id][to] += amount;

        emit TransferSingle(operator, from, to, id, amount);

        _afterTokenTransfer(operator, from, to, ids, amounts, data);

        _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);
    }

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}.
     *
     * Emits a {TransferBatch} event.
     *
     * Requirements:
     *
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
     * acceptance magic value.
     */
    function _safeBatchTransferFrom(
        address from,
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) internal virtual {
        require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");
        require(to != address(0), "ERC1155: transfer to the zero address");

        address operator = _msgSender();

        _beforeTokenTransfer(operator, from, to, ids, amounts, data);

        for (uint256 i = 0; i < ids.length; ++i) {
            uint256 id = ids[i];
            uint256 amount = amounts[i];

            uint256 fromBalance = _balances[id][from];
            require(fromBalance >= amount, "ERC1155: insufficient balance for transfer");
            unchecked {
                _balances[id][from] = fromBalance - amount;
            }
            _balances[id][to] += amount;
        }

        emit TransferBatch(operator, from, to, ids, amounts);

        _afterTokenTransfer(operator, from, to, ids, amounts, data);

        _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);
    }

    /**
     * @dev Sets a new URI for all token types, by relying on the token type ID
     * substitution mechanism
     * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].
     *
     * By this mechanism, any occurrence of the `\{id\}` substring in either the
     * URI or any of the amounts in the JSON file at said URI will be replaced by
     * clients with the token type ID.
     *
     * For example, the `https://token-cdn-domain/\{id\}.json` URI would be
     * interpreted by clients as
     * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`
     * for token type ID 0x4cce0.
     *
     * See {uri}.
     *
     * Because these URIs cannot be meaningfully represented by the {URI} event,
     * this function emits no events.
     */
    function _setURI(string memory newuri) internal virtual {
        _uri = newuri;
    }

    /**
     * @dev Creates `amount` tokens of token type `id`, and assigns them to `to`.
     *
     * Emits a {TransferSingle} event.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
     * acceptance magic value.
     */
    function _mint(
        address to,
        uint256 id,
        uint256 amount,
        bytes memory data
    ) internal virtual {
        require(to != address(0), "ERC1155: mint to the zero address");

        address operator = _msgSender();
        uint256[] memory ids = _asSingletonArray(id);
        uint256[] memory amounts = _asSingletonArray(amount);

        _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);

        _balances[id][to] += amount;
        emit TransferSingle(operator, address(0), to, id, amount);

        _afterTokenTransfer(operator, address(0), to, ids, amounts, data);

        _doSafeTransferAcceptanceCheck(operator, address(0), to, id, amount, data);
    }

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.
     *
     * Emits a {TransferBatch} event.
     *
     * Requirements:
     *
     * - `ids` and `amounts` must have the same length.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
     * acceptance magic value.
     */
    function _mintBatch(
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) internal virtual {
        require(to != address(0), "ERC1155: mint to the zero address");
        require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");

        address operator = _msgSender();

        _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);

        for (uint256 i = 0; i < ids.length; i++) {
            _balances[ids[i]][to] += amounts[i];
        }

        emit TransferBatch(operator, address(0), to, ids, amounts);

        _afterTokenTransfer(operator, address(0), to, ids, amounts, data);

        _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);
    }

    /**
     * @dev Destroys `amount` tokens of token type `id` from `from`
     *
     * Emits a {TransferSingle} event.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `from` must have at least `amount` tokens of token type `id`.
     */
    function _burn(
        address from,
        uint256 id,
        uint256 amount
    ) internal virtual {
        require(from != address(0), "ERC1155: burn from the zero address");

        address operator = _msgSender();
        uint256[] memory ids = _asSingletonArray(id);
        uint256[] memory amounts = _asSingletonArray(amount);

        _beforeTokenTransfer(operator, from, address(0), ids, amounts, "");

        uint256 fromBalance = _balances[id][from];
        require(fromBalance >= amount, "ERC1155: burn amount exceeds balance");
        unchecked {
            _balances[id][from] = fromBalance - amount;
        }

        emit TransferSingle(operator, from, address(0), id, amount);

        _afterTokenTransfer(operator, from, address(0), ids, amounts, "");
    }

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.
     *
     * Emits a {TransferBatch} event.
     *
     * Requirements:
     *
     * - `ids` and `amounts` must have the same length.
     */
    function _burnBatch(
        address from,
        uint256[] memory ids,
        uint256[] memory amounts
    ) internal virtual {
        require(from != address(0), "ERC1155: burn from the zero address");
        require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");

        address operator = _msgSender();

        _beforeTokenTransfer(operator, from, address(0), ids, amounts, "");

        for (uint256 i = 0; i < ids.length; i++) {
            uint256 id = ids[i];
            uint256 amount = amounts[i];

            uint256 fromBalance = _balances[id][from];
            require(fromBalance >= amount, "ERC1155: burn amount exceeds balance");
            unchecked {
                _balances[id][from] = fromBalance - amount;
            }
        }

        emit TransferBatch(operator, from, address(0), ids, amounts);

        _afterTokenTransfer(operator, from, address(0), ids, amounts, "");
    }

    /**
     * @dev Approve `operator` to operate on all of `owner` tokens
     *
     * Emits an {ApprovalForAll} event.
     */
    function _setApprovalForAll(
        address owner,
        address operator,
        bool approved
    ) internal virtual {
        require(owner != operator, "ERC1155: setting approval status for self");
        _operatorApprovals[owner][operator] = approved;
        emit ApprovalForAll(owner, operator, approved);
    }

    /**
     * @dev Hook that is called before any token transfer. This includes minting
     * and burning, as well as batched variants.
     *
     * The same hook is called on both single and batched variants. For single
     * transfers, the length of the `ids` and `amounts` arrays will be 1.
     *
     * Calling conditions (for each `id` and `amount` pair):
     *
     * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * of token type `id` will be  transferred to `to`.
     * - When `from` is zero, `amount` tokens of token type `id` will be minted
     * for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`
     * will be burned.
     * - `from` and `to` are never both zero.
     * - `ids` and `amounts` have the same, non-zero length.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address operator,
        address from,
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) internal virtual {}

    /**
     * @dev Hook that is called after any token transfer. This includes minting
     * and burning, as well as batched variants.
     *
     * The same hook is called on both single and batched variants. For single
     * transfers, the length of the `id` and `amount` arrays will be 1.
     *
     * Calling conditions (for each `id` and `amount` pair):
     *
     * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * of token type `id` will be  transferred to `to`.
     * - When `from` is zero, `amount` tokens of token type `id` will be minted
     * for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`
     * will be burned.
     * - `from` and `to` are never both zero.
     * - `ids` and `amounts` have the same, non-zero length.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(
        address operator,
        address from,
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) internal virtual {}

    function _doSafeTransferAcceptanceCheck(
        address operator,
        address from,
        address to,
        uint256 id,
        uint256 amount,
        bytes memory data
    ) private {
        if (to.isContract()) {
            try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {
                if (response != IERC1155Receiver.onERC1155Received.selector) {
                    revert("ERC1155: ERC1155Receiver rejected tokens");
                }
            } catch Error(string memory reason) {
                revert(reason);
            } catch {
                revert("ERC1155: transfer to non-ERC1155Receiver implementer");
            }
        }
    }

    function _doSafeBatchTransferAcceptanceCheck(
        address operator,
        address from,
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) private {
        if (to.isContract()) {
            try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (
                bytes4 response
            ) {
                if (response != IERC1155Receiver.onERC1155BatchReceived.selector) {
                    revert("ERC1155: ERC1155Receiver rejected tokens");
                }
            } catch Error(string memory reason) {
                revert(reason);
            } catch {
                revert("ERC1155: transfer to non-ERC1155Receiver implementer");
            }
        }
    }

    function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {
        uint256[] memory array = new uint256[](1);
        array[0] = element;

        return array;
    }
}


// File @openzeppelin/contracts/token/ERC1155/extensions/[email protected]

// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC1155/extensions/ERC1155Supply.sol)

pragma solidity ^0.8.0;

/**
 * @dev Extension of ERC1155 that adds tracking of total supply per id.
 *
 * Useful for scenarios where Fungible and Non-fungible tokens have to be
 * clearly identified. Note: While a totalSupply of 1 might mean the
 * corresponding is an NFT, there is no guarantees that no other token with the
 * same id are not going to be minted.
 */
abstract contract ERC1155Supply is ERC1155 {
    mapping(uint256 => uint256) private _totalSupply;

    /**
     * @dev Total amount of tokens in with a given id.
     */
    function totalSupply(uint256 id) public view virtual returns (uint256) {
        return _totalSupply[id];
    }

    /**
     * @dev Indicates whether any token exist with a given id, or not.
     */
    function exists(uint256 id) public view virtual returns (bool) {
        return ERC1155Supply.totalSupply(id) > 0;
    }

    /**
     * @dev See {ERC1155-_beforeTokenTransfer}.
     */
    function _beforeTokenTransfer(
        address operator,
        address from,
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) internal virtual override {
        super._beforeTokenTransfer(operator, from, to, ids, amounts, data);

        if (from == address(0)) {
            for (uint256 i = 0; i < ids.length; ++i) {
                _totalSupply[ids[i]] += amounts[i];
            }
        }

        if (to == address(0)) {
            for (uint256 i = 0; i < ids.length; ++i) {
                uint256 id = ids[i];
                uint256 amount = amounts[i];
                uint256 supply = _totalSupply[id];
                require(supply >= amount, "ERC1155: burn amount exceeds totalSupply");
                unchecked {
                    _totalSupply[id] = supply - amount;
                }
            }
        }
    }
}


// File @openzeppelin/contracts/security/[email protected]

// 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/token/ERC20/[email protected]

// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);
}


// File contracts/IEthrunesURI.sol

pragma solidity ^0.8.17;

interface IEthrunesURI {
	function uri(uint256 id) external view returns(string memory);
}


// File contracts/StringUtils.sol

pragma solidity ^0.8.17;

library StringUtils {
  function strLen(string memory s) internal pure returns (uint256) {
    uint256 len;
    uint256 i = 0;
    uint256 bytelength = bytes(s).length;
    for (len = 0; i < bytelength; len++) {
      bytes1 b = bytes(s)[i];
      if (b < 0x80) {
          i += 1;
      } else if (b < 0xE0) {
          i += 2;
      } else if (b < 0xF0) {
          i += 3;
      } else if (b < 0xF8) {
          i += 4;
      } else if (b < 0xFC) {
          i += 5;
      } else {
          i += 6;
      }
    }
    return len;
  }

  function toLower(string memory s) internal pure returns (string memory) {
    bytes memory _bytes = bytes(s);
    for (uint i = 0; i < _bytes.length; i++) {
      if (uint8(_bytes[i]) >= 65 && uint8(_bytes[i]) <= 90) {
        _bytes[i] = bytes1(uint8(_bytes[i]) + 32);
      }
    }
    return string(_bytes);
  }
}


// File contracts/TransferHelper.sol

pragma solidity >=0.6.0;

library TransferHelper {
    /// @notice Transfers tokens from the targeted address to the given destination
    /// @notice Errors with 'STF' if transfer fails
    /// @param token The contract address of the token to be transferred
    /// @param from The originating address from which the tokens will be transferred
    /// @param to The destination address of the transfer
    /// @param value The amount to be transferred
    function safeTransferFrom(
        address token,
        address from,
        address to,
        uint256 value
    ) internal {
        (bool success, bytes memory data) =
            token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF');
    }

    /// @notice Transfers tokens from msg.sender to a recipient
    /// @dev Errors with ST if transfer fails
    /// @param token The contract address of the token which will be transferred
    /// @param to The recipient of the transfer
    /// @param value The value of the transfer
    function safeTransfer(
        address token,
        address to,
        uint256 value
    ) internal {
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST');
    }

    /// @notice Approves the stipulated contract to spend the given allowance in the given token
    /// @dev Errors with 'SA' if transfer fails
    /// @param token The contract address of the token to be approved
    /// @param to The target of the approval
    /// @param value The amount of the given token the target will be allowed to spend
    function safeApprove(
        address token,
        address to,
        uint256 value
    ) internal {
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA');
    }

    /// @notice Transfers ETH to the recipient address
    /// @dev Fails with `STE`
    /// @param to The destination of the transfer
    /// @param value The value to be transferred
    function safeTransferETH(address to, uint256 value) internal {
        (bool success, ) = to.call{value: value}(new bytes(0));
        require(success, 'STE');
    }
}


// File contracts/Ethrunes.sol

pragma solidity ^0.8.17;






contract Ethrunes is ERC1155Supply, ReentrancyGuard {
	struct Token {
		uint160 id;
		uint8 decimals;
		uint256 supply;
		uint256 limit;
		string tick;
	}
	
	string public constant name = "Ethrunes";
	string public constant symbol = "ERS";

	address dev;
	IEthrunesURI public ethrunesURI;
	// No length limit if is 0
	uint256 public tickMaxLength = 4;

	uint160[] public allTokenIds;
	mapping (uint160 => Token) public tokens;

	event Deploy(uint8 typ, Token token);
	event Wrap(address sender, address erc20, uint256 amount);
	event Unwrap(address sender, address erc20, uint256 amount);

	constructor() ERC1155("") {
		dev = msg.sender;
	}

	modifier onlyEOA() { 
		require(msg.sender == tx.origin, "Only EOA"); 
		_; 
	}

	modifier checkTickLength(string memory tick) { 
		uint tickLen = StringUtils.strLen(tick);
		if(tickLen == 0) {
			revert("Tick is empty");
		}
		if(tickMaxLength > 0 && tickLen > tickMaxLength) {
			revert("Tick too long");
		}
		_;
	}
	
	function setDev(address _dev) external {
		require(msg.sender == dev);
		dev = _dev;
	}

	function setEthrunesURI(address _uri) external {
		require(msg.sender == dev);
		ethrunesURI = IEthrunesURI(_uri);
	}

	function setTickMaxLength(uint256 _len) external {
		require(msg.sender == dev);
		tickMaxLength = _len;
	}
	
	function _idOf(string memory tick) internal view returns(uint160) {
		return uint160(uint256(keccak256(abi.encodePacked("ethrunes:", block.chainid, ":", StringUtils.toLower(tick)))));
	}

	function deploy(
		string calldata tick,
		uint8 decimals,
		uint256 supply,
		uint256 limit
	) external checkTickLength(tick) {
		require(limit > 0 && limit <= supply, "Invalid deploy args");
		uint160 id = _idOf(tick);
		require(tokens[id].supply == 0, "Deployed");
		require(totalSupply(id) == 0, "Token id occupied");

		Token memory token = Token({
			id: id,
			decimals: decimals,
			supply: supply,
			limit: limit,
			tick: tick
		});

		tokens[id] = token;
		allTokenIds.push(id);
		emit Deploy(1, token);
	}

	function deploy2(
		string calldata tick,
		uint8 decimals,
		uint256 supply,
		address to
	) external payable checkTickLength(tick) {
		require(supply > 0, "Supply is 0");
		uint160 id = _idOf(tick);
		require(tokens[id].supply == 0, "Deployed");
		require(totalSupply(id) == 0, "Token id occupied");

		Token memory token = Token({
			id: id,
			decimals: decimals,
			supply: supply,
			limit: supply,
			tick: tick
		});
		
		tokens[id] = token;
		allTokenIds.push(id);
		_mint(to, id, supply, "");
		emit Deploy(2, token);
	}

	function mint(string calldata tick) external onlyEOA {
		uint160 id = _idOf(tick);
		Token memory token = tokens[id];
		require(token.supply != 0, "Token not exists");
		require(totalSupply(token.id) + token.limit <= token.supply, "Exceeded maxSupply");
		_mint(msg.sender, token.id, token.limit, "");
	}

	function wrapERC20(IERC20 erc20, uint256 amount) external nonReentrant {
		uint160 id = uint160(address(erc20));
		require(tokens[id].supply == 0, "Failed to wrap, token id deployed");
		uint256 balanceBefore = erc20.balanceOf(address(this));
		TransferHelper.safeTransferFrom(address(erc20), msg.sender, address(this), amount);
		uint256 balanceAfter = erc20.balanceOf(address(this));
		require(balanceAfter - balanceBefore == amount, "Invalid amount");
		_mint(msg.sender, id, amount, "");

		emit Wrap(msg.sender, address(erc20), amount);
	}

	function unwrapERC20(IERC20 erc20, uint256 amount) external {
		uint256 id = uint160(address(erc20));
		require(balanceOf(msg.sender, id) >= amount, "Insufficient balance");
		_burn(msg.sender, id, amount);
		TransferHelper.safeTransfer(address(erc20), msg.sender, amount);
		emit Unwrap(msg.sender, address(erc20), amount);
	}

	function symbolOf(uint160 id) public view returns(string memory) {
		if(tokens[id].supply > 0) {
			return tokens[id].tick;	
		} else {
			bytes memory data = abi.encodeWithSelector(bytes4(keccak256("symbol()")));
			(bool success, bytes memory returnData) = address(id).staticcall(data);
			require(success, "call symbol() failed");
			if(returnData.length == 32) {
				return string(abi.encodePacked(returnData));
			} else {
				return abi.decode(returnData, (string));
			}
		}
	}

	function decimalsOf(uint160 id) public view returns(uint8) {
		if(tokens[id].supply > 0) {
			return tokens[id].decimals;
		} else {
			bytes memory data = abi.encodeWithSelector(bytes4(keccak256("decimals()")));
			(bool success, bytes memory returnData) = address(id).staticcall(data);
			require(success, "call decimals() failed");
			return abi.decode(returnData, (uint8));
		}
	}

	function allTokensCount() public view returns(uint256) {
		return allTokenIds.length;
	}

	function getTokens(uint256 from, uint256 to) public view returns(Token[] memory tokenArray) {
		if(allTokenIds.length == 0) {
			return tokenArray;
		}
		if(to > allTokenIds.length) {
			to = allTokenIds.length;
		}
		require(from < to, "Invalid range");
		tokenArray = new Token[](to - from);
		for(uint256 i = 0; i < tokenArray.length; i++) {
			tokenArray[i] = tokens[allTokenIds[i + from]];
		}
	}

	// disabled setApprovalForAll
	function setApprovalForAll(address, bool) public override {
		revert("setApprovalForAll is disabled");
	}

	function transfer(
		address to,
		uint256 id,
		uint256 amount,
		bytes memory data
	) external payable nonReentrant {
		if(msg.value > 0) {
  		TransferHelper.safeTransferETH(to, msg.value);	
  	}
		safeTransferFrom(msg.sender, to, id, amount, data);
	}

	function batchTransfer(
		address to,
		uint256[] memory ids,
		uint256[] memory amounts,
		bytes memory data
	) external payable nonReentrant {
		if(msg.value > 0) {
			TransferHelper.safeTransferETH(to, msg.value);	
		}
		safeBatchTransferFrom(msg.sender, to, ids, amounts, data);
	}

	function uri(uint256 id) public view override returns (string memory){
		return ethrunesURI.uri(id);
	}
}