ETH Price: $2,526.25 (+0.00%)

Transaction Decoder

Block:
17029622 at Apr-12-2023 04:39:47 AM +UTC
Transaction Fee:
0.03832010234524992 ETH $96.81
Gas Used:
1,918,878 Gas / 19.97005664 Gwei

Emitted Events:

27 FreeMint.OwnershipTransferred( previousOwner=0x00000000...000000000, newOwner=[Sender] 0x17ccc50df2b4f9ac0520d0a840e7fdf1afd91786 )

Account State Difference:

  Address   Before After State Difference Code
0x126BcDE4...86d57e34c
0 Eth
Nonce: 0
0 Eth
Nonce: 1
From: 0 To: 210786126064685207265354033758064947180313803142671694565834821606794820396569340698611325894419950675960434944252293177685807509713170040519782266877779643719755531136244749111275316384735970891701059247226206368707977579824306970243181133328691864771103877766992394210701052610888595796193439356289225570889096298700162911353761084200822288001461950621099136296277156324405742743828482197917309308563254427988588305437178366475434738980727764922603812102736469750904456328106085746725993088217693810457305899997294590818464455339930984983428402569495349671538229821850507270032717242933476794542806649750003633423307303417041874838577981957833615084403468746482712338284786449999786542305304834855803000485855786814696752001132023036543071148417061956526860010232949625526701421296828869417539359538156902793903121858713018195902007265639129601516333034598603431101554946949889692168180624992650346851655775685055612985282452550616733709352771324796411772598849239475940900037779492420373625034214548968556393931930488938962372888756437392815089320151128967611140138725573451958026831610175928127242152229079831577127447090088296409792300292590137974787294521080349498899341387253748604254233259720802677736116327491116114494458042069734814419946589217912247566354699428910511316481302218912941351916904832406726212895048383079798283551123353979321755106308751146168511378975830819676871949704124252020048377056099709045350930934134889378511137873166180641208116906863908094993315125353689716460925487420826998709431117299482167839523061912649699812255515327519873281755099435907763293190441689683146671348864255696737455675239901337578336064699061715633331848701523809461875061346504963622914881038554705910382128247026612979128944623187900523602756299047444032379295708633495084848072386757552786713501758990337910555166630869543346723545341444413734313987618286185879627236449650491840714185856224088518404681542812810306903006550307280200909916134654692173972193008659637238554122133200187386137622286865914058345992817340131121471459539271700476990077613474230834099969684140533141530063054124730125537450153685640361727287107625832394141066170928764972526940480784725189268035650956625969184175040982180923208370537534408286932661668880820261207870857426306559688406302785162542775178144212308072705535815910519445331560527766755938223534827134712778243869970686645958230217278806639981045703922748521899290502992253352870789920103389701862822454578633651813929798595718179755077438148684160267429416089335351528834269461521096769043956889884501143895211397106775345371042692275003780368691358002640935063141930869090720613114775689680180434391645780016232897658947171530702858460521058118028542647484944040058391642514643729170472536517474894285030561133534515325334028829480665168626057033623737219979258416342848485182553037707775584090290240773707169318806365664723214017554077392232772812900622981138591670589457181859092008007912353764339652524527359417583665142521615559097266477960281544739528426474562570033303432568889882012466620364507397372693876498120285178615354250057088063912435940966143232108865162964877750357597633822741241050031990894725205535694068734526285726196558389837922511699614407859358603861979844382299862469232576027592633758320129413661973184395316918545244240251126193133187754374118323319772311797655853736730388778727242243524960734434669010628275729134793998389264868434111416829714758674349797076730885037199446398174270164090355079058704571429270608354272977105794898587603997340412340559497687774311172542989960918122120756679941380552744717145485597814577481593834730914272539023406751310736371788386368585702455932811172515578796320240965512648780557210562529301467495486693769886457165708110454051333483517162890922129566029172693455738293352971979135984383963098115690018952332776664515405120779688808188348595732459017039414569323469305461464453814838896947369678968756207615720996789235351531980306826191049154558133738495522490830496301647562804033756356795653946800562131947717679446136999889483193329586878269416961766529307251189159216121160550551408329839299212072730757170484875453403280893628758414276222880685608737779165220752729512713851134637556581018364433887523844088549957643569515741271567241397381723038628460175758049890328201584290220339757133531210183201951189940941997117915996420528383300340990447293834834479150153354547041040858137146389640404746449202533568544686866281728113915793651692888934455277295079262011971777940969628826095727664485443370990898972655909301764370209269367879849246515917188270397557490927609681896064736615767393165547134705706392158434632719185292397717489888366840861887422466272353527319614394074463498009044835486046035638789876531084824306285531500247702086203551409677119378695505454820533195893081967346970933277192960341226763092240461683895901059534149744319472650590433907580227178027716374581737985998099789697778377312599256225334451031484929180180313265894298154221691363497183358466610592882128756543913723524097857052442902091265835391508236631779536506736201839245381930674622055814494377439504042339124037604932816263645470191668723361694347148734617884791204967992864185908891987489185804815647825538999919978198291473279971395940382890709262274622245961794644017376021906117153680161515883275228685680854033570039545008641159706685322612786177631064642742197667411919004212014214217269690882989964201889046080129548594785230393501237921526261303018582549190112907941751660284275441262737992967532580657993662757568781080832275074343971997206480392053310461316377612172488914174783188444255289116204241461404587356523358535494470388241151794418199386627521869130701544758554023111135600045040092282494473642230504577515529672369987493692595854477585721560182006208781389003912642039184795731702075864650150647202679635062879070303663241404463992889456917256697439137104118611456260681861889209768770565818320075099016948904329568179180094839258884428288792636468900160932061667527497941904101534542311221965906277234614330137012680709803121197704689993039872183258567388241220495341492930671998099767574802871713430705213932077686691985698562084765174457223143021996725094984589915021402168583871751423230261677376682153134406487055523089702157361919871507913325011343740086566821779355100125302140753344565402203792489306083318435049257548743852244374088351751025059534419561613855671092604696119418381391876400677152383034511962807926390876725955870798167975568105620752893327631767527156761428716046822511919057300733628686845429285105474296291556811251615611559153595946169202384471595025664933312074540615830795717649462433398927310693070050016142221891599761518285888220205425769530294363389626629122245352144729027942388854220263142792193771051026060172901783078967614400591083921047661631056649502635119305591909933460952235305362073780569648425638988360908480904951405834128585423307507094701709649003050538060044599396365300404242531133699398066335726167988269485338336000684320589526243139361557550506493914472686112122910799197635637926408926164582255291602623459003746356624337495091937384438412698585474056065016566596377139876722087512214650855200790612100546329566033383324941996306542482203992885647075388519555237348676062334930108636923001564173515316791157274323962434839567556082049655608999745188929770113874381723303468338329147919432078902627103446770838367435410951801721944022102876654755558613251545679524917153028180685956625750096289957078039244486385205852467329436710203324505295953046361828608733925527892816314485670464743202647041983438831620329395467061644648626988667542999435468226912720146790561287055683182122136158776865905443716055049380998184393462133636597466277534793912914133906198912503774697037837459843322932160567117162759724950856573245312971878111538326670256880530207772148278376554591588460101654786130866332976687864934242551234429052642658648532609309332087632519012858722676259476587879070122169960765527641683722956687626897336049247381054178703201683395131302865600739564780217037769851734181376507583730673525609775984764631451702139204013043361332396916097790684351447140852178500328771745462443860375838374537702981482495387246034676812402447546974951704682921937387577844501476829286057243643316513135402355015930090128574310683161271255850219527274533884380961428209101394602220110685543140568178052970182844035428325442485412296742145150542582265544272890658652032159671108029404163840016033154627519141978028073669774080543329060020754505805746749156875119572785128180662522907169980402264605962239544320614699063212219894632514470675549832067941319397615758718178909047698420671224579837700340937023877130513817411321843697022692034888464072072288105567240220836798591621698668222728337568959221254060764123123555387427902694536104696577895091751386900724579107259998186733852695546899841815393236930217263284361133339930844349988183830749446722971617915558504414605762227680885162053016498835917865962457024140888966888215889352621677966584527329375730009469062609477474280364438118468432484839175880532598739789945650905202912183090060086385458179191469403852677123204701944352330858995623999593747862096930562279547643018336303801362185511927462562837153118842894996652335441672869419710027051815856733772588101034681683606661395812174748932436742383250666922812941976130091892938898466284807575183777241430363316569534699212067687609641866000772022829583673577379965796533591477942979912421535413944576820308562949648632491029873011044499343404037040255856756423957288583665733294302161018002826536862643188509548904372293479760570858535737201870080605366746961260732972407047233297737880290250557558189418220209718179394914484102973358191944003989311352620479467128675605350562253388149858686676515490981016125332101586383993654952547478293969468335919073382607187203845998573487028994842234469852586248760172178641835811363414759249061644440756934570756014683891815488247483416033249941788368547452143512359919386547301616606909698465147432807412425282937380746689957447568905534932520530314608995427462954478143278037620073497462842175717859195965171140299944893293445429910320695341808289984799892528873779412901816166642500642939365683107124405189574489962606818379114004601547834741963401849162183471313310656594622628712571682274613150697645892610022601555477824279111063004697323815596197411939307035674392192523103514445230241018742281034128570778128373717419902812552529088484646218308022839322281863584380356107898645895119785334895081502730959926320713291901790830793224575772288751736741718761380959851529077244021560705858118655376956463741795803195765444852839017687250971824761521728161873842999792735137693942892432446876508543325541337025019260697719327884152111290771212850498124545389853968612647529840048420396179860260890781848333782643876419580810844783512153292354953840945068297365205114798355589619810008465202715180679243726757423459790014561829488583523715839092195204362763968627608846593525367530473465909109940675377491549241302117003062377585896328333416458907441789689856938825250737876965265543815343418020852041081144490025598587392774041774230620368509599531254856246147168941101717300931394005037075163777879420496416685481586416437040145125613014840090407070300264636442265973005450506378948915386325648148528115717494487213722911236246416873725481904366892136642666518357905526660689431911295887933280831580288807583495733150730999293337605394504517362616501825236829691784259735663785205989393910578405693272416704615319073698103658121947253654519690890522300239848374150513488952884313314207631277129790004779534756853340565754309389235799669199383819792782422113162237072209291534703028865755283773245853906446919528355046542600061602780363540442354031024051369050038255444974555213943219024067330735730736106435646514418226272805750052226588232056535220662108624226993428914139574750867091914703005655938009863536881353841098818502354490630630395583781575423257938846601765755494288972419414656712741388878963156579872034528889502498671946390734027056948428648206021016157465708511042847314753244512785584296861946155195454084584379650803997473877170415224088876645439925535849349204228825383300267867946769390486414626010495098988350071884017014381344839610099562447383700726274609233472254409640664911424544036585951965384932761054865456252566536590968558061789929195469818429723594894351058092706187521604531854813531577573658664484085117312633584059720175663707988079557897306651035550185197462122891503281986064707848730204611746412459989143112627475409369161305544016302298231219996464955563249103652445410189506818225073510577001211908506201087482899454484849814396613634620585486048146023883330235641847933996789418966192263759926662457819098792700669295028798511120820479577666627173671731325675658838577233161782814012840339667690687450954878822501650653069169195827867593947856580753702137528780164222553653710571961236067944804205569763334119687356567587236891267534541416907840784273812149020596618501476043378546837750728776422232177977204463659734735203895676861454331362366724351833168916392255867172053646507133613879777288958191632946390037613683576450499087987368700662011730203939285179478716003315226384193618891726067019305416672052140964169059365321827617444024419943434278956690149972103940688243181641330829118934054274880656491299617547904918612867761576180808930143624177910153364625823976602351037881360006139428566056271947158157536502197874816225984741597424697791074807988061906374011926172927425545163536289166564755929793222969250443670497205598078304804091140771999863054410113934644154683229982007582012541976354318923827751632301237181791129643432116435891293912945385563017936290450476458062685380197471295368104381002243350933729190802000253504693158660128793197797225471052060142565838302012437910319566233002332256626286631416882060263258283916887019090552515980515678883645655910040380006726823874965849716785718324700255767625724935916330663069883358265321657568413367215988796761833767029169489932199784898517491120796370649699089430840128552434778743141318850145228812885186737693227357431693059105586245916435683240191847802185990245425906915279004014421222003427553156839608458514297371785338310375476411540665823945907315515848628840425892653974383321978341843372932707285129495228819387589002971361165582441908656966453766769992229712892375308939481632516396186387276825921294768181172101793884576985054446357731140415750557064057565599998021834142201301929789264404370514039376882228618033942443373291677923082967313255350956900111684124300953645474069358887642916800978715215873669784817782025653977672862728732400317052108382882790040873409068131000766536513565873212664972020905026267223987822210559272633600399834867283519456690791845051700016052836633177282377030379602834564933001453159813875231262833303143400167344473611411035860017023074069863795427712226200792633315545076873584844119232794233108918092864132046237274617178589564954686388091633621581955331699957489844833746116923669297234658550449400454133258317955732106783673339741000258099840401057707210622827102378221125031959560361798316491782732112404865983555120785527912437082296408940837041223679069464175151540057863240678078238766370060492648655312147862203073731119061349784846684166387360011240234000363411778662844213387571981955494968409027717182403248234493779275287066790951408207065693272996422449268484185871953147627670422551259052392526626686596088816333816899501993521310497787576628241046745021268232814493134312470683295511618474744631294714755733863596411985326918545992791224873182206930208370667972106428422301528236483280255725152157296529591265791964314359037001165462972858973576710337119645153118935129259830112044925507466359419737673522034661319480034006788740391964244914956608686787241299902486557495701716877252887753139613009945235959937139311524813837892061371960192636059535945127923975299707014303487082486606620017102194383881985489025880788261199162700330667518772985839930366032404201823996105918745549497761245140072807999879155160405721182053491861403699464216082631723547640080009917108057742371430837401374076820920746382033030819862609208987808223838389291977873822536776216839988956098717895155232823293247451150175755330625874385652350788998184116057063557938433143819113738727108273042630904093965087556921840134682428711014801131066599853101009444259882904969181938808046264306840738300466480885538539225959736718218882554630358708758794123024538863591783380126678642669461207500134458459826021916205237793041205637812258156969731517924317566384890244076564663482725342762335284816751579323955281966197018845803822092228596314488134871438163218308826026601536512788046400758896635481917801792315872542108717980344280267060733838809628436523177153124980234418447210303081563091866046302079572628639362897135639391745331738302851890354344697057863191313063001445109186082279658933866015624652305045651569015584681529375419214237130611613223317523334540453164122936308746196209376947410559784958755038271246129993980134096573410453686695019936100651206156872502387606084993959166281499358984961726971383811986279503659967375955269741567303149980126254042935545392407843439790960082720770854185767980361007879131731955971362292374733187350546669994374868033699426059299798669642296039390780932325614467639610688810165454814482241773021594448641213454987262139564469320847375871841107888413557245606111808268634985124699957648364664084716021617748964498800077603689075897259961714716638160295907620080663637245859362841392755117664333457374789203598859147940476245389994600487971889377388405297616757507125739038941548065440500322186968710581527386004207490038401949702424043335605135514885185771872068523824255597294195666017763574667926286105687616161460823591948500943404118144151527540639527243724375661314518823475878419038750095975092998368864222478980951710329952767981036157596215639610236685540564666587468298809883864567604411808745874288252054244681395346051125135843238098083724110037207436393989008895823212158557756221963883447932295077886304633536876437525063785147612086384258281709855707365792072813202145558155339964023251640580584176551850342406498162408085128192191107814649446959926441875307562856284024969219037508723880516057461089575620319863601621911904284337462885687523460885301119719846946639938676937761479888388527818715909003083223358167394570293680523384031466454011005868798327106671546837439914778061575756441683537641806865418754934787378606047972688056528665288197385713791308714066512351452392038851493279216215658552754971604059894018993111068548619399832719853733455035898069724539861035132289699113913015765074040475458256348575447881398322785847433057248846471512877911069590994976053886723292142313088138149814043305430365487042209714263797060031234361413289914101553313753946480628172019070479790216453310737078960633494795717635095911443400685052723644139379541632967564180082122599263664621329796299134604525823224594482751314593198471117532796406930467156832584499073902382282200469896097725964858074300595615275484850732386889115144698077099693912155352141529248737043451397782835535214015672274590011535061442916649593526438633980788220150657056463689653254707081277810643569026152271948903481066439127348583588633736901720390494401950469779459836934065055743715243517278513214769381653598069261438408470450453346772067962243692622030924661416997527956547175621364036623703333500831610567192713112766535370630269349704394299587750248290923742438018484573955150493097394971232456127761879269769414949079602764973220711704022348392236773667672736596230277117868663526251783051470289391760578297215225338589591822091187958540304508358360281913173504317152585821063028378738441405987766439266010753885538656406647047817315574604869809203598032607758637165754564743463574286291639607961240274157501602435730067301812406247640460674153943187018396636023782928905260802374997135938746539886728468120635092310765406136606986300447363511702820901470320271285742264763271647157439200070016162651976783789412744069817908970124769846605175862688030856763828124277771757523702044240135341036197504509976702639045068089857115995519919884206131
0x17CCc50d...1aFD91786
(MeteoriaNFT: Deployer)
0.202081219660571438 Eth
Nonce: 84
0.163761117315321518 Eth
Nonce: 85
0.03832010234524992
(beaverbuild)
98.313320894585917901 Eth98.315239772585917901 Eth0.001918878

Execution Trace

FreeMint.60806040( )
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

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

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

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Down, // Toward negative infinity
        Up, // Toward infinity
        Zero // Toward zero
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
     * with further edits by Uniswap Labs also under MIT license.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1);

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
            // See https://cs.stackexchange.com/q/138556/92363.

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
            // in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator,
        Rounding rounding
    ) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10**64) {
                value /= 10**64;
                result += 64;
            }
            if (value >= 10**32) {
                value /= 10**32;
                result += 32;
            }
            if (value >= 10**16) {
                value /= 10**16;
                result += 16;
            }
            if (value >= 10**8) {
                value /= 10**8;
                result += 8;
            }
            if (value >= 10**4) {
                value /= 10**4;
                result += 4;
            }
            if (value >= 10**2) {
                value /= 10**2;
                result += 2;
            }
            if (value >= 10**1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256, rounded down, of a positive value.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);
        }
    }
}


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

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

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _SYMBOLS = "0123456789abcdef";
    uint8 private constant _ADDRESS_LENGTH = 20;

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        unchecked {
            uint256 length = Math.log10(value) + 1;
            string memory buffer = new string(length);
            uint256 ptr;
            /// @solidity memory-safe-assembly
            assembly {
                ptr := add(buffer, add(32, length))
            }
            while (true) {
                ptr--;
                /// @solidity memory-safe-assembly
                assembly {
                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
                }
                value /= 10;
                if (value == 0) break;
            }
            return buffer;
        }
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        unchecked {
            return toHexString(value, Math.log256(value) + 1);
        }
    }

    /**
     * @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] = _SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }

    /**
     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
     */
    function toHexString(address addr) internal pure returns (string memory) {
        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
    }
}


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

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

/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    enum RecoverError {
        NoError,
        InvalidSignature,
        InvalidSignatureLength,
        InvalidSignatureS,
        InvalidSignatureV // Deprecated in v4.8
    }

    function _throwError(RecoverError error) private pure {
        if (error == RecoverError.NoError) {
            return; // no error: do nothing
        } else if (error == RecoverError.InvalidSignature) {
            revert("ECDSA: invalid signature");
        } else if (error == RecoverError.InvalidSignatureLength) {
            revert("ECDSA: invalid signature length");
        } else if (error == RecoverError.InvalidSignatureS) {
            revert("ECDSA: invalid signature 's' value");
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature` or error string. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     *
     * Documentation for signature generation:
     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
        if (signature.length == 65) {
            bytes32 r;
            bytes32 s;
            uint8 v;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            /// @solidity memory-safe-assembly
            assembly {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }
            return tryRecover(hash, v, r, s);
        } else {
            return (address(0), RecoverError.InvalidSignatureLength);
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, signature);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
     *
     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address, RecoverError) {
        bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
        uint8 v = uint8((uint256(vs) >> 255) + 27);
        return tryRecover(hash, v, r, s);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
     *
     * _Available since v4.2._
     */
    function recover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, r, vs);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,
     * `r` and `s` signature fields separately.
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address, RecoverError) {
        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
            return (address(0), RecoverError.InvalidSignatureS);
        }

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        if (signer == address(0)) {
            return (address(0), RecoverError.InvalidSignature);
        }

        return (signer, RecoverError.NoError);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function recover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from a `hash`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from `s`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
    }

    /**
     * @dev Returns an Ethereum Signed Typed Data, created from a
     * `domainSeparator` and a `structHash`. This produces hash corresponding
     * to the one signed with the
     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
     * JSON-RPC method as part of EIP-712.
     *
     * See {recover}.
     */
    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
    }
}


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

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

/**
 * @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/[email protected]

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

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

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

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

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

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

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

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

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

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

// File contracts/FreeMint.sol

interface IMeteoriaNFT {
    function ownerMint(uint256, address) external;
}

contract FreeMint is Ownable {
    using ECDSA for bytes32;

    error AmountGreaterThanMax();
    error MintPaused();
    error NotSale();
    error NotPresale();
    error OnlyEOA();
    error NotWhitelisted();
    error NotAllowedSigProtected();

    struct SaleConfig {
        uint64 presaleStart;
        uint64 presaleEnd;
        uint8 maxMintsPresale;
        uint8 maxMintsPublic;
        bool mintPaused;
        bool sigProtected;
    }

    struct Mint {
        uint128 presaleMints;
        uint128 publicMints;
    }

    address private constant _PRESALE_AUTHORITY =
        0x8734A7EA99895869a16d2c2fc5DBAD78a40F1C70;
    address public constant METEORIA_NFT =
        0x4bD3B5e3936254CE753d154907997597021ce64a;

    SaleConfig public config;

    mapping(address => Mint) public mints;

    event ConfigUpdated(SaleConfig newConf);

    constructor() {
        config = SaleConfig(
            1681473600,
            1681484400,
            3,
            2,
            false,
            true
        );
    }

    function giveBackOwnership() external onlyOwner {
        Ownable(METEORIA_NFT).transferOwnership(msg.sender);
    }

    function setConfig(SaleConfig calldata newConf) external onlyOwner {
        config = newConf;

        emit ConfigUpdated(newConf);
    }

    function presaleMint(uint256 amount, bytes calldata sig)
        external
        payable
    {
        if (msg.sender != tx.origin) revert OnlyEOA();
        if (
            _PRESALE_AUTHORITY != keccak256(
                abi.encodePacked(msg.sender, address(this))
            ).toEthSignedMessageHash().recover(sig)
        ) revert NotWhitelisted();

        SaleConfig memory conf = config;

        if (conf.mintPaused) revert MintPaused();
        if (
            block.timestamp < conf.presaleStart ||
            block.timestamp >= conf.presaleEnd
        ) revert NotPresale();

        Mint memory userMints = mints[msg.sender];

        uint256 nextPreMints = userMints.presaleMints + amount;

        if (nextPreMints > conf.maxMintsPresale)
            revert AmountGreaterThanMax();

        mints[msg.sender].presaleMints = uint128(nextPreMints);

        IMeteoriaNFT(METEORIA_NFT).ownerMint(amount, msg.sender);
    }

    function saleMint(uint256 amount, bytes calldata sig)
        external
        payable
    {
        if (msg.sender != tx.origin) revert OnlyEOA();
        // Not checking soldout => performed on MTO contract
        SaleConfig memory conf = config;

        if (conf.mintPaused) revert MintPaused();
        if (block.timestamp < conf.presaleEnd) revert NotSale();

        if (
            conf.sigProtected &&
            _PRESALE_AUTHORITY != keccak256(
                abi.encodePacked(msg.sender, address(this))
            ).toEthSignedMessageHash().recover(sig)
        ) revert NotAllowedSigProtected();

        Mint memory userMints = mints[msg.sender];

        uint256 nextPubMints = userMints.publicMints + amount;

        if (nextPubMints > conf.maxMintsPublic)
            revert AmountGreaterThanMax();

        mints[msg.sender].publicMints = uint128(nextPubMints);

        IMeteoriaNFT(METEORIA_NFT).ownerMint(amount, msg.sender);
    }
}